Replace jQuery animations with CSS animations

This commit is contained in:
Andrew Miner
2015-03-21 19:00:46 -07:00
parent 3d0908c421
commit 9956e64af0
32 changed files with 385 additions and 369 deletions
+16 -5
View File
@@ -20,10 +20,10 @@ exports.DefaultMods =
thermal_expansion: { defaultVersion: '4.0.0B8-23' } thermal_expansion: { defaultVersion: '4.0.0B8-23' }
exports.Duration = Duration = {} exports.Duration = Duration = {}
Duration.snap = 200 Duration.snap = 100
Duration.fast = Duration.snap * 2 Duration.fast = 200
Duration.normal = Duration.fast * 2 Duration.normal = 400
Duration.slow = Duration.normal * 2 Duration.slow = 1200
exports.Event = Event = {} exports.Event = Event = {}
Event.add = 'add' # collection, item... Event.add = 'add' # collection, item...
@@ -38,7 +38,18 @@ Event.request = 'request' # model
Event.route = 'route' Event.route = 'route'
Event.sort = 'sort' Event.sort = 'sort'
Event.sync = 'sync' # model, response Event.sync = 'sync' # model, response
Event.transitionEnd = 'webkitTransitionEnd otransitionend oTransitionEnd msTransitionEnd transitionend' Event.transitionEnd = (->
transitions =
'transition': 'transitionend',
'OTransition': 'oTransitionEnd',
'MSTransition': 'msTransitionEnd',
'MozTransition': 'transitionend',
'WebkitTransition': 'webkitTransitionEnd'
el = document.createElement 'fakeelement'
for styleName, eventName of transitions
return eventName if el.style[styleName]?
)()
exports.Key = Key = {} exports.Key = Key = {}
Key.Return = 13 Key.Return = 13
+65 -12
View File
@@ -5,7 +5,8 @@ Copyright (c) 2014-2015 by Redwood Labs
All rights reserved. All rights reserved.
### ###
views = require '../views' views = require '../views'
{Event} = require '../constants'
######################################################################################################################## ########################################################################################################################
@@ -31,13 +32,31 @@ module.exports = class BaseController extends Backbone.View
options.parent = this options.parent = this
child = new Controller options child = new Controller options
child.render() child.render options
@_children.push child @_children.push child
return child return child
hide: (args...)->
{$el, callback} = @_resolveShowHideArgs args
$el.addClass 'hideable' unless $el.hasClass 'hideable'
if $el.hasClass('hiding') or $el.hasClass('hidden')
_.defer => callback this
else
$el.one Event.transitionEnd, =>
$el.addClass 'hidden'
$el.removeClass 'hiding'
callback this
$el.addClass 'hiding'
refresh: -> refresh: ->
logger.verbose => "#{this} refreshing" logger.verbose => "#{this} refreshing"
remove: ->
@hide -> @$el.remove()
routeLinkClick: (event)-> routeLinkClick: (event)->
event.preventDefault() event.preventDefault()
href = $(event.target).attr 'href' href = $(event.target).attr 'href'
@@ -45,6 +64,23 @@ module.exports = class BaseController extends Backbone.View
logger.info "Re-routing link to internal navigation: #{href}" logger.info "Re-routing link to internal navigation: #{href}"
router.navigate href, trigger:true router.navigate href, trigger:true
show: (args...)->
{$el, callback} = @_resolveShowHideArgs args
$el.addClass 'hideable' unless $el.hasClass 'hideable'
if $el.hasClass('hiding') or $el.hasClass('hidden')
$el.one Event.transitionEnd, =>
callback this
$el.removeClass 'hiding'
$el.removeClass 'hidden'
else
_.defer => callback this
unrender: ->
@undelegateEvents()
@$el.empty()
# Event Methods ################################################################################ # Event Methods ################################################################################
onDidModelChange: -> onDidModelChange: ->
@@ -68,7 +104,7 @@ module.exports = class BaseController extends Backbone.View
if newModel?.on? if newModel?.on?
@listenTo newModel, 'sync', (e)=> @onDidModelSync e @listenTo newModel, 'sync', (e)=> @onDidModelSync e
@listenTo newModel, 'change', (e)=> @onDidModelChange e @listenTo newModel, 'change', (e)=> @onDidModelChange e
return true return newModel
# Property Methods ############################################################################# # Property Methods #############################################################################
@@ -77,8 +113,8 @@ module.exports = class BaseController extends Backbone.View
setModel: (newModel)-> setModel: (newModel)->
return if @model is newModel return if @model is newModel
return unless @onWillChangeModel @_model, newModel
newModel = @onWillChangeModel @_model, newModel
@_model = newModel @_model = newModel
@tryRefresh() @tryRefresh()
@@ -88,23 +124,27 @@ module.exports = class BaseController extends Backbone.View
return {} return {}
render: (options={})-> render: (options={})->
options.force ?= false
options.show ?= true
return this unless not @_rendered or options.force return this unless not @_rendered or options.force
data = (@model?.toHash? and @model.toHash()) or @model or {}
if not @_template? if not @_template?
logger.error => "Default render called for #{@constructor.name} without a template" logger.error => "Default render called for #{@constructor.name} without a template"
return this return this
data = (@model?.toHash? and @model.toHash()) or @model or {}
logger.verbose => "#{this} rendering with data: #{data}" logger.verbose => "#{this} rendering with data: #{data}"
$renderedEl = $($(@_template(data))[0])
@onWillRender() @onWillRender()
$oldEl = @$el @hide()
$newEl = Backbone.$(@_template(data))
if $oldEl @unrender()
$oldEl.replaceWith $newEl @$el.append $renderedEl.children()
$newEl.addClass $oldEl.attr 'class' @$el.addClass $renderedEl.attr 'class'
@delegateEvents()
@show() if options.show
@setElement $newEl
@_rendered = true @_rendered = true
@onDidRender() @onDidRender()
@@ -121,6 +161,19 @@ 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()
@@ -54,7 +54,6 @@ module.exports = class BrowsePageController extends PageController
while @_controllers.length > controllerIndex while @_controllers.length > controllerIndex
controller = @_controllers.pop() controller = @_controllers.pop()
controller.$el.addClass 'removing' controller.hide -> controller.$el.remove()
controller.$el.one Event.transitionEnd -> controller.$el.remove()
super super
@@ -79,9 +79,9 @@ module.exports = class CraftingTableController extends BaseController
@$multiplier.html '' @$multiplier.html ''
if not (@model.hasSteps and global.feedbackController?) if not (@model.hasSteps and global.feedbackController?)
@$problemControl.hide duration:Duration.snap @$problemControl.addClass 'hidden'
else else
@$problemControl.show duration:Duration.snap @$problemControl.removeClass 'hidden'
super super
@@ -49,9 +49,9 @@ module.exports = class FeedbackController extends BaseController
@model.send(message) @model.send(message)
.then => .then =>
@onToggle() @onToggle()
@$error.slideUp duration:Duration.normal @$error.addClass 'hidden'
.catch (error)=> .catch (error)=>
@$error.slideDown duration:Duration.normal @$error.removeClass 'hidden'
.finally => .finally =>
@$sendButton.removeAttr 'disabled' @$sendButton.removeAttr 'disabled'
@@ -120,12 +120,12 @@ module.exports = class InventoryController extends BaseController
events: -> events: ->
return _.extend super, return _.extend super,
'blur input[name="name"]': 'onNameFieldBlur' 'blur input[name="name"]': 'onNameFieldBlur'
'click button[name="add"]': 'onAddButtonClicked' 'click button[name="add"]': 'onAddButtonClicked'
'click button[name="clear"]': 'onClearButtonClicked' 'click button[name="clear"]': 'onClearButtonClicked'
'focus input[name="name"]': 'onNameFieldFocused' 'focus input[name="name"]': 'onNameFieldFocused'
'input input[name="name"]': 'onNameFieldChanged' 'input input[name="name"]': 'onNameFieldChanged'
'keyup input[name="name"]': 'onNameFieldKeyUp' 'keyup input[name="name"]': 'onNameFieldKeyUp'
# Private Methods ############################################################################## # Private Methods ##############################################################################
@@ -164,18 +164,16 @@ module.exports = class InventoryController extends BaseController
modPack: @modPack modPack: @modPack
onChange: @onChange onChange: @onChange
onRemove: if not @editable then null else (stack)=> @_removeStack(stack) onRemove: if not @editable then null else (stack)=> @_removeStack(stack)
controller.render()
controller.$el.hide()
controller.$el.insertBefore $lastRow
controller.$el.slideDown duration:Duration.fast
@_stackControllers.push controller @_stackControllers.push controller
controller.$el.insertBefore $lastRow
controller.render()
else else
controller.model = stack controller.model = stack
index += 1 index += 1
while @_stackControllers.length > index while @_stackControllers.length > index
controller = @_stackControllers.pop() @_stackControllers.pop().remove()
controller.$el.fadeOut duration:Duration.fast, complete:-> @remove()
_removeStack: (stack)-> _removeStack: (stack)->
@model.remove stack.itemSlug, stack.quantity @model.remove stack.itemSlug, stack.quantity
@@ -72,7 +72,7 @@ module.exports = class InventoryTableController extends BaseController
onNameFieldChanged: -> onNameFieldChanged: ->
item = @modPack.findItemByName @$nameField.val() item = @modPack.findItemByName @$nameField.val()
@_updateButtonState() @_refreshButtonState()
onNameFieldFocused: -> onNameFieldFocused: ->
@$nameField.val '' @$nameField.val ''
@@ -99,7 +99,7 @@ module.exports = class InventoryTableController extends BaseController
@$quantityField.removeClass 'error', Duration.normal @$quantityField.removeClass 'error', Duration.normal
@$quantityField.removeClass 'error-new', Duration.normal @$quantityField.removeClass 'error-new', Duration.normal
@_updateButtonState() @_refreshButtonState()
onQuantityFieldFocused: -> onQuantityFieldFocused: ->
@$quantityField.val '' @$quantityField.val ''
@@ -125,22 +125,10 @@ module.exports = class InventoryTableController extends BaseController
if _.isEmpty(@$quantityField.val()) then @$quantityField.val '1' if _.isEmpty(@$quantityField.val()) then @$quantityField.val '1'
@$table.find('tr:not(:last-child)').remove() @$table.find('tr:not(:last-child)').remove()
$lastRow = @$table.find 'tr:last-child'
@_stackControllers = []
@model.each (stack)=>
controller = new StackController
editable: @editable
imageLoader: @imageLoader
model: stack
modPack: @modPack
onRemove: if not @editable then null else (stack)=> @_removeStack(stack)
controller.render() @_refreshNameAutocomplete()
controller.$el.insertBefore $lastRow @_refreshButtonState()
@_stackControllers.push controller @_refreshStacks()
@_updateNameAutocomplete()
@_updateButtonState()
super super
@@ -160,10 +148,15 @@ module.exports = class InventoryTableController extends BaseController
# Private Methods ############################################################################## # Private Methods ##############################################################################
_removeStack: (stack)-> _refreshButtonState: ->
@model.remove stack.itemSlug, stack.quantity if @model.isEmpty then @$clearButton.attr('disabled', 'disabled') else @$clearButton.removeAttr('disabled')
_updateNameAutocomplete: -> itemValid = @modPack.findItemByName(@$nameField.val())?
quantityValid = @$quantityField.val().match(InventoryTableController.ONLY_DIGITS)
disable = not (itemValid and quantityValid)
if disable then @$addButton.attr('disabled', 'disabled') else @$addButton.removeAttr('disabled')
_refreshNameAutocomplete: ->
onChanged = => @onNameFieldChanged() onChanged = => @onNameFieldChanged()
onSelected = => @onItemSelected() onSelected = => @onItemSelected()
@@ -175,10 +168,31 @@ module.exports = class InventoryTableController extends BaseController
close: onChanged close: onChanged
select: onSelected select: onSelected
_updateButtonState: -> _refreshStacks: ->
if @model.isEmpty then @$clearButton.attr('disabled', 'disabled') else @$clearButton.removeAttr('disabled') @_stackControllers ?= []
index = 0
itemValid = @modPack.findItemByName(@$nameField.val())? $lastRow = @$table.find 'tr:last-child'
quantityValid = @$quantityField.val().match(InventoryTableController.ONLY_DIGITS) @model.each (stack)=>
disable = not (itemValid and quantityValid) controller = @_stackControllers[index]
if disable then @$addButton.attr('disabled', 'disabled') else @$addButton.removeAttr('disabled') if not controller?
controller = new StackController
editable: @editable
imageLoader: @imageLoader
model: stack
modPack: @modPack
onRemove: if not @editable then null else (stack)=> @_removeStack(stack)
@_stackControllers.push controller
controller.$el.insertBefore $lastRow
controller.render()
else
controller.model = stack
index += 1
while @_stackControllers.length > index
@_stackControllers.pop().remove()
_removeStack: (stack)->
@model.remove stack.itemSlug, stack.quantity
@@ -6,10 +6,10 @@ All rights reserved.
### ###
BaseController = require './base_controller' BaseController = require './base_controller'
{Duration} = require '../constants'
{Event} = require '../constants'
Item = require '../models/item' Item = require '../models/item'
ItemController = require './item_controller' ItemController = require './item_controller'
{Duration} = require '../constants'
{Event} = require '../constants'
######################################################################################################################## ########################################################################################################################
@@ -18,19 +18,15 @@ module.exports = class ItemGroupController extends BaseController
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'
options.model ?= []
options.title ?= '' options.title ?= ''
options.templateName = 'item_group' options.templateName = 'item_group'
super options super options
@_delayStep = 20
@_imageLoader = options.imageLoader @_imageLoader = options.imageLoader
@_itemControllers = []
@_modPack = options.modPack @_modPack = options.modPack
@_title = options.title @_title = options.title
Object.defineProperties this,
title: {get:@getTitle, set:@setTitle}
# Property Methods ############################################################################# # Property Methods #############################################################################
getTitle: -> getTitle: ->
@@ -40,6 +36,9 @@ module.exports = class ItemGroupController extends BaseController
@_title = title @_title = title
@tryRefresh() @tryRefresh()
Object.defineProperties @prototype,
title: {get:@prototype.getTitle, set:@prototype.setTitle}
# BaseController Overrides ##################################################################### # BaseController Overrides #####################################################################
onDidRender: -> onDidRender: ->
@@ -47,37 +46,37 @@ module.exports = class ItemGroupController extends BaseController
@$items = @$('.panel') @$items = @$('.panel')
super super
onWillChangeModel: (oldModel, newModel)->
newModel ?= []
return super oldModel, newModel
refresh: -> refresh: ->
@$title.html @_title if @model.length > 0
@_refreshItems() @$title.html @_title
@_refreshItems()
@show()
else
@hide()
super super
# Private Methods ############################################################################## # Private Methods ##############################################################################
_createItemController: (item, delay)->
controller = new ItemController imageLoader:@_imageLoader, model:item, modPack:@_modPack
@_itemControllers.push controller
attachController = =>
controller.render()
@$items.append controller.$el
_.delay attachController, delay
_refreshItems: -> _refreshItems: ->
@_itemControllers ?= []
controllerIndex = 0 controllerIndex = 0
delay = 0 delay = 0
if @model? for item in @model
for item in @model controller = @_itemControllers[controllerIndex]
controller = @_itemControllers[controllerIndex] if not controller?
if not controller? controller = new ItemController imageLoader:@_imageLoader, model:item, modPack:@_modPack
@_createItemController item, delay @_itemControllers.push controller
delay += @_delayStep @$items.append controller.$el
else controller.render()
controller.model = item else
controllerIndex += 1 controller.model = item
controllerIndex += 1
while @_itemControllers.length > controllerIndex while @_itemControllers.length > controllerIndex
controller = @_itemControllers.pop() @_itemControllers.pop().remove()
controller.$el.slideUp duration:Duration.normal, complete:-> @remove()
@@ -43,6 +43,7 @@ module.exports = class ItemPageController extends PageController
craftingPlanButtonClicked: -> craftingPlanButtonClicked: ->
display = @modPack.findItemDisplay @model.item.slug display = @modPack.findItemDisplay @model.item.slug
logger.debug "button clicked, going to: #{display.craftingUrl}"
router.navigate display.craftingUrl, trigger:true router.navigate display.craftingUrl, trigger:true
return false return false
@@ -56,21 +57,13 @@ module.exports = class ItemPageController extends PageController
onDidRender: -> onDidRender: ->
@adsenseController = @addChild AdsenseController, '.view__adsense', model:'sidebar_skyscraper' @adsenseController = @addChild AdsenseController, '.view__adsense', model:'sidebar_skyscraper'
@_similarItemsController = @addChild ItemGroupController, '.similar .view__item_group', options = imageLoader:@imageLoader, modPack:@modPack, show:false
imageLoader: @imageLoader @_similarItemsController = @addChild ItemGroupController, '.view__item_group.similar', options
modPack: @modPack @_usedAsToolToMakeController = @addChild ItemGroupController, '.view__item_group.usedAsToolToMake', options
@_usedToMakeController = @addChild ItemGroupController, '.view__item_group.usedToMake', options
@_usedAsToolToMakeController = @addChild ItemGroupController, '.usedAsToolToMake .view__item_group',
imageLoader: @imageLoader
modPack: @modPack
@_usedToMakeController = @addChild ItemGroupController, '.usedToMake .view__item_group',
imageLoader: @imageLoader
modPack: @modPack
@$byline = @$('.byline') @$byline = @$('.byline')
@$bylineLink = @$('.byline a') @$bylineLink = @$('.byline a')
@$craftingPlanButton = @$('button.craftingPlan')
@$descriptionPanel = @$('.description .panel') @$descriptionPanel = @$('.description .panel')
@$descriptionSection = @$('.description') @$descriptionSection = @$('.description')
@$name = @$('h1.name') @$name = @$('h1.name')
@@ -92,20 +85,18 @@ module.exports = class ItemPageController extends PageController
if @model.item? if @model.item?
display = @modPack.findItemDisplay @model.item.slug display = @modPack.findItemDisplay @model.item.slug
@$craftingPlanButton.fadeIn duration:Duration.fast
@imageLoader.load display.iconUrl, @$titleImage @imageLoader.load display.iconUrl, @$titleImage
@$name.html display.itemName @$name.html display.itemName
if @model.item.officialUrl? if @model.item.officialUrl?
@$officialPageLink.attr 'href', @model.item.officialUrl @$officialPageLink.attr 'href', @model.item.officialUrl
@$officialPageLink.fadeIn duration:Duration.normal @show @$officialPageLink
else else
@$officialPageLink.fadeOut duration:Duration.normal @hide @$officialPageLink
@$el.slideDown duration:Duration.normal @show()
else else
@$craftingPlanButton.fadeOut duration:Duration.fast @hide()
@$el.slideUp duration:Duration.normal
@_refreshByline() @_refreshByline()
@_refreshDescription() @_refreshDescription()
@@ -121,10 +112,10 @@ module.exports = class ItemPageController extends PageController
events: -> events: ->
return _.extend super, return _.extend super,
'click a.craftingPlan': 'routeLinkClick' 'click a.craftingPlan': 'routeLinkClick'
'click .byline a': 'routeLinkClick' 'click .byline a': 'routeLinkClick'
'click .markdown': 'routeLinkClick' 'click .markdown': 'routeLinkClick'
'click button.craftingPlan': 'craftingPlanButtonClicked' 'click button': 'craftingPlanButtonClicked'
# Private Methods ############################################################################## # Private Methods ##############################################################################
@@ -133,25 +124,25 @@ module.exports = class ItemPageController extends PageController
if mod?.name?.length > 0 if mod?.name?.length > 0
@$bylineLink.attr 'href', Url.mod modSlug:mod.slug @$bylineLink.attr 'href', Url.mod modSlug:mod.slug
@$bylineLink.html mod.name @$bylineLink.html mod.name
@$byline.fadeIn duration:Duration.fast
@show @$byline
else else
@$byline.fadeOut duration:Duration.fast @hide @$byline
_refreshDescription: -> _refreshDescription: ->
description = @model.compileDescription() description = @model.compileDescription()
if description? if description?
@$descriptionPanel.html description @$descriptionPanel.html description
@$descriptionSection.slideDown duration:Duration.normal @show @$descriptionPanel
else else
@$descriptionSection.slideUp duration:Duration.normal @hide @$descriptionPanel
_refreshRecipes: -> _refreshRecipes: ->
@_recipeControllers ?= [] @_recipeControllers ?= []
index = 0 index = 0
recipes = @model.findRecipes() recipes = @model.findRecipes()
if recipes? if recipes?.length > 0
@$recipesSection.slideDown duration:Duration.normal
@$recipesSectionTitle.html if recipes.length is 1 then 'Recipe' else 'Recipes' @$recipesSectionTitle.html if recipes.length is 1 then 'Recipe' else 'Recipes'
for recipe in @model.findRecipes() for recipe in @model.findRecipes()
@@ -159,17 +150,18 @@ module.exports = class ItemPageController extends PageController
if not controller? if not controller?
controller = new FullRecipeController imageLoader:@imageLoader, modPack:@modPack, model:recipe controller = new FullRecipeController imageLoader:@imageLoader, modPack:@modPack, model:recipe
@_recipeControllers.push controller @_recipeControllers.push controller
controller.render()
@$recipeContainer.append controller.$el @$recipeContainer.append controller.$el
controller.render()
else else
controller.model = recipe controller.model = recipe
index++ index++
@show @$recipesSection
else else
@$recipesSection.slideUp duration:Duration.normal @hide @$recipesSection
while @_recipeControllers.length > index while @_recipeControllers.length > index
controller = @_recipeControllers.pop() @_recipeControllers.pop().remove()
controller.$el.slideUp duration:Duration.normal, complete:-> controller.$el.remove()
_refreshSimilarItems: -> _refreshSimilarItems: ->
group = @model.item?.group group = @model.item?.group
@@ -179,28 +171,13 @@ module.exports = class ItemPageController extends PageController
else else
@_similarItemsController.model = null @_similarItemsController.model = null
if @_similarItemsController.model?
@$similarSection.slideDown duration:Duration.normal
else
@$similarSection.slideUp duration:Duration.normal
_refreshUsedAsToolToMake: -> _refreshUsedAsToolToMake: ->
@_usedAsToolToMakeController.title = 'Used as Tool to Make' @_usedAsToolToMakeController.title = 'Used as Tool to Make'
@_usedAsToolToMakeController.model = @model.findToolForRecipes() @_usedAsToolToMakeController.model = @model.findToolForRecipes()
if @_usedAsToolToMakeController.model?
@$usedAsToolToMakeSection.slideDown duration:Duration.normal
else
@$usedAsToolToMakeSection.slideUp duration:Duration.normal
_refreshUsedToMake: -> _refreshUsedToMake: ->
@_usedToMakeController.title = 'Used to Make' @_usedToMakeController.title = 'Used to Make'
@_usedToMakeController.model = @model.findComponentInItems() @_usedToMakeController.model = @model.findComponentInItems()
if @_usedToMakeController.model?
@$usedToMakeSection.slideDown duration:Duration.normal
else
@$usedToMakeSection.slideUp duration:Duration.normal
_refreshVideos: -> _refreshVideos: ->
@_videoControllers ?= [] @_videoControllers ?= []
@@ -208,7 +185,6 @@ module.exports = class ItemPageController extends PageController
videos = @model?.item?.videos or [] videos = @model?.item?.videos or []
if videos? and videos.length > 0 if videos? and videos.length > 0
@$videosSection.slideDown duration:Duration.normal
@$videosSectionTitle.html if videos.length is 1 then 'Video' else 'Videos' @$videosSectionTitle.html if videos.length is 1 then 'Video' else 'Videos'
for video in videos for video in videos
@@ -221,12 +197,13 @@ module.exports = class ItemPageController extends PageController
else else
controller.model = video controller.model = video
index++ index++
@show @$videosSection
else else
@$videosSection.slideUp duration:Duration.normal @hide @$videosSection
while @_videoControllers.length > index while @_videoControllers.length > index
controller = @_videoControllers.pop() @_videoControllers.pop().remove()
controller.$el.slideUp duration:Duration.normal, complete:-> controller.$el.remove()
_resolveItemSlug: -> _resolveItemSlug: ->
return if @model.item? return if @model.item?
+5 -9
View File
@@ -13,6 +13,7 @@ BaseController = require './base_controller'
module.exports = class ModController extends BaseController module.exports = class ModController extends BaseController
constructor: (options={})-> constructor: (options={})->
if not options.model? then throw new Error 'options.model is required'
options.templateName = 'mod' options.templateName = 'mod'
super options super options
@@ -26,15 +27,10 @@ module.exports = class ModController extends BaseController
super super
refresh: -> refresh: ->
if @model? @$link.attr 'href', Url.mod modSlug:@model.slug
@$el.removeClass 'empty' @$logo.attr 'src', Url.modIcon modSlug:@model.slug
@$name.html @model.name
@$link.attr 'href', Url.mod modSlug:@model.slug @$description.html @model.description
@$logo.attr 'src', Url.modIcon modSlug:@model.slug
@$name.html @model.name
@$description.html @model.description
else
@$el.addClass 'empty'
# Backbone.View Overrides ###################################################################### # Backbone.View Overrides ######################################################################
@@ -34,9 +34,6 @@ module.exports = class ModPageController extends PageController
@_effectiveModVersion = null @_effectiveModVersion = null
@_groupControllers = [] @_groupControllers = []
Object.defineProperties this,
effectiveModVersion: {get:@_getEffectiveModVersion}
# Event Methods ################################################################################ # Event Methods ################################################################################
onVersionChanged: -> onVersionChanged: ->
@@ -46,6 +43,21 @@ module.exports = class ModPageController extends PageController
if modVersion? then modVersion.fetch() if modVersion? then modVersion.fetch()
@refresh() @refresh()
# Property Methods #############################################################################
getEffectiveModVersion: ->
return @_effectiveModVersion if @_effectiveModVersion?
return null unless @model?
modVersion = @model.activeModVersion
modVersion ?= @model.getModVersion Mod.Version.Latest
modVersion.fetch() if modVersion?
return modVersion
Object.defineProperties @prototype,
effectiveModVersion: {get:@prototype.getEffectiveModVersion}
# PageController Overrides ##################################################################### # PageController Overrides #####################################################################
getTitle: -> getTitle: ->
@@ -56,34 +68,35 @@ module.exports = class ModPageController extends PageController
onDidRender: -> onDidRender: ->
@adsenseController = @addChild AdsenseController, '.view__adsense', model:'sidebar_skyscraper' @adsenseController = @addChild AdsenseController, '.view__adsense', model:'sidebar_skyscraper'
@$name = @$('.name') @$name = @$('.name')
@$byline = @$('.byline p') @$byline = @$('.byline p')
@$description = @$('.description p') @$description = @$('.description p')
@$documentationLink = @$('.documentation') @$documentationLink = @$('.documentation')
@$downloadLink = @$('.download') @$downloadLink = @$('.download')
@$homePageLink = @$('.homePage') @$homePageLink = @$('.homePage')
@$groupContainer = @$('.itemGroups') @$groupContainer = @$('.itemGroups')
@$titleImage = @$('.titleImage img') @$titleImage = @$('.titleImage img')
@$tutorialsSection = @$('.tutorials') @$titleImageContainer = @$('.titleImage')
@$tutorialsContainer = @$('.tutorials .panel') @$tutorialsSection = @$('.tutorials')
@$versionSelector = @$('select.version') @$tutorialsContainer = @$('.tutorials .panel')
@$versionSelector = @$('select.version')
super super
refresh: -> refresh: ->
if @model? if @model?.isLoaded and @effectiveModVersion?.isLoaded
@$name.html @model.name
@$byline.html "by #{@model.author}" @$byline.html "by #{@model.author}"
@$titleImage.attr 'src', Url.modIcon modSlug:@model.slug
@$description.html @model.description @$description.html @model.description
@$name.html @model.name
@$titleImage.attr 'src', Url.modIcon modSlug:@model.slug
@$el.slideDown duration:Duration.normal @show()
else else
@$el.slideUp duration:Duration.normal @hide()
@_refreshLink @$homePageLink, @model.homePageUrl @_refreshLink @$homePageLink, @model?.homePageUrl
@_refreshLink @$documentationLink, @model.documentationUrl @_refreshLink @$documentationLink, @model?.documentationUrl
@_refreshLink @$downloadLink, @model.downloadUrl @_refreshLink @$downloadLink, @model?.downloadUrl
@_refreshItemGroups() @_refreshItemGroups()
@_refreshTutorials() @_refreshTutorials()
@@ -97,33 +110,25 @@ module.exports = class ModPageController extends PageController
# Private Methods ############################################################################## # Private Methods ##############################################################################
_getEffectiveModVersion: ->
return @_effectiveModVersion if @_effectiveModVersion?
return null unless @model?
modVersion = @model.activeModVersion
modVersion ?= @model.getModVersion Mod.Version.Latest
modVersion.fetch() if modVersion?
return modVersion
_refreshItemGroups: -> _refreshItemGroups: ->
@_groupControllers ?= []
groupIndex = 0 groupIndex = 0
modVersion = @effectiveModVersion modVersion = @effectiveModVersion
if modVersion? if modVersion?
modVersion.eachGroup (group)=> modVersion.eachGroup (group)=>
controller = @_groupControllers[groupIndex] controller = @_groupControllers[groupIndex]
items = modVersion.allItemsInGroup group items = modVersion.allItemsInGroup group
if not controller? if not controller?
title = if group is Item.Group.Other then 'Items' else group
controller = new ItemGroupController controller = new ItemGroupController
imageLoader: @imageLoader imageLoader: @imageLoader
model: items model: items
modPack: @modPack modPack: @modPack
title: title title: if group is Item.Group.Other then 'Items' else group
controller.render()
@_groupControllers.push controller
@$groupContainer.append controller.$el @$groupContainer.append controller.$el
@_groupControllers[groupIndex] = controller controller.render()
else else
controller.modVersion = modVersion controller.modVersion = modVersion
controller.model = items controller.model = items
@@ -132,32 +137,28 @@ module.exports = class ModPageController extends PageController
while @_groupControllers.length > groupIndex + 1 while @_groupControllers.length > groupIndex + 1
controller = @_groupControllers.pop() controller = @_groupControllers.pop()
controller.$el.slideUp duration:Duration.normal, complete:-> @remove() controller.hide -> controller.$el.remove()
_refreshLink: ($link, url)-> _refreshLink: ($link, url)->
if url? if url?
$link.slideDown duration:Duration.normal
$link.attr 'href', url $link.attr 'href', url
$link.removeClass 'hidden'
else else
$link.slideUp duration:Duration.normal $link.addClass 'hidden'
_refreshTutorials: -> _refreshTutorials: ->
@_tutorialControllers ?= [] @_tutorialControllers ?= []
tutorials = @model.tutorials index = 0
tutorials = @model.tutorials
if tutorials.length is 0 if tutorials.length > 0
@$tutorialsSection.addClass 'hidden'
else
@$tutorialsSection.removeClass 'hidden'
index = 0
for tutorial in tutorials for tutorial in tutorials
controller = @_tutorialControllers[index] controller = @_tutorialControllers[index]
if not controller? if not controller?
controller = new TutorialController model:tutorial controller = new TutorialController model:tutorial
controller.render()
@$tutorialsContainer.append controller.$el
@_tutorialControllers.push controller @_tutorialControllers.push controller
@$tutorialsContainer.append controller.$el
controller.render()
else else
controller.model = model controller.model = model
@@ -165,12 +166,18 @@ module.exports = class ModPageController extends PageController
while @_tutorialControllers.length > index while @_tutorialControllers.length > index
controller = @_tutorialControllers.pop() controller = @_tutorialControllers.pop()
controller.$el.slideUp duration:Duration.normal, complete:-> @remove() controller.hide -> controller.$el.remove()
@show @$tutorialsSection
else
@hide @tutorialsSection
_refreshVersions: -> _refreshVersions: ->
@$versionSelector.empty() @$versionSelector.empty()
return unless @model? return unless @model?
@$versionSelector.removeClass 'hiding'
effectiveModVersion = @effectiveModVersion effectiveModVersion = @effectiveModVersion
versionCount = 0 versionCount = 0
@model.eachModVersion (modVersion)=> @model.eachModVersion (modVersion)=>
@@ -1,5 +1,5 @@
### ###
Crafting Guide - mod_controller.coffee Crafting Guide - mod_selector_controller.coffee
Copyright (c) 2014-2015 by Redwood Labs Copyright (c) 2014-2015 by Redwood Labs
All rights reserved. All rights reserved.
@@ -1,25 +0,0 @@
###
Crafting Guide - recipe_step_controller.coffee
Copyright (c) 2014-2015 by Redwood Labs
All rights reserved.
###
BaseController = require './base_controller'
########################################################################################################################
module.exports = class RecipeStepController 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'
options.templateName = 'recipe_step'
super options
# BaseController Overrides #####################################################################
onDidRender: ->
@$slotImages = (@$slots.push $(el) for el in @$('.table-slot img'))
@$output = @$('.output')
super
@@ -25,6 +25,7 @@ module.exports = class StackController extends BaseController
options.editable ?= false options.editable ?= false
options.onChange ?= -> # do nothing options.onChange ?= -> # do nothing
options.onRemove ?= (stack)-> # do nothing options.onRemove ?= (stack)-> # do nothing
options.tagName = 'tr'
options.templateName = 'stack' options.templateName = 'stack'
super options super options
@@ -95,6 +96,8 @@ module.exports = class StackController extends BaseController
super super
refresh: -> refresh: ->
if not @model? then throw new Error "must have a model to render"
display = @modPack.findItemDisplay @model.itemSlug display = @modPack.findItemDisplay @model.itemSlug
@_imageLoader.load display.iconUrl, @$image @_imageLoader.load display.iconUrl, @$image
@@ -53,64 +53,55 @@ module.exports = class TutorialPageController extends BaseController
refresh: -> refresh: ->
if @model? and @model.isLoaded if @model? and @model.isLoaded
@$el.removeClass 'hidden' @_refreshByline()
@_refreshOfficialUrl()
@_refreshSections()
@_refreshTitle()
@_refreshVideos()
@show()
else else
@$el.addClass 'hidden' @hide()
@_refreshByline()
@_refreshOfficialUrl()
@_refreshSections()
@_refreshTitle()
@_refreshVideos()
super super
# Private Methods ############################################################################## # Private Methods ##############################################################################
_refreshByline: -> _refreshByline: ->
if @model? @$bylineLink.html @modPack.getMod(@modSlug).name
@$byline.removeClass 'hidden' @$bylineLink.attr 'href', Url.mod modSlug:@modSlug
@$bylineLink.html @modPack.getMod(@modSlug).name
@$bylineLink.attr 'href', Url.mod modSlug:@modSlug
else
@$byline.addClass 'hidden'
_refreshOfficialUrl: -> _refreshOfficialUrl: ->
if @model?.officialUrl? if @model.officialUrl?
@$officialLink.attr 'href', @model.officialUrl @$officialLink.attr 'href', @model.officialUrl
@$officialLink.removeClass 'hidden' @show @$officialLink
else else
@$officialLink.addClass 'hidden' @hide @$officialLink
_refreshTitle: -> _refreshTitle: ->
if @model? @$title.html @model.name
@$title.html @model.name @$titleImage.attr 'src', Url.tutorialIcon modSlug:@modSlug, tutorialSlug:@tutorialSlug
@$titleImage.attr 'src', Url.tutorialIcon modSlug:@modSlug, tutorialSlug:@tutorialSlug
else
@$title.empty()
@$titleImage.removeAttr 'src'
_refreshSections: -> _refreshSections: ->
@_sectionControllers ?= [] @_sectionControllers ?= []
index = 0 index = 0
if @model? for section in @model.sections
for section in @model.sections controller = @_sectionControllers[index]
controller = @_sectionControllers[index] if not controller?
if not controller? controller = new MarkdownSectionController title:section.title, model:section.content
controller = new MarkdownSectionController title:section.title, model:section.content @_sectionControllers.push controller
controller.render() @$sectionsContainer.append controller.$el
@$sectionsContainer.append controller.$el controller.render()
@_sectionControllers.push controller else
else controller.title = section.title
controller.title = section.title controller.model = section.model
controller.model = section.model controller.refresh()
controller.refresh()
index += 1 index += 1
while @_sectionControllers.length > index while @_sectionControllers.length > index
controller = @_sectionController.pop() @_sectionController.pop().remove()
controller.$el.fadeOut duration:Duration.normal, complete:-> @remove()
_refreshVideos: -> _refreshVideos: ->
@_videoControllers ?= [] @_videoControllers ?= []
@@ -118,7 +109,6 @@ module.exports = class TutorialPageController extends BaseController
videos = @model?.videos or [] videos = @model?.videos or []
if videos? and videos.length > 0 if videos? and videos.length > 0
@$videosSection.slideDown duration:Duration.normal
@$videosSectionTitle.html if videos.length is 1 then 'Video' else 'Videos' @$videosSectionTitle.html if videos.length is 1 then 'Video' else 'Videos'
for video in videos for video in videos
@@ -126,17 +116,19 @@ module.exports = class TutorialPageController extends BaseController
if not controller? if not controller?
controller = new VideoController model:video controller = new VideoController model:video
@_videoControllers.push controller @_videoControllers.push controller
controller.render()
@$videosSectionPanel.append controller.$el @$videosSectionPanel.append controller.$el
controller.render()
else else
controller.model = video controller.model = video
index++
index += 1
@show @$videosSection
else else
@$videosSection.slideUp duration:Duration.normal @hide @$videosSection
while @_videoControllers.length > index while @_videoControllers.length > index
controller = @_videoControllers.pop() @_videoControllers.pop().remove()
controller.$el.slideUp duration:Duration.normal, complete:-> controller.$el.remove()
_resolveTutorial: -> _resolveTutorial: ->
return if @model? return if @model?
+11 -11
View File
@@ -163,27 +163,27 @@ module.exports = class CraftingGuideRouter extends Backbone.Router
@headerController.model = page @headerController.model = page
showDuration = Duration.normal showDuration = Duration.normal
show = => switchToNextController = (event)=>
logger.debug "show called: #{event}"
@_resetGlobals() @_resetGlobals()
@_controller.unrender() if @_controller?
@_page = page @_page = page
@_controller = controller @_controller = controller
$pageContent = $('.page')
$pageContent.attr 'class', 'page hideable hidden'
window.scrollTo 0, 0
controller.onWillShow() controller.onWillShow()
controller.$el = $pageContent
controller.render() controller.render()
$pageContent = $('.page')
controller.$el.addClass 'page'
$pageContent.replaceWith controller.$el
controller.$el.slideDown showDuration, ->
controller.onDidShow()
if @_controller? if @_controller?
showDuration = showDuration / 2 @_controller.hide -> switchToNextController()
@_controller.$el.slideUp showDuration, show
else else
show() switchToNextController()
_resetGlobals: -> _resetGlobals: ->
if global.env in ProductionEnvs if global.env in ProductionEnvs
+5
View File
@@ -87,6 +87,11 @@ module.exports = class ModVersion extends BaseModel
# Group Methods ################################################################################ # Group Methods ################################################################################
getAllGroups: ->
result = []
@eachGroup (group)-> result.push group
return result
eachGroup: (callback)-> eachGroup: (callback)->
groupNames = _.keys @_groups groupNames = _.keys @_groups
groupNames.sort (a, b)-> groupNames.sort (a, b)->
+1 -1
View File
@@ -23,7 +23,7 @@ html
.content .content
include ./includes/_header.jade include ./includes/_header.jade
.page .page.hideable
include ./includes/_footer.jade include ./includes/_footer.jade
block scripts block scripts
+1 -1
View File
@@ -11,4 +11,4 @@
.mainBody .mainBody
h2: p Active Mods h2: p Active Mods
.mods .mods
+1 -1
View File
@@ -15,5 +15,5 @@
.view__minimal_recipe .view__minimal_recipe
.next .next
.problem .problem.hideable
a report a problem a report a problem
+1 -1
View File
@@ -12,7 +12,7 @@
label(name="comment") Comment: label(name="comment") Comment:
textarea(name="comment") textarea(name="comment")
button(name="send") send button(name="send") send
.error: p Sending failed. Please try again later. .error.hideable.hidden: p Sending failed. Please try again later.
.label .label
img(src="/images/paper.png") img(src="/images/paper.png")
+20 -25
View File
@@ -47,6 +47,26 @@
.section .section
h2 What's new? h2 What's new?
.panel .panel
h3 2015-03-20
.entry
p.
Recently, I've been working on allowing mod authors to add more detail to the item pages here on
Crafting Guide. To that end, there are a couple of new features to announce. First, item detail
pages can now show text and pictures to describe the item (check out the <a
href="/browse/buildcraft/assembly_table">Assembly Table</a> for an example). Second, mods can
now include tutorial pages containing similar text and pictures to describe tricky concepts,
complex builds, or anything else their mod has to offer (see <a
href="/browse/buildcraft/tutorials/gates_wires_and_chips">Gates, Wires, and Chips</a> for an
example). Finally, both item pages and tutorial pages can display a list of YouTube videos. Only
a few pages in the Buildcraft section have been updated so far, but keep an eye out for
more to come!
p.
And... the second piece of news is that Crafting Guide now supports <a
href="/browse/thermal_dynamics">Thermal Dynamics</a>! This mod is an off-shoot from <a
href="/browse/thermal_expansion">Thermal Expansion</a> which contains all the ducts (item, fluid
and redstone flux) you're used to from TE3 plus some extras both for higher capacity throughput
and combining item ducts with redstone flux ducts.
h3 2015-03-13 h3 2015-03-13
.entry .entry
p. p.
@@ -126,28 +146,3 @@
| smelting ore directly in a furnace | smelting ore directly in a furnace
li recipes for vanilla items added by mods are now available (e.g., smelting Iron Dust into Iron li recipes for vanilla items added by mods are now available (e.g., smelting Iron Dust into Iron
| ingots) | ingots)
h3 2015-02-10
.entry
p.
I just pushed up some fixes to avoid confusing various items of the same name from different
mods. The best example of this are the two Wrenches from Buildcraft and IC2, but there are a
bunch of others.
h3 2015-02-09
.entry
p.
This release fixes a number of small issues and improves performance in a number of places. Most
especially, all links within the site have been changed to update the page in place without the
need to re-download anything. This should make browsing between item pages <i>much</i> faster.
h3 2015-02-08
.entry
p.
This is the singlest largest expansion of the website yet! Each item from each mod now has its
own page! This will expand in the future, but for now this shows all the recipes for the item as
well as all the closely related items and the others items that can be made using the item.
p.
This also changes things so that links to Crafting Guide from other sites will first go to the
item's page (instead of to the crafting plan). Not to worry though... there's still a direct
link from each item to the full crafting plan for that item.
+1 -1
View File
@@ -5,7 +5,7 @@
//- All rights reserved. //- All rights reserved.
//- //-
.view__item .view__item.hideable.hidden
a a
table table
tr tr
+1 -1
View File
@@ -5,6 +5,6 @@
//- All rights reserved. //- All rights reserved.
//- //-
.view__item_group.section .view__item_group.section.hideable.hidden
h2 h2
.panel .panel
+8 -8
View File
@@ -8,7 +8,7 @@
.view__item_page .view__item_page
.sidebar .sidebar
.titleImage: a: img .titleImage: a: img
a.officialPage.externalLink(target="new"): p Offical Documentation a.officialPage.externalLink.hideable.hidden(target="new"): p Offical Documentation
button.large.craftingPlan See Crafting Plan button.large.craftingPlan See Crafting Plan
@@ -16,22 +16,22 @@
.mainBody .mainBody
h1.name h1.name
.byline: p from <a></a> .byline.hideable.hidden: p from <a></a>
.recipes.section .recipes.section.hideable.hidden
h2 Recipes h2 Recipes
.panel .panel
.description.section .description.section.hideable.hidden
h2 Description h2 Description
.panel.markdown .panel.markdown
.videos.section .videos.section.hideable.hidden
h2 Videos h2 Videos
.panel .panel
.usedToMake: .view__item_group .view__item_group.usedToMake
.usedAsToolToMake: .view__item_group .view__item_group.usedAsToolToMake
.similar: .view__item_group .view__item_group.similar
+4 -4
View File
@@ -9,9 +9,9 @@
.sidebar .sidebar
.titleImage: a: img .titleImage: a: img
select.version select.version
a.homePage.externalLink(target="new"): p Offical Home Page a.homePage.externalLink.hideable.hidden(target="new"): p Offical Home Page
a.documentation.externalLink(target="new"): p Documentation a.documentation.externalLink.hideable.hidden(target="new"): p Documentation
a.download.externalLink(target="new"): p Download a.download.externalLink.hideable.hidden(target="new"): p Download
.view__adsense .view__adsense
@@ -20,7 +20,7 @@
.byline: p .byline: p
.description: p .description: p
.tutorials.section .tutorials.section.hideable.hidden
h2 Tutorials h2 Tutorials
.panel .panel
+2 -2
View File
@@ -8,7 +8,7 @@
.view__tutorial_page .view__tutorial_page
.sidebar .sidebar
.titleImage: a: img .titleImage: a: img
a.officialPage.externalLink(target="new"): p Offical Documentation a.officialPage.externalLink.hideable.hidden(target="new"): p Offical Documentation
.view__adsense .view__adsense
@@ -18,6 +18,6 @@
.sections .sections
.videos.section .videos.section.hideable.hidden
h2 h2
.panel .panel
+11 -5
View File
@@ -32,11 +32,20 @@ All rights reserved.
.error-new { background: $color-error-new !important; } .error-new { background: $color-error-new !important; }
.hidden { .hideable {
max-height: 0; opacity: 1;
transition: opacity $animate-normal;
}
.hiding {
opacity: 0; opacity: 0;
} }
.hidden {
opacity: 0;
display: none;
}
.mainBody { .mainBody {
position: relative; width: 81.25%; position: relative; width: 81.25%;
@@ -67,7 +76,6 @@ All rights reserved.
.externalLink { .externalLink {
position: relative; width: 80%; position: relative; width: 80%;
margin: 0.5em 10%; margin: 0.5em 10%;
display: none;
p { p {
font-family: $font-family-normal; font-family: $font-family-normal;
@@ -104,8 +112,6 @@ All rights reserved.
} }
.videos { .videos {
display: none;
.panel { .panel {
text-align: center; text-align: center;
} }
+3 -3
View File
@@ -28,9 +28,9 @@ All rights reserved.
// Animation Speeds //////////////////////////////////////////////////////////////////////////////// // Animation Speeds ////////////////////////////////////////////////////////////////////////////////
$animate-fast: 0.1s; $animate-fast: 0.200s;
$animate-normal: 0.25s; $animate-normal: 0.400s;
$animate-slow: 0.6s; $animate-slow: 1.200s;
// Font Faces ////////////////////////////////////////////////////////////////////////////////////// // Font Faces //////////////////////////////////////////////////////////////////////////////////////
-15
View File
@@ -6,18 +6,12 @@ All rights reserved.
*/ */
.view__item_page { .view__item_page {
display: none;
& > div { & > div {
vertical-align: top; vertical-align: top;
display: inline-block; display: inline-block;
} }
.sidebar { .sidebar {
.externalLink {
display: none;
}
button.large { button.large {
width: 100%; width: 100%;
} }
@@ -26,7 +20,6 @@ All rights reserved.
.mainBody { .mainBody {
.recipes { .recipes {
display: none;
.view__full_recipe { .view__full_recipe {
width: 100%; width: 100%;
@@ -37,14 +30,6 @@ All rights reserved.
} }
} }
} }
.similar {
display: none;
}
.usedToMake {
display: none;
}
} }
.view__item { .view__item {
-2
View File
@@ -6,8 +6,6 @@ All rights reserved.
*/ */
.view__mod_page { .view__mod_page {
display: none;
& > div { & > div {
vertical-align: top; vertical-align: top;
display: inline-block; display: inline-block;
+22 -19
View File
@@ -32,14 +32,29 @@ see full recipe lists, related items, recipes added by each tool, and even which
made from the item you're looking at.</a></p><p><a class="section-link" href="/craft">Craft</a><a> any number of items from your mod pack to see a made from the item you're looking at.</a></p><p><a class="section-link" href="/craft">Craft</a><a> any number of items from your mod pack to see a
full list of raw ingredients, and recipe-by-recipe instructions on how to make everything on full list of raw ingredients, and recipe-by-recipe instructions on how to make everything on
your list. No item is too complex, and no build is too big. your list. No item is too complex, and no build is too big.
</a></p></div></div></div><div class="section"><h2><a>What's new?</a></h2><div class="panel"><h3><a>2015-03-09</a></h3><div class="entry"><p><a>It may seem like not much has been happening lately, but that's because all the changes have </a></p></div></div></div><div class="section"><h2><a>What's new?</a></h2><div class="panel"><h3><a>2015-03-20</a></h3><div class="entry"><p><a>Recently, I've been working on allowing mod authors to add more detail to the item pages here on
Crafting Guide. To that end, there are a couple of new features to announce. First, item detail
pages can now show text and pictures to describe the item (check out the </a><a href="/browse/buildcraft/assembly_table">Assembly Table</a> for an example). Second, mods can
now include tutorial pages containing similar text and pictures to describe tricky concepts,
complex builds, or anything else their mod has to offer (see <a href="/browse/buildcraft/tutorials/gates_wires_and_chips">Gates, Wires, and Chips</a> for an
example). Finally, both item pages and tutorial pages can display a list of YouTube videos. Only
a few pages in the Buildcraft section have been updated so far, but keep an eye out for
more to come!</p><p>And... the second piece of news is that Crafting Guide now supports <a href="/browse/thermal_dynamics">Thermal Dynamics</a>! This mod is an off-shoot from <a href="/browse/thermal_expansion">Thermal Expansion</a> which contains all the ducts (item, fluid
and redstone flux) you're used to from TE3 plus some extras both for higher capacity throughput
and combining item ducts with redstone flux ducts.
</p></div><h3>2015-03-13</h3><div class="entry"><p>Happy Friday! For the weekend, you get <a href="/browse/big_reactors/">Big Reactors!</a> Enjoy!
</p></div><h3>2015-03-12</h3><div class="entry"><p>Thanks to the extraordinary generosity and effort of <a href="https://github.com/sheldongriffin">Sheldon Griffin</a>, Crafting Guide now supports
Forestry! Forestry is <i>not</i> a small mod, but he put in a huge effort, and it looks great.
If you'd like to help out too, head over to the <a href="https://github.com/andrewminer/crafting-guide/wiki/Adding-support-for-a-new-Mod">GitHub
Wiki</a> for full instructions: no programming required!</p><p>Also in the works is another significant expansion to the item pages. I've got the coding part
finished (you can peek at the final result <a href="/browse/buildcraft/advanced_crafting_table/">here</a>), and
now there's a lot of entering data left to be done... any volunteers?
</p></div><h3>2015-03-09</h3><div class="entry"><p>It may seem like not much has been happening lately, but that's because all the changes have
been behind the scenes, and focused on making Google happier with the site. This will make the been behind the scenes, and focused on making Google happier with the site. This will make the
site show up better is search results, and will make it load a bit faster. site show up better is search results, and will make it load a bit faster.</p><p>As a result of this work, the site also now qualifies for AdSense. I absolutely don't want to
As a result of this work, the site also now qualifies for AdSense. I absolutely don't want to
choke the site with ads as other big sites do, but it will be nice to pay the bills! choke the site with ads as other big sites do, but it will be nice to pay the bills!
</a></p></div><h3><a>2015-03-01</a></h3><div class="entry"><p><a>This release delivers the second major expansion of Crafting Guide! Here's the list of what's </p></div><h3>2015-03-01</h3><div class="entry"><p>This release delivers the second major expansion of Crafting Guide! Here's the list of what's
new:</a></p><ul><li><a>New home page!</a></li><li><a>Moved the crafting planner (the old home page) to its own </a><a href="/craft">Craft</a> page</li><li>Moved mod pack management to the new <a href="/configure">Configure</a> page</li><li>Added a <a href="/browse">Browse</a> page where you can peruse the list of supported mods</li></ul></div><h3>2015-02-26</h3><div class="entry"><p>This release adds a new section to the item pages called "Used as Tool to Make". The new section new:</p><ul><li>New home page!</li><li>Moved the crafting planner (the old home page) to its own <a href="/craft">Craft</a> page</li><li>Moved mod pack management to the new <a href="/configure">Configure</a> page</li><li>Added a <a href="/browse">Browse</a> page where you can peruse the list of supported mods</li></ul></div><h3>2015-02-26</h3><div class="entry"><p>This release adds a new section to the item pages called "Used as Tool to Make". The new section
shows all the other items which can be made by that tool. For example, the IC2 Macerator shows shows all the other items which can be made by that tool. For example, the IC2 Macerator shows
a bunch of things like Iron Dust, Gold Dust, etc. a bunch of things like Iron Dust, Gold Dust, etc.
</p></div><h3>2015-02-24</h3><div class="entry"><p>This release changes the crafting page to let you modify the quantity of items in the "Items You </p></div><h3>2015-02-24</h3><div class="entry"><p>This release changes the crafting page to let you modify the quantity of items in the "Items You
@@ -54,19 +69,7 @@ plans don't take so long.
that there are a few things you should notice:</p><ol><li>it will favor recipes which produce more of an item versus those which produce fewer (e.g., that there are a few things you should notice:</p><ol><li>it will favor recipes which produce more of an item versus those which produce fewer (e.g.,
IC2 plates get made with the Block Cutter instead of the Forge Hammer)</li><li>metal ingots will frequently (but not always) get crafted using 2x recipes instead of IC2 plates get made with the Block Cutter instead of the Forge Hammer)</li><li>metal ingots will frequently (but not always) get crafted using 2x recipes instead of
smelting ore directly in a furnace</li><li>recipes for vanilla items added by mods are now available (e.g., smelting Iron Dust into Iron smelting ore directly in a furnace</li><li>recipes for vanilla items added by mods are now available (e.g., smelting Iron Dust into Iron
ingots)</li></ol></div><h3>2015-02-10</h3><div class="entry"><p>I just pushed up some fixes to avoid confusing various items of the same name from different ingots)</li></ol></div></div></div></div></div>
mods. The best example of this are the two Wrenches from Buildcraft and IC2, but there are a
bunch of others.
</p></div><h3>2015-02-09</h3><div class="entry"><p>This release fixes a number of small issues and improves performance in a number of places. Most
especially, all links within the site have been changed to update the page in place without the
need to re-download anything. This should make browsing between item pages <i>much</i> faster.
</p></div><h3>2015-02-08</h3><div class="entry"><p>This is the singlest largest expansion of the website yet! Each item from each mod now has its
own page! This will expand in the future, but for now this shows all the recipes for the item as
well as all the closely related items and the others items that can be made using the item.</p><p>This also changes things so that links to Crafting Guide from other sites will first go to the
item's page (instead of to the crafting plan). Not to worry though... there's still a direct
link from each item to the full crafting plan for that item.
</p></div><h3>2015-02-02</h3><div class="entry"><p>Crafting Guide now has support for EnderIO! I tend to add new mods in order of those with the
most votes, so remember to suggest your favorites!</p></div></div></div></div></div>
<div class="view__footer"> <div class="view__footer">
<div class="divider top"></div> <div class="divider top"></div>
<div class="left"> <div class="left">