Permalink
Browse files

convert to JavaScript

  • Loading branch information...
1 parent 9b8c16e commit 8886500d159dcdf0afc68b97798d645a4811bf0e @benatkin benatkin committed Jul 6, 2012
View
@@ -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`.
@@ -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:
View
@@ -1,35 +0,0 @@
-require 'fileutils'
-require 'zip/zip'
-require 'zip/zipfilesystem'
-require 'coyote'
-require 'coyote/rake'
-
-task :build do
- FileUtils.mkdir_p "build"
- Coyote.run "src/retina.coffee", "build/retina.js", :compress => true
- FileUtils.mkdir_p "test/functional/public"
- Coyote.run "src/retina.coffee", "test/functional/public/retina.js"
-end
-
-coyote :watch do |config|
- config.input = "src/retina.coffee"
- config.output = "test/functional/public/retina.js"
-end
-
-task :package => [:build] do
- tmp = "tmp/#{Time.now.to_i}"
- zip = "pkg/retina.zip"
-
- FileUtils.rm zip, :force => true
- FileUtils.mkdir_p tmp
- FileUtils.cp "README.md", "#{tmp}/README.md"
- FileUtils.cp "src/retina.less", "#{tmp}/retina.less"
- FileUtils.cp "build/retina.js", "#{tmp}/retina.js"
-
- Zip::ZipFile.open(zip, 'w') do |zipfile|
- Dir["#{tmp}/**/**"].reject { |f| f == zip }.each do |file|
- zipfile.add(file.sub(tmp+'/',''),file)
- end
- end
-end
-
View
@@ -1,14 +0,0 @@
-# retina.coffee
-# Source for retina.js, a high-resolution image swapper (http://www.retinajs.com)
-
-#= require retina_image.coffee
-
-
-# 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 window.devicePixelRatio > 1
- window.onload = ->
- new RetinaImage(image) for image in document.getElementsByTagName("img")
View
@@ -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));
+ }
+ }
+}
+
+})();
View
@@ -1,39 +0,0 @@
-#= require retina_image_path.coffee
-
-class RetinaImage
-
- constructor: (@el) ->
- @path = new RetinaImagePath(@el.getAttribute('src'))
- @swap() if @path.has_2x_variant()
-
-
-
- # Method for swapping in a new image path
- # Applies the dimensions of the existing image
- # to the image with the new image path
- swap: (path = @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.
- do load = =>
-
- # Check that the image has loaded.
- # We need to wait for the image to load to grab proper dimensions.
- unless @el.complete
-
- # 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
-
- # 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
- else
- @el.setAttribute('width', @el.offsetWidth)
- @el.setAttribute('height', @el.offsetHeight)
- @el.setAttribute('src', path)
-
-
-root = exports ? window
-root.RetinaImage = RetinaImage
@@ -1,51 +0,0 @@
-class RetinaImagePath
-
- # Class variable [Array]
- # cache of files we've checked on the server
- @confirmed_paths = []
-
-
- constructor: (@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"
- path_segments = @path.split('.')
- path_without_extension = path_segments.slice(0, (path_segments.length - 1)).join(".")
- extension = path_segments[path_segments.length - 1]
- @at_2x_path = "#{path_without_extension}@2x.#{extension}"
-
-
- # Function to test if image is external
- is_external: ->
- !!( @path.match(/^https?\:/i) and !@path.match('//' + document.domain) )
-
- has_2x_variant: ->
- # If the image path is on an external server,
- # exit early to avoid cross-domain ajax errors
- if @is_external()
- return false
-
- # If we have already checked and confirmed that
- # the @2x variant exists, then just return true
- else if @at_2x_path in RetinaImagePath.confirmed_paths
- return true
-
- # 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
- else
- http = new XMLHttpRequest
- http.open('HEAD', @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 in [200..399]
- RetinaImagePath.confirmed_paths.push @at_2x_path
- return true
- else
- return false
-
-
-root = exports ? window
-root.RetinaImagePath = RetinaImagePath
View
@@ -1,19 +0,0 @@
-class Image
-
- constructor: ->
- @complete = true
- @attributes =
- src : "/images/some_image.png"
- offsetWidth : 500
- offsetHeight : 400
-
- setAttribute: (name, value) ->
- @attributes[name] = value
-
- getAttribute: (name) ->
- return @attributes[name]
-
-
-
-root = exports ? window
-root.Image = Image
View
@@ -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;
@@ -1,12 +0,0 @@
-class XMLHttpRequest
- @status = 200
-
- constructor: ->
- @status = XMLHttpRequest.status
-
- open: -> true
-
- send: -> true
-
-root = exports ? window
-root.XMLHttpRequest = XMLHttpRequest
@@ -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;
View
@@ -1,5 +0,0 @@
-require 'sinatra'
-
-get '/' do
- erb :index
-end
Oops, something went wrong.

0 comments on commit 8886500

Please sign in to comment.