Redesign the crafting page
This introduces the new crafting page design featuring a new vertical layout and list display of all crafting steps. It also makes it easy to move items between the have/need sections and even from each step into your inventory (causing a new crafting plan to be created which doesn't plan on making that item). * Convert the `BaseController.hide` and `show` methods to be much more robust in the use of CSS transitions (using a timer in case a transition doesn't actually fire). * Change `hide`/`show` to use events for communicating animation state instead of callbacks * Convert several controllers to fire events for communication with parent controllers instead of accepting functions. * Rewrite the `CraftPageController`, `CraftPage` model and related Jade/SCSS files to implement the new design. * Alter the `InventoryController` and `StackController` to allow a variety of action buttons, and for the events from those action buttons to bubble up to parent controllers * Add the `StepController` and its related model, template, and style sheet as part of the new craft page. * Tweak the `ItemSelectorController` and related files to allow for a variety of styles for the launcher button
@@ -39,6 +39,17 @@ Duration.slow = 1200
|
|||||||
|
|
||||||
exports.Event = Event = {}
|
exports.Event = Event = {}
|
||||||
Event.add = 'add' # collection, item...
|
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.change = 'change' # model
|
||||||
Event.click = 'click' # event
|
Event.click = 'click' # event
|
||||||
Event.load = {}
|
Event.load = {}
|
||||||
@@ -54,15 +65,17 @@ Event.sync = 'sync' # model, response
|
|||||||
Event.transitionEnd = (->
|
Event.transitionEnd = (->
|
||||||
return unless document?
|
return unless document?
|
||||||
transitions =
|
transitions =
|
||||||
'transition': 'transitionend',
|
|
||||||
'OTransition': 'oTransitionEnd',
|
|
||||||
'MSTransition': 'msTransitionEnd',
|
|
||||||
'MozTransition': 'transitionend',
|
|
||||||
'WebkitTransition': 'webkitTransitionEnd'
|
'WebkitTransition': 'webkitTransitionEnd'
|
||||||
|
'MozTransition': 'transitionend'
|
||||||
|
'MSTransition': 'msTransitionEnd'
|
||||||
|
'OTransition': 'oTransitionEnd'
|
||||||
|
'transition': 'transitionend'
|
||||||
|
|
||||||
el = document.createElement 'fakeelement'
|
el = document.createElement 'fakeelement'
|
||||||
for styleName, eventName of transitions
|
for styleName, eventName of transitions
|
||||||
return eventName if el.style[styleName]?
|
return eventName if el.style[styleName]?
|
||||||
|
|
||||||
|
throw new Error 'cannot determine transitionEnd event'
|
||||||
)()
|
)()
|
||||||
|
|
||||||
exports.Key = Key = {}
|
exports.Key = Key = {}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ All rights reserved.
|
|||||||
###
|
###
|
||||||
|
|
||||||
views = require '../views'
|
views = require '../views'
|
||||||
|
{Duration} = require '../constants'
|
||||||
{Event} = require '../constants'
|
{Event} = require '../constants'
|
||||||
|
|
||||||
########################################################################################################################
|
########################################################################################################################
|
||||||
@@ -13,14 +14,13 @@ views = require '../views'
|
|||||||
module.exports = class BaseController extends Backbone.View
|
module.exports = class BaseController extends Backbone.View
|
||||||
|
|
||||||
constructor: (options={})->
|
constructor: (options={})->
|
||||||
options.useAnimations ?= true
|
|
||||||
@tryRefresh = _.debounce @_tryRefresh, 100
|
@tryRefresh = _.debounce @_tryRefresh, 100
|
||||||
|
|
||||||
@_model = null
|
|
||||||
@_rendered = false
|
|
||||||
@_parent = options.parent
|
|
||||||
@_children = []
|
@_children = []
|
||||||
@_useAnimations = options.useAnimations
|
@_model = null
|
||||||
|
@_parent = options.parent
|
||||||
|
@_rendered = false
|
||||||
|
@_useAnimations = options.useAnimations ?= true
|
||||||
|
|
||||||
@_loadTemplate options.templateName
|
@_loadTemplate options.templateName
|
||||||
super options
|
super options
|
||||||
@@ -36,33 +36,39 @@ module.exports = class BaseController extends Backbone.View
|
|||||||
@_children.push child
|
@_children.push child
|
||||||
return child
|
return child
|
||||||
|
|
||||||
hide: (args...)->
|
hide: ($el)->
|
||||||
{$el, callback} = @_resolveShowHideArgs args
|
$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 not ($el.hasClass('hiding') or $el.hasClass('hidden'))
|
||||||
if $el.hasClass('hiding') or $el.hasClass('hidden')
|
logger.verbose => "#{this} is hiding \"#{$el.selector}\""
|
||||||
_.defer => callback this
|
@_onAnimationComplete $el, Duration.normal, =>
|
||||||
else
|
|
||||||
$el.off Event.transitionEnd
|
|
||||||
$el.one Event.transitionEnd, =>
|
|
||||||
$el.addClass 'hidden'
|
$el.addClass 'hidden'
|
||||||
$el.removeClass 'hiding'
|
$el.removeClass 'hiding'
|
||||||
callback this
|
logger.verbose => "#{this} is finished hiding #{$el.selector}"
|
||||||
|
@trigger Event.animate.hide.finish, this, $el
|
||||||
|
|
||||||
$el.addClass 'hiding'
|
$el.addClass 'hiding'
|
||||||
|
@trigger Event.animate.hide.start, this, $el
|
||||||
|
|
||||||
refresh: ->
|
refresh: ->
|
||||||
logger.verbose => "#{this} refreshing"
|
logger.verbose => "#{this} refreshing"
|
||||||
|
|
||||||
remove: ->
|
remove: ->
|
||||||
if @_useAnimations
|
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"
|
logger.verbose => "#{this} is removing its element from the DOM"
|
||||||
@$el.remove()
|
@$el.remove()
|
||||||
|
@off()
|
||||||
|
@hide()
|
||||||
else
|
else
|
||||||
@$el.remove()
|
@$el.remove()
|
||||||
|
@off()
|
||||||
|
|
||||||
routeLinkClick: (event)->
|
routeLinkClick: (event)->
|
||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
@@ -75,19 +81,22 @@ module.exports = class BaseController extends Backbone.View
|
|||||||
else
|
else
|
||||||
router.navigate href, trigger:true
|
router.navigate href, trigger:true
|
||||||
|
|
||||||
show: (args...)->
|
show: ($el)->
|
||||||
{$el, callback} = @_resolveShowHideArgs args
|
$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}"
|
@_onAnimationComplete $el, Duration.normal, =>
|
||||||
if $el.hasClass('hiding') or $el.hasClass('hidden')
|
logger.verbose => "#{this} is finished showing #{$el.selector}"
|
||||||
$el.off Event.transitionEnd
|
@trigger Event.animate.show.finish, this, $el
|
||||||
$el.one Event.transitionEnd, => callback this
|
|
||||||
$el.removeClass 'hiding'
|
$el.addClass 'hiding'
|
||||||
$el.removeClass 'hidden'
|
$el.removeClass 'hidden'
|
||||||
else
|
_.defer =>
|
||||||
_.defer => callback this
|
$el.removeClass 'hiding'
|
||||||
|
@trigger Event.animate.show.start, this, $el
|
||||||
|
|
||||||
unrender: ->
|
unrender: ->
|
||||||
@undelegateEvents()
|
@undelegateEvents()
|
||||||
@@ -164,14 +173,12 @@ module.exports = class BaseController extends Backbone.View
|
|||||||
$renderedEl = $($(@_template(data))[0])
|
$renderedEl = $($(@_template(data))[0])
|
||||||
|
|
||||||
@onWillRender()
|
@onWillRender()
|
||||||
@hide() if @_useAnimations
|
|
||||||
|
|
||||||
@unrender()
|
@unrender()
|
||||||
|
|
||||||
@$el.append $renderedEl.children()
|
@$el.append $renderedEl.children()
|
||||||
@$el.addClass $renderedEl.attr 'class'
|
@$el.addClass $renderedEl.attr 'class'
|
||||||
@$el.data $renderedEl.data()
|
@$el.data $renderedEl.data()
|
||||||
@delegateEvents()
|
@delegateEvents()
|
||||||
@show() if options.show and @_useAnimations
|
|
||||||
|
|
||||||
@_rendered = true
|
@_rendered = true
|
||||||
@onDidRender()
|
@onDidRender()
|
||||||
@@ -189,19 +196,20 @@ module.exports = class BaseController extends Backbone.View
|
|||||||
if templateName?
|
if templateName?
|
||||||
@_template = views[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: ->
|
_tryRefresh: ->
|
||||||
return unless @_rendered
|
return unless @_rendered
|
||||||
@refresh()
|
@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
|
||||||
|
|||||||
@@ -5,16 +5,12 @@ Copyright (c) 2014-2015 by Redwood Labs
|
|||||||
All rights reserved.
|
All rights reserved.
|
||||||
###
|
###
|
||||||
|
|
||||||
CraftingTableController = require './crafting_table_controller'
|
AdsenseController = require './adsense_controller'
|
||||||
CraftPage = require '../models/craft_page'
|
CraftPage = require '../models/craft_page'
|
||||||
{Event} = require '../constants'
|
|
||||||
ImageLoader = require './image_loader'
|
|
||||||
InventoryController = require './inventory_controller'
|
InventoryController = require './inventory_controller'
|
||||||
ModPackController = require './mod_pack_controller'
|
|
||||||
NameFinder = require '../models/name_finder'
|
|
||||||
PageController = require './page_controller'
|
PageController = require './page_controller'
|
||||||
Storage = require '../models/storage'
|
StepController = require './step_controller'
|
||||||
{Text} = require '../constants'
|
{Event} = require '../constants'
|
||||||
{Url} = require '../constants'
|
{Url} = require '../constants'
|
||||||
|
|
||||||
########################################################################################################################
|
########################################################################################################################
|
||||||
@@ -24,9 +20,9 @@ module.exports = class CraftPageController extends PageController
|
|||||||
constructor: (options={})->
|
constructor: (options={})->
|
||||||
if not options.imageLoader? then throw new Error 'options.imageLoader 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.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.model ?= new CraftPage modPack:options.modPack
|
||||||
options.storage ?= new Storage storage:window.localStorage
|
|
||||||
options.templateName = 'craft_page'
|
options.templateName = 'craft_page'
|
||||||
super options
|
super options
|
||||||
|
|
||||||
@@ -34,10 +30,46 @@ module.exports = class CraftPageController extends PageController
|
|||||||
@modPack = options.modPack
|
@modPack = options.modPack
|
||||||
@storage = options.storage
|
@storage = options.storage
|
||||||
|
|
||||||
|
@model.plan.on Event.change, => @refresh()
|
||||||
|
|
||||||
# Event Methods ################################################################################
|
# Event Methods ################################################################################
|
||||||
|
|
||||||
onToolsBoxToggled: ->
|
onCraftTool: (itemSlug)->
|
||||||
@model.plan.includingTools = @$('.includeTools:checked').length isnt 0
|
# 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 #####################################################################
|
# PageController Overrides #####################################################################
|
||||||
|
|
||||||
@@ -46,69 +78,105 @@ module.exports = class CraftPageController extends PageController
|
|||||||
|
|
||||||
# BaseController Overrides #####################################################################
|
# 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: ->
|
onWillRender: ->
|
||||||
@storage.register 'crafting-plan', @model.plan, 'includingTools'
|
|
||||||
@model.plan.have.clear()
|
@model.plan.have.clear()
|
||||||
@model.plan.have.parse @storage.load('crafting-plan:have')
|
@model.plan.have.parse @storage.load('crafting-plan:have')
|
||||||
super
|
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 '<label><input class="includeTools" type="checkbox"> include tools</label>'
|
|
||||||
@$includeToolsBox = @$('.includeTools')
|
|
||||||
|
|
||||||
super
|
|
||||||
|
|
||||||
refresh: ->
|
refresh: ->
|
||||||
if @model.plan.includingTools
|
@_refreshSectionVisibility()
|
||||||
@$includeToolsBox.attr 'checked', 'checked'
|
@_refreshSteps()
|
||||||
else
|
|
||||||
@$includeToolsBox.removeAttr 'checked'
|
|
||||||
|
|
||||||
super
|
super
|
||||||
|
|
||||||
# Backbone.View Overrides ######################################################################
|
# Backbone.View Overrides ########################################################################
|
||||||
|
|
||||||
events: ->
|
events: ->
|
||||||
return _.extend super,
|
return _.extend super,
|
||||||
'change .includeTools': 'onToolsBoxToggled'
|
'click .instructions a': 'routeLinkClick'
|
||||||
|
|
||||||
# Private Methods ##############################################################################
|
# Private Methods ################################################################################
|
||||||
|
|
||||||
_saveHaveInventory: ->
|
_isStepCompletable: (controller)->
|
||||||
@storage.store 'crafting-plan:have', @model.plan.have.unparse()
|
return not @model.plan.want.hasAtLeast controller.model.outputItemSlug
|
||||||
|
|
||||||
_updateLocation: ->
|
_refreshSectionVisibility: ->
|
||||||
text = @model.plan.want.unparse()
|
if @model.plan.want.isEmpty
|
||||||
url = Url.crafting inventoryText:text
|
for $el in [@$toolsSection, @$ingredientsSection, @$stepsSection]
|
||||||
router.navigate url
|
@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()
|
||||||
|
|||||||
@@ -81,7 +81,7 @@ module.exports = class HeaderController extends BaseController
|
|||||||
addThisUrl = '//s7.addthis.com/js/300/addthis_widget.js#pubid=ra-54f3c9717b2e530d'
|
addThisUrl = '//s7.addthis.com/js/300/addthis_widget.js#pubid=ra-54f3c9717b2e530d'
|
||||||
$('body').append "<script async src=\"#{addThisUrl}\"></script>"
|
$('body').append "<script async src=\"#{addThisUrl}\"></script>"
|
||||||
|
|
||||||
@_itemSelector = @addChild ItemSelectorController, '.view__item_selector',
|
@_itemSelector = @addChild ItemSelectorController, '.view__item_selector.search',
|
||||||
modPack: @modPack
|
modPack: @modPack
|
||||||
onChoseItem: (itemSlug)=> @_goToItem(itemSlug)
|
onChoseItem: (itemSlug)=> @_goToItem(itemSlug)
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
module.exports = class InventoryController extends BaseController
|
||||||
|
|
||||||
@MAX_QUANTITY = 9999
|
@MAX_QUANTITY = 9999
|
||||||
@@ -27,12 +35,15 @@ module.exports = class InventoryController extends BaseController
|
|||||||
if not options.model? then throw new Error 'options.model 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'
|
if not options.modPack? then throw new Error 'options.modPack is required'
|
||||||
|
|
||||||
|
@imageLoader = options.imageLoader
|
||||||
|
@modPack = options.modPack
|
||||||
|
|
||||||
@editable = options.editable ?= true
|
@editable = options.editable ?= true
|
||||||
@icon = options.icon ?= '/images/chest_front.png'
|
@icon = options.icon ?= '/images/chest_front.png'
|
||||||
@imageLoader = options.imageLoader
|
@firstButtonType = options.firstButtonType ?= null
|
||||||
@isAcceptable = options.isAcceptable ?= null
|
@isAcceptable = options.isAcceptable ?= null
|
||||||
@modPack = options.modPack
|
@secondButtonType = options.secondButtonType ?= null
|
||||||
@onChange = options.onChange ?= -> # do nothing
|
@shouldEnableButton = options.shouldEnableButton ?= (model, button)-> true
|
||||||
@title = options.title ?= 'Inventory'
|
@title = options.title ?= 'Inventory'
|
||||||
|
|
||||||
options.templateName = 'inventory'
|
options.templateName = 'inventory'
|
||||||
@@ -46,11 +57,19 @@ module.exports = class InventoryController extends BaseController
|
|||||||
|
|
||||||
onClearButtonClicked: ->
|
onClearButtonClicked: ->
|
||||||
@model.clear()
|
@model.clear()
|
||||||
@onChange()
|
@trigger Event.clear, this
|
||||||
|
@trigger Event.change, this
|
||||||
|
|
||||||
|
onFirstButtonClicked: (stackController)->
|
||||||
|
@trigger Event.button.first, this, stackController?.model?.itemSlug
|
||||||
|
|
||||||
onItemChosen: (itemSlug)->
|
onItemChosen: (itemSlug)->
|
||||||
@model.add itemSlug, 1
|
@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 #####################################################################
|
# BaseController Overrides #####################################################################
|
||||||
|
|
||||||
@@ -60,32 +79,23 @@ module.exports = class InventoryController extends BaseController
|
|||||||
modPack: @modPack,
|
modPack: @modPack,
|
||||||
onChoseItem: (itemSlug)=> @onItemChosen(itemSlug)
|
onChoseItem: (itemSlug)=> @onItemChosen(itemSlug)
|
||||||
|
|
||||||
@$clearButton = @$('button[name="clear"]')
|
@$clearButton = @$('button.clear')
|
||||||
@$icon = @$('.icon')
|
@$icon = @$('.icon')
|
||||||
@$editPanel = @$('.edit')
|
@$itemContainer = @$('.item_container')
|
||||||
@$scrollbox = @$('.scrollbox')
|
|
||||||
@$table = @$('table')
|
|
||||||
@$toolbar = @$('.toolbar')
|
|
||||||
@$title = @$('h2 p')
|
@$title = @$('h2 p')
|
||||||
super
|
super
|
||||||
|
|
||||||
refresh: ->
|
refresh: ->
|
||||||
if @editable
|
if @editable
|
||||||
@show @$editPanel
|
@selector.show()
|
||||||
@show @$toolbar, =>
|
|
||||||
@$scrollbox.css bottom:@$toolbar.height()
|
|
||||||
else
|
else
|
||||||
if not @$editPanel? then throw new Error "no edit panel"
|
@selector.hide()
|
||||||
if not @$toolbar? then throw new Error "no toolbar"
|
|
||||||
@hide @$editPanel
|
|
||||||
@hide @$toolbar
|
|
||||||
@$scrollbox.css bottom:0
|
|
||||||
|
|
||||||
@$icon.attr 'src', @icon
|
@$icon.attr 'src', @icon
|
||||||
@$title.html @title
|
@$title.html @title
|
||||||
|
@$clearButton.disabled = @model.isEmpty
|
||||||
|
|
||||||
@_refreshStacks()
|
@_refreshStacks()
|
||||||
@_refreshButtonState()
|
|
||||||
|
|
||||||
super
|
super
|
||||||
|
|
||||||
@@ -93,38 +103,37 @@ module.exports = class InventoryController extends BaseController
|
|||||||
|
|
||||||
events: ->
|
events: ->
|
||||||
return _.extend super,
|
return _.extend super,
|
||||||
'click button[name="clear"]': 'onClearButtonClicked'
|
'click button.clear': 'onClearButtonClicked'
|
||||||
|
'click button.first': 'onFirstButtonClicked'
|
||||||
|
'click button.second': 'onSecondButtonClicked'
|
||||||
|
|
||||||
# Private Methods ##############################################################################
|
# Private Methods ##############################################################################
|
||||||
|
|
||||||
_refreshButtonState: ->
|
|
||||||
if @model.isEmpty then @$clearButton.attr('disabled', 'disabled') else @$clearButton.removeAttr('disabled')
|
|
||||||
|
|
||||||
_refreshStacks: ->
|
_refreshStacks: ->
|
||||||
@_stackControllers ?= []
|
@_stackControllers ?= []
|
||||||
index = 0
|
index = 0
|
||||||
|
|
||||||
$lastRow = @$table.find 'tr:last-child'
|
|
||||||
@model.each (stack)=>
|
@model.each (stack)=>
|
||||||
controller = @_stackControllers[index]
|
controller = @_stackControllers[index]
|
||||||
if not controller?
|
if not controller?
|
||||||
controller = new StackController
|
controller = new StackController
|
||||||
editable: @editable
|
editable: @editable
|
||||||
|
firstButtonType: @firstButtonType
|
||||||
imageLoader: @imageLoader
|
imageLoader: @imageLoader
|
||||||
model: stack
|
model: stack
|
||||||
modPack: @modPack
|
modPack: @modPack
|
||||||
onChange: @onChange
|
secondButtonType: @secondButtonType
|
||||||
onRemove: if not @editable then null else (stack)=> @_removeStack(stack)
|
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
|
@_stackControllers.push controller
|
||||||
controller.$el.insertBefore $lastRow
|
@$itemContainer.append controller.$el
|
||||||
controller.render()
|
|
||||||
else
|
else
|
||||||
controller.model = stack
|
controller.model = stack
|
||||||
index += 1
|
index += 1
|
||||||
|
|
||||||
while @_stackControllers.length > index
|
while @_stackControllers.length > index
|
||||||
@_stackControllers.pop().remove()
|
@_stackControllers.pop().remove()
|
||||||
|
|
||||||
_removeStack: (stack)->
|
|
||||||
@model.remove stack.itemSlug, stack.quantity
|
|
||||||
|
|||||||
@@ -65,7 +65,6 @@ module.exports = class ItemGroupController extends BaseController
|
|||||||
_refreshItems: ->
|
_refreshItems: ->
|
||||||
@_itemControllers ?= []
|
@_itemControllers ?= []
|
||||||
controllerIndex = 0
|
controllerIndex = 0
|
||||||
delay = 0
|
|
||||||
|
|
||||||
for item in @model
|
for item in @model
|
||||||
controller = @_itemControllers[controllerIndex]
|
controller = @_itemControllers[controllerIndex]
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ module.exports = class MinimalRecipeController extends BaseController
|
|||||||
|
|
||||||
@imageLoader = options.imageLoader
|
@imageLoader = options.imageLoader
|
||||||
@modPack = options.modPack
|
@modPack = options.modPack
|
||||||
|
@multiplier = options.multiplier ?= null
|
||||||
|
|
||||||
# BaseController Overrides #####################################################################
|
# BaseController Overrides #####################################################################
|
||||||
|
|
||||||
@@ -36,6 +37,7 @@ module.exports = class MinimalRecipeController extends BaseController
|
|||||||
imageLoader: @imageLoader
|
imageLoader: @imageLoader
|
||||||
modPack: @modPack
|
modPack: @modPack
|
||||||
|
|
||||||
|
@$multiplier = @$('.multiplier')
|
||||||
@$outputImg = @$('.output img')
|
@$outputImg = @$('.output img')
|
||||||
@$outputLink = @$('.output a')
|
@$outputLink = @$('.output a')
|
||||||
@$outputQuantity = @$('.quantity')
|
@$outputQuantity = @$('.quantity')
|
||||||
@@ -46,6 +48,8 @@ module.exports = class MinimalRecipeController extends BaseController
|
|||||||
@gridController.model = @model
|
@gridController.model = @model
|
||||||
@outputSlotController.model = @model?.output?[0]
|
@outputSlotController.model = @model?.output?[0]
|
||||||
@$el.tooltip show:{delay:Duration.snap, duration:Duration.fast}
|
@$el.tooltip show:{delay:Duration.snap, duration:Duration.fast}
|
||||||
|
|
||||||
|
@_refreshMultiplier()
|
||||||
@_refreshTools()
|
@_refreshTools()
|
||||||
super
|
super
|
||||||
|
|
||||||
@@ -57,6 +61,12 @@ module.exports = class MinimalRecipeController extends BaseController
|
|||||||
|
|
||||||
# Private Methods ##############################################################################
|
# Private Methods ##############################################################################
|
||||||
|
|
||||||
|
_refreshMultiplier: ->
|
||||||
|
if @multiplier? and @multiplier > 1
|
||||||
|
@$multiplier.html "x#{@multiplier}"
|
||||||
|
else
|
||||||
|
@$multiplier.html ''
|
||||||
|
|
||||||
_refreshTools: ->
|
_refreshTools: ->
|
||||||
@$toolContainer.empty()
|
@$toolContainer.empty()
|
||||||
return unless @model?
|
return unless @model?
|
||||||
|
|||||||
@@ -159,7 +159,7 @@ module.exports = class ModPageController extends PageController
|
|||||||
@$tutorialsContainer.append controller.$el
|
@$tutorialsContainer.append controller.$el
|
||||||
controller.render()
|
controller.render()
|
||||||
else
|
else
|
||||||
controller.model = model
|
controller.model = tutorial
|
||||||
|
|
||||||
index += 1
|
index += 1
|
||||||
|
|
||||||
|
|||||||
@@ -6,13 +6,20 @@ All rights reserved.
|
|||||||
###
|
###
|
||||||
|
|
||||||
BaseController = require './base_controller'
|
BaseController = require './base_controller'
|
||||||
|
ImageLoader = require './image_loader'
|
||||||
{Duration} = require '../constants'
|
{Duration} = require '../constants'
|
||||||
{Event} = require '../constants'
|
{Event} = require '../constants'
|
||||||
ImageLoader = require './image_loader'
|
|
||||||
{Key} = require '../constants'
|
{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
|
module.exports = class StackController extends BaseController
|
||||||
|
|
||||||
@MAX_QUANTITY = 9999
|
@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.model? then throw new Error 'options.model is required'
|
||||||
if not options.modPack? then throw new Error 'options.modPack 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'
|
options.templateName = 'stack'
|
||||||
super options
|
super options
|
||||||
|
|
||||||
@editable = options.editable
|
@editable = options.editable ?= false
|
||||||
|
@firstButtonType = options.firstButtonType ?= null
|
||||||
|
@imageLoader = options.imageLoader
|
||||||
@modPack = options.modPack
|
@modPack = options.modPack
|
||||||
@onChange = options.onChange
|
@secondButtonType = options.secondButtonType ?= null
|
||||||
@onRemove = options.onRemove
|
@shouldEnableButton = options.shouldEnableButton ?= (model, button)-> true
|
||||||
@_imageLoader = options.imageLoader
|
|
||||||
|
|
||||||
@modPack.on Event.change, => @tryRefresh()
|
@modPack.on Event.change, => @tryRefresh()
|
||||||
|
|
||||||
# Event Methods ################################################################################
|
# Event Methods ################################################################################
|
||||||
|
|
||||||
|
onFirstButtonClicked: (event)->
|
||||||
|
@trigger Event.button.first, this, @firstButtonType
|
||||||
|
return false
|
||||||
|
|
||||||
onQuantityFieldBlur: ->
|
onQuantityFieldBlur: ->
|
||||||
return unless @editable
|
return unless @editable
|
||||||
|
|
||||||
|
@$bubble.removeClass 'editing'
|
||||||
|
|
||||||
|
oldQuantity = @_priorValue
|
||||||
quantityText = @$quantityField.val().trim()
|
quantityText = @$quantityField.val().trim()
|
||||||
if quantityText.length is 0
|
if quantityText.length is 0
|
||||||
quantity = @_priorValue
|
newQuantity = oldQuantity
|
||||||
else if not quantityText.match /^[0-9]*$/
|
else if not quantityText.match /^[0-9]*$/
|
||||||
quantity = 1
|
newQuantity = 1
|
||||||
else
|
else
|
||||||
quantity = parseInt quantityText, 10
|
newQuantity = parseInt quantityText, 10
|
||||||
if _.isNaN quantity then quantity = 1
|
if _.isNaN newQuantity then newQuantity = 1
|
||||||
|
|
||||||
quantity = Math.min quantity, StackController.MAX_QUANTITY
|
newQuantity = Math.min newQuantity, StackController.MAX_QUANTITY
|
||||||
quantity = Math.max 1, quantity
|
newQuantity = Math.max 1, newQuantity
|
||||||
|
|
||||||
if quantity?
|
if newQuantity? and newQuantity isnt oldQuantity
|
||||||
@$quantityField.val "#{quantity}"
|
@$quantityField.val "#{newQuantity}"
|
||||||
@$quantityField.removeClass 'error', Duration.snap
|
@$bubble.removeClass 'error', Duration.snap
|
||||||
@$quantityField.removeClass 'error-new', Duration.snap
|
@$bubble.removeClass 'error-new', Duration.snap
|
||||||
|
|
||||||
@model.quantity = quantity
|
@model.quantity = newQuantity
|
||||||
@onChange()
|
@trigger Event.change + ':quantity', this, oldQuantity, newQuantity
|
||||||
|
@trigger Event.change, this
|
||||||
|
|
||||||
onQuantityFieldChanged: ->
|
onQuantityFieldChanged: ->
|
||||||
return unless @editable
|
return unless @editable
|
||||||
|
|
||||||
quantityText = @$quantityField.val().trim()
|
quantityText = @$quantityField.val().trim()
|
||||||
if not quantityText.match /^[0-9]*$/
|
if not quantityText.match /^[0-9]*$/
|
||||||
@$quantityField.addClass 'error', 0
|
@$bubble.addClass 'error', 0
|
||||||
@$quantityField.addClass 'error-new', 0
|
@$bubble.addClass 'error-new', 0
|
||||||
@$quantityField.removeClass 'error-new', Duration.fast
|
@$bubble.removeClass 'error-new', Duration.fast
|
||||||
else
|
else
|
||||||
@$quantityField.removeClass 'error', Duration.snap
|
@$bubble.removeClass 'error', Duration.snap
|
||||||
@$quantityField.removeClass 'error-new', Duration.snap
|
@$bubble.removeClass 'error-new', Duration.snap
|
||||||
|
|
||||||
onQuantityFieldFocused: ->
|
onQuantityFieldFocused: ->
|
||||||
|
|
||||||
if @editable
|
if @editable
|
||||||
|
@$bubble.addClass 'editing'
|
||||||
@_priorValue = @model.quantity
|
@_priorValue = @model.quantity
|
||||||
@$quantityField.val ''
|
@$quantityField.val ''
|
||||||
else
|
else
|
||||||
@@ -87,18 +101,20 @@ module.exports = class StackController extends BaseController
|
|||||||
if event.which is Key.Return
|
if event.which is Key.Return
|
||||||
@$quantityField.blur()
|
@$quantityField.blur()
|
||||||
|
|
||||||
onRemoveClicked: ->
|
onSecondButtonClicked: (event)->
|
||||||
@onRemove @model
|
event.preventDefault()
|
||||||
@onChange()
|
@trigger Event.button.second, this, @secondButtonType
|
||||||
|
|
||||||
# BaseController Overrides #####################################################################
|
# BaseController Overrides #####################################################################
|
||||||
|
|
||||||
onDidRender: ->
|
onDidRender: ->
|
||||||
@$action = @$('.action')
|
@$action = @$('.action')
|
||||||
|
@$bubble = @$('.bubble')
|
||||||
|
@$firstButton = @$('button.first')
|
||||||
@$image = @$('.icon img')
|
@$image = @$('.icon img')
|
||||||
@$nameLink = @$('.name a')
|
@$nameLink = @$('.name a')
|
||||||
@$quantityField = @$('.quantity input')
|
@$quantityField = @$('.quantity input')
|
||||||
@$removeButton = @$('button.remove')
|
@$secondButton = @$('button.second')
|
||||||
super
|
super
|
||||||
|
|
||||||
refresh: ->
|
refresh: ->
|
||||||
@@ -106,19 +122,23 @@ module.exports = class StackController extends BaseController
|
|||||||
|
|
||||||
display = @modPack.findItemDisplay @model.itemSlug
|
display = @modPack.findItemDisplay @model.itemSlug
|
||||||
|
|
||||||
@_imageLoader.load display.iconUrl, @$image
|
@imageLoader.load display.iconUrl, @$image
|
||||||
@$nameLink.html display.itemName
|
@$nameLink.html display.itemName
|
||||||
@$nameLink.attr 'href', display.itemUrl
|
@$nameLink.attr 'href', display.itemUrl
|
||||||
@$quantityField.val @model.quantity
|
@$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
|
if @editable
|
||||||
@$quantityField.removeAttr 'readonly'
|
@$quantityField.removeAttr 'readonly'
|
||||||
@$quantityField.addClass 'editable'
|
@$bubble.addClass 'editable'
|
||||||
else
|
else
|
||||||
@$quantityField.attr 'readonly', 'readonly'
|
@$quantityField.attr 'readonly', 'readonly'
|
||||||
@$quantityField.removeClass 'editable'
|
@$bubble.removeClass 'editable'
|
||||||
|
|
||||||
@$action.css display:(if @editable then 'table-cell' else 'none')
|
|
||||||
|
|
||||||
super
|
super
|
||||||
|
|
||||||
@@ -127,8 +147,21 @@ module.exports = class StackController extends BaseController
|
|||||||
events: ->
|
events: ->
|
||||||
return _.extend super,
|
return _.extend super,
|
||||||
'blur .quantity input': 'onQuantityFieldBlur'
|
'blur .quantity input': 'onQuantityFieldBlur'
|
||||||
'click button.remove': 'onRemoveClicked'
|
|
||||||
'click .name a': 'routeLinkClick'
|
'click .name a': 'routeLinkClick'
|
||||||
|
'click button.first': 'onFirstButtonClicked'
|
||||||
|
'click button.second': 'onSecondButtonClicked'
|
||||||
'focus .quantity input': 'onQuantityFieldFocused'
|
'focus .quantity input': 'onQuantityFieldFocused'
|
||||||
'input .quantity input': 'onQuantityFieldChanged'
|
'input .quantity input': 'onQuantityFieldChanged'
|
||||||
'keyup .quantity input': 'onQuantityKeyUp'
|
'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'
|
||||||
|
|||||||
@@ -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'
|
||||||
@@ -224,9 +224,11 @@ module.exports = class CraftingGuideRouter extends Backbone.Router
|
|||||||
controller.onWillShow()
|
controller.onWillShow()
|
||||||
controller.$el = $pageContent
|
controller.$el = $pageContent
|
||||||
controller.render()
|
controller.render()
|
||||||
|
controller.show()
|
||||||
|
|
||||||
if @_controller?
|
if @_controller?
|
||||||
@_controller.hide -> switchToNextController()
|
@_controller.once Event.animate.hide.finish, switchToNextController
|
||||||
|
@_controller.hide()
|
||||||
else
|
else
|
||||||
switchToNextController()
|
switchToNextController()
|
||||||
|
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ module.exports = class CraftPage extends BaseModel
|
|||||||
|
|
||||||
@modPack.on Event.change, => @_consumeParams()
|
@modPack.on Event.change, => @_consumeParams()
|
||||||
@on Event.change + ':params', => @_consumeParams()
|
@on Event.change + ':params', => @_consumeParams()
|
||||||
|
@plan.on Event.change, => @trigger Event.change, this
|
||||||
|
|
||||||
# Private Methods ##############################################################################
|
# Private Methods ##############################################################################
|
||||||
|
|
||||||
|
|||||||
@@ -6,9 +6,10 @@ All rights reserved.
|
|||||||
###
|
###
|
||||||
|
|
||||||
BaseModel = require './base_model'
|
BaseModel = require './base_model'
|
||||||
{Event} = require '../constants'
|
|
||||||
Inventory = require './inventory'
|
Inventory = require './inventory'
|
||||||
ItemSlug = require './item_slug'
|
ItemSlug = require './item_slug'
|
||||||
|
Step = require './step'
|
||||||
|
{Event} = require '../constants'
|
||||||
|
|
||||||
########################################################################################################################
|
########################################################################################################################
|
||||||
|
|
||||||
@@ -26,7 +27,7 @@ module.exports = class CraftingPlan extends BaseModel
|
|||||||
|
|
||||||
recraft = _.debounce (=> @craft()), 100
|
recraft = _.debounce (=> @craft()), 100
|
||||||
for inventory in [@have, @want]
|
for inventory in [@have, @want]
|
||||||
inventory.on 'change', recraft
|
inventory.on Event.change, recraft
|
||||||
|
|
||||||
@on Event.change + ':includingTools', recraft
|
@on Event.change + ':includingTools', recraft
|
||||||
|
|
||||||
@@ -140,7 +141,7 @@ module.exports = class CraftingPlan extends BaseModel
|
|||||||
@_findSteps inputStack.itemSlug, parentSteps
|
@_findSteps inputStack.itemSlug, parentSteps
|
||||||
|
|
||||||
logger.verbose -> "adding step for: #{recipe.slug}"
|
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
|
foundValidRecipe = true
|
||||||
break
|
break
|
||||||
catch error
|
catch error
|
||||||
@@ -166,16 +167,26 @@ module.exports = class CraftingPlan extends BaseModel
|
|||||||
return itemSlug
|
return itemSlug
|
||||||
|
|
||||||
_removeExtraSteps: ->
|
_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
|
@steps = result
|
||||||
|
|
||||||
_resolveNeeds: ->
|
_resolveNeeds: ->
|
||||||
for i in [@steps.length-1..0] by -1
|
for i in [@steps.length-1..0] by -1
|
||||||
step = @steps[i]
|
step = @steps[i]
|
||||||
recipe = step.recipe
|
step.number = i + 1
|
||||||
outputQuantity = recipe.getQuantityProducedOf step.itemSlug
|
|
||||||
|
|
||||||
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
|
if @includingTools
|
||||||
recipe.eachToolStack (stack)=>
|
recipe.eachToolStack (stack)=>
|
||||||
|
|||||||
@@ -20,9 +20,6 @@ module.exports = class Inventory extends BaseModel
|
|||||||
attributes.modPack ?= null
|
attributes.modPack ?= null
|
||||||
@clear()
|
@clear()
|
||||||
|
|
||||||
Object.defineProperties this,
|
|
||||||
isEmpty: { get:-> @_itemSlugs.length is 0 }
|
|
||||||
|
|
||||||
# Class Methods ################################################################################
|
# Class Methods ################################################################################
|
||||||
|
|
||||||
@Delimiters =
|
@Delimiters =
|
||||||
@@ -161,6 +158,14 @@ module.exports = class Inventory extends BaseModel
|
|||||||
|
|
||||||
return parts.join Inventory.Delimiters.Stack
|
return parts.join Inventory.Delimiters.Stack
|
||||||
|
|
||||||
|
# Property Methods #############################################################################
|
||||||
|
|
||||||
|
getIsEmpty: ->
|
||||||
|
return @_itemSlugs.length is 0
|
||||||
|
|
||||||
|
Object.defineProperties @prototype,
|
||||||
|
isEmpty: { get:@prototype.getIsEmpty }
|
||||||
|
|
||||||
# Object Overrides #############################################################################
|
# Object Overrides #############################################################################
|
||||||
|
|
||||||
toString: ->
|
toString: ->
|
||||||
@@ -185,7 +190,7 @@ module.exports = class Inventory extends BaseModel
|
|||||||
stack = @_stacks[itemSlug]
|
stack = @_stacks[itemSlug]
|
||||||
if not stack?
|
if not stack?
|
||||||
stack = new Stack itemSlug:itemSlug, quantity:quantity
|
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
|
@_stacks[itemSlug] = stack
|
||||||
@_itemSlugs.push itemSlug
|
@_itemSlugs.push itemSlug
|
||||||
@_sort()
|
@_sort()
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ module.exports = class ItemSelector extends BaseModel
|
|||||||
|
|
||||||
constructor: (attributes={}, options={})->
|
constructor: (attributes={}, options={})->
|
||||||
if not options.modPack? then throw new Error 'options.modPack is required'
|
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
|
super attributes, options
|
||||||
|
|
||||||
@_isAcceptable = options.isAcceptable
|
@_isAcceptable = options.isAcceptable
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -30,4 +30,4 @@
|
|||||||
p Craft
|
p Craft
|
||||||
.dot
|
.dot
|
||||||
|
|
||||||
.view__item_selector: p.placeholder find an item...
|
.view__item_selector.search: p find an item...
|
||||||
|
|||||||
@@ -6,8 +6,50 @@
|
|||||||
//-
|
//-
|
||||||
|
|
||||||
.view__craft_page
|
.view__craft_page
|
||||||
.view__inventory.want
|
.sidebar
|
||||||
.view__inventory.have
|
ins.view__adsense
|
||||||
.view__inventory.need
|
|
||||||
|
|
||||||
.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 <a href="/configure">Configure</a> 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 <img src="/images/up.png"> button to mark any items you already possess
|
||||||
|
li Use the <img src="/images/check.png"> button to complete any step if you already have that item
|
||||||
|
|||||||
@@ -6,13 +6,6 @@
|
|||||||
//-
|
//-
|
||||||
|
|
||||||
.view__inventory
|
.view__inventory
|
||||||
h2
|
.item_container
|
||||||
img.icon
|
.empty_placeholder.hideable.hidden Empty
|
||||||
p
|
.view__item_selector.hideable.hidden.button: p add an item...
|
||||||
.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
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
//- All rights reserved.
|
//- All rights reserved.
|
||||||
//-
|
//-
|
||||||
|
|
||||||
.view__item.hideable.hidden
|
.view__item
|
||||||
a
|
a
|
||||||
table
|
table
|
||||||
tr
|
tr
|
||||||
|
|||||||
@@ -6,8 +6,6 @@
|
|||||||
//-
|
//-
|
||||||
|
|
||||||
.view__item_selector
|
.view__item_selector
|
||||||
p.placeholder find items...
|
|
||||||
|
|
||||||
.view__item_selector_popup.hideable.hiding
|
.view__item_selector_popup.hideable.hiding
|
||||||
.search
|
.search
|
||||||
input
|
input
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
|
|
||||||
.view__minimal_recipe
|
.view__minimal_recipe
|
||||||
.input
|
.input
|
||||||
table.view__crafting_grid
|
.view__crafting_grid
|
||||||
.tool
|
.tool
|
||||||
.output.view__slot
|
.output.view__slot
|
||||||
|
.multiplier
|
||||||
@@ -5,9 +5,10 @@
|
|||||||
//- All rights reserved.
|
//- All rights reserved.
|
||||||
//-
|
//-
|
||||||
|
|
||||||
tr.view__stack
|
.view__stack
|
||||||
td.quantity: input
|
.quantity: .bubble: input
|
||||||
td.icon: img(src='')
|
.icon: img(src='')
|
||||||
td.name(width='*'): a
|
.name: a
|
||||||
td.action
|
.action
|
||||||
button.remove
|
button.second
|
||||||
|
button.first
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -101,12 +101,20 @@ All rights reserved.
|
|||||||
font-family: $font-family-header;
|
font-family: $font-family-header;
|
||||||
font-size: $font-size-large;
|
font-size: $font-size-large;
|
||||||
margin-bottom: 0.5em;
|
margin-bottom: 0.5em;
|
||||||
|
|
||||||
|
&:first-child {
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
h3 {
|
h3 {
|
||||||
font-family: $font-family-header;
|
font-family: $font-family-header;
|
||||||
font-size: $font-size-normal;
|
font-size: $font-size-normal;
|
||||||
margin: 2em 0 0 0.5em;
|
margin: 2em 0 0 0.5em;
|
||||||
|
|
||||||
|
&:first-child {
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.entry {
|
.entry {
|
||||||
@@ -118,6 +126,10 @@ All rights reserved.
|
|||||||
background: white;
|
background: white;
|
||||||
padding: 1em;
|
padding: 1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&:first-child {
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.slideable {
|
.slideable {
|
||||||
|
|||||||
@@ -7,20 +7,44 @@ All rights reserved.
|
|||||||
|
|
||||||
.view__craft_page {
|
.view__craft_page {
|
||||||
|
|
||||||
& > div {
|
.want.section {
|
||||||
display: inline-block;
|
.view__inventory {
|
||||||
margin-top: 2em;
|
position: relative; width: 100%;
|
||||||
padding: 0 2em;
|
}
|
||||||
position: relative;
|
|
||||||
vertical-align: top;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.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 {
|
.instructions.section {
|
||||||
position: absolute; top: 50%; left: 0.5em;
|
p {
|
||||||
@include transform(translateY(-50%));
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,5 +27,6 @@ All rights reserved.
|
|||||||
@import 'mod_selector';
|
@import 'mod_selector';
|
||||||
@import 'stack';
|
@import 'stack';
|
||||||
@import 'slot';
|
@import 'slot';
|
||||||
|
@import 'step';
|
||||||
@import 'tutorial';
|
@import 'tutorial';
|
||||||
@import 'video';
|
@import 'video';
|
||||||
|
|||||||
@@ -6,92 +6,72 @@ All rights reserved.
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
.view__inventory {
|
.view__inventory {
|
||||||
min-height: 14em;
|
|
||||||
|
.item_container {
|
||||||
|
position: relative; width: 100%;
|
||||||
|
|
||||||
|
.view__stack > div {
|
||||||
|
height: 4.2em;
|
||||||
|
padding: 0 1em 0.5em 0;
|
||||||
|
vertical-align: middle;
|
||||||
|
|
||||||
|
&:last-child {
|
||||||
|
padding: 0 0 0.5em 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon {
|
||||||
|
img {
|
||||||
|
height: 3.6em; width: 3.6em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.name {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|
||||||
.edit td {
|
|
||||||
padding-top: 1em;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.panel {
|
.action {
|
||||||
position: absolute; top: 3.6em; right: 2em; bottom: 0; left: 2em;
|
white-space: nowrap;
|
||||||
background: $color-background-panel;
|
|
||||||
text-align: right;
|
|
||||||
}
|
|
||||||
|
|
||||||
.scrollbox {
|
button:first-child {
|
||||||
position: absolute; top: 0em; right: 0em; bottom: 3em; left: 0em;
|
margin-right: 0.5em;
|
||||||
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 {
|
.view__item_selector {
|
||||||
height: 2.5em; width: 80%;
|
position: relative; width: 80%;
|
||||||
background: $color-gray-faint;
|
margin: 1em auto;
|
||||||
margin: 0 auto;
|
|
||||||
|
|
||||||
transition: background $animate-normal;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
background: $color-background-panel;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
button[name="clear"] {
|
&.large {
|
||||||
position: absolute; bottom: 0.5em; right: 0.5em;
|
.item_container {
|
||||||
|
.view__stack > div {
|
||||||
|
height: 5em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.quantity {
|
||||||
|
.bubble {
|
||||||
|
border-radius: 3em;
|
||||||
|
|
||||||
input {
|
input {
|
||||||
border: 1px solid $color-gray-light;
|
font-size: $font-size-large;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
button:disabled {
|
.icon {
|
||||||
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 {
|
img {
|
||||||
width: 100%; height: auto;
|
height: 4.8em; width: 4.8em;
|
||||||
max-height: 4.8em;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
td.name {
|
.name {
|
||||||
text-align: left;
|
a {
|
||||||
padding-right: 1em;
|
font-size: $font-size-large;
|
||||||
|
font-weight: bold;
|
||||||
input {
|
|
||||||
width: 100%;
|
|
||||||
border: 0;
|
|
||||||
border-bottom: 1px dashed $color-gray-light;
|
|
||||||
outline: 0;
|
|
||||||
|
|
||||||
&:focus {
|
|
||||||
border: 1px solid $color-gray-light;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
td.action {
|
|
||||||
width: 4em;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,30 +6,42 @@ All rights reserved.
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
.view__item_selector {
|
.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: 0.1em solid $color-gray-medium;
|
||||||
border-radius: 1.5em;
|
border-radius: 1.5em;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
padding: 0 0.75em;
|
padding: 0 0.75em;
|
||||||
|
|
||||||
p {
|
&.search {
|
||||||
position: relative; top: 50%; width: 100%;
|
background: $color-background-panel;
|
||||||
@include transform(translateY(-50%));
|
|
||||||
|
|
||||||
&.placeholder {
|
p {
|
||||||
color: $color-gray-medium;
|
color: $color-gray-medium;
|
||||||
font-family: $font-family-input;
|
font-family: $font-family-input;
|
||||||
font-size: $font-size-normal;
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&.button-label {
|
&.button {
|
||||||
|
background: $color-gray-faint;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: $color-background-panel;
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
color: $color-active;
|
color: $color-active;
|
||||||
font-family: $font-family-normal;
|
font-family: $font-family-normal;
|
||||||
font-size: $font-size-normal;
|
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
position: absolute; top: 50%; width: 100%;
|
||||||
|
@include transform(translateY(-50%));
|
||||||
|
font-size: $font-size-normal;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.view__item_selector_popup {
|
.view__item_selector_popup {
|
||||||
|
|||||||
@@ -44,13 +44,6 @@ All rights reserved.
|
|||||||
@include transform(translate(-50%, -50%));
|
@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 {
|
.quantity {
|
||||||
position: absolute; right: 0.1em; bottom: 0;
|
position: absolute; right: 0.1em; bottom: 0;
|
||||||
color: white;
|
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;
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,6 +29,10 @@ All rights reserved.
|
|||||||
font-size: $font-size-large;
|
font-size: $font-size-large;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.itemGroups {
|
||||||
|
margin-top: 2em;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.view__item {
|
.view__item {
|
||||||
|
|||||||
@@ -7,38 +7,36 @@ All rights reserved.
|
|||||||
|
|
||||||
.view__stack {
|
.view__stack {
|
||||||
font-family: $font-family-normal;
|
font-family: $font-family-normal;
|
||||||
|
display: table-row;
|
||||||
|
|
||||||
td {
|
& > div {
|
||||||
padding: 0.2em 0;
|
display: table-cell;
|
||||||
|
vertical-align: middle;
|
||||||
}
|
}
|
||||||
|
|
||||||
td.quantity {
|
.quantity {
|
||||||
position: relative;
|
.bubble {
|
||||||
width: 5em;
|
border: 0.1em solid $color-gray-light;
|
||||||
|
border-radius: 1.5em;
|
||||||
|
background: $color-ice;
|
||||||
|
|
||||||
input {
|
input {
|
||||||
position: absolute; top: 50%; height: $font-size-small; width: 100%;
|
width: 3em;
|
||||||
@include transform(translateY(-50%));
|
background: none;
|
||||||
|
border: none;
|
||||||
border-radius: 0.75em;
|
|
||||||
background: $color-ice;
|
|
||||||
color: $color-background-panel;
|
color: $color-background-panel;
|
||||||
font-family: $font-family-normal;
|
font-family: $font-family-normal;
|
||||||
font-size: $font-size-normal;
|
font-size: $font-size-normal;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
text-align: center;
|
line-height: $font-size-normal;
|
||||||
|
|
||||||
&.editable {
|
|
||||||
&:focus {
|
|
||||||
background: $color-background-panel;
|
|
||||||
color: $color-text;
|
|
||||||
font-family: $font-family-input;
|
|
||||||
font-weight: normal;
|
|
||||||
outline: none;
|
outline: none;
|
||||||
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
&:hover {
|
&.editable:hover, &.editing {
|
||||||
background: $color-background-panel;
|
background: $color-background-panel;
|
||||||
|
|
||||||
|
input {
|
||||||
color: $color-text;
|
color: $color-text;
|
||||||
font-family: $font-family-input;
|
font-family: $font-family-input;
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
@@ -47,10 +45,7 @@ All rights reserved.
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
td.icon {
|
.icon {
|
||||||
width: 4.6em;
|
|
||||||
padding: 0.2em 0.5em;
|
|
||||||
|
|
||||||
img {
|
img {
|
||||||
width: 100%; height: auto;
|
width: 100%; height: auto;
|
||||||
max-height: 4.8em;
|
max-height: 4.8em;
|
||||||
@@ -58,9 +53,9 @@ All rights reserved.
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
td.name a {
|
.name {
|
||||||
|
a {
|
||||||
color: $color-text;
|
color: $color-text;
|
||||||
display: inline;
|
|
||||||
font-size: $font-size-normal;
|
font-size: $font-size-normal;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
|
|
||||||
@@ -69,26 +64,88 @@ All rights reserved.
|
|||||||
text-decoration: underline;
|
text-decoration: underline;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
td.action {
|
.action {
|
||||||
text-align: right;
|
text-align: right;
|
||||||
}
|
|
||||||
|
|
||||||
button.remove {
|
button {
|
||||||
opacity: 0;
|
position: relative; width: 3.0em; height: 3.0em;
|
||||||
position: relative; width: 1.8em; height: 1.8em;
|
display: inline-block;
|
||||||
background: url('/images/remove.png') no-repeat center;
|
|
||||||
border: 0;
|
border: 0;
|
||||||
|
font-size: $font-size-small;
|
||||||
|
margin: 0;
|
||||||
outline: none;
|
outline: none;
|
||||||
|
padding: 0;
|
||||||
|
|
||||||
&:hover {
|
&.check {
|
||||||
background: url('/images/remove-hover.png') no-repeat center;
|
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 {
|
&:hover {
|
||||||
button.remove {
|
background: url('/images/check_hover.png') no-repeat center;
|
||||||
opacity: 1;
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.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;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Before Width: | Height: | Size: 282 B |
|
Before Width: | Height: | Size: 302 B |
|
Before Width: | Height: | Size: 282 B |
|
Before Width: | Height: | Size: 277 B |
|
Before Width: | Height: | Size: 296 B |
|
Before Width: | Height: | Size: 280 B |
|
After Width: | Height: | Size: 2.5 KiB |
|
After Width: | Height: | Size: 2.5 KiB |
|
After Width: | Height: | Size: 1.8 KiB |
|
After Width: | Height: | Size: 2.4 KiB |
|
After Width: | Height: | Size: 2.1 KiB |
|
After Width: | Height: | Size: 2.2 KiB |
|
After Width: | Height: | Size: 1.8 KiB |
|
After Width: | Height: | Size: 2.0 KiB |
|
After Width: | Height: | Size: 2.3 KiB |
|
After Width: | Height: | Size: 1.9 KiB |
|
After Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 921 B |
|
Before Width: | Height: | Size: 853 B After Width: | Height: | Size: 2.2 KiB |
|
After Width: | Height: | Size: 2.4 KiB |
|
After Width: | Height: | Size: 1.8 KiB |
|
After Width: | Height: | Size: 2.1 KiB |
|
After Width: | Height: | Size: 2.3 KiB |
|
After Width: | Height: | Size: 2.3 KiB |
|
After Width: | Height: | Size: 1.7 KiB |
|
After Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 35 KiB |