Skip to content
This repository was archived by the owner on Jan 26, 2024. It is now read-only.

Commit 7a52034

Browse files
authored
Merge pull request #21 from benox3/noscript
Add noscript image to use high quality image and modify bundling
2 parents 40b4e07 + a8dceab commit 7a52034

13 files changed

+242
-62
lines changed

README.md

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,10 @@ npm install react-pic --save
1919

2020
#### CDN:
2121
```html
22-
<script src='https://unpkg.com/[email protected]/dist/react-pic.js'></script>
22+
<script src='https://unpkg.com/[email protected]/dist/umd/react-pic.js'></script>
2323

2424
<!-- or use minified -->
25-
<script src='https://unpkg.com/[email protected]/dist/react-pic.min.js'></script>
25+
<script src='https://unpkg.com/[email protected]/dist/umd/react-pic.min.js'></script>
2626
```
2727

2828
## Usage
@@ -53,7 +53,9 @@ export default class Example extends Component {
5353
| name | required | type | description |
5454
|--------------|----------|--------|----------------------------------------------------------------------------------------------------------------------------|
5555
| images | true | Array | The collection of images you would like to use as a source. |
56-
| defaultIndex | false | Number | The image object to use on initial render. |
56+
| alt | false | string | Text equivalent of the image. https://www.w3.org/QA/Tips/altAttribute |
57+
| defaultIndex | false | Number | The image object to use on initial render. **Default is 0** |
58+
| noscriptIndex | false | Number | The image object to use on noscript render. **Default is last image in images** |
5759
| style | false | Object | Override the style object. **This will remove the default style:** `{ margin: '0 auto', maxWidth: '100%', width: '100%' }` |
5860

5961
## Testing

lib/ImageClient.js

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import React, { Component } from 'react';
2+
3+
export default class ImageClient extends Component {
4+
render() {
5+
const { alt, style, image } = this.props;
6+
7+
return (
8+
<img
9+
alt={alt}
10+
style={style}
11+
src={image.url} />
12+
);
13+
}
14+
}

lib/ImageServer.js

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import React, { Component } from 'react';
2+
import NoScriptImg from './NoScriptImg';
3+
4+
export default class ImageServer extends Component {
5+
render() {
6+
const { alt, style, image, noScriptImage } = this.props;
7+
8+
return (
9+
<div>
10+
<NoScriptImg
11+
alt={alt}
12+
image={noScriptImage}
13+
style={style} />
14+
15+
<img
16+
alt={alt}
17+
style={style}
18+
src={image.url} />
19+
</div>
20+
);
21+
}
22+
}

lib/NoScriptImg.js

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import React, { Component } from 'react';
2+
import ReactDOMServer from 'react-dom/server';
3+
4+
export default class NoScriptImg extends Component {
5+
render() {
6+
const { alt, style, image} = this.props;
7+
8+
if(!image) {
9+
return null;
10+
}
11+
12+
return (
13+
<noscript dangerouslySetInnerHTML={{
14+
__html: ReactDOMServer.renderToStaticMarkup(
15+
<img
16+
alt={alt}
17+
style={{
18+
...style,
19+
position: 'absolute'
20+
}}
21+
src={image.url} />
22+
)
23+
}} />
24+
);
25+
}
26+
}

lib/index.js

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import React, { Component } from 'react';
2-
import debounce from 'lodash/debounce';
3-
import get from 'lodash/get';
42
import getResponsiveImage from './utils/getResponsiveImage';
3+
import debounce from './utils/debounce';
4+
import Image from './ImageServer';
55

66
/**
77
* Pic Component
@@ -10,7 +10,11 @@ export default class Pic extends Component {
1010
constructor(props) {
1111
super(props);
1212
this.state = {
13-
image: get(props.images, props.defaultIndex)
13+
image: props.images[props.defaultIndex],
14+
noScriptImage: props.noscriptIndex ?
15+
props.images[props.noScriptIndex] :
16+
props.images[props.images.length-1],
17+
isMounted: false
1418
};
1519

1620
this.setResponsiveImage = this.setResponsiveImage.bind(this);
@@ -19,9 +23,12 @@ export default class Pic extends Component {
1923
componentDidMount() {
2024
this.setResponsiveImage();
2125

26+
this.setState({
27+
isMounted: true
28+
});
29+
2230
// set responsive image on resize
2331
window.addEventListener('resize', debounce(this.setResponsiveImage, 150));
24-
2532
}
2633

2734
/**
@@ -46,18 +53,15 @@ export default class Pic extends Component {
4653
}
4754

4855
render() {
49-
const { alt, style } = this.props;
50-
5156
if (!this.state.image) {
5257
return null;
5358
}
5459

5560
return (
56-
<div ref='base'>
57-
<img
58-
alt={alt}
59-
style={style}
60-
src={this.state.image.url} />
61+
<div ref='base' style={{
62+
position: 'relative'
63+
}}>
64+
<Image {...this.props} {...this.state} />
6165
</div>
6266
);
6367
}
@@ -103,5 +107,6 @@ Pic.propTypes = {
103107
}
104108
},
105109
defaultIndex: React.PropTypes.number, // The default image to render
110+
noscriptIndex: React.PropTypes.number, // The default image to render on noscript
106111
alt: React.PropTypes.string
107112
};

lib/utils/debounce.js

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
/**
2+
* Trigger last function invoked at end of wait
3+
* @callback func - The function to invoke
4+
* @param {Number} wait - The ammount of time to wait before invoking
5+
* @param {Boolean} [immediate] - Should the callback be invoked immediately
6+
*/
7+
export default function debounce(func, wait, immediate) {
8+
let timeout;
9+
return function() {
10+
const context = this, args = arguments;
11+
const later = function() {
12+
timeout = null;
13+
if (!immediate) func.apply(context, args);
14+
};
15+
var callNow = immediate && !timeout;
16+
clearTimeout(timeout);
17+
timeout = setTimeout(later, wait);
18+
if (callNow) func.apply(context, args);
19+
};
20+
}

lib/utils/getResponsiveImage.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import reduce from 'lodash/reduce';
1+
import reduce from 'core-js/library/fn/array/reduce';
22

33
/**
44
* Get the responsive image.

package.json

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
{
22
"name": "react-pic",
3-
"version": "0.0.6",
3+
"version": "0.0.7",
44
"description": "A responsive image loading component.",
55
"author": "Ben Budnevich",
6-
"main": "dist/react-pic.js",
6+
"main": "dist/commonjs/react-pic.js",
77
"scripts": {
8-
"build": "npm run build:umd && npm run build:umd:min",
9-
"build:umd": "cross-env NODE_ENV=development webpack lib/index.js dist/react-pic.js",
10-
"build:umd:min": "cross-env NODE_ENV=production webpack lib/index.js dist/react-pic.min.js",
8+
"build": "npm run build:commonjs && npm run build:umd && npm run build:umd:min",
9+
"build:commonjs": "cross-env NODE_ENV=development webpack --config webpack.config.commonjs.js dist/commonjs/react-pic.js",
10+
"build:umd": "cross-env NODE_ENV=development webpack --config webpack.config.umd.js dist/umd/react-pic.js",
11+
"build:umd:min": "cross-env NODE_ENV=production webpack --config webpack.config.umd.js dist/umd/react-pic.min.js",
1112
"clean": "npm run clean:coverage && npm run clean:dist",
1213
"clean:coverage": "rimraf coverage",
1314
"clean:dist": "rimraf dist",
@@ -48,14 +49,14 @@
4849
"babel-preset-es2015": "^6.16.0",
4950
"babel-preset-react": "^6.16.0",
5051
"chai": "^3.5.0",
52+
"core-js": "^2.4.1",
5153
"coveralls": "^2.11.14",
5254
"cross-env": "^1.0.7",
5355
"enzyme": "^2.4.1",
5456
"eslint": "^2.0.0",
5557
"eslint-plugin-react": "^4.2.3",
5658
"express": "^4.14.0",
5759
"istanbul": "^1.0.0-alpha.2",
58-
"lodash": "^4.16.3",
5960
"mocha": "^3.0.2",
6061
"nodemon": "^1.10.2",
6162
"npm-run-all": "^3.1.0",
@@ -71,5 +72,8 @@
7172
"react": "0.14.x || ^15.0.0-0 || 15.x",
7273
"react-dom": "0.14.x || ^15.0.0-0 || 15.x"
7374
},
75+
"browser": {
76+
"./lib/ImageServer.js": "./lib/ImageClient.js"
77+
},
7478
"license": "MIT"
7579
}

playground/index.js

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,27 +14,27 @@ export default class Playground extends Component {
1414
<body>
1515
<div id="root">
1616
<Pic
17-
alt='heart'
17+
alt='winky face'
1818
images={[
1919
{
2020
width: 40,
21-
url: 'http://placehold.it/40?text='
21+
url: 'http://placehold.it/40?text=😉'
2222
},
2323
{
2424
width: 200,
25-
url: 'http://placehold.it/200?text='
25+
url: 'http://placehold.it/200?text=😉'
2626
},
2727
{
2828
width: 400,
29-
url: 'http://placehold.it/400?text='
29+
url: 'http://placehold.it/400?text=😉'
3030
},
3131
{
3232
width: 600,
33-
url: 'http://placehold.it/600?text='
33+
url: 'http://placehold.it/600?text=😉'
3434
},
3535
{
3636
width: 800,
37-
url: 'http://placehold.it/800?text='
37+
url: 'http://placehold.it/800?text=😉'
3838
}
3939
]} />
4040
</div>

test/component.js

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import React from 'react';
22
import { expect } from 'chai';
3-
import { shallow, mount } from 'enzyme';
3+
import { shallow, mount, render } from 'enzyme';
44
import Pic from '../lib/';
55
import { spy } from 'sinon';
66

@@ -20,7 +20,7 @@ describe('Pic', function() {
2020
]
2121
};
2222

23-
const pic = shallow(
23+
const pic = mount(
2424
<Pic { ...props } />
2525
);
2626

@@ -47,7 +47,7 @@ describe('Pic', function() {
4747
]
4848
};
4949

50-
const pic = shallow(
50+
const pic = mount(
5151
<Pic { ...props } />
5252
);
5353

@@ -58,6 +58,29 @@ describe('Pic', function() {
5858
)).to.equal(true);
5959
});
6060

61+
it('should render the last image in noscript', function() {
62+
const props = {
63+
alt: 'heart',
64+
images: [
65+
{
66+
width: 290,
67+
url: 'http://placehold.it/290?text=♥'
68+
},
69+
{
70+
width: 320,
71+
url: 'http://placehold.it/320?text=♥'
72+
}
73+
]
74+
};
75+
76+
const pic = render(
77+
<Pic { ...props } />
78+
);
79+
80+
expect(pic.find('noscript img').length).to.equal(1);
81+
expect(pic.find('noscript img').attr('src')).to.equal(props.images[1].url);
82+
});
83+
6184
it('should not render image if props are not passed', function() {
6285

6386
const pic = shallow(

0 commit comments

Comments
 (0)