Source: control2/container/Rating.js

(function() {
    /**
     * @typedef {Help4.control2.container.Container.Params} Help4.control2.container.Rating.Params
     * @property {number} count - number of rating stars to add
     * @property {number} [value = 0] - rating to be selected
     */

    /**
     * A control for giving rating
     * @augments Help4.control2.container.Container
     * @property {number} count - number of rating stars to add
     * @property {number} value - rating to be selected
     */
    Help4.control2.container.Rating = class extends Help4.control2.container.Container {
        /**
         * @override
         * @param {Help4.control2.container.Rating.Params} [params]
         * @param {Help4.jscore.ControlBase.Params} [derived]
         */
        constructor(params, derived) {
            const {ControlBase} = Help4.jscore;
            const T = ControlBase.TYPES;

            super(params, {
                params: {
                    type:  {init: 'Help4.control2.button.Button'},

                    count: {type: T.number, mandatory: true, readonly: true},
                    value: {type: T.number},
                    role:  {init: 'group'}
                },
                config: {
                    css: 'control-rating'
                },
                derived
            });
        }

        /**
         * @override
         * @param {HTMLElement} dom - control DOM
         */
        _onDomCreated(dom) {
            const {count, value, rtl, mobile, language, id} = this;
            const {starEmpty: icon} = Help4.control.ICONS
            const {Localization} = Help4;

            for (let i = 1; i <= count; i++) {
                const title = Localization.getText(`tooltip.rating.weight.${i}`);
                this.add({
                    _metadata: {index: i},
                    id: `${id}-star${i}`,
                    icon,
                    toggle: true,
                    appearance: 'rate',
                    active: value >= i,
                    ariaLabel: title,
                    title,
                    dom,
                    rtl,
                    mobile,
                    language
                })
                .addListener('click', ({target: [button]}) => _onRating.call(this, button));
            }
        }

        /**
         * @override
         * @param {Help4.jscore.ControlBase.PropertyChangeEvent} event - the change event
         */
        _applyPropertyToDom({name, value, oldValue}) {
            if (name === 'value') {
                this.forEach(button => {
                    const index = button.getMetadata('index');
                    button.active = value >= index;
                });
            } else {
                super._applyPropertyToDom({name, value, oldValue});
            }
        }
    }

    /**
     * @memberof Help4.control2.container.Rating#
     * @param {Help4.control2.button.Button} button - button control
     * @private
     */
    function _onRating(button) {
        const rating = button.getMetadata('index');
        if (this.value !== rating) {
            this.value = rating;
            this.addCss('changed');
            this._fireEvent({type: 'change', data: rating});
        }
    }
})();