From 9f7972237848166e45d06cc47ad856a48129143d Mon Sep 17 00:00:00 2001 From: Andrew Miner Date: Wed, 7 Jan 2015 11:20:49 -0800 Subject: [PATCH] Refactor image loading code into ImageLoader class --- src/scripts/controllers/image_loader.coffee | 81 +++++++++++++++++++ .../controllers/inventory_controller.coffee | 21 +++-- .../controllers/item_page_controller.coffee | 33 ++++---- .../controllers/stack_controller.coffee | 34 +++----- src/scripts/models/crafting_table.coffee | 37 +-------- 5 files changed, 125 insertions(+), 81 deletions(-) create mode 100644 src/scripts/controllers/image_loader.coffee diff --git a/src/scripts/controllers/image_loader.coffee b/src/scripts/controllers/image_loader.coffee new file mode 100644 index 000000000..b16c28741 --- /dev/null +++ b/src/scripts/controllers/image_loader.coffee @@ -0,0 +1,81 @@ +### +Crafting Guide - image_loader.coffee + +Copyright (c) 2014 by Redwood Labs +All rights reserved. +### + +{Duration} = require '../constants' + +######################################################################################################################## + +module.exports = class ImageLoader + + constructor: (options={})-> + options.defaultUrl ?= '' + options.onLoading ?= -> @hide() + options.onLoad ?= -> @fadeIn Duration.fast + + @defaultUrl = options.defaultUrl + @onLoading = options.onLoading + @onLoad = options.onLoad + + @_images = {} + + # Class Methods ################################################################################ + + @load: (imageUrl, $el, options={}) -> + loader = new ImageLoader options + loader.load $el, options + return loader + + # Public Methods ############################################################################### + + isLoaded: (imageUrl)-> + data = @_images[imageUrl] + return false unless data? + return data.isLoaded + + load: (imageUrl, $el)-> + data = @preload imageUrl + return if $el.attr('src').indexOf(imageUrl) isnt -1 + + if @onLoading? then @onLoading.call $el + $el.data 'isLoading', true + $el.data 'isLoaded', false + + if data.isLoaded? + @_loadImageIntoElement data.imageUrl, $el + else + if @defaultUrl? then $el.attr 'src', @defaultUrl + if data.elements.indexOf($el) is -1 then data.elements.push $el + + return this + + preload: (imageUrl)-> + data = @_images[imageUrl] + if not data? + data = imageUrl:imageUrl, elements:[], image:new Image, isLoaded:false + @_images[imageUrl] = data + + data.image = new Image + data.image.onload = => @_onImageLoaded data + data.image.src = imageUrl + + return data + + # Private Methods ############################################################################## + + _onImageLoaded: (data)-> + for $el in data.elements + @_loadImageIntoElement data.imageUrl, $el + + data.elements = [] + data.isLoaded = true + + _loadImageIntoElement: (imageUrl, $el)-> + $el.data 'isLoading', false + $el.data 'isLoaded', true + $el.attr 'src', imageUrl + + if @onLoad? then @onLoad.call $el diff --git a/src/scripts/controllers/inventory_controller.coffee b/src/scripts/controllers/inventory_controller.coffee index 60a1c7333..ee9a8b259 100644 --- a/src/scripts/controllers/inventory_controller.coffee +++ b/src/scripts/controllers/inventory_controller.coffee @@ -8,6 +8,7 @@ All rights reserved. BaseController = require './base_controller' {Duration} = require '../constants' {Key} = require '../constants' +ImageLoader = require './image_loader' StackController = require './stack_controller' ######################################################################################################################## @@ -22,14 +23,17 @@ module.exports = class InventoryController extends BaseController options.icon ?= '/images/chest_front.png' options.editable ?= true - options.templateName = 'inventory' + options.imageLoader ?= new ImageLoader defaultUrl:'/images/unknown.png' options.title ?= 'Inventory' + + options.templateName = 'inventory' super options - @editable = options.editable - @icon = options.icon - @modPack = options.modPack - @title = options.title + @editable = options.editable + @icon = options.icon + @imageLoader = options.imageLoader + @modPack = options.modPack + @title = options.title @_stackControllers = [] @@ -114,9 +118,10 @@ module.exports = class InventoryController extends BaseController @_stackControllers = [] @model.each (stack)=> options = - model: stack - modPack: @modPack - onRemove: if not @editable then null else (stack)=> @_removeStack(stack) + imageLoader: @imageLoader + model: stack + modPack: @modPack + onRemove: if not @editable then null else (stack)=> @_removeStack(stack) controller = new StackController options controller.render() diff --git a/src/scripts/controllers/item_page_controller.coffee b/src/scripts/controllers/item_page_controller.coffee index b7b8e2ad4..736ccd314 100644 --- a/src/scripts/controllers/item_page_controller.coffee +++ b/src/scripts/controllers/item_page_controller.coffee @@ -7,6 +7,7 @@ All rights reserved. BaseController = require './base_controller' CraftingTableController = require './crafting_table_controller' +ImageLoader = require './image_loader' InventoryController = require './inventory_controller' ItemPage = require '../models/item_page' ModPackController = require './mod_pack_controller' @@ -17,6 +18,7 @@ module.exports = class ItemPageController extends BaseController constructor: (options={})-> options.model ?= new ItemPage + options.imageLoader ?= new ImageLoader defaultUrl:'/images/unknown.png' options.templateName = 'item_page' super options @@ -35,26 +37,29 @@ module.exports = class ItemPageController extends BaseController onDidRender: -> options = - editable: true, - model: @model.plan.have, - modPack: @model.modPack, - title: 'Items you have' + editable: true, + imageLoader: @imageLoader + model: @model.plan.have, + modPack: @model.modPack, + title: 'Items you have' @haveController = @addChild InventoryController, '.have', options options = - editable: true - icon: '/images/fishing_rod.png', - model: @model.plan.want, - modPack: @model.modPack, - title: 'Items you want' + editable: true + icon: '/images/fishing_rod.png', + imageLoader: @imageLoader + model: @model.plan.want, + modPack: @model.modPack, + title: 'Items you want' @wantController = @addChild InventoryController, '.want', options options = - editable: false - icon: '/images/boots.png', - model: @model.plan.need, - modPack: @model.modPack, - title: "Items you'll need" + editable: false + icon: '/images/boots.png', + imageLoader: @imageLoader + model: @model.plan.need, + modPack: @model.modPack, + title: "Items you'll need" @needController = @addChild InventoryController, '.need', options @modPackController = @addChild ModPackController, '.view__mod_pack', model:@model.modPack diff --git a/src/scripts/controllers/stack_controller.coffee b/src/scripts/controllers/stack_controller.coffee index 13509f793..759b4e9e4 100644 --- a/src/scripts/controllers/stack_controller.coffee +++ b/src/scripts/controllers/stack_controller.coffee @@ -6,7 +6,8 @@ All rights reserved. ### BaseController = require './base_controller' -{ImageUrl} = require '../constants' +{ImageUrl} = require '../constants' +ImageLoader = require './image_loader' ######################################################################################################################## @@ -15,20 +16,12 @@ module.exports = class StackController 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.imageLoader ?= new ImageLoader defaultUrl:'/images/unknown.png' options.templateName = 'stack' super options - @modPack = options.modPack - @_loadImage() - - # Event Methods ################################################################################ - - onImageLoaded: -> - return if @_image.loaded - - logger.trace "#{@constructor.name}.onImageLoaded(#{@_image.src})" - @_image.loaded = true - @$image.attr 'src', @_image.src + @modPack = options.modPack + @_imageLoader = options.imageLoader # BaseController Overrides ##################################################################### @@ -39,10 +32,12 @@ module.exports = class StackController extends BaseController super refresh: -> - {itemName} = @_gatherData() + {itemName, itemSlug, modSlug} = @_gatherData() + imageUrl = ImageUrl itemSlug:itemSlug, modSlug:modSlug + @$nameField.html itemName @$quantityField.html @model.quantity - @$image.attr 'src', (if @_image?.loaded then @_image.src else '/images/unknown.png') + @_imageLoader.load imageUrl, @$image super # Private Methods ############################################################################## @@ -58,14 +53,3 @@ module.exports = class StackController extends BaseController modSlug = 'minecraft' return itemName:itemName, itemSlug:itemSlug, modSlug:modSlug - - _loadImage: -> - {itemSlug, modSlug} = @_gatherData() - url = ImageUrl(modSlug:modSlug, itemSlug:itemSlug) - return if @$image?.attr('src').indexOf(url) is -1 - - @_image = new Image() - @_image.loaded = false - @_image.onload = => @onImageLoaded() - @_image.src = url - logger.verbose "loading image: #{url}" diff --git a/src/scripts/models/crafting_table.coffee b/src/scripts/models/crafting_table.coffee index d55e577f5..2e9682d4a 100644 --- a/src/scripts/models/crafting_table.coffee +++ b/src/scripts/models/crafting_table.coffee @@ -15,42 +15,11 @@ Inventory = require './inventory' module.exports = class CraftingTable extends BaseModel constructor: (attributes={}, options={})-> - if not attributes.modPack? then throw new Error "attributes.modPack is required" - attributes.name ?= null - attributes.quantity ?= 1 - attributes.includingTools ?= false - attributes.have ?= new Inventory - attributes.plan ?= null - attributes.want ?= new Inventory + if not attributes.plan? then throw new Error "attributes.plan is required" + attributes.step ?= 0 super attributes, options - Object.defineProperty @prototype, 'need', -> @plan?.need - - # Public Methods ############################################################################### - - craft: -> - if not @modPack.hasRecipe @name - @plan = null - return - - toolPhrase = if @includingTools then ' including tools' else '' - logger.verbose "calculating build plan for #{@quantity} #{@name}#{toolPhrase} with inventory: #{@have}" - - @modPack.enableModsForItem @name - - plan = new CraftingPlan @modPack, @includingTools - plan.includingTools = @includingTools - plan.craft @name, @quantity, @have - - @plan = plan - # Object Overrides ############################################################################# toString: -> - return "#{@constructor.name} (#{@cid}) { - name:#{@name}, - quantity:#{@quantity}, - includingTools:#{@includingTools}, - have:#{@have}, - plan:#{@plan} - }" + return "#{@constructor.name} (#{@cid}) { plan:#{@plan}, step:#{@step} }"