Last active
November 23, 2015 13:44
-
-
Save michaelcontento/b1272b27e555c56e93ff to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
'use strict'; | |
var React = require('react/addons'); | |
var PureRenderMixin = React.addons.PureRenderMixin; | |
var MAX_LOADING_TASKS = 3; | |
var loadingQueue = []; | |
var loadingQueueDirty = false; | |
var loadingTasks = 0; | |
function startLoadingTask() { | |
// enough jobs running | |
if (loadingTasks >= MAX_LOADING_TASKS) { | |
return; | |
} | |
// no job available | |
if (loadingQueue.length <= 0) { | |
return; | |
} | |
// sort queue only if neccessary | |
if (loadingQueueDirty) { | |
loadingQueueDirty = false; | |
loadingQueue.sort(function(a, b) { | |
return a.sortBy() - b.sortBy(); | |
}); | |
} | |
// helper to ensure loadingTasks is decremented | |
function startNextLoadingTask() { | |
loadingTasks -= 1; | |
// break nesting hierarchy | |
setTimeout(startLoadingTask, 0); | |
} | |
// pop job | |
loadingTasks += 1; | |
var job = loadingQueue.shift(); | |
// check if the job need to be processed | |
if (!job.isActive()) { | |
return startNextLoadingTask(); | |
} | |
// actual work | |
var img = new Image(); | |
img.onload = function() { | |
job.onLoad(); | |
startNextLoadingTask(); | |
}; | |
img.src = job.getSrc(); | |
} | |
/** | |
* Example: | |
* <PreloadImage src="https://www.google.com/images/logos/url_shortener_logo.gif"> | |
* Loading ... | |
* </PreloadImage> | |
*/ | |
var PreloadImage = React.createClass({ | |
mixins: [PureRenderMixin], | |
propTypes: { | |
src: React.PropTypes.string.isRequired, | |
children: React.PropTypes.element.isRequired, | |
preloadOrder: React.PropTypes.number, | |
}, | |
getDefaultProps: function() { | |
return { | |
preloadOrder: 0, | |
}; | |
}, | |
getInitialState: function() { | |
return { | |
loaded: false, | |
}; | |
}, | |
componentDidMount: function() { | |
loadingQueue.push(this.getJob()); | |
loadingQueueDirty = true; | |
setTimeout(startLoadingTask, 0); | |
}, | |
getJob: function() { | |
var self = this; | |
return { | |
getSrc: function() { | |
return self.props.src; | |
}, | |
isActive: function() { | |
return self.isMounted(); | |
}, | |
sortBy: function() { | |
return self.props.preloadOrder; | |
}, | |
onLoad: function() { | |
if (self.isMounted()) { | |
self.setState({ loaded: true }); | |
} | |
}, | |
}; | |
}, | |
render: function() { | |
if (this.state.loaded) { | |
var imgProps = this.props; | |
delete imgProps.preloadOrder; | |
return( | |
<img {...imgProps} /> | |
); | |
} else { | |
return this.props.children; | |
} | |
} | |
}); | |
module.exports = PreloadImage; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment