Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/master'
Browse files Browse the repository at this point in the history
Conflicts:
	package.json
	src/retina.js
  • Loading branch information
jbinney committed Jul 10, 2014
2 parents 77163e2 + a70e736 commit b81715c
Show file tree
Hide file tree
Showing 13 changed files with 492 additions and 149 deletions.
15 changes: 15 additions & 0 deletions .editorconfig
@@ -0,0 +1,15 @@
root = true

[*]
indent_style = space
indent_size = 4
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true

[*.{less,sass,scss,json}]
indent_size = 2

[*.md]
trim_trailing_whitespace = false
26 changes: 26 additions & 0 deletions .jshintrc
@@ -0,0 +1,26 @@
{
"bitwise": true,
"browser": true,
"curly": true,
"eqeqeq": true,
"es3": true,
"forin": true,
"freeze": true,
"immed": true,
"indent": 4,
"jquery": true,
"latedef": true,
"maxcomplexity": 6,
"maxdepth": 3,
"maxparams": 3,
"newcap": true,
"noarg": true,
"node": true,
"noempty": true,
"nonew": true,
"plusplus": true,
"quotmark": "single",
"trailing": true,
"undef": true,
"unused": true
}
3 changes: 1 addition & 2 deletions .travis.yml
@@ -1,7 +1,6 @@
language: node_js
node_js:
- 0.8
- 0.6
- "0.10"
notifications:
recipients:
- ci@imulus.com
83 changes: 83 additions & 0 deletions Gruntfile.js
@@ -0,0 +1,83 @@
module.exports = function (grunt) {
'use strict';

var addBanner = function (content) {
var banner = grunt.config.get('banner');
banner = grunt.template.process(banner);
return banner.concat('\n', content);
};

grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
year: (function () {
return new Date().getFullYear();
})(),
banner: '/*!\n' +
' * Retina.js v<%= pkg.version %>\n' +
' *\n' +
' * Copyright <%= year %> Imulus, LLC\n' +
' * Released under the MIT license\n' +
' *\n' +
' * Retina.js is an open source script that makes it easy to serve\n' +
' * high-resolution images to devices with retina displays.\n' +
' */\n',

clean: ['dist'],

jshint: {
options: {
trailing: true,
jshintrc: '.jshintrc'
},
grunt: {
src: 'Gruntfile.js'
},
src: {
src: 'src/*.js'
}
},

copy: {
js: {
src: 'src/retina.js',
dest: 'dist/retina.js',
options: {
process: addBanner
}
}
},

uglify: {
build: {
options: {
banner: '<%= banner %>'
},
files: {
'dist/retina.min.js': 'dist/retina.js'
}
}
},

compress: {
pkg: {
options: {
archive: 'dist/retina-<%= pkg.version %>.zip'
},
files: [{
src: ['**'],
cwd: 'dist/',
dest: '/',
expand: true
}]
}
}
});

grunt.loadNpmTasks('grunt-contrib-clean');
grunt.loadNpmTasks('grunt-contrib-compress');
grunt.loadNpmTasks('grunt-contrib-copy');
grunt.loadNpmTasks('grunt-contrib-jshint');
grunt.loadNpmTasks('grunt-contrib-uglify');

grunt.registerTask('default', ['clean', 'jshint', 'copy', 'uglify', 'compress']);
};
32 changes: 0 additions & 32 deletions Makefile

This file was deleted.

7 changes: 7 additions & 0 deletions README.md
Expand Up @@ -41,6 +41,13 @@ The JavaScript helper script automatically replaces images on your page with hig
<script type="text/javascript" src="/scripts/retina.js"></script>
```

You can also exlude an image, which has no high-res version. Simple add `data-no-retina`.


``` html
<img src="/path/to/image" data-no-retina />
```

###LESS & SASS

The LESS & SASS CSS mixins are helpers for applying high-resolution background images in your stylesheet. You provide it with an image path and the dimensions of the original-resolution image. The mixin creates a media query specifically for Retina displays, changes the background image for the selector elements to use the high-resolution (@2x) variant and applies a background-size of the original image in order to maintain proper dimensions. To use it, download the mixin, import or include it in your LESS or SASS stylesheet, and apply it to elements of your choice. The SASS versions require you pass the extension separately from the path.
Expand Down
17 changes: 17 additions & 0 deletions bower.json
@@ -0,0 +1,17 @@
{
"name": "retina.js",
"version": "1.2.0",
"homepage": "https://github.com/imulus/retinajs",
"authors": [
"Imulus, LLC <developer@imulus.com>"
],
"description": "JavaScript, Less and Sass helpers for rendering high-resolution image variants",
"main": "build/js/retina-1.2.0.js",
"license": "MIT",
"ignore": [
"**/.*",
"node_modules",
"bower_components",
"test"
]
}
Binary file added dist/retina-1.3.0.zip
Binary file not shown.
182 changes: 182 additions & 0 deletions dist/retina.js
@@ -0,0 +1,182 @@
/*!
* Retina.js v1.3.0
*
* Copyright 2014 Imulus, LLC
* Released under the MIT license
*
* Retina.js is an open source script that makes it easy to serve
* high-resolution images to devices with retina displays.
*/

(function() {
var root = (typeof exports === 'undefined' ? window : exports);
var config = {
// An option to choose a suffix for 2x images
retinaImageSuffix : '@2x',

// Ensure Content-Type is an image before trying to load @2x image
// https://github.com/imulus/retinajs/pull/45)
check_mime_type: true,

// Resize high-resolution images to original image's pixel dimensions
// https://github.com/imulus/retinajs/issues/8
force_original_dimensions: true
};

function Retina() {}

root.Retina = Retina;

Retina.configure = function(options) {
if (options === null) {
options = {};
}

for (var prop in options) {
if (options.hasOwnProperty(prop)) {
config[prop] = options[prop];
}
}
};

Retina.init = function(context) {
if (context === null) {
context = root;
}

var existing_onload = context.onload || function(){};

context.onload = function() {
var images = document.getElementsByTagName('img'), retinaImages = [], i, image;
for (i = 0; i < images.length; i += 1) {
image = images[i];
if (!!!image.getAttributeNode('data-no-retina')) {
retinaImages.push(new RetinaImage(image));
}
}
existing_onload();
};
};

Retina.isRetina = function(){
var mediaQuery = '(-webkit-min-device-pixel-ratio: 1.5), (min--moz-device-pixel-ratio: 1.5), (-o-min-device-pixel-ratio: 3/2), (min-resolution: 1.5dppx)';

if (root.devicePixelRatio > 1) {
return true;
}

if (root.matchMedia && root.matchMedia(mediaQuery).matches) {
return true;
}

return false;
};


var regexMatch = /\.\w+$/;
function suffixReplace (match) {
return config.retinaImageSuffix + match;
}

function RetinaImagePath(path, at_2x_path) {
this.path = path || '';
if (typeof at_2x_path !== 'undefined' && at_2x_path !== null) {
this.at_2x_path = at_2x_path;
this.perform_check = false;
} else {
if (undefined !== document.createElement) {
var locationObject = document.createElement('a');
locationObject.href = this.path;
locationObject.pathname = locationObject.pathname.replace(regexMatch, suffixReplace);
this.at_2x_path = locationObject.href;
} else {
var parts = this.path.split('?');
parts[0] = parts[0].replace(regexMatch, suffixReplace);
this.at_2x_path = parts.join('?');
}
this.perform_check = true;
}
}

root.RetinaImagePath = RetinaImagePath;

RetinaImagePath.confirmed_paths = [];

RetinaImagePath.prototype.is_external = function() {
return !!(this.path.match(/^https?\:/i) && !this.path.match('//' + document.domain) );
};

RetinaImagePath.prototype.check_2x_variant = function(callback) {
var http, that = this;
if (this.is_external()) {
return callback(false);
} else if (!this.perform_check && typeof this.at_2x_path !== 'undefined' && this.at_2x_path !== null) {
return callback(true);
} else if (this.at_2x_path in RetinaImagePath.confirmed_paths) {
return callback(true);
} else {
http = new XMLHttpRequest();
http.open('HEAD', this.at_2x_path);
http.onreadystatechange = function() {
if (http.readyState !== 4) {
return callback(false);
}

if (http.status >= 200 && http.status <= 399) {
if (config.check_mime_type) {
var type = http.getResponseHeader('Content-Type');
if (type === null || !type.match(/^image/i)) {
return callback(false);
}
}

RetinaImagePath.confirmed_paths.push(that.at_2x_path);
return callback(true);
} else {
return callback(false);
}
};
http.send();
}
};


function RetinaImage(el) {
this.el = el;
this.path = new RetinaImagePath(this.el.getAttribute('src'), this.el.getAttribute('data-at2x'));
var that = this;
this.path.check_2x_variant(function(hasVariant) {
if (hasVariant) {
that.swap();
}
});
}

root.RetinaImage = RetinaImage;

RetinaImage.prototype.swap = function(path) {
if (typeof path === 'undefined') {
path = this.path.at_2x_path;
}

var that = this;
function load() {
if (! that.el.complete) {
setTimeout(load, 5);
} else {
if (config.force_original_dimensions) {
that.el.setAttribute('width', that.el.offsetWidth);
that.el.setAttribute('height', that.el.offsetHeight);
}

that.el.setAttribute('src', path);
}
}
load();
};


if (Retina.isRetina()) {
Retina.init(root);
}
})();
10 changes: 10 additions & 0 deletions dist/retina.min.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit b81715c

Please sign in to comment.