196 lines
6.2 KiB
CoffeeScript
196 lines
6.2 KiB
CoffeeScript
###
|
|
Crafting Guide - item_selector_controller.coffee
|
|
|
|
Copyright (c) 2015 by Redwood Labs
|
|
All rights reserved.
|
|
###
|
|
|
|
$ = require 'jquery'
|
|
_ = require 'underscore'
|
|
BaseController = require './base_controller'
|
|
{Duration} = require '../constants'
|
|
{Event} = require '../constants'
|
|
ItemSelector = require '../models/item_selector'
|
|
ItemSelectorElementController = require './item_selector_element_controller'
|
|
{Key} = require '../constants'
|
|
|
|
########################################################################################################################
|
|
|
|
module.exports = class ItemSelectorController extends BaseController
|
|
|
|
constructor: (options)->
|
|
if not options.modPack? then throw new Error 'options.modPack is required'
|
|
options.isAcceptable ?= null
|
|
options.model ?= new ItemSelector {}, modPack:options.modPack, isAcceptable:options.isAcceptable
|
|
options.onChoseItem ?= (item)-> # do nothing
|
|
options.templateName = 'item_selector'
|
|
super options
|
|
|
|
@modPack = options.modPack
|
|
@onChoseItem = options.onChoseItem
|
|
|
|
@_elementControllers = []
|
|
|
|
# Event Methods ################################################################################
|
|
|
|
onHintKeyPress: (event)->
|
|
switch event.which
|
|
when Key.Escape
|
|
@_close()
|
|
return false
|
|
when Key.Enter
|
|
@_chooseSelected()
|
|
return false
|
|
when Key.DownArrow
|
|
@_selectNext()
|
|
return false
|
|
when Key.UpArrow
|
|
@_selectPrevious()
|
|
return false
|
|
|
|
onHintChanged: (event)->
|
|
@model.hint = @$hintField.val()
|
|
@tryRefresh()
|
|
@onResultSelected @_elementControllers[0]
|
|
|
|
onLaunchButtonClicked: (event)->
|
|
event.preventDefault()
|
|
@model.hint = ''
|
|
@refresh()
|
|
|
|
$('body').addClass 'stop-scrolling'
|
|
|
|
@$screen.append @$popup
|
|
@$screen.css 'display', 'block'
|
|
|
|
@$popup.offset @$el.offset()
|
|
@$popup.css 'width', @$el.css 'width'
|
|
@$popup.off Event.click
|
|
@$popup.on Event.click, (event)=> @onPopupClicked(event)
|
|
@$popup.removeClass 'hiding'
|
|
|
|
@$hintField.off 'keyup input'
|
|
@$hintField.on 'keyup', (event)=> @onHintKeyPress(event)
|
|
@$hintField.on 'input', (event)=> @onHintChanged(event)
|
|
|
|
@$popup.off Event.transitionEnd
|
|
@$popup.one Event.transitionEnd, => @onPopupDisplayed()
|
|
@$screen.one Event.click, (event)=> @onScreenClicked(event)
|
|
|
|
onPopupClicked: (event)->
|
|
return false
|
|
|
|
onPopupDisplayed: ->
|
|
@$hintField.focus()
|
|
|
|
onResultClicked: (controller)->
|
|
@_close()
|
|
@onChoseItem controller.model.slug
|
|
|
|
onResultSelected: (controller)->
|
|
for c in @_elementControllers
|
|
c.selected = false
|
|
|
|
if controller?
|
|
controller.selected = true
|
|
|
|
onScreenClicked: (event)->
|
|
@_close()
|
|
return false
|
|
|
|
# BaseController Overrides #####################################################################
|
|
|
|
onDidRender: ->
|
|
@$screen = $('.view__screen') # find the shared, global screen
|
|
@$popup = @$('.view__item_selector_popup')
|
|
@$hintField = @$('.view__item_selector_popup input')
|
|
@$searchInput = @$('.search input')
|
|
@$resultsContainer = @$('.results')
|
|
|
|
@$popup.detach()
|
|
super
|
|
|
|
refresh: ->
|
|
@$hintField.val @model.hint
|
|
@_refreshResults()
|
|
super
|
|
|
|
render: ->
|
|
$buttonContent = @$el.html()
|
|
super
|
|
@$el.html $buttonContent
|
|
|
|
# Backbone.View Overrides ######################################################################
|
|
|
|
events: ->
|
|
return _.extend super,
|
|
'click': 'onLaunchButtonClicked'
|
|
|
|
# Private Methods ##############################################################################
|
|
|
|
_chooseSelected: ->
|
|
for controller in @_elementControllers
|
|
if controller.selected
|
|
@onResultClicked controller
|
|
return
|
|
|
|
_close: ->
|
|
$('body').removeClass 'stop-scrolling'
|
|
|
|
@$popup.addClass 'hiding'
|
|
|
|
@$popup.off Event.transitionEnd
|
|
@$popup.one Event.transitionEnd, =>
|
|
@$screen.css 'display', 'none'
|
|
@$popup.detach()
|
|
@model.hint = ''
|
|
|
|
_refreshResults: ->
|
|
index = 0
|
|
|
|
for itemSlug in @model.results
|
|
displayModel = @modPack.findItemDisplay itemSlug
|
|
controller = @_elementControllers[index]
|
|
if not controller?
|
|
controller = new ItemSelectorElementController
|
|
model: displayModel
|
|
onClicked: (c)=> @onResultClicked(c)
|
|
onSelected: (c)=> @onResultSelected(c)
|
|
controller.render show:false
|
|
@_elementControllers[index] = controller
|
|
@$resultsContainer.append controller.$el
|
|
else
|
|
controller.model = displayModel
|
|
|
|
controller.show()
|
|
index += 1
|
|
|
|
while @_elementControllers.length > index
|
|
@_elementControllers.pop().remove()
|
|
|
|
_selectNext: ->
|
|
for i in [0...(@_elementControllers.length - 1)] by 1
|
|
controller = @_elementControllers[i]
|
|
nextController = @_elementControllers[i + 1]
|
|
|
|
if controller.selected
|
|
controller.selected = false
|
|
nextController.selected = true
|
|
@_showElement nextController.$el
|
|
return
|
|
|
|
_selectPrevious: ->
|
|
for i in [1...@_elementControllers.length] by 1
|
|
previousController = @_elementControllers[i - 1]
|
|
controller = @_elementControllers[i]
|
|
|
|
if controller.selected
|
|
previousController.selected = true
|
|
controller.selected = false
|
|
@_showElement previousController.$el
|
|
return
|
|
|
|
_showElement: ($el)->
|
|
top = $el.position().top + @$resultsContainer.scrollTop()
|
|
@$resultsContainer.animate {scrollTop:top}, duration:Duration.snap
|