Refactor image loading code into ImageLoader class

This commit is contained in:
Andrew Miner
2015-01-07 11:20:49 -08:00
parent 4a10a36e37
commit 9f79722378
5 changed files with 125 additions and 81 deletions
@@ -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
@@ -8,6 +8,7 @@ All rights reserved.
BaseController = require './base_controller' BaseController = require './base_controller'
{Duration} = require '../constants' {Duration} = require '../constants'
{Key} = require '../constants' {Key} = require '../constants'
ImageLoader = require './image_loader'
StackController = require './stack_controller' StackController = require './stack_controller'
######################################################################################################################## ########################################################################################################################
@@ -22,14 +23,17 @@ module.exports = class InventoryController extends BaseController
options.icon ?= '/images/chest_front.png' options.icon ?= '/images/chest_front.png'
options.editable ?= true options.editable ?= true
options.templateName = 'inventory' options.imageLoader ?= new ImageLoader defaultUrl:'/images/unknown.png'
options.title ?= 'Inventory' options.title ?= 'Inventory'
options.templateName = 'inventory'
super options super options
@editable = options.editable @editable = options.editable
@icon = options.icon @icon = options.icon
@modPack = options.modPack @imageLoader = options.imageLoader
@title = options.title @modPack = options.modPack
@title = options.title
@_stackControllers = [] @_stackControllers = []
@@ -114,9 +118,10 @@ module.exports = class InventoryController extends BaseController
@_stackControllers = [] @_stackControllers = []
@model.each (stack)=> @model.each (stack)=>
options = options =
model: stack imageLoader: @imageLoader
modPack: @modPack model: stack
onRemove: if not @editable then null else (stack)=> @_removeStack(stack) modPack: @modPack
onRemove: if not @editable then null else (stack)=> @_removeStack(stack)
controller = new StackController options controller = new StackController options
controller.render() controller.render()
@@ -7,6 +7,7 @@ All rights reserved.
BaseController = require './base_controller' BaseController = require './base_controller'
CraftingTableController = require './crafting_table_controller' CraftingTableController = require './crafting_table_controller'
ImageLoader = require './image_loader'
InventoryController = require './inventory_controller' InventoryController = require './inventory_controller'
ItemPage = require '../models/item_page' ItemPage = require '../models/item_page'
ModPackController = require './mod_pack_controller' ModPackController = require './mod_pack_controller'
@@ -17,6 +18,7 @@ module.exports = class ItemPageController extends BaseController
constructor: (options={})-> constructor: (options={})->
options.model ?= new ItemPage options.model ?= new ItemPage
options.imageLoader ?= new ImageLoader defaultUrl:'/images/unknown.png'
options.templateName = 'item_page' options.templateName = 'item_page'
super options super options
@@ -35,26 +37,29 @@ module.exports = class ItemPageController extends BaseController
onDidRender: -> onDidRender: ->
options = options =
editable: true, editable: true,
model: @model.plan.have, imageLoader: @imageLoader
modPack: @model.modPack, model: @model.plan.have,
title: 'Items you have' modPack: @model.modPack,
title: 'Items you have'
@haveController = @addChild InventoryController, '.have', options @haveController = @addChild InventoryController, '.have', options
options = options =
editable: true editable: true
icon: '/images/fishing_rod.png', icon: '/images/fishing_rod.png',
model: @model.plan.want, imageLoader: @imageLoader
modPack: @model.modPack, model: @model.plan.want,
title: 'Items you want' modPack: @model.modPack,
title: 'Items you want'
@wantController = @addChild InventoryController, '.want', options @wantController = @addChild InventoryController, '.want', options
options = options =
editable: false editable: false
icon: '/images/boots.png', icon: '/images/boots.png',
model: @model.plan.need, imageLoader: @imageLoader
modPack: @model.modPack, model: @model.plan.need,
title: "Items you'll need" modPack: @model.modPack,
title: "Items you'll need"
@needController = @addChild InventoryController, '.need', options @needController = @addChild InventoryController, '.need', options
@modPackController = @addChild ModPackController, '.view__mod_pack', model:@model.modPack @modPackController = @addChild ModPackController, '.view__mod_pack', model:@model.modPack
@@ -6,7 +6,8 @@ All rights reserved.
### ###
BaseController = require './base_controller' 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={})-> constructor: (options={})->
if not options.model? then throw new Error 'options.model is required' 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.modPack? then throw new Error 'options.modPack is required'
options.imageLoader ?= new ImageLoader defaultUrl:'/images/unknown.png'
options.templateName = 'stack' options.templateName = 'stack'
super options super options
@modPack = options.modPack @modPack = options.modPack
@_loadImage() @_imageLoader = options.imageLoader
# Event Methods ################################################################################
onImageLoaded: ->
return if @_image.loaded
logger.trace "#{@constructor.name}.onImageLoaded(#{@_image.src})"
@_image.loaded = true
@$image.attr 'src', @_image.src
# BaseController Overrides ##################################################################### # BaseController Overrides #####################################################################
@@ -39,10 +32,12 @@ module.exports = class StackController extends BaseController
super super
refresh: -> refresh: ->
{itemName} = @_gatherData() {itemName, itemSlug, modSlug} = @_gatherData()
imageUrl = ImageUrl itemSlug:itemSlug, modSlug:modSlug
@$nameField.html itemName @$nameField.html itemName
@$quantityField.html @model.quantity @$quantityField.html @model.quantity
@$image.attr 'src', (if @_image?.loaded then @_image.src else '/images/unknown.png') @_imageLoader.load imageUrl, @$image
super super
# Private Methods ############################################################################## # Private Methods ##############################################################################
@@ -58,14 +53,3 @@ module.exports = class StackController extends BaseController
modSlug = 'minecraft' modSlug = 'minecraft'
return itemName:itemName, itemSlug:itemSlug, modSlug:modSlug 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}"
+3 -34
View File
@@ -15,42 +15,11 @@ Inventory = require './inventory'
module.exports = class CraftingTable extends BaseModel module.exports = class CraftingTable extends BaseModel
constructor: (attributes={}, options={})-> constructor: (attributes={}, options={})->
if not attributes.modPack? then throw new Error "attributes.modPack is required" if not attributes.plan? then throw new Error "attributes.plan is required"
attributes.name ?= null attributes.step ?= 0
attributes.quantity ?= 1
attributes.includingTools ?= false
attributes.have ?= new Inventory
attributes.plan ?= null
attributes.want ?= new Inventory
super attributes, options 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 ############################################################################# # Object Overrides #############################################################################
toString: -> toString: ->
return "#{@constructor.name} (#{@cid}) { return "#{@constructor.name} (#{@cid}) { plan:#{@plan}, step:#{@step} }"
name:#{@name},
quantity:#{@quantity},
includingTools:#{@includingTools},
have:#{@have},
plan:#{@plan}
}"