From c4338d2ae878a167c409e91dea6d1783fc7e30ba Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Wed, 18 Jul 2012 00:02:21 -0400 Subject: put away back --- static/js/src/imgcache.js | 141 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 141 insertions(+) create mode 100644 static/js/src/imgcache.js (limited to 'static/js/src/imgcache.js') diff --git a/static/js/src/imgcache.js b/static/js/src/imgcache.js new file mode 100644 index 0000000..9cffb1d --- /dev/null +++ b/static/js/src/imgcache.js @@ -0,0 +1,141 @@ + +/* + timb: + the ImgCache manages loading images and keeping track of image sizes... + it can be passed a bunch of urls to load and a callback that gets called when more images are ready + image loading can also be paused and started again. + there can be separate ImageCaches, eg, one for search result images, one for chat images (but they all share the actual image cache) + In theory it should also avoid a few http requests bc we can just dup DOM nodes for images that are already loaded that don't have cache headers (not sure tho, browsers probably pretty aggressive with that already) +*/ + +var ImgCache = { + "imgs": {}, // nodes indexed by url + "caches": {}, + + "init": function(name){ + // don't clear callback + var callback = emptyFunc + if (name in ImgCache.caches) + callback = ImgCache.caches[name].onImgsLoaded + delete ImgCache.caches[name] + + ImgCache.caches[name] = { + "loadAtATime": 10, + "urlsToLoad": [], + "imgsLoading": {}, + "imgsLoadingCounter" : 0, // a hack so i don't have to iterate over the object to always get its size... + "imgsLoaded": {}, + "onImgsLoaded": callback, + "paused": false + } + }, + + "add": function(name, urls){ + if (!(name in ImgCache.caches)) ImgCache.init(name) + if (!$.isArray(urls)) urls = [urls]; + + var cache = ImgCache.caches[name] + + urls.forEach(function(url){ + cache.urlsToLoad.push(url) + }) + + }, + + "config": function(name, cfg){ + if (!(name in ImgCache.caches)) ImgCache.init(name) + var cache = ImgCache.caches[name] + for(var key in cfg) + cache[key] = cfg[key] + }, + + "clear": function(name){ ImgCache.init(name) }, + "pause": function(name){ ImgCache.caches[name].paused = true }, + "unpause": function(name){ ImgCache.caches[name].paused = false }, + + "loadImages": function(cache){ + if (cache.paused) return; + + while(cache.urlsToLoad.length && cache.imgsLoadingCounter < cache.loadAtATime) { + var url = cache.urlsToLoad.shift() + if (url in ImgCache.imgs) { // already loading this image + var img = ImgCache.imgs[url] + if (img.complete) { + cache.imgsLoaded[url] = ImgCache.imgs[url] + } else if (!(url in cache.imgsLoading)) { + cache.imgsLoading[url] = ImgCache.imgs[url] + cache.imgsLoadingCounter += 1 + } + } else { + var img = new Image() + img.src = url + img.animated = (parseUri(url)["file"].toLowerCase().substr(-3) == "gif") ? true : false; + ImgCache.imgs[url] = img + cache.imgsLoading[url] = img + cache.imgsLoadingCounter += 1 + } + } + }, + "processLoadingImages": function(cache){ + for (var url in cache.imgsLoading) { + var img = cache.imgsLoading[url] + if (img.complete) { + cache.imgsLoaded[url] = img + delete cache.imgsLoading[url] + cache.imgsLoadingCounter -= 1 + } + } + }, + + "loader": function(){ + for (name in ImgCache.caches){ + var cache = ImgCache.caches[name] + ImgCache.processLoadingImages(cache) // move images from imgsLoading into imgsLoaded + ImgCache.loadImages(cache) // put new images in imgsLoading/imgsLoaded from urlsToLoad + for (var url in cache.imgsLoaded) { + cache.onImgsLoaded(cache.imgsLoaded) // only call if new images actually loaded + delete cache.imgsLoaded + cache.imgsLoaded = {} + break; + } + + } + setTimeout(ImgCache.loader, 500) + } +} + +ImgCache.loader() + + +// parseUri 1.2.2 from http://blog.stevenlevithan.com/archives/parseuri +// (c) Steven Levithan , MIT License +// timb: todo: this can't deal with @s in urls correctly. ex: http://www.classicbattletech.com/images/gallery/Combat_Operations_Cover@1280x960.jpg +function parseUri (str) { + var o = parseUri.options, + m = o.parser[o.strictMode ? "strict" : "loose"].exec(str), + uri = {}, + i = 14; + + while (i--) uri[o.key[i]] = m[i] || ""; + + uri[o.q.name] = {}; + uri[o.key[12]].replace(o.q.parser, function ($0, $1, $2) { + if ($1) uri[o.q.name][$1] = $2; + }); + + return uri; +}; + +parseUri.options = { + strictMode: false, + key: ["source","protocol","authority","userInfo","user","password","host","port","relative","path","directory","file","query","anchor"], + q: { + name: "queryKey", + parser: /(?:^|&)([^&=]*)=?([^&]*)/g + }, + parser: { + strict: /^(?:([^:\/?#]+):)?(?:\/\/((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?))?((((?:[^?#\/]*\/)*)([^?#]*))(?:\?([^#]*))?(?:#(.*))?)/, + loose: /^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/ + } +}; +// end parseUri -- cgit v1.2.3-70-g09d2