Skip to content

Commit

Permalink
convert to JavaScript
Browse files Browse the repository at this point in the history
  • Loading branch information
benatkin committed Jul 6, 2012
1 parent 9b8c16e commit 8886500
Show file tree
Hide file tree
Showing 15 changed files with 273 additions and 311 deletions.
25 changes: 7 additions & 18 deletions README.md
Expand Up @@ -61,22 +61,6 @@ Will compile to:
}
}

#Building & Testing retina.js

##How to build

We use [Coyote](http://imulus.github.com/coyote/) to stitch everything together. Install Coyote by running `gem install coyote`.

$ rake build

This will compile the CoffeeScript and put the new build in `build/retina.js`

During development, you can use:

$ rake watch

to keep an eye on the source files and automatically compile them to `test/functional/public`. Handy for testing in the browser.

##How to test

We use [mocha](http://visionmedia.github.com/mocha/) for unit testing with [should](https://github.com/visionmedia/should.js) assertions. Install mocha and should by running `npm install -g mocha should`.
Expand All @@ -85,19 +69,24 @@ To run the test suite:

$ mocha

We also have a [Sinatra](http://sinatrarb.com) app for testing in the browser locally. This is handy for testing on your retina devices.
Use [http-server](https://github.com/nodeapps/http-server) for node.js to test it.

If you've updated `retina.js` be sure to copy it from `src/retina.js` to `test/functional/public/retina.js`.

To start the server, run:

$ cd test/functional && ruby app.rb
$ cd test/functional && http-server

Then navigate your browser to [http://localhost:4567](http://localhost:4567)

After that, open up `test/functional/public/index.html` in your editor, and try commenting out the line that spoofs retina support, and reloading it.

#License

(MIT License)

Copyright (C) 2012 Ben Atkin

Copyright (C) 2012 [Imulus](http://imulus.com)

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
Expand Down
35 changes: 0 additions & 35 deletions Rakefile

This file was deleted.

14 changes: 0 additions & 14 deletions src/retina.coffee

This file was deleted.

114 changes: 114 additions & 0 deletions src/retina.js
@@ -0,0 +1,114 @@
// retina.js
// Source for retina.js, a high-resolution image swapper (http://www.retinajs.com)

(function() {

var root = (typeof exports == 'undefined' ? window : exports);

function RetinaImagePath(path) {
this.path = path;
// Split the file extension off the image path,
// and put it back together with @2x before the extension.
// "/path/to/image.png" => "/path/to/image@2x.png"
var path_segments = this.path.split('.');
var path_without_extension = path_segments.slice(0, (path_segments.length - 1)).join(".");
var extension = path_segments[path_segments.length - 1];
this.at_2x_path = path_without_extension + "@2x." + extension;
}

root.RetinaImagePath = RetinaImagePath;

// Class variable [Array]
// cache of files we've checked on the server
RetinaImagePath.confirmed_paths = [];

// Function to test if image is external
RetinaImagePath.prototype.is_external = function() {
return !!(this.path.match(/^https?\:/i) && !this.path.match('//' + document.domain) )
}

RetinaImagePath.prototype.has_2x_variant = function() {
var http;
if (this.is_external()) {
// If the image path is on an external server,
// exit early to avoid cross-domain ajax errors
return false;
} else if (this.at_2x_path in RetinaImagePath.confirmed_paths) {
// If we have already checked and confirmed that
// the @2x variant exists, then just return true
return true
} else {
// Otherwise, prepare an AJAX request for the HEAD only.
// We don't need a full request because we're only
// checking to see if the @2x version exists on the server
http = new XMLHttpRequest;
http.open('HEAD', this.at_2x_path, false);
http.send();

// If we get an A-OK from the server,
// push file path onto array of confirmed files
if (http.status >= 200 && http.status <= 399) {
RetinaImagePath.confirmed_paths.push(this.at_2x_path);
return true;
} else {
return false;
}
}
}

function RetinaImage(el) {
this.el = el;
this.path = new RetinaImagePath(this.el.getAttribute('src'));
if (this.path.has_2x_variant()) {
this.swap();
}
}

root.RetinaImage = RetinaImage;

// Method for swapping in a new image path
// Applies the dimensions of the existing image
// to the image with the new image path
RetinaImage.prototype.swap = function(path) {
if (typeof path == 'undefined') path = this.path.at_2x_path;

// We wrap this in a named self-executer so we can reference
// it in a setTimeout if the image has not loaded yet.
var that = this;
function load() {
if (! that.el.complete) {
// Check that the image has loaded.
// We need to wait for the image to load to grab proper dimensions.

// If it has not, try again in a few milliseconds.
// We've found 5ms to be the fastest we can crank this up
// and still have the script detect image loads reliably and efficiently.
setTimeout(load, 5);
} else {
// Once the the image has loaded we know we
// can grab the proper dimensions of the original image
// and go ahead and swap in the new image path and apply the dimensions
that.el.setAttribute('width', that.el.offsetWidth);
that.el.setAttribute('height', that.el.offsetHeight);
that.el.setAttribute('src', path);
}
}
load();
}

// First check that we're on a retina device.
// We don't even want this guy executing if we're not.
// Bind everything to the window object's onload.
// This helps wait for the images to get loaded into the DOM.

if (root.devicePixelRatio > 1) {
window.onload = function() {
var images = document.getElementsByTagName("img"), retinaImages = [], i, image;
for (i = 0; i < images.length; i++) {
image = images[i];
retinaImages.push(new RetinaImage(image));
}
}
}

})();
39 changes: 0 additions & 39 deletions src/retina_image.coffee

This file was deleted.

51 changes: 0 additions & 51 deletions src/retina_image_path.coffee

This file was deleted.

19 changes: 0 additions & 19 deletions test/fixtures/image.coffee

This file was deleted.

19 changes: 19 additions & 0 deletions test/fixtures/image.js
@@ -0,0 +1,19 @@
function Image() {
this.complete = true;
this.attributes = {
src : "/images/some_image.png",
offsetWidth : 500,
offsetHeight : 400
};
}

Image.prototype.setAttribute = function(name, value) {
this.attributes[name] = value;
}

Image.prototype.getAttribute = function(name) {
return this.attributes[name];
}

var root = (exports || window);
root.Image = Image;
12 changes: 0 additions & 12 deletions test/fixtures/xml_http_request.coffee

This file was deleted.

16 changes: 16 additions & 0 deletions test/fixtures/xml_http_request.js
@@ -0,0 +1,16 @@
function XMLHttpRequest() {
this.status = XMLHttpRequest.status;
}

XMLHttpRequest.status = 200;

XMLHttpRequest.prototype.open = function() {
return true;
}

XMLHttpRequest.prototype.send = function() {
return true;
}

var root = (exports || window);
root.XMLHttpRequest = XMLHttpRequest;
5 changes: 0 additions & 5 deletions test/functional/app.rb

This file was deleted.

0 comments on commit 8886500

Please sign in to comment.