├── .gitignore ├── .npmignore ├── .travis.yml ├── CONTRIBUTING.md ├── LICENSE.md ├── README.md ├── build └── image.js ├── gulpfile.js ├── index.js ├── package.json └── src └── image.js /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | npm-debug.log 3 | .DS_Store -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | .gitignore 2 | node_modules 3 | src 4 | test 5 | gulpfile.js 6 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | 3 | node_js: 4 | - "0.12" 5 | 6 | before_script: 7 | - "npm install -g gulp" 8 | - "npm install" 9 | 10 | script: 11 | - "npm run build" 12 | 13 | notifications: 14 | email: 15 | - ram@hiddentao.com 16 | 17 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contribute to react-image-holder 2 | 3 | This guide guidelines for those wishing to contribute to react-image-holder. 4 | 5 | ## Contributor license agreement 6 | 7 | By submitting code as an individual or as an entity you agree that your code is licensed the same as react-image-holder. 8 | 9 | ## Issues and pull requests 10 | 11 | Issues and merge requests should be in English and contain appropriate language for audiences of all ages. 12 | 13 | We will only accept a merge requests which meets the following criteria: 14 | 15 | * Includes proper tests and all tests pass (unless it contains a test exposing a bug in existing code) 16 | * Can be merged without problems (if not please use: `git rebase master`) 17 | * Does not break any existing functionality 18 | * Fixes one specific issue or implements one specific feature (do not combine things, send separate merge requests if needed) 19 | * Keeps the code base clean and well structured 20 | * Contains functionality we think other users will benefit from too 21 | * Doesn't add unnessecary configuration options since they complicate future changes 22 | 23 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015 [Ramesh Nair](http://www.hiddentao.com/) 2 | 3 | Permission is hereby granted, free of charge, to any person 4 | obtaining a copy of this software and associated documentation 5 | files (the "Software"), to deal in the Software without 6 | restriction, including without limitation the rights to use, 7 | copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the 9 | Software is furnished to do so, subject to the following 10 | conditions: 11 | 12 | The above copyright notice and this permission notice shall be 13 | included in all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 17 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 19 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 20 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # react-image-holder 2 | 3 | [![Build Status](https://secure.travis-ci.org/hiddentao/react-image-holder.png)](http://travis-ci.org/hiddentao/react-image-holder) 4 | 5 | An `` component for React which can render _real_ images as well use an offline _placeholder_ as a fallback if need be. 6 | 7 | All placeholders are rendered using [holder.js](https://github.com/imsky/holder), meaning they will work even when offline. You can even configure the component to always render a placeholder for all its instances. 8 | 9 | [View demo](https://hiddentao.github.io/react-image-holder) 10 | 11 | ## Installation 12 | 13 | ```bash 14 | $ npm install react-image-holder 15 | ``` 16 | 17 | ## Examples 18 | 19 | All examples assume you have `require()`-d the component: 20 | 21 | ```js 22 | var Img = require('react-image-holder'); 23 | ``` 24 | 25 | **A real image** 26 | 27 | ```js 28 | var realImage = ( 29 | 30 | ); 31 | ``` 32 | 33 | Output: 34 | 35 | ```html 36 | 37 | ``` 38 | 39 | **Additional attributes** 40 | 41 | ```js 42 | var realImage = ( 43 | 47 | ); 48 | ``` 49 | 50 | Output: 51 | 52 | ```html 53 | 54 | ``` 55 | 56 | 57 | **Use a placeholder instead** 58 | 59 | ```js 60 | var realImage = ( 61 | 67 | ); 68 | ``` 69 | 70 | Output: 71 | 72 | ```html 73 | 74 | ``` 75 | 76 | _Holder.js then processes the above tag and renders a placeholder_. 77 | 78 | 79 | 80 | **Setting placeholder properties** 81 | 82 | ```js 83 | var placeholderProps = { 84 | theme: 'blue', 85 | size: 50, 86 | auto: false, 87 | }; 88 | 89 | var realImage = ( 90 | 96 | ); 97 | ``` 98 | 99 | Output: 100 | 101 | ```html 102 | 103 | ``` 104 | 105 | _See [holder.js property list](https://github.com/imsky/holder) for all available properties_. 106 | 107 | 108 | **Global placeholders** 109 | 110 | Rather than passing the `usePlaceholder` property to each instance of the component you can 111 | also set this property's default value at the start of your app: 112 | 113 | ```js 114 | Img.DEFAULT_PROPS.usePlaceholder = true; 115 | ``` 116 | 117 | Now all subsequent instances of the component will automatically use a 118 | placeholder image. And you can still override the setting on per-instance basis! 119 | 120 | 121 | ## Building 122 | 123 | ```bash 124 | $ npm install 125 | $ npm run build 126 | ``` 127 | 128 | ## Contributing 129 | 130 | Contributions are welcome! Please see [CONTRIBUTING.md](https://github.com/hiddentao/react-image-holder/blob/master/CONTRIBUTING.md). 131 | 132 | 133 | ## License 134 | 135 | MIT - see [LICENSE.md](https://github.com/hiddentao/react-image-holder/blob/master/LICENSE.md) -------------------------------------------------------------------------------- /build/image.js: -------------------------------------------------------------------------------- 1 | "use strict";var _extends=Object.assign||function(e){for(var r=1;r", 21 | "license": "MIT", 22 | "bugs": { 23 | "url": "https://github.com/hiddentao/react-image-holder/issues" 24 | }, 25 | "homepage": "https://github.com/hiddentao/react-image-holder", 26 | "devDependencies": { 27 | "gulp": "~3.8.1", 28 | "gulp-babel": "~5.2.0", 29 | "gulp-uglify": "~0.3.0", 30 | "run-sequence": "~0.3.6" 31 | }, 32 | "peerDependencies": { 33 | "react": ">=0.14.7", 34 | "react-dom": "*" 35 | }, 36 | "dependencies": { 37 | "holderjs": "~2.8.1", 38 | "lodash": "~4.11.1", 39 | "query-string": "~2.4.0" 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/image.js: -------------------------------------------------------------------------------- 1 | var omit = require('lodash/omit'), 2 | React = require('react'), 3 | ReactDOM = require('react-dom'), 4 | qs = require('query-string'); 5 | 6 | 7 | var DEFAULT_PROPS = { 8 | usePlaceholder: false, 9 | placeholder: { 10 | /* See https://github.com/imsky/holder#placeholder-options for info on more props and themes */ 11 | theme: 'vine', 12 | auto: true, 13 | }, 14 | }; 15 | 16 | 17 | var Img = React.createClass({ 18 | propTypes: { 19 | src: React.PropTypes.string.isRequired, 20 | usePlaceholder: React.PropTypes.bool, 21 | placeholder: React.PropTypes.object, 22 | }, 23 | 24 | getDefaultProps: function() { 25 | return DEFAULT_PROPS; 26 | }, 27 | 28 | render: function() { 29 | let props = this.props; 30 | 31 | let { width, height } = this.props; 32 | 33 | let attrs = omit(props, 'src', 'usePlaceholder', 'placeholder'); 34 | 35 | // placeholder 36 | if (props.usePlaceholder) { 37 | let query = qs.stringify(props.placeholder); 38 | 39 | let src = `holder.js/${width}x${height}?${query}`; 40 | 41 | let placeholderAttrs = omit(attrs, 'width', 'height'); 42 | 43 | return ( 44 | 45 | ); 46 | } 47 | // real 48 | else { 49 | return ( 50 | 51 | ); 52 | } 53 | }, 54 | 55 | componentDidMount: function() { 56 | this._initPlaceholderImage(); 57 | }, 58 | 59 | 60 | componentDidUpdate: function(oldProps) { 61 | this._initPlaceholderImage(); 62 | }, 63 | 64 | 65 | _initPlaceholderImage: function() { 66 | if (!(typeof window != 'undefined' && window.document)) { 67 | return; 68 | } 69 | if (!this.props.usePlaceholder) { 70 | return; 71 | } 72 | 73 | let node = ReactDOM.findDOMNode(this.refs.placeholder); 74 | 75 | // require in here to prevent errors during server-side rendering 76 | let Holder = require('holderjs'); 77 | 78 | Holder.run({ 79 | domain: 'holder.js', 80 | images: node, 81 | object: null, 82 | bgnodes: null, 83 | stylenodes: null, 84 | }); 85 | }, 86 | 87 | }); 88 | 89 | 90 | // make 91 | Img.DEFAULT_PROPS = DEFAULT_PROPS; 92 | 93 | 94 | module.exports = Img; 95 | --------------------------------------------------------------------------------