(function ($) {
var pluginName = "starRating";
var defaultOptions = {
starCount: 5,
readOnly: false,
interval: 1,
size: '30px'
};
var methods = {
initialize: function(opts) {
return this.each(function() {
var $input = $(this);
var attrOpts = {};
var inputData = $input.data();
if (inputData[pluginName.toLowerCase()] === true) {
if (console && console.log) {
console.log("star rating has already been initialized; skipping...");
}
return;
}
$input.attr("data-" + pluginName.toLowerCase(), "true");
if (inputData.interval) {
attrOpts.interval = inputData.interval;
}
if (inputData.starcount) {
attrOpts.starCount = inputData.starcount;
}
if (inputData.size) {
attrOpts.size = inputData.size;
}
if ($input.is(":disabled")) {
attrOpts.readOnly = true;
}
var options = _.extend({}, defaultOptions, attrOpts, opts);
var $widget = $("").addClass("star-rating").css({'font-size': options.size});
var $emptySet = $("").addClass("empty-set").appendTo($widget);
var $filledSet = $("").addClass("filled-set").appendTo($widget);
options.$input = $input;
options.$emptySet = $emptySet;
for (var x = 1; x <= options.starCount; x++) {
$emptySet.append(
$("").addClass("star empty")
);
$filledSet.append(
$("").addClass("star full")
);
}
$widget.data(pluginName + ".options", options);
$input.data(pluginName, true).hide().after($widget);
privateMethods.updateStars($widget);
if (!options.readOnly) {
$widget
.on("click." + pluginName, function(e) {
var value = privateMethods.calculateRating($widget, e.pageX);
privateMethods.setValue($widget, value);
})
.on("mousemove." + pluginName, function(e) {
var value = privateMethods.calculateRating($widget, e.pageX);
privateMethods.updateStars($widget, value);
})
.on("mouseleave." + pluginName, function (e) {
privateMethods.updateStars($widget);
});
}
$input
.on("change." + pluginName, function() {
privateMethods.updateStars($widget);
});
});
}
};
var privateMethods = {
updateStars: function($widget, value) {
var options = $widget.data(pluginName + ".options");
value = (value == null ? (parseFloat(options.$input.val() || 0)) : value);
$widget.find(".filled-set").css({width: privateMethods.calculateWidth($widget, value)});
},
setValue: function($widget, value) {
var options = $widget.data(pluginName + ".options");
options.$input.val(value);
privateMethods.updateStars($widget);
},
calculateWidth: function($widget, value) {
var options = $widget.data(pluginName + ".options");
var width = options.$emptySet.width();
return ((value / options.starCount) * 100).toString() + "%";
},
// Given a screen X coordinate, calculates the nearest valid value for this rating widget
calculateRating: function($widget, screenX) {
var options = $widget.data(pluginName + ".options");
var offset = options.$emptySet.offset();
var width = options.$emptySet.width();
var ratio = (screenX - offset.left) / width;
ratio = Math.max(0, Math.min(1, ratio));
return Math.ceil(options.starCount * (1 / options.interval) * ratio) / (1 / options.interval);
}
};
$.fn[pluginName] = function(method) {
if (methods[method]) {
return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
} else if (typeof method === 'object' || ! method) {
return methods.initialize.apply(this, arguments);
} else {
$.error('Method ' + method + ' does not exist on jQuery.' + pluginName);
}
};
})(jQuery);