Use new item picker for inventory manipulations

This commit is contained in:
Andrew Miner
2015-04-06 13:34:18 -07:00
parent 99d486f33b
commit 8aaf82db02
10 changed files with 86 additions and 105 deletions
@@ -31,6 +31,7 @@ module.exports = class CraftPageController extends PageController
super options super options
@imageLoader = options.imageLoader @imageLoader = options.imageLoader
@modPack = options.modPack
@storage = options.storage @storage = options.storage
# Event Methods ################################################################################ # Event Methods ################################################################################
@@ -53,13 +54,14 @@ module.exports = class CraftPageController extends PageController
onDidRender: -> onDidRender: ->
@wantController = @addChild InventoryController, '.want', @wantController = @addChild InventoryController, '.want',
editable: true editable: true
icon: '/images/fishing_rod.png' icon: '/images/fishing_rod.png'
imageLoader: @imageLoader imageLoader: @imageLoader
model: @model.plan.want isAcceptable: (item)-> item.isCraftable
modPack: @model.modPack model: @model.plan.want
onChange: => @_updateLocation() modPack: @model.modPack
title: 'Items you want' onChange: => @_updateLocation()
title: 'Items you want'
@haveController = @addChild InventoryController, '.have', @haveController = @addChild InventoryController, '.have',
editable: true, editable: true,
@@ -67,7 +69,6 @@ module.exports = class CraftPageController extends PageController
model: @model.plan.have model: @model.plan.have
modPack: @model.modPack modPack: @model.modPack
onChange: => @_saveHaveInventory() onChange: => @_saveHaveInventory()
nameFinder: new NameFinder @model.modPack, includeGatherable:true
title: 'Items you have' title: 'Items you have'
@needController = @addChild InventoryController, '.need', @needController = @addChild InventoryController, '.need',
@@ -5,13 +5,14 @@ Copyright (c) 2014-2015 by Redwood Labs
All rights reserved. All rights reserved.
### ###
BaseController = require './base_controller' BaseController = require './base_controller'
{Duration} = require '../constants' ImageLoader = require './image_loader'
{Event} = require '../constants' ItemSelectorController = require './item_selector_controller'
{Key} = require '../constants' NameFinder = require '../models/name_finder'
ImageLoader = require './image_loader' StackController = require './stack_controller'
NameFinder = require '../models/name_finder' {Duration} = require '../constants'
StackController = require './stack_controller' {Event} = require '../constants'
{Key} = require '../constants'
######################################################################################################################## ########################################################################################################################
@@ -26,13 +27,13 @@ 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'
@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 @imageLoader = options.imageLoader
@modPack = options.modPack @isAcceptable = options.isAcceptable ?= null
@nameFinder = options.nameFinder ?= new NameFinder options.modPack @modPack = options.modPack
@onChange = options.onChange ?= -> # do nothing @onChange = options.onChange ?= -> # do nothing
@title = options.title ?= 'Inventory' @title = options.title ?= 'Inventory'
options.templateName = 'inventory' options.templateName = 'inventory'
super options super options
@@ -43,59 +44,25 @@ module.exports = class InventoryController extends BaseController
# Event Methods ################################################################################ # Event Methods ################################################################################
onAddButtonClicked: ->
if @$nameField.val().trim().length is 0
@$nameField.focus()
return
item = @modPack.findItemByName @$nameField.val()
return unless item?
@model.add item.slug, 1
@$nameField.val ''
@$scrollbox.scrollTop @$scrollbox.prop 'scrollHeight'
@$nameField.autocomplete 'close'
@onChange()
onClearButtonClicked: -> onClearButtonClicked: ->
@model.clear() @model.clear()
@onChange() @onChange()
onItemSelected: -> onItemChosen: (itemSlug)->
func = => @model.add itemSlug, 1
@onNameFieldChanged() @onChange()
@onAddButtonClicked()
@$nameField.blur()
setTimeout func, 10 # needed to allow the autocomplete to finish
return true
onNameFieldBlur: ->
item = @modPack.findItemByName @$nameField.val()
@$nameField.val if item? then item.name else ''
@onNameFieldChanged()
onNameFieldChanged: ->
@_refreshButtonState()
onNameFieldFocused: ->
@$nameField.val ''
@$nameField.autocomplete 'search'
onNameFieldKeyUp: (event)->
if event.which is Key.Return
@onAddButtonClicked()
# BaseController Overrides ##################################################################### # BaseController Overrides #####################################################################
onDidRender: -> onDidRender: ->
@$addButton = @$('button[name="add"]') @selector = @addChild ItemSelectorController, '.view__item_selector',
isAcceptable: @isAcceptable
modPack: @modPack,
onChoseItem: (itemSlug)=> @onItemChosen(itemSlug)
@$clearButton = @$('button[name="clear"]') @$clearButton = @$('button[name="clear"]')
@$icon = @$('.icon') @$icon = @$('.icon')
@$editPanel = @$('.edit') @$editPanel = @$('.edit')
@$nameField = @$('input[name="name"]')
@$scrollbox = @$('.scrollbox') @$scrollbox = @$('.scrollbox')
@$table = @$('table') @$table = @$('table')
@$toolbar = @$('.toolbar') @$toolbar = @$('.toolbar')
@@ -118,7 +85,6 @@ module.exports = class InventoryController extends BaseController
@$title.html @title @$title.html @title
@_refreshStacks() @_refreshStacks()
@_refreshNameAutocomplete()
@_refreshButtonState() @_refreshButtonState()
super super
@@ -127,35 +93,13 @@ module.exports = class InventoryController extends BaseController
events: -> events: ->
return _.extend super, return _.extend super,
'blur input[name="name"]': 'onNameFieldBlur'
'click button[name="add"]': 'onAddButtonClicked'
'click button[name="clear"]': 'onClearButtonClicked' 'click button[name="clear"]': 'onClearButtonClicked'
'focus input[name="name"]': 'onNameFieldFocused'
'input input[name="name"]': 'onNameFieldChanged'
'keyup input[name="name"]': 'onNameFieldKeyUp'
# Private Methods ############################################################################## # Private Methods ##############################################################################
_refreshButtonState: -> _refreshButtonState: ->
if @model.isEmpty then @$clearButton.attr('disabled', 'disabled') else @$clearButton.removeAttr('disabled') if @model.isEmpty then @$clearButton.attr('disabled', 'disabled') else @$clearButton.removeAttr('disabled')
noText = @$nameField.val().trim().length is 0
itemValid = @modPack.findItemByName(@$nameField.val())?
disable = not (itemValid or noText)
if disable then @$addButton.attr('disabled', 'disabled') else @$addButton.removeAttr('disabled')
_refreshNameAutocomplete: ->
onChanged = => @onNameFieldChanged()
onSelected = => @onItemSelected()
@$nameField.autocomplete
source: (request, callback)=> callback @nameFinder.search request.term
delay: 0
minLength: 0
change: onChanged
close: onChanged
select: onSelected
_refreshStacks: -> _refreshStacks: ->
@_stackControllers ?= [] @_stackControllers ?= []
index = 0 index = 0
@@ -18,7 +18,8 @@ module.exports = class ItemSelectorController extends BaseController
constructor: (options)-> constructor: (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.model ?= new ItemSelector {}, modPack:options.modPack options.isAcceptable ?= null
options.model ?= new ItemSelector {}, modPack:options.modPack, isAcceptable:options.isAcceptable
options.onChoseItem ?= (item)-> # do nothing options.onChoseItem ?= (item)-> # do nothing
options.templateName = 'item_selector' options.templateName = 'item_selector'
super options super options
@@ -66,6 +67,7 @@ module.exports = class ItemSelectorController extends BaseController
@$popup.on Event.click, (event)=> @onPopupClicked(event) @$popup.on Event.click, (event)=> @onPopupClicked(event)
@$popup.removeClass 'hiding' @$popup.removeClass 'hiding'
@$hintField.off 'keyup input'
@$hintField.on 'keyup', (event)=> @onHintKeyPress(event) @$hintField.on 'keyup', (event)=> @onHintKeyPress(event)
@$hintField.on 'input', (event)=> @onHintChanged(event) @$hintField.on 'input', (event)=> @onHintChanged(event)
@@ -111,6 +113,11 @@ module.exports = class ItemSelectorController extends BaseController
@_refreshResults() @_refreshResults()
super super
render: ->
$buttonContent = @$el.html()
super
@$el.html $buttonContent
# Backbone.View Overrides ###################################################################### # Backbone.View Overrides ######################################################################
events: -> events: ->
@@ -134,6 +141,7 @@ module.exports = class ItemSelectorController extends BaseController
@$popup.one Event.transitionEnd, => @$popup.one Event.transitionEnd, =>
@$screen.css 'display', 'none' @$screen.css 'display', 'none'
@$popup.detach() @$popup.detach()
@model.hint = ''
_refreshResults: -> _refreshResults: ->
index = 0 index = 0
+6 -2
View File
@@ -43,7 +43,9 @@ client.onStatusChanged = (c, oldStatus, newStatus)->
logger.info "Crafting Guide server status changed from #{oldStatus} to #{newStatus}" logger.info "Crafting Guide server status changed from #{oldStatus} to #{newStatus}"
client.trigger 'change:status', client, oldStatus, newStatus client.trigger 'change:status', client, oldStatus, newStatus
client.trigger 'change', client client.trigger 'change', client
client.checkStatus()
# Disabled until required by some feature -- andrewminer 2015-04-06
# client.checkStatus()
global.router = new CraftingGuideRouter client:client global.router = new CraftingGuideRouter client:client
global.util = require 'util' global.util = require 'util'
@@ -53,7 +55,9 @@ global.markdown = global.markdown.markdown
global.feedbackController = new FeedbackController el:'.view__feedback' global.feedbackController = new FeedbackController el:'.view__feedback'
feedbackController.render() feedbackController.render()
global.router.loadCurrentUser() # Disabled until required by some feature. -- andrewminer 2015-04-06
# global.router.loadCurrentUser()
global.router.loadDefaultModPack() global.router.loadDefaultModPack()
logger.info -> "CraftingGuide is ready" logger.info -> "CraftingGuide is ready"
+9 -4
View File
@@ -14,9 +14,10 @@ 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
super attributes, options super attributes, options
@_isAcceptable = options.isAcceptable
@_maxResults = 100 @_maxResults = 100
@_minHintLength = 3 @_minHintLength = 3
@_modPack = options.modPack @_modPack = options.modPack
@@ -46,7 +47,7 @@ module.exports = class ItemSelector extends BaseModel
# Private Methods ############################################################################## # Private Methods ##############################################################################
_isMatch: (name)-> _isMatch: (name, itemSlug)->
hintIndex = 0 hintIndex = 0
hintLetter = @_hint[hintIndex] hintLetter = @_hint[hintIndex]
name = name.toLowerCase() name = name.toLowerCase()
@@ -54,7 +55,10 @@ module.exports = class ItemSelector extends BaseModel
for nameIndex in [0...name.length] by 1 for nameIndex in [0...name.length] by 1
if name.charAt(nameIndex) is hintLetter if name.charAt(nameIndex) is hintLetter
hintIndex += 1 hintIndex += 1
return true if hintIndex is @_hint.length if hintIndex is @_hint.length
item = @_modPack.findItem itemSlug
return false unless item?
return @_isAcceptable item
hintLetter = @_hint[hintIndex] hintLetter = @_hint[hintIndex]
return false return false
@@ -68,11 +72,12 @@ module.exports = class ItemSelector extends BaseModel
if @_hint.length >= @_minHintLength if @_hint.length >= @_minHintLength
@_modPack.eachMod (mod)=> @_modPack.eachMod (mod)=>
return if count >= @_maxResults return if count >= @_maxResults
return unless mod.enabled
mod.eachName (name, itemSlug)=> mod.eachName (name, itemSlug)=>
return if count >= @_maxResults return if count >= @_maxResults
if @_isMatch name if @_isMatch name, itemSlug
if itemSlug.isQualified if itemSlug.isQualified
newResults[itemSlug] = itemSlug newResults[itemSlug] = itemSlug
count += 1 count += 1
+1 -1
View File
@@ -30,4 +30,4 @@
p Craft p Craft
.dot .dot
.view__item_selector .view__item_selector: p.placeholder find an item...
+1 -4
View File
@@ -13,9 +13,6 @@
.scrollbox .scrollbox
table table
tr.edit.hideable.hidden tr.edit.hideable.hidden
td.quantity td.name(colspan="4", width="*"): .view__item_selector: p.button-label add an item...
td.icon
td.name(width="*"): input(name="name")
td.action: button(name="add") add
.toolbar.hideable.hidden .toolbar.hideable.hidden
button(name="clear") clear button(name="clear") clear
+12
View File
@@ -31,6 +31,18 @@ All rights reserved.
border-top: 1px solid $color-gray-light; 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;
}
}
button[name="clear"] { button[name="clear"] {
position: absolute; bottom: 0.5em; right: 0.5em; position: absolute; bottom: 0.5em; right: 0.5em;
} }
+14 -4
View File
@@ -12,13 +12,23 @@ All rights reserved.
cursor: pointer; cursor: pointer;
padding: 0 0.75em; padding: 0 0.75em;
p.placeholder { p {
position: relative; top: 50%; width: 100%; position: relative; top: 50%; width: 100%;
@include transform(translateY(-50%)); @include transform(translateY(-50%));
color: $color-gray-medium; &.placeholder {
font-family: $font-family-input; color: $color-gray-medium;
font-size: $font-size-normal; font-family: $font-family-input;
font-size: $font-size-normal;
}
&.button-label {
color: $color-active;
font-family: $font-family-normal;
font-size: $font-size-normal;
font-weight: bold;
text-align: center;
}
} }
} }
@@ -6,8 +6,8 @@ All rights reserved.
*/ */
.view__item_selector_element { .view__item_selector_element {
height: 3.6em; height: 4.0em;
padding: 0.3em 1em; padding: 0.2em 1em;
clear: both; clear: both;
transition: background $animate-fast, color $animate-fast; transition: background $animate-fast, color $animate-fast;