summaryrefslogtreecommitdiff
path: root/jaws-assets-named.coffee
diff options
context:
space:
mode:
Diffstat (limited to 'jaws-assets-named.coffee')
-rw-r--r--jaws-assets-named.coffee456
1 files changed, 456 insertions, 0 deletions
diff --git a/jaws-assets-named.coffee b/jaws-assets-named.coffee
new file mode 100644
index 0000000..4a7a5df
--- /dev/null
+++ b/jaws-assets-named.coffee
@@ -0,0 +1,456 @@
+# LGPL-licensed, please consult jawsjs.com
+# conversion to coffeescript modification of src_assets.js from 'jawsjs.com' by Michele Bini
+
+# this supports named assets: like named:ImageName:image.png"
+
+jaws = ((jaws) ->
+
+ ###*
+ @fileOverview jaws.assets properties and functions
+
+ Loads and processes image, sound, video, and json assets
+ (Used internally by JawsJS to create <b>jaws.assets</b>)
+
+ @class Jaws.Assets
+ @constructor
+ @property {boolean} bust_cache Add a random argument-string to assets-urls when loading to bypass any cache
+ @property {boolean} fuchia_to_transparent Convert the color fuchia to transparent when loading .bmp-files
+ @property {boolean} image_to_canvas Convert all image assets to canvas internally
+ @property {string} root Rootdir from where all assets are loaded
+ @property {array} file_type Listing of file postfixes and their associated types
+ @property {array} can_play Listing of postfixes and (during runtime) populated booleans
+ ###
+
+ ###*
+ Returns the length of the resource list
+ @public
+ @returns {number} The length of the resource list
+ ###
+
+ ###*
+ Set root prefix-path to all assets
+
+ @example
+ jaws.assets.setRoot("music/").add(["music.mp3", "music.ogg"]).loadAll()
+
+ @public
+ @param {string} path-prefix for all following assets
+ @returns {object} self
+ ###
+
+ ###*
+ Get one or more resources from their URLs. Supports simple wildcard (you can end a string with "*").
+
+ @example
+ jaws.assets.add(["song.mp3", "song.ogg"])
+ jaws.assets.get("song.*") // -> Will return song.ogg in firefox and song.mp3 in IE
+
+ @public
+ @param {string|array} src The resource(s) to retrieve
+ @returns {array|object} Array or single resource if found in cache. Undefined otherwise.
+ ###
+
+ # Wildcard? song.*, match against asset-srcs, make sure it's loaded and return content of first match.
+
+ # TODO: self.loaded[src] is false for supported files for some odd reason.
+
+ ###*
+ Returns if specified resource is currently loading or not
+ @public
+ @param {string} src Resource URL
+ @return {boolean|undefined} If resource is currently loading. Otherwise, undefined.
+ ###
+
+ ###*
+ Returns if specified resource is loaded or not
+ @param src Source URL
+ @return {boolean|undefined} If specified resource is loaded or not. Otherwise, undefined.
+ ###
+
+ ###*
+ Returns lowercase postfix of specified resource
+ @public
+ @param {string} src Resource URL
+ @returns {string} Lowercase postfix of resource
+ ###
+
+ ###*
+ Determine type of file (Image, Audio, or Video) from its postfix
+ @private
+ @param {string} src Resource URL
+ @returns {string} Matching type {Image, Audio, Video} or the postfix itself
+ ###
+
+ ###*
+ Add URL(s) to asset listing for later loading
+ @public
+ @param {string|array|arguments} src The resource URL(s) to add to the asset listing
+ @example
+ jaws.assets.add("player.png")
+ jaws.assets.add(["media/bullet1.png", "media/bullet2.png"])
+ jaws.assets.add("foo.png", "bar.png")
+ jaws.assets.loadAll({onload: start_game})
+ ###
+
+ ###*
+ Iterate through the list of resource URL(s) and load each in turn.
+ @public
+ @param {Object} options Object-literal of callback functions
+ @config {function} [options.onprogress] The function to be called on progress (when one assets of many is loaded)
+ @config {function} [options.onerror] The function to be called if an error occurs
+ @config {function} [options.onload] The function to be called when finished
+ ###
+
+ ###*
+ Loads a single resource from its given URL
+ Will attempt to match a resource to known MIME types.
+ If unknown, loads the file as a blob-object.
+
+ @public
+ @param {string} src Resource URL
+ @param {Object} options Object-literal of callback functions
+ @config {function} [options.onload] Function to be called when assets has loaded
+ @config {function} [options.onerror] Function to be called if an error occurs
+ @example
+ jaws.load("media/foo.png")
+ jaws.load("http://place.tld/foo.png")
+ ###
+ # NOTE: assetLoaded can be called several times during loading.
+
+ #Load everything else as raw blobs...
+
+ # ... But don't load un-supported audio-files.
+
+ # Initial loading callback for all assets for parsing specific filetypes or
+ # optionally converting images to canvas-objects.
+ # @private
+ # @param {EventObject} event The EventObject populated by the calling event
+ # @see processCallbacks()
+
+ #
+ # * Only increment load_count ONCE per unique asset.
+ # * This is needed cause assetLoaded-callback can in certain cases be called several for a single asset...
+ # * ..and not only Once when it's loaded.
+ #
+
+ # Called when jaws asset-handler decides that an asset shouldn't be loaded
+ # For example, an unsupported audio-format won't be loaded.
+
+ # @private
+
+ # Increases the error count and calls processCallbacks with false flag set
+ # @see processCallbacks()
+ # @private
+ # @param {EventObject} event The EventObject populated by the calling event
+
+ # Processes (if set) the callbacks per resource
+ # @private
+ # @param {object} asset The asset to be processed
+ # @param {boolean} ok If an error has occured with the asset loading
+ # @param {EventObject} event The EventObject populated by the calling event
+ # @see jaws.start() in core.js
+
+ # Displays the progress of asset handling as an overall percentage of all loading
+ # (Can be overridden as jaws.assets.displayProgress = function(percent_done) {})
+ # @public
+ # @param {number} percent_done The overall percentage done across all resource handling
+
+ # Make Fuchia (0xFF00FF) transparent (BMPs ONLY)
+ # @private
+ # @param {HTMLImageElement} image The Bitmap Image to convert
+ # @returns {CanvasElement} canvas The translated CanvasElement
+
+ fuchiaToTransparent = (image) ->
+ return unless jaws.isDrawable(image)
+ canvas = (if jaws.isImage(image) then jaws.imageToCanvas(image) else image)
+ context = canvas.getContext("2d")
+ img_data = context.getImageData(0, 0, canvas.width, canvas.height)
+ pixels = img_data.data
+ i = 0
+
+ while i < pixels.length
+ # Color: Fuchia
+ pixels[i + 3] = 0 if pixels[i] is 255 and pixels[i + 1] is 0 and pixels[i + 2] is 255 # Set total see-through transparency
+ i += 4
+ context.putImageData img_data, 0, 0
+ canvas
+ jaws.Assets = Assets = ->
+ getType = (src) ->
+ if jaws.isString(src)
+ postfix = self.getPostfix(src)
+ (if self.file_type[postfix] then self.file_type[postfix] else postfix)
+ else
+ jaws.log.error "jaws.assets.getType: Argument not a String with " + src
+ return
+ assetLoaded = (event) ->
+ asset = @asset
+ src = asset.src
+ filetype = getType(asset.src)
+ try
+ if filetype is "json"
+ return if @readyState isnt 4
+ self.data[asset.src] = JSON.parse(@responseText)
+ else if filetype is "image"
+ new_image = (if self.image_to_canvas then jaws.imageToCanvas(asset.image) else asset.image)
+ new_image = fuchiaToTransparent(new_image) if self.fuchia_to_transparent and self.getPostfix(asset.src) is "bmp"
+ self.data[asset.src] = new_image
+ else if filetype is "audio" and self.can_play[self.getPostfix(asset.src)]
+ self.data[asset.src] = asset.audio
+ else if filetype is "video" and self.can_play[self.getPostfix(asset.src)]
+ self.data[asset.src] = asset.video
+ else
+ self.data[asset.src] = @response
+ catch e
+ jaws.log.error "Cannot process " + src + " (Message: " + e.message + ", Name: " + e.name + ")"
+ self.data[asset.src] = null
+ self.load_count++ unless self.loaded[src]
+ self.loaded[src] = true
+ self.loading[src] = false
+ processCallbacks asset, true, event
+ return
+ assetSkipped = (asset) ->
+ self.loaded[asset.src] = true
+ self.loading[asset.src] = false
+ self.load_count++
+ processCallbacks asset, true
+ return
+ assetError = (event) ->
+ asset = @asset
+ self.error_count++
+ processCallbacks asset, false, event
+ return
+ processCallbacks = (asset, ok, event) ->
+ percent = parseInt((self.load_count + self.error_count) / self.src_list.length * 100)
+ if ok
+ self.onprogress asset.src, percent if self.onprogress
+ asset.onprogress event if asset.onprogress and event isnt `undefined`
+ else
+ self.onerror asset.src, percent if self.onerror
+ asset.onerror event if asset.onerror and event isnt `undefined`
+ if percent is 100
+ self.onload() if self.onload
+ self.onprogress = null
+ self.onerror = null
+ self.onload = null
+ return
+ return new arguments.callee() unless this instanceof arguments.callee
+ self = this
+ self.loaded = []
+ self.loading = []
+ self.src_list = []
+ self.data = []
+ self.bust_cache = false
+ self.image_to_canvas = true
+ self.fuchia_to_transparent = true
+ self.root = ""
+ self.file_type = {}
+ self.file_type["json"] = "json"
+ self.file_type["wav"] = "audio"
+ self.file_type["mp3"] = "audio"
+ self.file_type["ogg"] = "audio"
+ self.file_type["m4a"] = "audio"
+ self.file_type["weba"] = "audio"
+ self.file_type["aac"] = "audio"
+ self.file_type["mka"] = "audio"
+ self.file_type["flac"] = "audio"
+ self.file_type["png"] = "image"
+ self.file_type["jpg"] = "image"
+ self.file_type["jpeg"] = "image"
+ self.file_type["gif"] = "image"
+ self.file_type["bmp"] = "image"
+ self.file_type["tiff"] = "image"
+ self.file_type["mp4"] = "video"
+ self.file_type["webm"] = "video"
+ self.file_type["ogv"] = "video"
+ self.file_type["mkv"] = "video"
+ self.can_play = {}
+ try
+ audioTest = new Audio()
+ self.can_play["wav"] = !!audioTest.canPlayType("audio/wav; codecs=\"1\"").replace(/^no$/, "")
+ self.can_play["ogg"] = !!audioTest.canPlayType("audio/ogg; codecs=\"vorbis\"").replace(/^no$/, "")
+ self.can_play["mp3"] = !!audioTest.canPlayType("audio/mpeg;").replace(/^no$/, "")
+ self.can_play["m4a"] = !!(audioTest.canPlayType("audio/x-m4a;") or audioTest.canPlayType("audio/aac;")).replace(/^no$/, "")
+ self.can_play["weba"] = !!audioTest.canPlayType("audio/webm; codecs=\"vorbis\"").replace(/^no$/, "")
+ self.can_play["aac"] = !!audioTest.canPlayType("audio/aac;").replace(/^no$/, "")
+ self.can_play["mka"] = !!audioTest.canPlayType("audio/x-matroska;").replace(/^no$/, "")
+ self.can_play["flac"] = !!audioTest.canPlayType("audio/x-flac;").replace(/^no$/, "")
+ try
+ videoTest = document.createElement("video")
+ self.can_play["mp4"] = !!videoTest.canPlayType("video/mp4;").replace(/^no$/, "")
+ self.can_play["webm"] = !!videoTest.canPlayType("video/webm; codecs=\"vorbis\"").replace(/^no$/, "")
+ self.can_play["ogv"] = !!videoTest.canPlayType("video/ogg; codecs=\"vorbis\"").replace(/^no$/, "")
+ self.can_play["mkv"] = !!videoTest.canPlayType("video/x-matroska;").replace(/^no$/, "")
+ self.length = ->
+ self.src_list.length
+
+ self.setRoot = (path) ->
+ self.root = path
+ self
+
+ self.get = (src) ->
+ if jaws.isArray(src)
+ src.map (i) ->
+ self.data[i]
+
+ else if jaws.isString(src)
+ if src[src.length - 1] is "*"
+ needle = src.replace("*", "")
+ i = 0
+
+ while i < self.src_list.length
+ return self.data[self.src_list[i]] if self.src_list[i].indexOf(needle) is 0 and self.data[self.src_list[i]]
+ i++
+ if self.data[src]
+ self.data[src]
+ else
+ jaws.log.warn "No such asset: " + src, true
+ else
+ jaws.log.error "jaws.get: Neither String nor Array. Incorrect URL resource " + src
+ return
+ return
+
+ self.isLoading = (src) ->
+ if jaws.isString(src)
+ self.loading[src]
+ else
+ jaws.log.error "jaws.isLoading: Argument not a String with " + src
+ return
+
+ self.isLoaded = (src) ->
+ if jaws.isString(src)
+ self.loaded[src]
+ else
+ jaws.log.error "jaws.isLoaded: Argument not a String with " + src
+ return
+
+ self.getPostfix = (src) ->
+ if jaws.isString(src)
+ src.toLowerCase().match(/.+\.([^?]+)(\?|$)/)[1]
+ else
+ jaws.log.error "jaws.assets.getPostfix: Argument not a String with " + src
+ return
+
+ self.add = (src) ->
+ list = arguments
+ list = list[0] if list.length is 1 and jaws.isArray(list[0])
+ i = 0
+
+ while i < list.length
+ if jaws.isArray(list[i])
+ self.add list[i]
+ else
+ if jaws.isString(list[i])
+ self.src_list.push list[i]
+ else
+ jaws.log.error "jaws.assets.add: Neither String nor Array. Incorrect URL resource " + src
+ i++
+ self
+
+ self.loadAll = (options) ->
+ self.load_count = 0
+ self.error_count = 0
+ self.onprogress = options.onprogress if options.onprogress and jaws.isFunction(options.onprogress)
+ self.onerror = options.onerror if options.onerror and jaws.isFunction(options.onerror)
+ self.onload = options.onload if options.onload and jaws.isFunction(options.onload)
+ self.src_list.forEach (item) ->
+ self.load item
+ return
+
+ self
+
+ self.load = (src, options) ->
+ options = {} unless options
+ unless jaws.isString(src)
+ jaws.log.error "jaws.assets.load: Argument not a String with " + src
+ return
+ asset = {}
+ resolved_src = ""
+ if parts =/^named:([^:]+):/.exec src
+ asset.name = parts[1]
+ src = src.substring parts[0].length
+ asset.src = src
+ asset.onload = options.onload
+ asset.onerror = options.onerror
+ self.loading[src] = true
+ parser = RegExp("^((f|ht)tp(s)?:)?//")
+ if /^[a-z][a-z0-9-]*:/.test(src)
+ resolved_src = asset.src
+ else
+ resolved_src = self.root + asset.src
+ resolved_src += "?" + parseInt(Math.random() * 10000000) if self.bust_cache
+ type = getType(asset.src)
+ if type is "image"
+ try
+ asset.image = new Image()
+ asset.image.asset = asset
+ asset.image.addEventListener "load", assetLoaded
+ asset.image.addEventListener "error", assetError
+ asset.image.src = resolved_src
+ catch e
+ jaws.log.error "Cannot load Image resource " + resolved_src + " (Message: " + e.message + ", Name: " + e.name + ")"
+ else if self.can_play[self.getPostfix(asset.src)]
+ if type is "audio"
+ try
+ asset.audio = new Audio()
+ asset.audio.asset = asset
+ asset.audio.addEventListener "error", assetError
+ asset.audio.addEventListener "canplay", assetLoaded
+ self.data[asset.src] = asset.audio
+ asset.audio.src = resolved_src
+ asset.audio.load()
+ catch e
+ jaws.log.error "Cannot load Audio resource " + resolved_src + " (Message: " + e.message + ", Name: " + e.name + ")"
+ else if type is "video"
+ try
+ asset.video = document.createElement("video")
+ asset.video.asset = asset
+ self.data[asset.src] = asset.video
+ asset.video.setAttribute "style", "display:none;"
+ asset.video.addEventListener "error", assetError
+ asset.video.addEventListener "canplay", assetLoaded
+ document.body.appendChild asset.video
+ asset.video.src = resolved_src
+ asset.video.load()
+ catch e
+ jaws.log.error "Cannot load Video resource " + resolved_src + " (Message: " + e.message + ", Name: " + e.name + ")"
+ else
+ if type is "audio" and not self.can_play[self.getPostfix(asset.src)]
+ assetSkipped asset
+ return self
+ try
+ req = new XMLHttpRequest()
+ req.asset = asset
+ req.onreadystatechange = assetLoaded
+ req.onerror = assetError
+ req.open "GET", resolved_src, true
+ req.responseType = "blob" if type isnt "json"
+ req.send null
+ catch e
+ jaws.log.error "Cannot load " + resolved_src + " (Message: " + e.message + ", Name: " + e.name + ")"
+ self
+
+ self.displayProgress = (percent_done) ->
+ return unless jaws.isNumber(percent_done)
+ return unless jaws.context
+ jaws.context.save()
+ jaws.context.fillStyle = "black"
+ jaws.context.fillRect 0, 0, jaws.width, jaws.height
+ jaws.context.fillStyle = "white"
+ jaws.context.strokeStyle = "white"
+ jaws.context.textAlign = "center"
+ jaws.context.strokeRect 50 - 1, (jaws.height / 2) - 30 - 1, jaws.width - 100 + 2, 60 + 2
+ jaws.context.fillRect 50, (jaws.height / 2) - 30, ((jaws.width - 100) / 100) * percent_done, 60
+ jaws.context.font = "11px verdana"
+ jaws.context.fillText "Loading... " + percent_done + "%", jaws.width / 2, jaws.height / 2 - 35
+ jaws.context.font = "11px verdana"
+ jaws.context.fillStyle = "#ccc"
+ jaws.context.textBaseline = "bottom"
+ jaws.context.fillText "powered by www.jawsjs.com", jaws.width / 2, jaws.height - 1
+ jaws.context.restore()
+ return
+
+ return
+
+ jaws.assets = new jaws.Assets()
+ jaws
+)(jaws or {})