ngx-stars
Version:
Simple stars rating component for Angular >= 2
217 lines (209 loc) • 15.1 kB
JavaScript
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@angular/core'), require('@angular/common')) :
typeof define === 'function' && define.amd ? define('ngx-stars', ['exports', '@angular/core', '@angular/common'], factory) :
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global['ngx-stars'] = {}, global.ng.core, global.ng.common));
}(this, (function (exports, core, common) { 'use strict';
var NgxStarsComponent = /** @class */ (function () {
function NgxStarsComponent() {
var _this = this;
this.maxStars = 5;
this.initialStars = 0;
this.animationSpeed = 100;
this.wholeStars = false;
this.ratingOutput = new core.EventEmitter();
this.customClassIdentifier = Math.random().toString(36).substring(2);
this.safeSize = function () { return (Number.isInteger(_this.size) && _this.size > 0 && _this.size < 6) ? _this.size : 1; };
}
NgxStarsComponent.prototype.ngOnInit = function () {
this.setupStarImages();
this.editableStars = Array.from(new Array(this.maxStars)).map(function (elem, index) { return new EditableStar(index); });
this.setRating(this.initialStars);
if (this.animation) {
this.animationInterval = setInterval(this.starAnimation.bind(this), this.animationSpeed);
}
};
NgxStarsComponent.prototype.ngOnDestroy = function () {
// remove the three custom classes we created if custom image urls were provided
if (this.customCssClasses) {
this.customCssClasses.forEach(function (style) {
if (style && style.parentNode) {
style.parentNode.removeChild(style);
}
});
}
};
NgxStarsComponent.prototype.setupStarImages = function () {
var _this = this;
if (this.customStarIcons) {
this.customCssClasses = [];
Object.keys(this.customStarIcons).map(function (key) { return key; }).forEach(function (starType) {
var classname = _this.getStarClass(starType);
_this.createCssClass(classname, starType);
});
}
};
NgxStarsComponent.prototype.createCssClass = function (classname, starType) {
var clazz = document.createElement('style');
clazz.type = 'text/css';
clazz.innerHTML = "." + classname + " {\n -webkit-mask-image: url(" + this.customStarIcons[starType] + ");\n mask-image: url(" + this.customStarIcons[starType] + ");\n }";
document.getElementsByTagName('head')[0].appendChild(clazz);
this.customCssClasses.push(clazz);
};
NgxStarsComponent.prototype.starPadding = function () {
return { 'margin-right': this.customPadding || "calc(" + this.starSize().width + " / 10)" };
};
NgxStarsComponent.prototype.starColorAndSize = function () {
return Object.assign({}, this.starColor(), this.starSize());
};
NgxStarsComponent.prototype.starColor = function () {
return { 'background-color': this.color || 'crimson' };
};
NgxStarsComponent.prototype.starSize = function () {
return {
height: this.customSize || 15 * this.safeSize() + "px",
width: this.customSize || 16 * this.safeSize() + "px",
};
};
NgxStarsComponent.prototype.starAnimation = function () {
this.animationRunning = true;
if (this.rating < this.maxStars) {
this.setRating(this.rating += 0.5);
}
else {
this.setRating(0);
}
};
NgxStarsComponent.prototype.cancelStarAnimation = function () {
if (this.animationRunning) {
clearInterval(this.animationInterval);
this.rating = 0;
this.animationRunning = false;
}
};
NgxStarsComponent.prototype.setRating = function (rating) {
this.rating = Math.round(rating * 2) / 2;
this.onStarsUnhover();
};
NgxStarsComponent.prototype.onStarHover = function (event, clickedStar) {
var _this = this;
this.cancelStarAnimation();
var clickedInFirstHalf = this.clickedInFirstHalf(event);
// fill in either a half or whole star depending on where user clicked
clickedStar.classname = (!this.wholeStars && clickedInFirstHalf) ? this.getStarClass('half') : this.getStarClass('full');
// fill in all stars in previous positions and clear all in later ones
this.editableStars.forEach(function (star) {
if (star.position > clickedStar.position) {
star.classname = _this.getStarClass('empty');
}
else if (star.position < clickedStar.position) {
star.classname = _this.getStarClass('full');
}
});
};
NgxStarsComponent.prototype.onStarClick = function (event, clickedStar) {
this.cancelStarAnimation();
// lock in current rating
var clickedInFirstHalf = this.clickedInFirstHalf(event);
this.rating = clickedStar.position + ((!this.wholeStars && clickedInFirstHalf) ? 0.5 : 1);
this.ratingOutput.emit(this.rating);
};
// hidden star to left of first star lets user click there to set to 0
NgxStarsComponent.prototype.onZeroStarClick = function () {
this.setRating(0);
this.ratingOutput.emit(this.rating);
};
NgxStarsComponent.prototype.onZeroStarHover = function () {
var _this = this;
// clear all stars
this.editableStars.forEach(function (star) { return star.classname = _this.getStarClass('empty'); });
};
NgxStarsComponent.prototype.onStarsUnhover = function () {
var _this = this;
// when user stops hovering we want to make stars reflect the last rating applied by clicking
this.editableStars.forEach(function (star) {
var starNumber = star.position + 1;
if (_this.rating >= starNumber) {
star.classname = _this.getStarClass('full');
}
else if (_this.rating > starNumber - 1 && _this.rating < starNumber) {
star.classname = _this.getStarClass('half');
}
else {
star.classname = _this.getStarClass('empty');
}
});
};
NgxStarsComponent.prototype.clickedInFirstHalf = function (event) {
var starIcon = event.target;
return event.pageX < starIcon.getBoundingClientRect().left + starIcon.offsetWidth / 2;
};
NgxStarsComponent.prototype.noop = function () { };
NgxStarsComponent.prototype.getStarClass = function (starType) {
if (this.customCssClasses) {
return "ngx-stars-star-" + starType + "-" + this.customClassIdentifier;
}
return "star-" + starType;
};
// this and the aria-labels and role in the html inspired by https://stackoverflow.com/q/55966205
NgxStarsComponent.prototype.getAriaLabel = function () {
return "Rating: " + this.rating + " out of " + this.maxStars + " stars " + (this.readonly ? '' : '. Can be edited.');
};
return NgxStarsComponent;
}());
NgxStarsComponent.decorators = [
{ type: core.Component, args: [{
selector: 'ngx-stars',
template: "<div class=\"stars-line\" (mouseleave)=\"readonly ? noop() : onStarsUnhover()\" role=\"img\" [attr.aria-label]=\"getAriaLabel()\">\n <span class=\"star zero-star\" [ngStyle]=\"starSize()\" aria-hidden=\"true\" (click)=\"onZeroStarClick()\" (mousemove)=\"readonly ? noop() : onZeroStarHover()\"></span>\n <div *ngFor=\"let star of editableStars;\" [ngStyle]=\"starPadding()\" aria-hidden=\"true\" (click)=\"readonly ? noop() : onStarClick($event, star)\" (mousemove)=\"readonly ? noop() : onStarHover($event, star)\">\n <span class=\"star\" [ngClass]=\"star.classname\" [ngStyle]=\"starColorAndSize()\" aria-hidden=\"true\"></span>\n </div>\n</div>\n",
styles: [".stars-line{display:flex;align-items:center;position:relative}.stars-line>div{z-index:999}.zero-star{color:transparent;position:absolute;left:-16px}.star{display:inline-block;-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat}.star-empty{-webkit-mask-image:url(\"data:image/svg+xml,%3Csvg aria-hidden='true' focusable='false' data-prefix='far' data-icon='star' class='svg-inline--fa fa-star fa-w-18' role='img' xmlns='http://www.w3.org/2000/svg' viewBox='0 0 576 512'%3E%3Cpath fill='currentColor' d='M528.1 171.5L382 150.2 316.7 17.8c-11.7-23.6-45.6-23.9-57.4 0L194 150.2 47.9 171.5c-26.2 3.8-36.7 36.1-17.7 54.6l105.7 103-25 145.5c-4.5 26.3 23.2 46 46.4 33.7L288 439.6l130.7 68.7c23.2 12.2 50.9-7.4 46.4-33.7l-25-145.5 105.7-103c19-18.5 8.5-50.8-17.7-54.6zM388.6 312.3l23.7 138.4L288 385.4l-124.3 65.3 23.7-138.4-100.6-98 139-20.2 62.2-126 62.2 126 139 20.2-100.6 98z'%3E%3C/path%3E%3C/svg%3E%0A\");mask-image:url(\"data:image/svg+xml,%3Csvg aria-hidden='true' focusable='false' data-prefix='far' data-icon='star' class='svg-inline--fa fa-star fa-w-18' role='img' xmlns='http://www.w3.org/2000/svg' viewBox='0 0 576 512'%3E%3Cpath fill='currentColor' d='M528.1 171.5L382 150.2 316.7 17.8c-11.7-23.6-45.6-23.9-57.4 0L194 150.2 47.9 171.5c-26.2 3.8-36.7 36.1-17.7 54.6l105.7 103-25 145.5c-4.5 26.3 23.2 46 46.4 33.7L288 439.6l130.7 68.7c23.2 12.2 50.9-7.4 46.4-33.7l-25-145.5 105.7-103c19-18.5 8.5-50.8-17.7-54.6zM388.6 312.3l23.7 138.4L288 385.4l-124.3 65.3 23.7-138.4-100.6-98 139-20.2 62.2-126 62.2 126 139 20.2-100.6 98z'%3E%3C/path%3E%3C/svg%3E%0A\")}.star-half{-webkit-mask-image:url(\"data:image/svg+xml,%3C!-- had to hack this one's viewbox otherwise it didn't line up with the other two --%3E%3C!-- changed viewbox from '0 0 536 512' to '-20 0 576 512' --%3E%3Csvg aria-hidden='true' focusable='false' data-prefix='fas' data-icon='star-half-alt' class='svg-inline--fa fa-star-half-alt fa-w-17' role='img' xmlns='http://www.w3.org/2000/svg' viewBox='-20 0 576 512'%3E%3Cpath fill='currentColor' d='M508.55 171.51L362.18 150.2 296.77 17.81C290.89 5.98 279.42 0 267.95 0c-11.4 0-22.79 5.9-28.69 17.81l-65.43 132.38-146.38 21.29c-26.25 3.8-36.77 36.09-17.74 54.59l105.89 103-25.06 145.48C86.98 495.33 103.57 512 122.15 512c4.93 0 10-1.17 14.87-3.75l130.95-68.68 130.94 68.7c4.86 2.55 9.92 3.71 14.83 3.71 18.6 0 35.22-16.61 31.66-37.4l-25.03-145.49 105.91-102.98c19.04-18.5 8.52-50.8-17.73-54.6zm-121.74 123.2l-18.12 17.62 4.28 24.88 19.52 113.45-102.13-53.59-22.38-11.74.03-317.19 51.03 103.29 11.18 22.63 25.01 3.64 114.23 16.63-82.65 80.38z'%3E%3C/path%3E%3C/svg%3E\");mask-image:url(\"data:image/svg+xml,%3C!-- had to hack this one's viewbox otherwise it didn't line up with the other two --%3E%3C!-- changed viewbox from '0 0 536 512' to '-20 0 576 512' --%3E%3Csvg aria-hidden='true' focusable='false' data-prefix='fas' data-icon='star-half-alt' class='svg-inline--fa fa-star-half-alt fa-w-17' role='img' xmlns='http://www.w3.org/2000/svg' viewBox='-20 0 576 512'%3E%3Cpath fill='currentColor' d='M508.55 171.51L362.18 150.2 296.77 17.81C290.89 5.98 279.42 0 267.95 0c-11.4 0-22.79 5.9-28.69 17.81l-65.43 132.38-146.38 21.29c-26.25 3.8-36.77 36.09-17.74 54.59l105.89 103-25.06 145.48C86.98 495.33 103.57 512 122.15 512c4.93 0 10-1.17 14.87-3.75l130.95-68.68 130.94 68.7c4.86 2.55 9.92 3.71 14.83 3.71 18.6 0 35.22-16.61 31.66-37.4l-25.03-145.49 105.91-102.98c19.04-18.5 8.52-50.8-17.73-54.6zm-121.74 123.2l-18.12 17.62 4.28 24.88 19.52 113.45-102.13-53.59-22.38-11.74.03-317.19 51.03 103.29 11.18 22.63 25.01 3.64 114.23 16.63-82.65 80.38z'%3E%3C/path%3E%3C/svg%3E\")}.star-full{-webkit-mask-image:url(\"data:image/svg+xml,%3Csvg aria-hidden='true' focusable='false' data-prefix='fas' data-icon='star' class='svg-inline--fa fa-star fa-w-18' role='img' xmlns='http://www.w3.org/2000/svg' viewBox='0 0 576 512'%3E%3Cpath fill='currentColor' d='M259.3 17.8L194 150.2 47.9 171.5c-26.2 3.8-36.7 36.1-17.7 54.6l105.7 103-25 145.5c-4.5 26.3 23.2 46 46.4 33.7L288 439.6l130.7 68.7c23.2 12.2 50.9-7.4 46.4-33.7l-25-145.5 105.7-103c19-18.5 8.5-50.8-17.7-54.6L382 150.2 316.7 17.8c-11.7-23.6-45.6-23.9-57.4 0z'%3E%3C/path%3E%3C/svg%3E\");mask-image:url(\"data:image/svg+xml,%3Csvg aria-hidden='true' focusable='false' data-prefix='fas' data-icon='star' class='svg-inline--fa fa-star fa-w-18' role='img' xmlns='http://www.w3.org/2000/svg' viewBox='0 0 576 512'%3E%3Cpath fill='currentColor' d='M259.3 17.8L194 150.2 47.9 171.5c-26.2 3.8-36.7 36.1-17.7 54.6l105.7 103-25 145.5c-4.5 26.3 23.2 46 46.4 33.7L288 439.6l130.7 68.7c23.2 12.2 50.9-7.4 46.4-33.7l-25-145.5 105.7-103c19-18.5 8.5-50.8-17.7-54.6L382 150.2 316.7 17.8c-11.7-23.6-45.6-23.9-57.4 0z'%3E%3C/path%3E%3C/svg%3E\")}"]
},] }
];
NgxStarsComponent.propDecorators = {
maxStars: [{ type: core.Input }],
initialStars: [{ type: core.Input }],
readonly: [{ type: core.Input }],
size: [{ type: core.Input }],
customSize: [{ type: core.Input }],
color: [{ type: core.Input }],
animation: [{ type: core.Input }],
animationSpeed: [{ type: core.Input }],
customPadding: [{ type: core.Input }],
wholeStars: [{ type: core.Input }],
customStarIcons: [{ type: core.Input }],
ratingOutput: [{ type: core.Output }]
};
var EditableStar = /** @class */ (function () {
function EditableStar(position) {
this.position = position;
}
return EditableStar;
}());
var NgxStarsModule = /** @class */ (function () {
function NgxStarsModule() {
}
return NgxStarsModule;
}());
NgxStarsModule.decorators = [
{ type: core.NgModule, args: [{
imports: [
common.CommonModule
],
declarations: [
NgxStarsComponent
],
exports: [
NgxStarsComponent
]
},] }
];
/*
* Public API Surface of ngx-stars
*/
/**
* Generated bundle index. Do not edit.
*/
exports.EditableStar = EditableStar;
exports.NgxStarsComponent = NgxStarsComponent;
exports.NgxStarsModule = NgxStarsModule;
Object.defineProperty(exports, '__esModule', { value: true });
})));
//# sourceMappingURL=ngx-stars.umd.js.map