Created
March 13, 2012 17:03
-
-
Save froots/2029936 to your computer and use it in GitHub Desktop.
Apple Image Replacer - prettified from http://images.apple.com/v/ipad/a/scripts/image_replacer.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
if (typeof (AC) === "undefined") { | |
AC = {} | |
} | |
AC.ImageReplacer = Class.create({ | |
_defaultOptions: { | |
listenToSwapView: true, | |
filenameRegex: /(.*)(\.[a-z]{3}($|#.*|\?.*))/i, | |
filenameInsert: "_☃x", | |
ignoreCheck: /(^http:\/\/movies\.apple\.com\/|\/105\/|\/global\/elements\/quicktime\/|_(([2-9]|[1-9][0-9]+)x|nohires)(\.[a-z]{3})($|#.*|\?.*))/i, | |
attribute: "data-hires", | |
recursive: true, | |
preload: false, | |
checkExists: true, | |
queueSize: 8, | |
debug: false | |
}, | |
_lowestPriority: 2, | |
__replacedAttribute: "data-hires-status", | |
initialize: function (b) { | |
if (typeof b !== "object") { | |
b = {} | |
} | |
this.options = Object.extend(Object.clone(this._defaultOptions), b); | |
this.options.lowestPriority = this._lowestPriority; | |
this.options.replacedAttribute = this.__replacedAttribute; | |
if ((this.options.debug !== true) && ((typeof AC.Detector !== "undefined" && AC.Detector.isMobile()) || (AC.ImageReplacer.devicePixelRatio() <= 1))) { | |
return | |
} | |
if (this.options.debug === true) { | |
AC.ImageReplacer._devicePixelRatio = 2 | |
} | |
Object.synthesize(this); | |
if (windowHasLoaded) { | |
this.__setup() | |
} else { | |
var a = this.__setup.bind(this); | |
Event.observe(window, "load", a) | |
} | |
}, | |
log: function () { | |
if (this.__canLog !== false && this.options.debug === true) { | |
var a = $A(arguments); | |
if (a.length < 2) { | |
a = a[0] | |
} | |
try { | |
console.log(a) | |
} catch (b) { | |
this.__canLog = false | |
} | |
} | |
}, | |
isReplaceable: function (c) { | |
if ((c.getAttribute(this.options.attribute) === "false") || (c.up("[" + this.options.attribute + '="false"]') && this.options.recursive === true)) { | |
return false | |
} | |
var a = (typeof c.responsiveImageObject === "undefined"); | |
if (c.tagName.toLowerCase() === "img") { | |
return a | |
} else { | |
if (c.hasClassName("imageLink") && c.tagName.toLowerCase() === "a") { | |
return true | |
} else { | |
var b = AC.ImageReplacer.Image.removeCSSURLSyntax(c.getStyle("background-image")); | |
return (((b.match(AC.ImageReplacer.normalImageTypeRegex) !== null) && a)) | |
} | |
} | |
}, | |
potentialElements: function (g, f) { | |
if (typeof g === "undefined") { | |
g = document.body | |
} | |
var b = $(g).getElementsBySelector("[" + this.options.attribute + "]"); | |
var a; | |
var c = function (h) { | |
if (typeof f === "undefined") { | |
return typeof g.up("[" + h + "]") !== "undefined" | |
} else { | |
return f.getAttribute(h) !== null || typeof f.up("[" + h + "]") !== "undefined" | |
} | |
}; | |
if (this.options.recursive === true) { | |
if (g !== document.body && c(this.options.attribute)) { | |
b = b.concat(g) | |
} | |
a = []; | |
var e = this.isReplaceable.bind(this); | |
var d = function (h) { | |
if (e(h)) { | |
a.push(h) | |
} | |
a = a.concat(this.replaceableElementsWithinElement(h)) | |
}.bind(this); | |
$A(b).each(d) | |
} else { | |
a = b | |
} | |
return a | |
}, | |
prioritize: function (a) { | |
var c = []; | |
var d = function (f) { | |
if (typeof f.responsiveImageObject !== "undefined") { | |
return | |
} | |
var e = new AC.ImageReplacer.Image(f, this.options); | |
if (e.hiResSrc() !== null && !e.isHiRes()) { | |
if (typeof c[e.priority()] === "undefined") { | |
c[e.priority()] = [] | |
} | |
c[e.priority()].push(e) | |
} else { | |
if (e.hiResSrc() && e.isHiRes()) { | |
e.setStatus("already-hires") | |
} else { | |
e.setStatus("not-replaceable") | |
} | |
} | |
}.bind(this); | |
$A(a).each(d); | |
var b; | |
for (b = this._lowestPriority; | |
b >= 0; b--) { | |
if (typeof c[b] === "undefined") { | |
c[b] = [] | |
} | |
} | |
return c.flatten() | |
}, | |
replaceableElementsWithinElement: function (d) { | |
d = $(d); | |
var a = this; | |
var b = d.descendants(); | |
var c = this.isReplaceable.bind(this); | |
return b.findAll(c) | |
}, | |
addToQueue: function (a) { | |
if (typeof this.__queues === "undefined") { | |
this.__queues = $A() | |
} | |
if (this.__queues.length === 0) { | |
this.__queues.push($A()) | |
} | |
this.__queues[this.__queues.length - 1].push(a) | |
}, | |
replace: function () { | |
if (typeof this.__queues === "undefined") { | |
this.__queues = $A() | |
} | |
if (this.__queues.length > 0 && this.__queues[0].length > 0) { | |
this.__queues.push($A()); | |
var a = this.replace.bind(this); | |
this.__replaceNextQueue(a) | |
} else { | |
this.log("There are no queues to replace") | |
} | |
}, | |
__replaceNextQueue: function (d) { | |
var a = this.__queues[0].reverse(); | |
var b = this.log.bind(this); | |
this.__queues.splice(0, 1); | |
var c = function () { | |
b("Found " + a.length + " elements to replace."); | |
var e = function () { | |
var f = a.pop(); | |
if (!f) { | |
b("No more images to start replacing."); | |
if (typeof d === "function") { | |
d() | |
} | |
d = Prototype.emptyFunction; | |
return | |
} | |
f.replace(function (g) { | |
b("Replaced image.", f.hiResSrc(), "status: " + f.status()); | |
e() | |
}) | |
}; | |
$R(0, this.options.queueSize - 1).each(e) | |
}.bind(this); | |
window.setTimeout(c, 10) | |
}, | |
__respondToSwapView: function (c) { | |
var b = c.event_data.data.incomingView.content; | |
var a = c.event_data.data.sender.view.view(); | |
var d = this.addToQueue.bind(this); | |
this.prioritize(this.potentialElements(b, a)).each(d); | |
this.replace() | |
}, | |
__setup: function () { | |
if (this.options.listenToSwapView === true && "Listener" in Event && typeof AC.ViewMaster !== "undefined") { | |
this.respondToSwapView = this.__respondToSwapView.bindAsEventListener(this); | |
Event.Listener.listenForEvent(AC.ViewMaster, "ViewMasterDidShowNotification", false, this.respondToSwapView) | |
} | |
var a = this.addToQueue.bind(this); | |
this.prioritize(this.potentialElements()).each(a); | |
this.replace() | |
} | |
}); | |
AC.ImageReplacer.normalImageTypeRegex = /(\.jpg($|#.*|\?.*)|\.png($|#.*|\?.*)|\.gif($|#.*|\?.*))/; | |
AC.ImageReplacer.devicePixelRatio = function () { | |
if (typeof AC.ImageReplacer._devicePixelRatio !== "undefined") { | |
return AC.ImageReplacer._devicePixelRatio | |
} | |
if ("devicePixelRatio" in window && window.devicePixelRatio > 1) { | |
return AC.ImageReplacer._devicePixelRatio = 2 | |
} else { | |
return AC.ImageReplacer._devicePixelRatio = 1 | |
} | |
}; | |
AC.ImageReplacer.Image = Class.create(Object.clone(AC.Synthesize), { | |
initialize: function (b, a) { | |
if (Object.isElement(b)) { | |
this._el = b; | |
this._tagName = this._el.tagName.toLowerCase(); | |
this.options = Object.extend(Object.clone(a), AC.ImageReplacer.Image.convertParametersToOptions(this.src())); | |
this.setStatus("considered"); | |
this.synthesize() | |
} | |
}, | |
__synthesizeSetter: Prototype.emptyFunction, | |
preload: function (b) { | |
if (this._isPreloaded) { | |
return true | |
} | |
this.setStatus("loading"); | |
var a = new Element("img"); | |
a.observe("load", function () { | |
this._isPreloaded = true; | |
this.width = a.width; | |
this.height = a.height; | |
this.setStatus("replaced"); | |
if (typeof b === "function") { | |
b() | |
} | |
}.bind(this)); | |
a.observe("error", function () { | |
this.setStatus("404"); | |
this._exists = false; | |
if (typeof b === "function") { | |
b() | |
} | |
}.bind(this)); | |
a.src = this.hiResSrc() | |
}, | |
replace: function (b) { | |
var a = this.replace.bind(this, b); | |
if (this._exists === false) { | |
this.setStatus("404"); | |
if (typeof b === "function") { | |
b(false) | |
} | |
return | |
} | |
if (this.options.checkExists === true && typeof this._exists === "undefined") { | |
return this.requestHeaders(a) | |
} | |
if (this.isImageLink()) { | |
this._el.setAttribute("href", this.hiResSrc()); | |
this.setStatus("replaced"); | |
if (typeof b === "function") { | |
b(true) | |
} | |
} else { | |
if ((this.options.preload === true || this._tagName !== "img") && this._isPreloaded !== true) { | |
return this.preload(a) | |
} | |
if (this._tagName === "img") { | |
this._el.setAttribute("src", this.hiResSrc()); | |
if ((this.options.preload !== true)) { | |
this.setStatus("loading"); | |
this._el.observe("load", function (c) { | |
this.setStatus("replaced"); | |
if (typeof b === "function") { | |
b(true) | |
} | |
}.bindAsEventListener(this)); | |
this._el.observe("error", function (c) { | |
this.setStatus("404"); | |
this._el.setAttribute("src", this.src()); | |
if (typeof b === "function") { | |
b(false) | |
} | |
}.bindAsEventListener(this)) | |
} | |
} else { | |
this._el.setStyle("background-image:url(" + this.hiResSrc() + ");"); | |
this._el.setStyle("background-size:" + (this.width / AC.ImageReplacer.devicePixelRatio()) + "px " + (this.height / AC.ImageReplacer.devicePixelRatio()) + "px;"); | |
if (typeof b === "function") { | |
b(true) | |
} | |
} | |
} | |
this._el.responsiveImageObject = this; | |
this.synthesize() | |
}, | |
requestHeaders: function (c) { | |
var a = this; | |
if (typeof a._headers === "undefined") { | |
var b = new XMLHttpRequest(); | |
var a = this; | |
src = this.hiResSrc().replace(/^http:\/\/.*\.apple\.com\//, "/"); | |
b.open("HEAD", src, true); | |
b.onreadystatechange = function () { | |
if (b.readyState == 4) { | |
if (b.status === 200) { | |
a._exists = true; | |
var f = b.getAllResponseHeaders(); | |
a._headers = { | |
src: src | |
}; | |
var d, e; | |
f = f.split("\r"); | |
for (d = 0; | |
d < f.length; d++) { | |
e = f[d].split(": "); | |
if (e.length > 1) { | |
a._headers[e[0].replace("\n", "")] = e[1] | |
} | |
} | |
} else { | |
a._exists = false; | |
a._headers = null | |
} | |
if (typeof c === "function") { | |
c(a._headers, a) | |
} | |
} | |
}; | |
b.send(null) | |
} else { | |
c(a._headers, a) | |
} | |
}, | |
requestFileSize: function (c) { | |
var b = this; | |
if (typeof b._fileSize === "undefined") { | |
var a = function (d) { | |
b._fileSize = parseFloat(d["Content-Length"]) / 1000; | |
if (typeof c === "function") { | |
c(b._fileSize, b) | |
} | |
}; | |
this.requestHeaders(a) | |
} else { | |
c(b._fileSize, b) | |
} | |
}, | |
src: function () { | |
if (typeof this._src !== "undefined") { | |
return this._src | |
} | |
if (this.isImageLink()) { | |
this._src = this._el.getAttribute("href") | |
} else { | |
if (this._tagName === "img") { | |
this._src = this._el.getAttribute("src") | |
} else { | |
this._src = AC.ImageReplacer.Image.removeCSSURLSyntax(this._el.getStyle("background-image")); | |
if (this._src === "none") { | |
return this._src = "" | |
} | |
} | |
} | |
return this._src | |
}, | |
hiResSrc: function () { | |
if (typeof this._hiResSrc !== "undefined") { | |
return this._hiResSrc | |
} | |
var a; | |
if (typeof this.options.hiresFormat === "string") { | |
a = this.src().match(/^(.*)((\.[a-z]{3})($|#.*|\?.*))/i); | |
if (a !== null && a.length > 1) { | |
return this._hiResSrc = a[1] + "." + this.options.hiresFormat + (a[4] || "") | |
} | |
} | |
a = this.src().match(this.options.filenameRegex); | |
if (a === null) { | |
return this._hiResSrc = null | |
} else { | |
return this._hiResSrc = a[1] + this.options.filenameInsert.replace("☃", AC.ImageReplacer.devicePixelRatio()) + a[2] | |
} | |
}, | |
isHiRes: function () { | |
if (this._isHiRes === true) { | |
return this._isHiRes | |
} | |
if (this.status() === "replaced") { | |
return this._isHiRes = true | |
} | |
var a = this.src(); | |
if (a.match(AC.ImageReplacer.normalImageTypeRegex) === null) { | |
return this._isHiRes = true | |
} | |
if (a.match(this.options.ignoreCheck) !== null) { | |
return this._isHiRes = true | |
} | |
this._isHiRes = false | |
}, | |
isImageLink: function () { | |
if (typeof this._isImageLink !== "undefined") { | |
return this._isImageLink | |
} | |
return this._isImageLink = (this._el.hasClassName("imageLink") && this._tagName === "a") | |
}, | |
priority: function () { | |
if (typeof this._priority !== "undefined") { | |
return this._priority | |
} | |
if (this.options.recursive && this._el.hasAttribute(this.options.attribute) === false) { | |
var a = this._el.up("[" + this.options.attribute + "]"); | |
if ( !! a) { | |
this._priority = parseInt(a.getAttribute(this.options.attribute)) | |
} else { | |
this._priority = this.options.lowestPriority | |
} | |
} else { | |
this._priority = parseInt(this._el.getAttribute(this.options.attribute)) | |
} | |
if (isNaN(this._priority) || this._priority > this.options.lowestPriority) { | |
this._priority = this.options.lowestPriority | |
} else { | |
if (this._priority < 0) { | |
this._priority = 0 | |
} | |
} | |
return this._priority | |
}, | |
setStatus: function (a) { | |
if (typeof a === "string") { | |
this._status = a; | |
this._el.setAttribute(this.options.replacedAttribute, a) | |
} | |
}, | |
status: function () { | |
return this._el.getAttribute(this.options.replacedAttribute) | |
} | |
}); | |
AC.ImageReplacer.Image.removeCSSURLSyntax = function (a) { | |
if (typeof a === "string" && typeof a.replace === "function") { | |
return a.replace(/^url\(/, "").replace(/\)$/, "") | |
} | |
return "" | |
}; | |
AC.ImageReplacer.Image.convertParametersToOptions = function (b) { | |
if (typeof b === "string" && typeof b.toQueryParams === "function") { | |
var a = b.toQueryParams(), | |
c; | |
for (c in a) { | |
if (a.hasOwnProperty(c)) { | |
a[c.camelize()] = a[c] | |
} | |
} | |
return a | |
} | |
return {} | |
}; | |
AC.ImageReplacer.autoInstance = new AC.ImageReplacer(); | |
var windowHasLoaded = false; | |
Event.observe(window, "load", function () { | |
windowHasLoaded = true | |
}); |
great. thank-you
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
thanks!