Add site-wide search function
This commit is contained in:
@@ -13,12 +13,14 @@ views = require '../views'
|
||||
module.exports = class BaseController extends Backbone.View
|
||||
|
||||
constructor: (options={})->
|
||||
options.useAnimations ?= true
|
||||
@tryRefresh = _.debounce @_tryRefresh, 100
|
||||
|
||||
@_model = null
|
||||
@_rendered = false
|
||||
@_parent = options.parent
|
||||
@_children = []
|
||||
@_model = null
|
||||
@_rendered = false
|
||||
@_parent = options.parent
|
||||
@_children = []
|
||||
@_useAnimations = options.useAnimations
|
||||
|
||||
@_loadTemplate options.templateName
|
||||
super options
|
||||
@@ -55,8 +57,12 @@ module.exports = class BaseController extends Backbone.View
|
||||
logger.verbose => "#{this} refreshing"
|
||||
|
||||
remove: ->
|
||||
logger.verbose => "#{this} is removing its element from the DOM"
|
||||
@hide => @$el.remove()
|
||||
if @_useAnimations
|
||||
@hide =>
|
||||
logger.verbose => "#{this} is removing its element from the DOM"
|
||||
@$el.remove()
|
||||
else
|
||||
@$el.remove()
|
||||
|
||||
routeLinkClick: (event)->
|
||||
event.preventDefault()
|
||||
@@ -158,14 +164,14 @@ module.exports = class BaseController extends Backbone.View
|
||||
$renderedEl = $($(@_template(data))[0])
|
||||
|
||||
@onWillRender()
|
||||
@hide()
|
||||
@hide() if @_useAnimations
|
||||
|
||||
@unrender()
|
||||
@$el.append $renderedEl.children()
|
||||
@$el.addClass $renderedEl.attr 'class'
|
||||
@$el.data $renderedEl.data()
|
||||
@delegateEvents()
|
||||
@show() if options.show
|
||||
@show() if options.show and @_useAnimations
|
||||
|
||||
@_rendered = true
|
||||
@onDidRender()
|
||||
|
||||
@@ -5,11 +5,12 @@ Copyright (c) 2015 by Redwood Labs
|
||||
All rights reserved.
|
||||
###
|
||||
|
||||
BaseController = require './base_controller'
|
||||
{Duration} = require '../constants'
|
||||
{Event} = require '../constants'
|
||||
{ProductionEnvs} = require '../constants'
|
||||
{Url} = require '../constants'
|
||||
BaseController = require './base_controller'
|
||||
ItemSelectorController = require './item_selector_controller'
|
||||
{Duration} = require '../constants'
|
||||
{Event} = require '../constants'
|
||||
{ProductionEnvs} = require '../constants'
|
||||
{Url} = require '../constants'
|
||||
|
||||
########################################################################################################################
|
||||
|
||||
@@ -17,10 +18,12 @@ module.exports = class HeaderController extends BaseController
|
||||
|
||||
constructor: (options={})->
|
||||
if not options.client? then throw new Error 'options.client is required'
|
||||
if not options.modPack? then throw new Error 'options.modPack is required'
|
||||
super options
|
||||
|
||||
@client = options.client
|
||||
@_user = options.user
|
||||
@client = options.client
|
||||
@modPack = options.modPack
|
||||
@_user = options.user
|
||||
|
||||
# Event Methods ################################################################################
|
||||
|
||||
@@ -78,6 +81,10 @@ module.exports = class HeaderController extends BaseController
|
||||
addThisUrl = '//s7.addthis.com/js/300/addthis_widget.js#pubid=ra-54f3c9717b2e530d'
|
||||
$('body').append "<script async src=\"#{addThisUrl}\"></script>"
|
||||
|
||||
@_itemSelector = @addChild ItemSelectorController, '.view__item_selector',
|
||||
modPack: @modPack
|
||||
onChoseItem: (itemSlug)=> @_goToItem(itemSlug)
|
||||
|
||||
refresh: ->
|
||||
if @user?
|
||||
@$loginName.html "Hello #{router.user.login}!"
|
||||
@@ -105,3 +112,8 @@ module.exports = class HeaderController extends BaseController
|
||||
'click a.logo': 'onLogoClicked'
|
||||
'click .navBar a': 'onNavItemClicked'
|
||||
'click .login a': 'onLoginLinkClicked'
|
||||
|
||||
# Private Methods ##############################################################################
|
||||
|
||||
_goToItem: (itemSlug)->
|
||||
router.navigate Url.item(itemSlug:itemSlug.item, modSlug:itemSlug.mod), trigger:true
|
||||
|
||||
@@ -0,0 +1,185 @@
|
||||
###
|
||||
Crafting Guide - item_selector_controller.coffee
|
||||
|
||||
Copyright (c) 2015 by Redwood Labs
|
||||
All rights reserved.
|
||||
###
|
||||
|
||||
BaseController = require './base_controller'
|
||||
ItemSelector = require '../models/item_selector'
|
||||
ItemSelectorElementController = require './item_selector_element_controller'
|
||||
{Duration} = require '../constants'
|
||||
{Event} = require '../constants'
|
||||
{Key} = require '../constants'
|
||||
|
||||
########################################################################################################################
|
||||
|
||||
module.exports = class ItemSelectorController extends BaseController
|
||||
|
||||
constructor: (options)->
|
||||
if not options.modPack? then throw new Error 'options.modPack is required'
|
||||
options.model ?= new ItemSelector {}, modPack:options.modPack
|
||||
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.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
|
||||
|
||||
# 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()
|
||||
|
||||
_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
|
||||
@@ -0,0 +1,79 @@
|
||||
###
|
||||
Crafting Guide - item_selector_element_controller.coffee
|
||||
|
||||
Copyright (c) 2015 by Redwood Labs
|
||||
All rights reserved.
|
||||
###
|
||||
|
||||
BaseController = require './base_controller'
|
||||
{Event} = require '../constants'
|
||||
|
||||
########################################################################################################################
|
||||
|
||||
module.exports = class ItemSelectorElementController extends BaseController
|
||||
|
||||
constructor: (options={})->
|
||||
if not options.model? then throw new Error 'options.model is required'
|
||||
options.onClicked ?= (controller)-> # do nothing
|
||||
options.onSelected ?= (controller)-> # do nothing
|
||||
options.templateName = 'item_selector_element'
|
||||
options.useAnimations = false
|
||||
super options
|
||||
|
||||
@onClicked = options.onClicked
|
||||
@onSelected = options.onSelected
|
||||
|
||||
# Property Methods #############################################################################
|
||||
|
||||
isSelected: ->
|
||||
return @_selected
|
||||
|
||||
setSelected: (newSelected)->
|
||||
oldSelected = @_selected
|
||||
return if newSelected is oldSelected
|
||||
|
||||
@_selected = newSelected
|
||||
@tryRefresh()
|
||||
|
||||
@trigger Event.change + ':selected', this, oldSelected, newSelected
|
||||
@trigger Event.change, this
|
||||
|
||||
Object.defineProperties @prototype,
|
||||
selected: {get:@prototype.isSelected, set:@prototype.setSelected}
|
||||
|
||||
# BaseController Overrides #####################################################################
|
||||
|
||||
onDidRender: ->
|
||||
@$icon = @$('img')
|
||||
@$name = @$('.name p')
|
||||
@$modName = @$('.modName p')
|
||||
super
|
||||
|
||||
refresh: ->
|
||||
@$icon.attr 'src', @model.iconUrl
|
||||
@$name.html @model.itemName
|
||||
@$modName.html @model.modName
|
||||
|
||||
if @_selected
|
||||
@$el.addClass 'selected'
|
||||
else
|
||||
@$el.removeClass 'selected'
|
||||
|
||||
super
|
||||
|
||||
# Backbone.View Overrides ######################################################################
|
||||
|
||||
events: ->
|
||||
return _.extend super,
|
||||
'click': '_onClick'
|
||||
'mouseenter': '_onMouseEnter'
|
||||
|
||||
# Private Methods ##############################################################################
|
||||
|
||||
_onClick: (event)->
|
||||
event.preventDefault()
|
||||
@onClicked this
|
||||
|
||||
_onMouseEnter: (event)->
|
||||
event.preventDefault()
|
||||
@onSelected this
|
||||
Reference in New Issue
Block a user