diff --git a/src/css/main.scss b/src/css/main.scss index 2e943ce51..db1d33a52 100644 --- a/src/css/main.scss +++ b/src/css/main.scss @@ -37,7 +37,7 @@ $font-family-input: monospace; $font-size-small: 1.0em; $font-size-normal: 1.5em; $font-size-large: 2.0em; -$font-size-x-large: 2.5em; +$font-size-x-large: 3.0em; $font-size-xx-large: 4.0em; // Gray Palette //////////////////////////////////////////////////////////////////////////////////// diff --git a/src/css/mixins.scss b/src/css/mixins.scss index 7c476ad9f..d05ba268b 100644 --- a/src/css/mixins.scss +++ b/src/css/mixins.scss @@ -24,3 +24,11 @@ All rights reserved. -webkit-transform: $transforms; transform: $transforms; } + +@mixin pixel-image { + image-rendering: -moz-crisp-edges; /* Firefox */ + image-rendering: -o-crisp-edges; /* Opera */ + image-rendering: -webkit-optimize-contrast; /* Webkit (non-standard naming) */ + image-rendering: crisp-edges; + -ms-interpolation-mode: nearest-neighbor; /* IE (non-standard property) */ +} diff --git a/src/css/templates/index.scss b/src/css/templates/index.scss index e3984100e..be4632821 100644 --- a/src/css/templates/index.scss +++ b/src/css/templates/index.scss @@ -10,6 +10,7 @@ All rights reserved. @import 'feedback'; @import 'inventory'; @import 'item'; +@import 'item_page'; @import 'crafting_page'; @import 'mod'; @import 'mod_pack'; diff --git a/src/css/templates/item_page.scss b/src/css/templates/item_page.scss new file mode 100644 index 000000000..6eaa33ccd --- /dev/null +++ b/src/css/templates/item_page.scss @@ -0,0 +1,68 @@ +/* +Crafting Guide - item_page.scss + +Copyright (c) 2014 by Redwood Labs +All rights reserved. +*/ + +.view__item_page { + & > div { + vertical-align: top; + display: inline-block; + } + + .sidebar { + position: relative; width: 18.75%; + padding: 1em; + + .titleImage { + position: relative; height: 16em; width: 16em; + margin-bottom: 2em; + + img { + position: relative; width: 100%; + @include pixel-image; + } + } + } + + .mainBody { + position: relative; width: 81.25%; + padding: 1em; + padding-top: 2em; + + .name { + font-family: $font-family-header; + font-size: $font-size-x-large; + margin: 0; + } + + .byline { + display: none; + margin: 0.25em 0 2em 0; + + p { + font-family: $font-family-normal; + font-size: $font-size-normal; + font-style: italic; + } + } + + .description { + margin-bottom: 4em; + + p { + font-family: $font-family-normal; + font-size: $font-size-large; + } + } + + .usedInMaking { + display: none; + } + + .similar { + display: none; + } + } +} diff --git a/src/css/templates/mod.scss b/src/css/templates/mod.scss index 1e002d6a5..41a3bd8a2 100644 --- a/src/css/templates/mod.scss +++ b/src/css/templates/mod.scss @@ -15,7 +15,11 @@ All rights reserved. } .version { - width: 10em; + width: 12em; + + select { + position: relative; width: 100%; + } } .name { diff --git a/src/css/templates/mod_page.scss b/src/css/templates/mod_page.scss index e910fdd9b..e6c8394f4 100644 --- a/src/css/templates/mod_page.scss +++ b/src/css/templates/mod_page.scss @@ -21,6 +21,7 @@ All rights reserved. img { position: relative; width: 100%; + @include pixel-image; } } @@ -59,7 +60,7 @@ All rights reserved. p { font-family: $font-family-normal; - font-size: $font-size-small; + font-size: $font-size-normal; font-style: italic; } } @@ -72,23 +73,5 @@ All rights reserved. font-size: $font-size-large; } } - - .section { - h2 { - font-family: $font-family-header; - font-size: $font-size-large; - } - - .panel { - background: white; - padding: 1em; - - & > div { - position: relative; width: 33%; - display: inline-block; - padding: 0.5em; - } - } - } } } diff --git a/src/scripts/controllers/base_controller.coffee b/src/scripts/controllers/base_controller.coffee index dbe43c5dd..d6bbc6feb 100644 --- a/src/scripts/controllers/base_controller.coffee +++ b/src/scripts/controllers/base_controller.coffee @@ -12,6 +12,7 @@ views = require '../views' module.exports = class BaseController extends Backbone.View constructor: (options={})-> + @tryRefresh = _.debounce @_tryRefresh, 100 Object.defineProperty this, 'model', get:@getModel, set:@setModel @_model = null @@ -23,8 +24,6 @@ module.exports = class BaseController extends Backbone.View @_loadTemplate options.templateName super options - @_tryRefresh = _.debounce @_tryRefresh, 100 - # Public Methods ############################################################################### addChild: (Controller, atSelector, options={})-> @@ -47,15 +46,15 @@ module.exports = class BaseController extends Backbone.View # Event Methods ################################################################################ onDidModelChange: -> - @_tryRefresh() + @tryRefresh() onDidModelSync: -> - @_tryRefresh() + @tryRefresh() onWillRender: -> # do nothing onDidRender: -> - @_tryRefresh() + @tryRefresh() onWillShow: -> # do nothing @@ -79,7 +78,7 @@ module.exports = class BaseController extends Backbone.View return unless @onWillChangeModel @_model, newModel @_model = newModel - @_tryRefresh() + @tryRefresh() # Backbone.View Overrides ###################################################################### diff --git a/src/scripts/controllers/item_controller.coffee b/src/scripts/controllers/item_controller.coffee index 8f1e0cb66..868753b7f 100644 --- a/src/scripts/controllers/item_controller.coffee +++ b/src/scripts/controllers/item_controller.coffee @@ -6,7 +6,6 @@ All rights reserved. ### BaseController = require './base_controller' -{Url} = require '../constants' ######################################################################################################################## @@ -31,9 +30,9 @@ module.exports = class ItemController extends BaseController refresh: -> display = @_modPack.findItemDisplay @model.slug - @$icon.attr 'src', Url.itemIcon display + @$icon.attr 'src', display.iconUrl @$name.html display.itemName - @$nameLink.attr 'href', Url.item display + @$nameLink.attr 'href', display.itemUrl # Backbone.View Overrides ###################################################################### diff --git a/src/scripts/controllers/item_group_controller.coffee b/src/scripts/controllers/item_group_controller.coffee index 7d1af2ed4..9e25a1d5d 100644 --- a/src/scripts/controllers/item_group_controller.coffee +++ b/src/scripts/controllers/item_group_controller.coffee @@ -16,17 +16,26 @@ ItemController = require './item_controller' module.exports = class ItemGroupController 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' - if not options.modVersion? then throw new Error 'options.modVersion is required' - options.templateName = 'item_group' + if not options.modPack? then throw new Error 'options.modPack is required' + options.title ?= '' + options.templateName = 'item_group' super options - @modVersion = options.modVersion - @_modPack = options.modPack @_itemControllers = [] + @_modPack = options.modPack + @_title = options.title - @modVersion.on Event.change, => @refresh() + Object.defineProperties this, + title: {get:@getTitle, set:@setTitle} + + # Property Methods ############################################################################# + + getTitle: -> + return @_title + + setTitle: (title)-> + @_title = title + @tryRefresh() # BaseController Overrides ##################################################################### @@ -36,7 +45,7 @@ module.exports = class ItemGroupController extends BaseController super refresh: -> - @$title.html if @model is Item.Group.Other then 'Items' else @model + @$title.html @_title @_refreshItems() super @@ -55,15 +64,16 @@ module.exports = class ItemGroupController extends BaseController controllerIndex = 0 delay = 0 - @modVersion.eachItemInGroup @model, (item)=> - controller = @_itemControllers[controllerIndex] - if not controller? - _.delay (=> @_createItemController item), delay - delay += @_delayStep - else - controller.model = item - controller.refresh() - controllerIndex += 1 + if @model? + for item in @model + controller = @_itemControllers[controllerIndex] + if not controller? + _.delay ((i)=> return => @_createItemController i)(item), delay + delay += @_delayStep + else + controller.model = item + controller.refresh() + controllerIndex += 1 while @_itemControllers.length > controllerIndex controller = @_itemControllers.pop() diff --git a/src/scripts/controllers/item_page_controller.coffee b/src/scripts/controllers/item_page_controller.coffee new file mode 100644 index 000000000..61c559bea --- /dev/null +++ b/src/scripts/controllers/item_page_controller.coffee @@ -0,0 +1,99 @@ +### +Crafting Guide - item_page_controller.coffee + +Copyright (c) 2015 by Redwood Labs +All rights reserved. +### + +BaseController = require './base_controller' +{Duration} = require '../constants' +{Event} = require '../constants' +ImageLoader = require './image_loader' +ItemGroupController = require './item_group_controller' +ItemPage = require '../models/item_page' +{Url} = require '../constants' + +######################################################################################################################## + +module.exports = class ItemPageController extends BaseController + + constructor: (options={})-> + if not options.modPack? then throw new Error 'options.modPack is required' + if not options.itemSlug? then throw new Error 'options.itemSlug is required' + + options.imageLoader ?= new ImageLoader defaultUrl:'/images/unknown.png' + options.model ?= new ItemPage modPack:options.modPack + options.templateName ?= 'item_page' + + super options + + @_imageLoader = options.imageLoader + @_itemSlug = options.itemSlug + @_modPack = options.modPack + + @_modPack.on Event.change, => @_resolveItemSlug() + @_resolveItemSlug() + + # BaseController Overrides ##################################################################### + + onDidRender: -> + @_similarItemsController = @addChild ItemGroupController, '.similar .view__item_group', modPack:@_modPack + @_usedInMakingController = @addChild ItemGroupController, '.usedInMaking .view__item_group', modPack:@_modPack + + @$byline = @$('.byline') + @$bylineLink = @$('.byline a') + @$usedInMakingContainer = @$('.usedInMaking') + @$name = @$('h1.name') + @$recipeContainer = @$('.recipe') + @$similarContainer = @$('.similar') + @$titleImage = @$('.titleImage img') + super + + refresh: -> + display = @_modPack.findItemDisplay @model.item?.slug + if display? + @_imageLoader.load display.iconUrl, @$titleImage + @$name.html display.itemName + else + @$titleImage.removeAttr 'src' + @$name.html '' + + @_refreshByline() + @_refreshSimilarItems() + @_refreshComponentIn() + + super + + # Private Methods ############################################################################## + + _refreshByline: -> + mod = @model.item?.modVersion?.mod + if mod?.name?.length > 0 + @$bylineLink.attr 'href', Url.mod modSlug:mod.slug + @$bylineLink.html mod.name + @$byline.fadeIn duration:Duration.fast + else + @$byline.fadeOut duration:Duration.fast + + _refreshComponentIn: -> + @_usedInMakingController.title = 'Used in Making' + + @_usedInMakingController.model = @model.findComponentInItems() + if @_usedInMakingController.model? + @$usedInMakingContainer.fadeIn duration:Duration.fast + else + @$usedInMakingContainer.fadeOut duration:Duration.fast + + _refreshSimilarItems: -> + group = @model.item?.group + @_similarItemsController.title = if group? then "Other #{group}" else 'Similar Items' + + @_similarItemsController.model = @model.findSimilarItems() + if @_similarItemsController.model? + @$similarContainer.fadeIn duration:Duration.fast + else + @$similarContainer.fadeOut duration:Duration.fast + + _resolveItemSlug: -> + @model.item = @_modPack.findItem @_itemSlug, includeDisabled:true + diff --git a/src/scripts/controllers/mod_controller.coffee b/src/scripts/controllers/mod_controller.coffee index dead23c35..16a43b86e 100644 --- a/src/scripts/controllers/mod_controller.coffee +++ b/src/scripts/controllers/mod_controller.coffee @@ -33,7 +33,7 @@ module.exports = class ModController extends BaseController # BaseController Overrides ##################################################################### onDidRender: -> - @$version = @$('.version') + @$version = @$('select') @$nameLink = @$('.name a') @$nameText = @$('.name p') @$description = @$('.description p') @@ -69,5 +69,5 @@ module.exports = class ModController extends BaseController events: -> return _.extend super, - 'change .version': 'onVersionChanged' + 'change select': 'onVersionChanged' 'click a': 'routeLinkClick' diff --git a/src/scripts/controllers/mod_page_controller.coffee b/src/scripts/controllers/mod_page_controller.coffee index 462eba94b..bafcc5f52 100644 --- a/src/scripts/controllers/mod_page_controller.coffee +++ b/src/scripts/controllers/mod_page_controller.coffee @@ -9,6 +9,7 @@ BaseController = require './base_controller' {Duration} = require '../constants' Mod = require '../models/mod' ModPack = require '../models/mod_pack' +Item = require '../models/item' ItemGroupController = require './item_group_controller' {Text} = require '../constants' {Url} = require '../constants' @@ -84,25 +85,28 @@ module.exports = class ModPageController extends BaseController modVersion = @model.activeModVersion modVersion ?= @model.getModVersion Mod.Version.Latest - modVersion.fetch() + modVersion.fetch() if modVersion? return modVersion _refreshItemGroups: -> groupIndex = 0 modVersion = @effectiveModVersion - modVersion.eachGroup (group)=> - controller = @_groupControllers[groupIndex] - if not controller? - controller = new ItemGroupController model:group, modVersion:modVersion, modPack:@_modPack - controller.render() - @$groupContainer.append controller.$el - @_groupControllers[groupIndex] = controller - else - controller.modVersion = modVersion - controller.model = group - controller.refresh() - groupIndex++ + if modVersion? + modVersion.eachGroup (group)=> + controller = @_groupControllers[groupIndex] + items = modVersion.allItemsInGroup group + if not controller? + title = if group is Item.Group.Other then 'Items' else group + controller = new ItemGroupController model:items, modPack:@_modPack, title:title + controller.render() + @$groupContainer.append controller.$el + @_groupControllers[groupIndex] = controller + else + controller.modVersion = modVersion + controller.model = items + controller.refresh() + groupIndex++ while @_groupControllers.length > groupIndex + 1 controller = @_groupControllers.pop() diff --git a/src/scripts/crafting_guide_router.coffee b/src/scripts/crafting_guide_router.coffee index 47f8563d5..a759514a6 100644 --- a/src/scripts/crafting_guide_router.coffee +++ b/src/scripts/crafting_guide_router.coffee @@ -5,18 +5,20 @@ Copyright (c) 2014-2015 by Redwood Labs All rights reserved. ### + +CraftingPageController = require './controllers/crafting_page_controller' {DefaultMods} = require './constants' {Duration} = require './constants' {Event} = require './constants' HeaderController = require './controllers/header_controller' -CraftingPageController = require './controllers/crafting_page_controller' +ItemPageController = require './controllers/item_page_controller' Mod = require './models/mod' ModPack = require './models/mod_pack' ModPageController = require './controllers/mod_page_controller' {Opacity} = require './constants' Storage = require './models/storage' -UrlParams = require './url_params' {Url} = require './constants' +UrlParams = require './url_params' ######################################################################################################################## @@ -55,13 +57,31 @@ module.exports = class CraftingGuideRouter extends Backbone.Router @_recordPageView() routes: - '': 'root' - 'item/(:inventoryText)': 'crafting' - 'crafting/(:inventoryText)': 'crafting' - 'mod/:slug': 'mod' + '': 'root' + 'item/:itemSlug': 'item' + 'crafting/(:text)': 'crafting' + 'mod/:modSlug': 'mod' # Route Methods ################################################################################ + crafting: (text)-> + controller = new CraftingPageController _.extend {}, @_defaultOptions + controller.model.params = inventoryText:text + @_setPage 'crafting', controller + + item: (slug)-> + # Temporarily re-route these to crafting until item page is complete. -- aminer 2015-02-08 + # + # controller = new ItemPageController _.extend {itemSlug:slug}, @_defaultOptions + # @_setPage 'item', controller + + @navigate "/crafting/#{slug}", trigger:true + + mod: (slug)-> + controller = new ModPageController _.extend {}, @_defaultOptions + controller.model = @modPack.getMod slug + @_setPage 'mod', controller + root: -> params = new UrlParams recipeName:{type:'string'}, count:{type:'integer'} @@ -74,16 +94,6 @@ module.exports = class CraftingGuideRouter extends Backbone.Router @navigate Url.crafting(inventoryText:text), trigger:true - crafting: (inventoryText)-> - controller = new CraftingPageController @_defaultOptions - controller.model.params = inventoryText:inventoryText - @_setPage 'crafting', controller - - mod: (slug)-> - controller = new ModPageController @_defaultOptions - controller.model = @modPack.getMod slug - @_setPage 'mod', controller - # Private Methods ############################################################################## _recordPageView: -> @@ -96,9 +106,9 @@ module.exports = class CraftingGuideRouter extends Backbone.Router logger.info "Suppressing GA page view: #{pathname}" _setPage: (page, controller)-> - return if @_page is page + return if @_controller is controller - logger.info "changing to #{page} page" + logger.info "changing to page controller: #{controller.constructor.name}" showDuration = Duration.normal show = => @_page = page @@ -115,7 +125,7 @@ module.exports = class CraftingGuideRouter extends Backbone.Router controller.onDidShow() if @_controller? - showDuration = Duration.fast + showDuration = Duration.long @_controller.$el.fadeOut showDuration, show else show() diff --git a/src/scripts/models/item_page.coffee b/src/scripts/models/item_page.coffee new file mode 100644 index 000000000..250fcd4f7 --- /dev/null +++ b/src/scripts/models/item_page.coffee @@ -0,0 +1,66 @@ +### +Crafting Guide - item_page.coffee + +Copyright (c) 2015 by Redwood Labs +All rights reserved. +### + +BaseModel = require './base_model' +CraftingPlan = require './crafting_plan' +Event = require '../constants' + +######################################################################################################################## + +module.exports = class ItemPage extends BaseModel + + constructor: (attributes={}, options={})-> + if not attributes.modPack? then throw new Error 'attributes.modPack is required' + attributes.item ?= null + super attributes, options + + @_plan = new CraftingPlan modPack:@modPack + @on Event.change + ':item', => @_updateCraftingPlan() + @_updateCraftingPlan() + + Object.defineProperties this, + craftingRawMaterials: {get:-> @_plan.need} + craftingSteps: {get:-> @_plan.steps} + similarItems: {get:=> @getSimilarItems()} + + # Property Methods ############################################################################# + + findSimilarItems: -> + return null unless @item?.modVersion? + + result = [] + @item.modVersion.eachItemInGroup @item.group, (item)=> + return if item is @item + result.push item + + return null unless result.length > 0 + return result + + findComponentInItems: -> + return null unless @item? + + itemSlug = @item.slug + result = {} + @modPack.eachMod (mod)-> + mod.eachItem (item)-> + item.eachRecipe (recipe)-> + for stack in recipe.input + if stack.slug is itemSlug + result[item.slug] = item + + result = _.values(result).sort (a, b)-> a.compareTo b + return null unless result.length > 0 + return result + + # Private Methods ############################################################################## + + _updateCraftingPlan: -> + @_plan.clear() + + if @item? + @_plan.want.add @item.slug + @_plan.craft() \ No newline at end of file diff --git a/src/scripts/models/mod_pack.coffee b/src/scripts/models/mod_pack.coffee index ddd787141..ed2441f84 100644 --- a/src/scripts/models/mod_pack.coffee +++ b/src/scripts/models/mod_pack.coffee @@ -45,6 +45,8 @@ module.exports = class ModPack extends BaseModel return null findItemDisplay: (slug)-> + if not slug? then return null + result = {} item = @findItem slug, includeDisabled:true if item? diff --git a/src/scripts/models/mod_version.coffee b/src/scripts/models/mod_version.coffee index 639d3a2af..2dcfac51c 100644 --- a/src/scripts/models/mod_version.coffee +++ b/src/scripts/models/mod_version.coffee @@ -39,6 +39,12 @@ module.exports = class ModVersion extends BaseModel @registerSlug item.slug, item.name return this + allItemsInGroup: (group)-> + result = [] + @eachItemInGroup group, (item)-> result.push item + return null if result.length is 0 + return result + compareTo: (that)-> if this.mod? and that.mod? return this.mod.compareTo that.mod diff --git a/src/templates/item_page.jade b/src/templates/item_page.jade new file mode 100644 index 000000000..8cee7252f --- /dev/null +++ b/src/templates/item_page.jade @@ -0,0 +1,20 @@ +//- +//- Crafting Guide - item_page.jade +//- +//- Copyright (c) 2015 by Redwood Labs +//- All rights reserved. +//- + +.view__item_page + .sidebar + .titleImage: img + + .mainBody + h1.name + .byline: p from + .description: p + + .recipe + .usedInMaking: .view__item_group + .similar: .view__item_group + .plan \ No newline at end of file diff --git a/src/templates/mod.jade b/src/templates/mod.jade index a97624c4b..d6a125dcd 100644 --- a/src/templates/mod.jade +++ b/src/templates/mod.jade @@ -6,8 +6,9 @@ //- .view__mod - select.version - option(value="none") None + .version + select + option(value="none") None .name a: p .description: p