retinajs-rails 0.2 → 2.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: b543d7cfda51df21fe2c7633829f99e8187e0d8d
4
- data.tar.gz: 278d5c80eca30acf827d357a26d7abf2a7fbdcaf
3
+ metadata.gz: d7d7b055ab3b02ec01c58e348d388f2d588b8439
4
+ data.tar.gz: 712146e59a0f9842d5465237a6a00509b3718151
5
5
  SHA512:
6
- metadata.gz: 121d8b255c47c3e5d561cc77f272ad244ec0bc31ff2789b198965720f52029d38657f16a53502db3e6710de58800a176c60f38a3ba0d987a0c6f8a132d98e2ef
7
- data.tar.gz: e2d1b3be8a6d4e9ed9f10469d38e089284daa6e4f226d83dcbfe1d2fe5445fbf10c7de510c6a717b341c36427c047d7f092381442940377e5d8c3dd9a05734a6
6
+ metadata.gz: 9276307acb3d2290994064a38f9305c5f2b86b844f726c6a124786eaff2280ed6f5243cd104a35b0a9b90be714414047b1df541a45dccb28b8047e02d92363b8
7
+ data.tar.gz: 0e3a00adb827256b814320bee9e2c33893084931d066b4b25b5ac9d94aac5cba8a8223fdce707faa2f499c2bfbb363cec3ac066fefd18314f5064f377cac85f1
data/README.md CHANGED
@@ -8,7 +8,7 @@ Retina.js is an awesome and simple plugin for rendering retina images for displa
8
8
 
9
9
  Add this line to your application's Gemfile:
10
10
 
11
- gem "retinajs-rails", "~> 0.1"
11
+ gem "retinajs-rails", "~> 2.1"
12
12
 
13
13
  And then execute:
14
14
 
@@ -1,182 +1,253 @@
1
1
  /*!
2
- * Retina.js v1.3.0
2
+ * Retina.js v2.1.0
3
3
  *
4
- * Copyright 2014 Imulus, LLC
4
+ * Copyright 2016 Axial, LLC
5
5
  * Released under the MIT license
6
6
  *
7
7
  * Retina.js is an open source script that makes it easy to serve
8
8
  * high-resolution images to devices with retina displays.
9
9
  */
10
+ 'use strict';
10
11
 
11
- (function() {
12
- var root = (typeof exports === 'undefined' ? window : exports);
13
- var config = {
14
- // An option to choose a suffix for 2x images
15
- retinaImageSuffix : '@2x',
16
-
17
- // Ensure Content-Type is an image before trying to load @2x image
18
- // https://github.com/imulus/retinajs/pull/45)
19
- check_mime_type: true,
20
-
21
- // Resize high-resolution images to original image's pixel dimensions
22
- // https://github.com/imulus/retinajs/issues/8
23
- force_original_dimensions: true
24
- };
25
-
26
- function Retina() {}
27
-
28
- root.Retina = Retina;
29
-
30
- Retina.configure = function(options) {
31
- if (options === null) {
32
- options = {};
33
- }
34
-
35
- for (var prop in options) {
36
- if (options.hasOwnProperty(prop)) {
37
- config[prop] = options[prop];
38
- }
39
- }
40
- };
41
-
42
- Retina.init = function(context) {
43
- if (context === null) {
44
- context = root;
45
- }
46
-
47
- var existing_onload = context.onload || function(){};
48
-
49
- context.onload = function() {
50
- var images = document.getElementsByTagName('img'), retinaImages = [], i, image;
51
- for (i = 0; i < images.length; i += 1) {
52
- image = images[i];
53
- if (!!!image.getAttributeNode('data-no-retina')) {
54
- retinaImages.push(new RetinaImage(image));
55
- }
56
- }
57
- existing_onload();
58
- };
59
- };
12
+ Object.defineProperty(exports, "__esModule", {
13
+ value: true
14
+ });
15
+ /*
16
+ * Determine whether or not `window` is available.
17
+ */
18
+ var hasWindow = typeof window !== 'undefined';
60
19
 
61
- Retina.isRetina = function(){
62
- 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)';
20
+ /*
21
+ * Get the device pixel ratio per our environment.
22
+ * Default to 1.
23
+ */
24
+ var environment = hasWindow ? window.devicePixelRatio || 1 : 1;
63
25
 
64
- if (root.devicePixelRatio > 1) {
65
- return true;
66
- }
26
+ /*
27
+ * Define a pattern for capturing src url suffixes.
28
+ */
29
+ var srcReplace = /(\.[A-z]{3,4}\/?(\?.*)?)$/;
30
+ var inlineReplace = /url\(('|")?([^\)'"]+)('|")?\)/i;
67
31
 
68
- if (root.matchMedia && root.matchMedia(mediaQuery).matches) {
69
- return true;
70
- }
32
+ /*
33
+ * Define our selectors for elements to target.
34
+ */
35
+ var selector = '[data-rjs]';
71
36
 
72
- return false;
73
- };
37
+ /*
38
+ * Define the attribute we'll use to mark an image as having been processed.
39
+ */
40
+ var processedAttr = 'data-rjs-processed';
74
41
 
42
+ /**
43
+ * Shortcut for turning some iterable object into an array.
44
+ *
45
+ * @param {Iterable} object Any iterable object.
46
+ *
47
+ * @return {Array}
48
+ */
49
+ function arrayify(object) {
50
+ return Array.prototype.slice.call(object);
51
+ }
75
52
 
76
- var regexMatch = /\.\w+$/;
77
- function suffixReplace (match) {
78
- return config.retinaImageSuffix + match;
53
+ /**
54
+ * Chooses the actual image size to fetch, (for example 2 or 3) that
55
+ * will be used to create a suffix like "@2x" or "@3x".
56
+ *
57
+ * @param {String|Number} cap The number the user provided indicating that
58
+ * they have prepared images up to this size.
59
+ *
60
+ * @return {Number} The number we'll be using to create a suffix.
61
+ */
62
+ function chooseCap(cap) {
63
+ var numericCap = parseInt(cap, 10);
64
+
65
+ /*
66
+ * If the environment's device pixel ratio is less than what the user
67
+ * provided, we'll only grab images at that size.
68
+ */
69
+ if (environment < numericCap) {
70
+ return environment;
71
+
72
+ /*
73
+ * If the device pixel ratio is greater than or equal to what the
74
+ * user provided, we'll use what the user provided.
75
+ */
76
+ } else {
77
+ return numericCap;
79
78
  }
79
+ }
80
80
 
81
- function RetinaImagePath(path, at_2x_path) {
82
- this.path = path || '';
83
- if (typeof at_2x_path !== 'undefined' && at_2x_path !== null) {
84
- this.at_2x_path = at_2x_path;
85
- this.perform_check = false;
86
- } else {
87
- if (undefined !== document.createElement) {
88
- var locationObject = document.createElement('a');
89
- locationObject.href = this.path;
90
- locationObject.pathname = locationObject.pathname.replace(regexMatch, suffixReplace);
91
- this.at_2x_path = locationObject.href;
92
- } else {
93
- var parts = this.path.split('?');
94
- parts[0] = parts[0].replace(regexMatch, suffixReplace);
95
- this.at_2x_path = parts.join('?');
96
- }
97
- this.perform_check = true;
98
- }
81
+ /**
82
+ * Makes sure that, since we are going to swap out the source of an image,
83
+ * the image does not change size on the page.
84
+ *
85
+ * @param {Element} image An image element in the DOM.
86
+ *
87
+ * @return {Element} The same element that was passed in.
88
+ */
89
+ function forceOriginalDimensions(image) {
90
+ if (!image.hasAttribute('data-no-resize')) {
91
+ if (image.offsetWidth === 0 && image.offsetHeight === 0) {
92
+ image.setAttribute('width', image.naturalWidth);
93
+ image.setAttribute('height', image.naturalHeight);
94
+ } else {
95
+ image.setAttribute('width', image.offsetWidth);
96
+ image.setAttribute('height', image.offsetHeight);
99
97
  }
100
-
101
- root.RetinaImagePath = RetinaImagePath;
102
-
103
- RetinaImagePath.confirmed_paths = [];
104
-
105
- RetinaImagePath.prototype.is_external = function() {
106
- return !!(this.path.match(/^https?\:/i) && !this.path.match('//' + document.domain) );
107
- };
108
-
109
- RetinaImagePath.prototype.check_2x_variant = function(callback) {
110
- var http, that = this;
111
- if (this.is_external()) {
112
- return callback(false);
113
- } else if (!this.perform_check && typeof this.at_2x_path !== 'undefined' && this.at_2x_path !== null) {
114
- return callback(true);
115
- } else if (this.at_2x_path in RetinaImagePath.confirmed_paths) {
116
- return callback(true);
117
- } else {
118
- http = new XMLHttpRequest();
119
- http.open('HEAD', this.at_2x_path);
120
- http.onreadystatechange = function() {
121
- if (http.readyState !== 4) {
122
- return callback(false);
123
- }
124
-
125
- if (http.status >= 200 && http.status <= 399) {
126
- if (config.check_mime_type) {
127
- var type = http.getResponseHeader('Content-Type');
128
- if (type === null || !type.match(/^image/i)) {
129
- return callback(false);
130
- }
131
- }
132
-
133
- RetinaImagePath.confirmed_paths.push(that.at_2x_path);
134
- return callback(true);
135
- } else {
136
- return callback(false);
137
- }
138
- };
139
- http.send();
140
- }
141
- };
142
-
143
-
144
- function RetinaImage(el) {
145
- this.el = el;
146
- this.path = new RetinaImagePath(this.el.getAttribute('src'), this.el.getAttribute('data-at2x'));
147
- var that = this;
148
- this.path.check_2x_variant(function(hasVariant) {
149
- if (hasVariant) {
150
- that.swap();
151
- }
152
- });
98
+ }
99
+ return image;
100
+ }
101
+
102
+ /**
103
+ * Determines whether the retina image actually exists on the server.
104
+ * If so, swaps out the retina image for the standard one. If not,
105
+ * leaves the original image alone.
106
+ *
107
+ * @param {Element} image An image element in the DOM.
108
+ * @param {String} newSrc The url to the retina image.
109
+ *
110
+ * @return {undefined}
111
+ */
112
+ function setSourceIfAvailable(image, retinaURL) {
113
+ var imgType = image.nodeName.toLowerCase();
114
+
115
+ /*
116
+ * Create a new image element and give it a load listener. When the
117
+ * load listener fires, it means the URL is correct and we will then
118
+ * attach it to the user's image.
119
+ */
120
+ var testImage = document.createElement('img');
121
+ testImage.addEventListener('load', function () {
122
+ /*
123
+ * If we're dealing with an image tag, force it's dimensions
124
+ * and set the source attribute. If not, go after the background-image
125
+ * inline style.
126
+ */
127
+ if (imgType === 'img') {
128
+ forceOriginalDimensions(image).setAttribute('src', retinaURL);
129
+ } else {
130
+ image.style.backgroundImage = 'url(' + retinaURL + ')';
153
131
  }
132
+ });
133
+
134
+ /*
135
+ * Attach the retina URL to our proxy image to load in the new
136
+ * image resource.
137
+ */
138
+ testImage.setAttribute('src', retinaURL);
139
+
140
+ /*
141
+ * Mark our image as processed so that it won't be processed again.
142
+ */
143
+ image.setAttribute(processedAttr, true);
144
+ }
145
+
146
+ /**
147
+ * Attempts to do an image url swap on a given image.
148
+ *
149
+ * @param {Element} image An image in the DOM.
150
+ * @param {String} src The original image source attribute.
151
+ * @param {String|Number} rjs The pixel density cap for images provided.
152
+ *
153
+ * @return {undefined}
154
+ */
155
+ function dynamicSwapImage(image, src) {
156
+ var rjs = arguments.length <= 2 || arguments[2] === undefined ? 1 : arguments[2];
157
+
158
+ var cap = chooseCap(rjs);
159
+
160
+ /*
161
+ * Don't do anything if the cap is less than 2 or there is no src.
162
+ */
163
+ if (src && cap > 1) {
164
+ var newSrc = src.replace(srcReplace, '@' + cap + 'x$1');
165
+ setSourceIfAvailable(image, newSrc);
166
+ }
167
+ }
168
+
169
+ /**
170
+ * Performs an image url swap on a given image with a provided url.
171
+ *
172
+ * @param {Element} image An image in the DOM.
173
+ * @param {String} src The original image source attribute.
174
+ * @param {String} hdsrc The path for a 2x image.
175
+ *
176
+ * @return {undefined}
177
+ */
178
+ function manualSwapImage(image, src, hdsrc) {
179
+ if (environment > 1) {
180
+ setSourceIfAvailable(image, hdsrc);
181
+ }
182
+ }
183
+
184
+ /**
185
+ * Collects all images matching our selector, and converts our
186
+ * NodeList into an Array so that Array methods will be available to it.
187
+ *
188
+ * @param {Iterable} images Optional. An Array, jQuery selection, or NodeList
189
+ * of elements to affect with retina.js.
190
+ *
191
+ * @return {Iterable} Contains all elements matching our selector.
192
+ */
193
+ function getImages(images) {
194
+ if (!images) {
195
+ return typeof document !== 'undefined' ? arrayify(document.querySelectorAll(selector)) : [];
196
+ } else {
197
+ return typeof images.forEach === 'function' ? images : arrayify(images);
198
+ }
199
+ }
200
+
201
+ /**
202
+ * Converts a string like "url(hello.png)" into "hello.png".
203
+ *
204
+ * @param {Element} img An HTML element with a background image.
205
+ *
206
+ * @return {String}
207
+ */
208
+ function cleanBgImg(img) {
209
+ return img.style.backgroundImage.replace(inlineReplace, '$2');
210
+ }
211
+
212
+ /**
213
+ * Gets all participating images and dynamically swaps out each one for its
214
+ * retina equivalent taking into account the environment capabilities and
215
+ * the densities for which the user has provided images.
216
+ *
217
+ * @param {Iterable} images Optional. An Array, jQuery selection, or NodeList
218
+ * of elements to affect with retina.js. If not
219
+ * provided, retina.js will grab all images on the
220
+ * page.
221
+ *
222
+ * @return {undefined}
223
+ */
224
+ function retina(images) {
225
+ getImages(images).forEach(function (img) {
226
+ if (!img.getAttribute(processedAttr)) {
227
+ var isImg = img.nodeName.toLowerCase() === 'img';
228
+ var src = isImg ? img.getAttribute('src') : cleanBgImg(img);
229
+ var rjs = img.getAttribute('data-rjs');
230
+ var rjsIsNumber = !isNaN(parseInt(rjs, 10));
231
+
232
+ /*
233
+ * If the user provided a number, dynamically swap out the image.
234
+ * If the user provided a url, do it manually.
235
+ */
236
+ if (rjsIsNumber) {
237
+ dynamicSwapImage(img, src, rjs);
238
+ } else {
239
+ manualSwapImage(img, src, rjs);
240
+ }
241
+ }
242
+ });
243
+ }
154
244
 
155
- root.RetinaImage = RetinaImage;
156
-
157
- RetinaImage.prototype.swap = function(path) {
158
- if (typeof path === 'undefined') {
159
- path = this.path.at_2x_path;
160
- }
161
-
162
- var that = this;
163
- function load() {
164
- if (! that.el.complete) {
165
- setTimeout(load, 5);
166
- } else {
167
- if (config.force_original_dimensions) {
168
- that.el.setAttribute('width', that.el.offsetWidth);
169
- that.el.setAttribute('height', that.el.offsetHeight);
170
- }
171
-
172
- that.el.setAttribute('src', path);
173
- }
174
- }
175
- load();
176
- };
177
-
245
+ /*
246
+ * If this environment has `window`, activate the plugin.
247
+ */
248
+ if (hasWindow) {
249
+ window.addEventListener('load', retina);
250
+ window.retinajs = retina;
251
+ }
178
252
 
179
- if (Retina.isRetina()) {
180
- Retina.init(root);
181
- }
182
- })();
253
+ exports.default = retina;
@@ -1,20 +1,102 @@
1
- // retina.sass
1
+ // retina.scss
2
2
  // A helper mixin for applying high-resolution background images (http://www.retinajs.com)
3
3
 
4
4
  // Submitted by Nathan Crank
5
5
  // nathancrank.com
6
6
 
7
- @mixin at2x($path, $ext: "jpg", $w: auto, $h: auto) {
8
- $at1x_path: "#{$path}.#{$ext}";
9
- $at2x_path: "#{$path}@2x.#{$ext}";
7
+ // Updated by Gabriel R. Sezefredo
8
+ // gabriel.sezefredo.com.br
10
9
 
11
- background-image: image-url("#{$at1x_path}");
10
+ // Updated by John Newman
11
+ // github.com/jgnewman
12
+ // http://axial.agency
12
13
 
13
- @media all and (-webkit-min-device-pixel-ratio : 1.5),
14
- all and (-o-min-device-pixel-ratio: 3/2),
15
- all and (min--moz-device-pixel-ratio: 1.5),
16
- all and (min-device-pixel-ratio: 1.5) {
17
- background-image: image-url("#{$at2x_path}");
18
- background-size: $w $h;
14
+
15
+ /**
16
+ * Allows you to use retina images at various pixel densities.
17
+ * Examples:
18
+ *
19
+ * @include retina(/images/mypic.jpg, 2);
20
+ * @include retina(/images/mypic.jpg, 3, 100px 100px, left top no-repeat transparent);
21
+ *
22
+ * @param {Value} $path The path to the file name minus extension.
23
+ * @param {Number} $cap: 2 The highest pixel density level images exist for.
24
+ * @param {Value} $size: auto auto The intended width of the rendered image.
25
+ * @param {Value} $extras: null Any other `background` values to be added.
26
+ */
27
+ @mixin retina($path, $cap: 2, $size: auto auto, $extras: null) {
28
+
29
+ /*
30
+ * Set a counter and get the length of the image path.
31
+ */
32
+ $position: -1;
33
+ $strpath: '#{$path}';
34
+ $length: str-length($strpath);
35
+
36
+ /*
37
+ * Loop ver the image path and figure out the
38
+ * position of the dot where the extension begins.
39
+ */
40
+ @for $i from $length through $length - 10{
41
+ @if $position == -1 {
42
+ $char : str-slice($strpath, $i, $i);
43
+ @if str-index($char, ".") == 1 {
44
+ $position: $i;
45
+ }
46
+ }
47
+ }
48
+
49
+ /*
50
+ * If we were able to figure out where the extension is,
51
+ * slice the path into a base and an extension. Use that to
52
+ * calculate urls for different density environments. Set
53
+ * values for different environments.
54
+ */
55
+ @if $position != -1 {
56
+ $ext: str-slice($strpath, $position + 1, $length);
57
+ $base: str-slice($strpath, 1, $position - 1);
58
+ $at1x_path: "#{$base}.#{$ext}";
59
+ $at2x_path: "#{$base}@2x.#{$ext}";
60
+
61
+ /*
62
+ * Set a base background for 1x environments.
63
+ */
64
+ background: url("#{$at1x_path}") $extras;
65
+ background-size: $size;
66
+
67
+ /*
68
+ * Create an @2x-ish media query.
69
+ */
70
+ @media all and (-webkit-min-device-pixel-ratio : 1.5),
71
+ all and (-o-min-device-pixel-ratio: 3/2),
72
+ all and (min--moz-device-pixel-ratio: 1.5),
73
+ all and (min-device-pixel-ratio: 1.5) {
74
+ background : url("#{$at2x_path}") $extras;
75
+ background-size : $size;
76
+ }
77
+
78
+ /*
79
+ * Create media queries for all environments that the user has
80
+ * provided images for.
81
+ */
82
+ @if $cap >= 2 {
83
+ @for $env from 2 through $cap {
84
+ $suffix: "@#{$env}x";
85
+ @media (-webkit-min-device-pixel-ratio: $env),
86
+ (min-resolution: $env * 96dpi) {
87
+ background : url("#{$base}#{$suffix}.#{$ext}") $extras;
88
+ background-size : $size;
89
+ }
90
+ }
91
+ }
92
+
93
+ /*
94
+ * If anything went wrong trying to separate the file from its
95
+ * extension, set a background value without doing anything to it.
96
+ */
97
+ } @else {
98
+ background: url("#{$path}") $extras;
99
+ background-size: $size;
19
100
  }
101
+
20
102
  }
@@ -2,7 +2,7 @@
2
2
 
3
3
  Gem::Specification.new do |gem|
4
4
  gem.name = 'retinajs-rails'
5
- gem.version = '0.2'
5
+ gem.version = '2.1'
6
6
  gem.date = Date.today
7
7
  gem.authors = ["Joshua Jansen"]
8
8
  gem.email = ["joshuajansen88@gmail.com"]
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: retinajs-rails
3
3
  version: !ruby/object:Gem::Version
4
- version: '0.2'
4
+ version: '2.1'
5
5
  platform: ruby
6
6
  authors:
7
7
  - Joshua Jansen
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-02-05 00:00:00.000000000 Z
11
+ date: 2016-07-14 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Adds retina.js assets and image helpers to your Rails app
14
14
  email: