Add site-wide search function
This commit is contained in:
@@ -36,6 +36,7 @@ Duration.slow = 1200
|
|||||||
exports.Event = Event = {}
|
exports.Event = Event = {}
|
||||||
Event.add = 'add' # collection, item...
|
Event.add = 'add' # collection, item...
|
||||||
Event.change = 'change' # model
|
Event.change = 'change' # model
|
||||||
|
Event.click = 'click' # event
|
||||||
Event.load = {}
|
Event.load = {}
|
||||||
Event.load.started = 'load:started' # controller, url
|
Event.load.started = 'load:started' # controller, url
|
||||||
Event.load.succeeded = 'load:succeeded' # controller, book
|
Event.load.succeeded = 'load:succeeded' # controller, book
|
||||||
@@ -60,8 +61,12 @@ Event.transitionEnd = (->
|
|||||||
return eventName if el.style[styleName]?
|
return eventName if el.style[styleName]?
|
||||||
)()
|
)()
|
||||||
|
|
||||||
exports.Key = Key = {}
|
exports.Key = Key = {}
|
||||||
Key.Return = 13
|
Key.Enter = 13
|
||||||
|
Key.Return = 13
|
||||||
|
Key.Escape = 27
|
||||||
|
Key.UpArrow = 38
|
||||||
|
Key.DownArrow = 40
|
||||||
|
|
||||||
exports.Login = Login = {}
|
exports.Login = Login = {}
|
||||||
Login.authorizeUrl = _.template "https://github.com/login/oauth/authorize" +
|
Login.authorizeUrl = _.template "https://github.com/login/oauth/authorize" +
|
||||||
|
|||||||
@@ -13,12 +13,14 @@ 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
|
@_model = null
|
||||||
@_rendered = false
|
@_rendered = false
|
||||||
@_parent = options.parent
|
@_parent = options.parent
|
||||||
@_children = []
|
@_children = []
|
||||||
|
@_useAnimations = options.useAnimations
|
||||||
|
|
||||||
@_loadTemplate options.templateName
|
@_loadTemplate options.templateName
|
||||||
super options
|
super options
|
||||||
@@ -55,8 +57,12 @@ module.exports = class BaseController extends Backbone.View
|
|||||||
logger.verbose => "#{this} refreshing"
|
logger.verbose => "#{this} refreshing"
|
||||||
|
|
||||||
remove: ->
|
remove: ->
|
||||||
logger.verbose => "#{this} is removing its element from the DOM"
|
if @_useAnimations
|
||||||
@hide => @$el.remove()
|
@hide =>
|
||||||
|
logger.verbose => "#{this} is removing its element from the DOM"
|
||||||
|
@$el.remove()
|
||||||
|
else
|
||||||
|
@$el.remove()
|
||||||
|
|
||||||
routeLinkClick: (event)->
|
routeLinkClick: (event)->
|
||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
@@ -158,14 +164,14 @@ module.exports = class BaseController extends Backbone.View
|
|||||||
$renderedEl = $($(@_template(data))[0])
|
$renderedEl = $($(@_template(data))[0])
|
||||||
|
|
||||||
@onWillRender()
|
@onWillRender()
|
||||||
@hide()
|
@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
|
@show() if options.show and @_useAnimations
|
||||||
|
|
||||||
@_rendered = true
|
@_rendered = true
|
||||||
@onDidRender()
|
@onDidRender()
|
||||||
|
|||||||
@@ -5,11 +5,12 @@ Copyright (c) 2015 by Redwood Labs
|
|||||||
All rights reserved.
|
All rights reserved.
|
||||||
###
|
###
|
||||||
|
|
||||||
BaseController = require './base_controller'
|
BaseController = require './base_controller'
|
||||||
{Duration} = require '../constants'
|
ItemSelectorController = require './item_selector_controller'
|
||||||
{Event} = require '../constants'
|
{Duration} = require '../constants'
|
||||||
{ProductionEnvs} = require '../constants'
|
{Event} = require '../constants'
|
||||||
{Url} = require '../constants'
|
{ProductionEnvs} = require '../constants'
|
||||||
|
{Url} = require '../constants'
|
||||||
|
|
||||||
########################################################################################################################
|
########################################################################################################################
|
||||||
|
|
||||||
@@ -17,10 +18,12 @@ module.exports = class HeaderController extends BaseController
|
|||||||
|
|
||||||
constructor: (options={})->
|
constructor: (options={})->
|
||||||
if not options.client? then throw new Error 'options.client is required'
|
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
|
super options
|
||||||
|
|
||||||
@client = options.client
|
@client = options.client
|
||||||
@_user = options.user
|
@modPack = options.modPack
|
||||||
|
@_user = options.user
|
||||||
|
|
||||||
# Event Methods ################################################################################
|
# Event Methods ################################################################################
|
||||||
|
|
||||||
@@ -78,6 +81,10 @@ 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',
|
||||||
|
modPack: @modPack
|
||||||
|
onChoseItem: (itemSlug)=> @_goToItem(itemSlug)
|
||||||
|
|
||||||
refresh: ->
|
refresh: ->
|
||||||
if @user?
|
if @user?
|
||||||
@$loginName.html "Hello #{router.user.login}!"
|
@$loginName.html "Hello #{router.user.login}!"
|
||||||
@@ -105,3 +112,8 @@ module.exports = class HeaderController extends BaseController
|
|||||||
'click a.logo': 'onLogoClicked'
|
'click a.logo': 'onLogoClicked'
|
||||||
'click .navBar a': 'onNavItemClicked'
|
'click .navBar a': 'onNavItemClicked'
|
||||||
'click .login a': 'onLoginLinkClicked'
|
'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
|
||||||
@@ -0,0 +1,84 @@
|
|||||||
|
###
|
||||||
|
Crafting Guide - item_selector.coffee
|
||||||
|
|
||||||
|
Copyright (c) 2015 by Redwood Labs
|
||||||
|
All rights reserved.
|
||||||
|
###
|
||||||
|
|
||||||
|
BaseModel = require './base_model'
|
||||||
|
ItemSlug = require './item_slug'
|
||||||
|
|
||||||
|
########################################################################################################################
|
||||||
|
|
||||||
|
module.exports = class ItemSelector extends BaseModel
|
||||||
|
|
||||||
|
constructor: (attributes={}, options={})->
|
||||||
|
if not options.modPack? then throw new Error 'options.modPack is required'
|
||||||
|
|
||||||
|
super attributes, options
|
||||||
|
|
||||||
|
@_maxResults = 100
|
||||||
|
@_minHintLength = 3
|
||||||
|
@_modPack = options.modPack
|
||||||
|
@_results = []
|
||||||
|
|
||||||
|
# Property Methods #############################################################################
|
||||||
|
|
||||||
|
getHint: ->
|
||||||
|
return @_hint
|
||||||
|
|
||||||
|
setHint: (newHint)->
|
||||||
|
oldHint = @_hint
|
||||||
|
return if newHint is oldHint
|
||||||
|
|
||||||
|
@_hint = newHint.toLowerCase()
|
||||||
|
|
||||||
|
@trigger Event.change + ':hint', this, oldHint, newHint
|
||||||
|
@_refreshResults()
|
||||||
|
@trigger Event.change, this
|
||||||
|
|
||||||
|
getResults: ->
|
||||||
|
return @_results
|
||||||
|
|
||||||
|
Object.defineProperties @prototype,
|
||||||
|
hint: {get:@prototype.getHint, set:@prototype.setHint}
|
||||||
|
results: {get:@prototype.getResults}
|
||||||
|
|
||||||
|
# Private Methods ##############################################################################
|
||||||
|
|
||||||
|
_isMatch: (name)->
|
||||||
|
hintIndex = 0
|
||||||
|
hintLetter = @_hint[hintIndex]
|
||||||
|
name = name.toLowerCase()
|
||||||
|
|
||||||
|
for nameIndex in [0...name.length] by 1
|
||||||
|
if name.charAt(nameIndex) is hintLetter
|
||||||
|
hintIndex += 1
|
||||||
|
return true if hintIndex is @_hint.length
|
||||||
|
hintLetter = @_hint[hintIndex]
|
||||||
|
|
||||||
|
return false
|
||||||
|
|
||||||
|
_refreshResults: ->
|
||||||
|
oldResults = @_results
|
||||||
|
newResults = {}
|
||||||
|
count = 0
|
||||||
|
|
||||||
|
logger.verbose => "Looking for items which match: #{@_hint}"
|
||||||
|
if @_hint.length >= @_minHintLength
|
||||||
|
@_modPack.eachMod (mod)=>
|
||||||
|
return if count >= @_maxResults
|
||||||
|
|
||||||
|
mod.eachName (name, itemSlug)=>
|
||||||
|
return if count >= @_maxResults
|
||||||
|
|
||||||
|
if @_isMatch name
|
||||||
|
if itemSlug.isQualified
|
||||||
|
newResults[itemSlug] = itemSlug
|
||||||
|
count += 1
|
||||||
|
|
||||||
|
newResults = _.values(newResults)
|
||||||
|
newResults.sort ItemSlug.compare
|
||||||
|
|
||||||
|
@_results = newResults
|
||||||
|
@trigger Event.change + ':results', this, oldResults, newResults
|
||||||
@@ -25,20 +25,10 @@ module.exports = class ItemSlug
|
|||||||
# Class Methods ################################################################################
|
# Class Methods ################################################################################
|
||||||
|
|
||||||
@compare: (a, b)->
|
@compare: (a, b)->
|
||||||
aIsRequired = a.mod in RequiredMods
|
if a.item isnt b.item
|
||||||
bIsRequired = b.mod in RequiredMods
|
|
||||||
|
|
||||||
if aIsRequired isnt bIsRequired
|
|
||||||
return -1 if aIsRequired
|
|
||||||
return +1 if bIsRequired
|
|
||||||
else if a.isQualified isnt b.isQualified
|
|
||||||
return -1 if a.isQualified
|
|
||||||
return +1 if b.isQualified
|
|
||||||
else if a.mod isnt b.mod
|
|
||||||
return if a.mod < b.mod then -1 else +1
|
|
||||||
else if a.item isnt b.item
|
|
||||||
return if a.item < b.item then -1 else +1
|
return if a.item < b.item then -1 else +1
|
||||||
|
if a.mod isnt b.mod
|
||||||
|
return if a.mod < b.mod then -1 else +1
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
@equal: (a, b)->
|
@equal: (a, b)->
|
||||||
|
|||||||
@@ -53,22 +53,23 @@ module.exports = class ModPack extends BaseModel
|
|||||||
findItemDisplay: (itemSlug)->
|
findItemDisplay: (itemSlug)->
|
||||||
if not itemSlug? then throw new Error 'itemSlug is required'
|
if not itemSlug? then throw new Error 'itemSlug is required'
|
||||||
|
|
||||||
result = {}
|
result = {slug:itemSlug}
|
||||||
item = @findItem itemSlug, includeDisabled:true
|
item = @findItem itemSlug, includeDisabled:true
|
||||||
if item?
|
if item?
|
||||||
|
result.itemName = item.name
|
||||||
|
result.itemSlug = item.slug.item
|
||||||
result.modSlug = item.slug.mod
|
result.modSlug = item.slug.mod
|
||||||
result.modVersion = item.modVersion.version
|
result.modVersion = item.modVersion.version
|
||||||
result.itemSlug = item.slug.item
|
|
||||||
result.itemName = item.name
|
|
||||||
else
|
else
|
||||||
|
result.itemName = @findName itemSlug, includeDisabled:true
|
||||||
|
result.itemSlug = itemSlug.item
|
||||||
result.modSlug = @_mods[0].slug
|
result.modSlug = @_mods[0].slug
|
||||||
result.modVersion = @_mods[0].activeVersion
|
result.modVersion = @_mods[0].activeVersion
|
||||||
result.itemSlug = itemSlug.item
|
|
||||||
result.itemName = @findName itemSlug, includeDisabled:true
|
|
||||||
|
|
||||||
result.craftingUrl = Url.crafting inventoryText:itemSlug.item
|
result.craftingUrl = Url.crafting inventoryText:itemSlug.item
|
||||||
result.iconUrl = Url.itemIcon result
|
result.iconUrl = Url.itemIcon result
|
||||||
result.itemUrl = Url.item result
|
result.itemUrl = Url.item result
|
||||||
|
result.modName = @getMod(result.modSlug).name
|
||||||
return result
|
return result
|
||||||
|
|
||||||
findName: (slug, options={})->
|
findName: (slug, options={})->
|
||||||
|
|||||||
@@ -29,3 +29,5 @@
|
|||||||
a(data-page="craft", href="/craft/")
|
a(data-page="craft", href="/craft/")
|
||||||
p Craft
|
p Craft
|
||||||
.dot
|
.dot
|
||||||
|
|
||||||
|
.view__item_selector
|
||||||
|
|||||||
@@ -0,0 +1,14 @@
|
|||||||
|
//-
|
||||||
|
//- Crafting Guide - item_selector.jade
|
||||||
|
//-
|
||||||
|
//- Copyright (c) 2015 by Redwood Labs
|
||||||
|
//- All rights reserved.
|
||||||
|
//-
|
||||||
|
|
||||||
|
.view__item_selector
|
||||||
|
p.placeholder find items...
|
||||||
|
|
||||||
|
.view__item_selector_popup.hideable.hiding
|
||||||
|
.search
|
||||||
|
input
|
||||||
|
.results
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
//-
|
||||||
|
//- Crafting Guide - item_selector_element.jade
|
||||||
|
//-
|
||||||
|
//- Copyright (c) 2015 by Redwood Labs
|
||||||
|
//- All rights reserved.
|
||||||
|
//-
|
||||||
|
|
||||||
|
.view__item_selector_element
|
||||||
|
img
|
||||||
|
.name: p
|
||||||
|
.modName: p
|
||||||
@@ -130,6 +130,11 @@ All rights reserved.
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.stop-scrolling {
|
||||||
|
height: 100%;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
.two-thirds-content {
|
.two-thirds-content {
|
||||||
position: relative; width: 66%;
|
position: relative; width: 66%;
|
||||||
margin: 5em 16.5%;
|
margin: 5em 16.5%;
|
||||||
|
|||||||
@@ -17,6 +17,8 @@ All rights reserved.
|
|||||||
@import 'inventory_table';
|
@import 'inventory_table';
|
||||||
@import 'item';
|
@import 'item';
|
||||||
@import 'item_page';
|
@import 'item_page';
|
||||||
|
@import 'item_selector';
|
||||||
|
@import 'item_selector_element';
|
||||||
@import 'login_page';
|
@import 'login_page';
|
||||||
@import 'minimal_recipe';
|
@import 'minimal_recipe';
|
||||||
@import 'mod';
|
@import 'mod';
|
||||||
|
|||||||
@@ -0,0 +1,51 @@
|
|||||||
|
/*
|
||||||
|
Crafting Guide - item_selector.scss
|
||||||
|
|
||||||
|
Copyright (C) 2015 by Redwood Labs
|
||||||
|
All rights reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
.view__item_selector {
|
||||||
|
background: $color-background-panel;
|
||||||
|
border: 0.1em solid $color-gray-medium;
|
||||||
|
border-radius: 1.5em;
|
||||||
|
cursor: pointer;
|
||||||
|
padding: 0 0.75em;
|
||||||
|
|
||||||
|
p.placeholder {
|
||||||
|
position: relative; top: 50%; width: 100%;
|
||||||
|
@include transform(translateY(-50%));
|
||||||
|
|
||||||
|
color: $color-gray-medium;
|
||||||
|
font-family: $font-family-input;
|
||||||
|
font-size: $font-size-normal;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.view__item_selector_popup {
|
||||||
|
position: absolute; top: 0; left: 0;
|
||||||
|
min-height: 5em;
|
||||||
|
|
||||||
|
background: $color-background-panel;
|
||||||
|
border: 0.1em solid $color-gray-medium;
|
||||||
|
border-radius: 1.5em 1.5em 0 0;
|
||||||
|
box-shadow: 10px 10px 20px #666;
|
||||||
|
|
||||||
|
.search {
|
||||||
|
border-bottom: 0.1em solid $color-gray-medium;
|
||||||
|
margin: 1em;
|
||||||
|
|
||||||
|
input {
|
||||||
|
border: none;
|
||||||
|
outline: none;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.results {
|
||||||
|
position: relative;
|
||||||
|
max-height: 50em;
|
||||||
|
overflow-y: auto;
|
||||||
|
padding-bottom: 1em;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
/*
|
||||||
|
Crafting Guide - item_selector_element.scss
|
||||||
|
|
||||||
|
Copyright (C) 2015 by Redwood Labs
|
||||||
|
All rights reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
.view__item_selector_element {
|
||||||
|
height: 3.6em;
|
||||||
|
padding: 0.3em 1em;
|
||||||
|
clear: both;
|
||||||
|
|
||||||
|
transition: background $animate-fast, color $animate-fast;
|
||||||
|
|
||||||
|
&.selected {
|
||||||
|
background: $color-active-hover;
|
||||||
|
color: $color-text-light;
|
||||||
|
}
|
||||||
|
|
||||||
|
img {
|
||||||
|
height: 3.6em; width: 3.6em;
|
||||||
|
float: left;
|
||||||
|
margin-right: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modName p {
|
||||||
|
color: $color-gray-medium;
|
||||||
|
font-size: $font-size-small;
|
||||||
|
margin-top: 0.2em;
|
||||||
|
}
|
||||||
|
}
|
||||||
+5
-1
@@ -132,6 +132,10 @@ All rights reserved.
|
|||||||
transition: color $animate-normal;
|
transition: color $animate-normal;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.view__item_selector {
|
||||||
|
position: absolute; top: 0; right: 0; height: 3em; width: 35em;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -139,4 +143,4 @@ All rights reserved.
|
|||||||
position: fixed; top: 0; right: 0; bottom: 0; left: 0;
|
position: fixed; top: 0; right: 0; bottom: 0; left: 0;
|
||||||
display: none;
|
display: none;
|
||||||
z-index: $layer-screen;
|
z-index: $layer-screen;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -129,9 +129,9 @@ describe 'inventory.coffee', ->
|
|||||||
inventory.each (stack)-> slugs.push stack.itemSlug.qualified
|
inventory.each (stack)-> slugs.push stack.itemSlug.qualified
|
||||||
slugs.should.eql [
|
slugs.should.eql [
|
||||||
'minecraft__boat'
|
'minecraft__boat'
|
||||||
|
'buildcraft__stone_gear'
|
||||||
'minecraft__string'
|
'minecraft__string'
|
||||||
'minecraft__wool'
|
'minecraft__wool'
|
||||||
'buildcraft__stone_gear'
|
|
||||||
]
|
]
|
||||||
|
|
||||||
it 'ignores qualified slugs', ->
|
it 'ignores qualified slugs', ->
|
||||||
@@ -143,9 +143,9 @@ describe 'inventory.coffee', ->
|
|||||||
inventory.each (stack)-> slugs.push stack.itemSlug.qualified
|
inventory.each (stack)-> slugs.push stack.itemSlug.qualified
|
||||||
slugs.should.eql [
|
slugs.should.eql [
|
||||||
'minecraft__boat'
|
'minecraft__boat'
|
||||||
|
'buildcraft__stone_gear'
|
||||||
'minecraft__string'
|
'minecraft__string'
|
||||||
'minecraft__wool'
|
'minecraft__wool'
|
||||||
'buildcraft__stone_gear'
|
|
||||||
]
|
]
|
||||||
|
|
||||||
describe 'parse', ->
|
describe 'parse', ->
|
||||||
|
|||||||
@@ -35,20 +35,6 @@ describe 'item_slug.coffee', ->
|
|||||||
|
|
||||||
describe 'ItemSlug.compare', ->
|
describe 'ItemSlug.compare', ->
|
||||||
|
|
||||||
it 'sorts qualified slugs first', ->
|
|
||||||
a = new ItemSlug 'alpha'
|
|
||||||
b = new ItemSlug 'bravo', 'charlie'
|
|
||||||
|
|
||||||
ItemSlug.compare(a, b).should.equal +1
|
|
||||||
ItemSlug.compare(b, a).should.equal -1
|
|
||||||
|
|
||||||
it 'sorts by mod when both are qualified', ->
|
|
||||||
a = new ItemSlug 'alpha', 'bravo'
|
|
||||||
b = new ItemSlug 'charlie', 'delta'
|
|
||||||
|
|
||||||
ItemSlug.compare(a, b).should.equal -1
|
|
||||||
ItemSlug.compare(b, a).should.equal +1
|
|
||||||
|
|
||||||
it 'sorts by item when both are qualified in the same mod', ->
|
it 'sorts by item when both are qualified in the same mod', ->
|
||||||
a = new ItemSlug 'alpha', 'bravo'
|
a = new ItemSlug 'alpha', 'bravo'
|
||||||
b = new ItemSlug 'charlie', 'bravo'
|
b = new ItemSlug 'charlie', 'bravo'
|
||||||
|
|||||||
@@ -184,7 +184,7 @@ describe 'mod_version_parser_v1.coffee', ->
|
|||||||
it 'registers slugs for each output name', ->
|
it 'registers slugs for each output name', ->
|
||||||
modVersion = parser.parse baseText + 'extras:Delta, Echo'
|
modVersion = parser.parse baseText + 'extras:Delta, Echo'
|
||||||
(s.qualified for s in modVersion._slugs).should.eql [
|
(s.qualified for s in modVersion._slugs).should.eql [
|
||||||
'test__bravo', 'test__delta', 'charlie', 'echo'
|
'test__bravo', 'charlie', 'test__delta', 'echo'
|
||||||
]
|
]
|
||||||
|
|
||||||
it 'does not allow a duplicate "extras" declaration', ->
|
it 'does not allow a duplicate "extras" declaration', ->
|
||||||
|
|||||||
Reference in New Issue
Block a user