Update URL scheme to include /item/*

* Update the router to understand /item/:name routes in addition to
  v1.0-style parameterized routes
* Add support for updating the current URL based upon the item being
  viewed
* Change LandingPage* to ItemPage*
This commit is contained in:
Andrew Miner
2014-12-28 12:59:29 -08:00
parent 8cde02a10b
commit bf113d26ab
9 changed files with 105 additions and 53 deletions
+1 -1
View File
@@ -8,6 +8,6 @@
.view__header .view__header
h1 h1
a(href="/") a(href="/")
img(src="images/workbench_front.png") img(src="/images/workbench_front.png")
p Crafting Guide p Crafting Guide
.divider.bottom .divider.bottom
+1 -1
View File
@@ -15,7 +15,7 @@ html
meta(charset="UTF-8") meta(charset="UTF-8")
block styles block styles
link(rel="stylesheet", type="text/css", href="css/main.css") link(rel="stylesheet", type="text/css", href="/css/main.css")
body body
.content .content
@@ -29,7 +29,7 @@ module.exports = class CraftingTableController extends BaseController
onCatalogChanged: -> onCatalogChanged: ->
return unless @rendered return unless @rendered
@_updateNameAutocomplete() @_updateNameAutocomplete()
@_parseUrlParameters() @_craft()
onHaveFieldChanged: -> onHaveFieldChanged: ->
return unless @rendered return unless @rendered
@@ -69,12 +69,19 @@ module.exports = class CraftingTableController extends BaseController
@$makeList = @$('td.make ul') @$makeList = @$('td.make ul')
@$resultList = @$('td.result ul') @$resultList = @$('td.result ul')
@_updateNameAutocomplete()
@_craft()
super super
@_updateNameAutocomplete()
@_parseUrlParameters()
refresh: -> refresh: ->
@$nameField.val @model.name
@$quantityField.val @model.quantity
if @model.includingTools
@$includingToolsField.attr 'checked', 'checked'
else
@$includingToolsField.removeAttr 'checked'
@$needList.empty() @$needList.empty()
@$makeList.empty() @$makeList.empty()
@$resultList.empty() @$resultList.empty()
@@ -92,45 +99,18 @@ module.exports = class CraftingTableController extends BaseController
# Backbone.View Overrides ###################################################################### # Backbone.View Overrides ######################################################################
events: events:
'input textarea[name="have"]': 'onHaveFieldChanged' 'input textarea[name="have"]': 'onHaveFieldChanged'
'focus input[name="name"]': 'onNameFieldFocused' 'focus input[name="name"]': 'onNameFieldFocused'
'input input[name="name"]': 'onNameFieldChanged' 'input input[name="name"]': 'onNameFieldChanged'
'input select[name="quantity"]': 'onQuantityFieldChanged' 'input select[name="quantity"]': 'onQuantityFieldChanged'
'change input[name="including_tools"]': 'onIncludingToolsFieldChanged' 'change input[name="including_tools"]': 'onIncludingToolsFieldChanged'
# Private Methods ############################################################################## # Private Methods ##############################################################################
_craft: -> _craft: ->
router.navigate "/item/#{encodeURIComponent(@model.name)}"
@model.craft() @model.craft()
_parseUrlParameters: ->
params = url.parse(window.location.href, true).query
if params[UrlParam.includingTools]?
param = params[UrlParam.includingTools]
if param in ['true', 'yes']
@$includingToolsField.attr 'checked', 'checked'
else if param in ['false', 'no']
@$includingToolsField.removeAttr 'checked'
else
console.log "invalid including tools value in URL param: #{params[UrlParam.includingTools]}"
@onIncludingToolsFieldChanged()
if params[UrlParam.quantity]?
@$quantityField.val parseInt params[UrlParam.quantity]
if @$quantityField.find(':selected').length is 0
console.log "invalid quantity in URL param: #{params[UrlParam.quantity]}"
@onQuantityFieldChanged()
# Do this check last to avoid recalculting the recipe multiple times
if params[UrlParam.recipe]?
recipeName = params[UrlParam.recipe]
if @model.catalog.findRecipes(recipeName).length > 0
@$nameField.val recipeName
else
console.log "invalid recipe name in URL param: #{params[UrlParam.recipe]}"
@onNameFieldChanged()
_updateNameAutocomplete: -> _updateNameAutocomplete: ->
onChanged = => @onNameFieldChanged() onChanged = => @onNameFieldChanged()
@@ -1,5 +1,5 @@
### ###
# Crafting Guide - landing_page_controller.coffee # Crafting Guide - item_page_controller.coffee
# #
# Copyright (c) 2014 by Redwood Labs # Copyright (c) 2014 by Redwood Labs
# All rights reserved. # All rights reserved.
@@ -7,18 +7,25 @@
BaseController = require './base_controller' BaseController = require './base_controller'
CraftingTableController = require './crafting_table_controller' CraftingTableController = require './crafting_table_controller'
LandingPage = require '../models/landing_page' ItemPage = require '../models/item_page'
RecipeCatalogController = require './recipe_catalog_controller' RecipeCatalogController = require './recipe_catalog_controller'
######################################################################################################################## ########################################################################################################################
module.exports = class LandingPageController extends BaseController module.exports = class ItemPageController extends BaseController
constructor: (options={})-> constructor: (options={})->
options.model ?= new LandingPage options.model ?= new ItemPage
options.templateName = 'landing_page' options.templateName = 'item_page'
super options super options
# Public Methods ###############################################################################
setParams: (params)->
@model.table.name = params.name if params.name?
@model.table.quantity = params.quantity if params.quantity?
logger.debug "quantity updated to: #{@model.table.quantity} with params: #{params.count}"
# BaseController Overrides ##################################################################### # BaseController Overrides #####################################################################
onDidRender: -> onDidRender: ->
+20 -7
View File
@@ -5,9 +5,10 @@
# All rights reserved. # All rights reserved.
### ###
{Duration} = require './constants' {Duration} = require './constants'
LandingPageController = require './controllers/landing_page_controller' ItemPageController = require './controllers/item_page_controller'
{Opacity} = require './constants' {Opacity} = require './constants'
UrlParams = require './url_params'
######################################################################################################################## ########################################################################################################################
@@ -21,13 +22,25 @@ module.exports = class CraftingGuideRouter extends Backbone.Router
# Backbone.Router Overrides #################################################################### # Backbone.Router Overrides ####################################################################
routes: routes:
'': 'landing' '': 'root'
'item(/:name)': 'item'
# Route Methods ################################################################################ # Route Methods ################################################################################
landing: -> root: ->
@_pageControllers.landing ?= new LandingPageController params = new UrlParams
@_setPage 'landing' recipeName: {type:'string'}
count: {type:'integer'}
if params.recipeName?
@navigate "/item/#{encodeURIComponent(params.recipeName)}"
@item params.recipeName, params.count
item: (name, quantity=1)->
@_pageControllers.item ?= new ItemPageController
@_pageControllers.item.setParams name:name, quantity:quantity
@_setPage 'item'
# Private Methods ############################################################################## # Private Methods ##############################################################################
@@ -1,5 +1,5 @@
### ###
# Crafting Guide - landing_page.coffee # Crafting Guide - item_page.coffee
# #
# Copyright (c) 2014 by Redwood Labs # Copyright (c) 2014 by Redwood Labs
# All rights reserved. # All rights reserved.
@@ -11,7 +11,7 @@ RecipeCatalog = require './recipe_catalog'
######################################################################################################################## ########################################################################################################################
module.exports = class LandingPage extends BaseModel module.exports = class ItemPage extends BaseModel
constructor: (attributes={}, options={})-> constructor: (attributes={}, options={})->
attributes.catalog ?= new RecipeCatalog attributes.catalog ?= new RecipeCatalog
+52
View File
@@ -0,0 +1,52 @@
###
# Crafting Guide - url_params.coffee
#
# Copyright (c) 2014 by Redwood Labs
# All rights reserved.
###
url = require 'url'
########################################################################################################################
module.exports = class UrlParams
constructor: (parseMap, url=null)->
if not parseMap? then throw new Error 'parseMap is required'
url ?= window.location.href
@_parseMap = {}
for name, options of parseMap
options.type ?= 'string'
options.default ?= null
options.parse = this["_#{options.type}"]
if not options.parse? then throw new Error "#{options.type} is not a valid type"
@_parseMap[name] = options
@parse url
parse: (urlText)->
params = url.parse(urlText, true).query
for name, options of @_parseMap
value = params[name]
if value?
this[name] = options.parse value
else
this[name] = options.default
# Private Methods ##############################################################################
_boolean: (text)->
return true if text in ['true', 'yes']
return false
_integer: (text)->
return null unless text?
result = parseInt text
return null unless _.isNumber result
return result
_string: (text)->
return text
+1 -1
View File
@@ -11,7 +11,7 @@ var jade_indent = [];
buf.push("\n<div class=\"view__crafting_table\">\n <h2><img src=\"/images/workbench_top.png\"/>\n <p>Crafting Table</p>\n </h2>\n <div class=\"recipe_selector\">\n <p>I want to make</p>\n <select name=\"quantity\">\n <option value=\"1\">1</option>\n <option value=\"2\">2</option>\n <option value=\"4\">4</option>\n <option value=\"8\">8</option>\n <option value=\"16\">16</option>\n <option value=\"64\">64</option>\n </select>\n <input name=\"name\" placeholder=\"enter an item name\"/>\n <label>\n <input name=\"including_tools\" type=\"checkbox\"/>including tools\n </label>\n </div>\n <table>\n <tr>\n <td class=\"have\">\n <h3>\n <p>You have...</p>\n </h3>\n <textarea name=\"have\" placeholder=\"For example:\n\n3 wool\n4 iron ingot\"></textarea>\n </td>\n <td class=\"need\">\n <h3>\n <p>You'll need...</p>\n </h3>\n <ul></ul>\n </td>\n <td class=\"make\">\n <h3>\n <p>You'll make...</p>\n </h3>\n <ul></ul>\n </td>\n <td class=\"result\">\n <h3>\n <p>You'll get...</p>\n </h3>\n <ul></ul>\n </td>\n </tr>\n </table>\n</div>");;return buf.join(""); buf.push("\n<div class=\"view__crafting_table\">\n <h2><img src=\"/images/workbench_top.png\"/>\n <p>Crafting Table</p>\n </h2>\n <div class=\"recipe_selector\">\n <p>I want to make</p>\n <select name=\"quantity\">\n <option value=\"1\">1</option>\n <option value=\"2\">2</option>\n <option value=\"4\">4</option>\n <option value=\"8\">8</option>\n <option value=\"16\">16</option>\n <option value=\"64\">64</option>\n </select>\n <input name=\"name\" placeholder=\"enter an item name\"/>\n <label>\n <input name=\"including_tools\" type=\"checkbox\"/>including tools\n </label>\n </div>\n <table>\n <tr>\n <td class=\"have\">\n <h3>\n <p>You have...</p>\n </h3>\n <textarea name=\"have\" placeholder=\"For example:\n\n3 wool\n4 iron ingot\"></textarea>\n </td>\n <td class=\"need\">\n <h3>\n <p>You'll need...</p>\n </h3>\n <ul></ul>\n </td>\n <td class=\"make\">\n <h3>\n <p>You'll make...</p>\n </h3>\n <ul></ul>\n </td>\n <td class=\"result\">\n <h3>\n <p>You'll get...</p>\n </h3>\n <ul></ul>\n </td>\n </tr>\n </table>\n</div>");;return buf.join("");
}; };
this["JST"]["landing_page"] = function template(locals) { this["JST"]["item_page"] = function template(locals) {
var buf = []; var buf = [];
var jade_mixins = {}; var jade_mixins = {};
var jade_interp; var jade_interp;