I have been doing server-side development for a couple of years, but I am just now getting into doing some client-side programming. As a JavaScript exercise, I created a dead-simple jQuery image slider plugin, but I don't know if I did it the "right" way.
Specifically, I was wondering what improvements ought to be made to make the code clearer and more self-documenting. Also, are their any places where I have "re-invented the wheel" where I could have used the JS (or jQuery) standard library? Feel free to point out any glaring deficiencies, egregious oversights, or logical aberrations.
(function ($) {
$.fn.sliderize = function( options ) {
var settings = $.extend({
srcAttrib: "src", // data attribute containing image source
delayTime: 6000,
transitionTime: 1000,
randomize: false, // "randomize" the slides
width: 700,
height: 276
}, options);
// If we don't do this, then the plugin can throw the browser into an infinite loop :-o
if (this.length === 0 || this.find('img').length === 0) {
return new Array();
};
var images = new Array(),
statePlaying = true,
currentIndex = 0;
enqueue = function($image) {
images.push($image);
}
nextImg = function() {
// Check to see if random setting is on
if (settings.randomize) {
// Selects a "random" index... ensures that the same slide does not display 2x in a row
while(true) {
candidateIndex = Math.floor(Math.random() * (images.length - 1));
if (candidateIndex !== currentIndex) {
currentIndex = candidateIndex;
break;
}
}
} else if (currentIndex === images.length - 1) {
// If we're at the end, then get the first image again
currentIndex = 0;
} else {
// Otherwise, increment the index
currentIndex++;
}
// Implement a crude form of preloading, loading 1 image in advance
if (images[currentIndex].data('loaded') !== true) {
theSrc = images[currentIndex].data(settings.srcAttrib);
images[currentIndex].attr('src', theSrc)
.data('loaded', true)
.css({
position: "absolute",
top: 0,
left: 0,
margin: 0
});
}
return images[currentIndex];
}
playShow = function($img) {
if (statePlaying === false) return;
$img.fadeIn(settings.transitionTime / 2, function() {
$nextImg = nextImg();
setTimeout(function() {
$img.fadeOut(settings.transitionTime / 2, function() {
playShow($nextImg);
});
}, settings.delayTime - settings.transitionTime);
});
};
// LOOP THROUGH IMAGES AND ADD THEM TO THE QUEUE
this.find('img').each(function() {
enqueue($(this));
$(this).hide();
});
// Ensure that the container element is position relatively
this.css({
width: settings.width,
height: settings.height,
position: 'relative'
}).addClass('loading');
currentIndex = -1;
setTimeout(playShow(nextImg()), 0);
// Maintain chainability
return this;
};
})(jQuery);
And here is an example of the usage:
<div id="slider-container">
<img src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=="
data-src="img/1.jpg" />
<!-- ...More images -->
</div>
<!-- ...cut... -->
<script type="text/javascript">
jQuery(document).ready(function() {
$('#slider-container').sliderize({randomize: true});
});
</script>