├── .babelrc ├── .codeclimate.yml ├── .eslintignore ├── .eslintrc.json ├── .github ├── FUNDING.yml └── workflows │ └── tests.yml ├── .gitignore ├── .hound.yml ├── .npmignore ├── .prettierrc.json ├── LICENSE ├── README.md ├── UPGRADE.md ├── __tests__ ├── features │ ├── cancel_class_spec.js │ ├── cancel_hint_spec.js │ ├── cancel_off_spec.js │ ├── cancel_on_spec.js │ ├── cancel_place_spec.js │ ├── cancel_spec.js │ ├── click_spec.js │ ├── fn_cancel_spec.js │ ├── fn_click_spec.js │ ├── fn_get_score_spec.js │ ├── fn_move_spec.js │ ├── fn_readonly_spec.js │ ├── fn_set_score_spec.js │ ├── half_spec.js │ ├── hints_spec.js │ ├── icon_range_same_spec.js │ ├── icon_range_spec.js │ ├── markup_spec.js │ ├── mouseout_spec.js │ ├── mouseover_spec.js │ ├── number_max_spec.js │ ├── number_spec.js │ ├── path_spec.js │ ├── precision_spec.js │ ├── read_only_spec.js │ ├── score_name_spec.js │ ├── score_spec.js │ ├── single_spec.js │ ├── space_spec.js │ ├── star_off_spec.js │ ├── star_on_spec.js │ ├── star_type_spec.js │ ├── stars_spec.js │ ├── target_format_spec.js │ ├── target_score_spec.js │ ├── target_spec.js │ ├── target_text_spec.js │ └── target_type_spec.js └── models │ ├── _adjustHintsSpec.js │ ├── _adjustNumberSpec.js │ ├── _adjustPrecisionSpec.js │ ├── _adjustStarNameSpec.js │ ├── _adjustedScoreSpec.js │ ├── _attributesForIndexSpec.js │ ├── _betweenSpec.js │ ├── _createStarsSpec.js │ ├── _executeCallbacksSpec.js │ ├── _getDecimalSpec.js │ ├── _isReadOnlySpec.js │ ├── _nameForIndexSpec.js │ ├── _parseOptionsSpec.js │ ├── _setPathSpec.js │ ├── _starNameSpec.js │ ├── initSpec.js │ └── optionsSpec.js ├── bower.json ├── build ├── raty.amd.min.js ├── raty.commonjs.min.js ├── raty.js ├── raty.min.js ├── raty.module.min.js ├── raty.systemjs.min.js └── raty.umd.min.js ├── changelog.md ├── composer.json ├── gulpfile.js ├── jest.config.js ├── package.json ├── src ├── fonts │ ├── raty.eot │ ├── raty.svg │ ├── raty.ttf │ └── raty.woff ├── images │ ├── cancel-off.png │ ├── cancel-on.png │ ├── star-half.png │ ├── star-off.png │ └── star-on.png ├── raty.css ├── raty.d.ts └── raty.js ├── test-helper └── index.js ├── tutorial.md └── yarn.lock /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "comments": false, 3 | "presets": [ 4 | [ 5 | "@babel/preset-env", 6 | { 7 | "targets": { "node": "current" } 8 | } 9 | ] 10 | ] 11 | } 12 | -------------------------------------------------------------------------------- /.codeclimate.yml: -------------------------------------------------------------------------------- 1 | exclude_patterns: 2 | - "__tests__/" 3 | - ".github/" 4 | - "**/node_modules/" 5 | - "build/" 6 | - "gulpfile.js" 7 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | /node_modules/ 2 | -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": {}, 3 | "extends": [ 4 | "prettier" 5 | ], 6 | "globals": { 7 | "Atomics": "readonly", 8 | "SharedArrayBuffer": "readonly" 9 | }, 10 | "parserOptions": { 11 | "ecmaVersion": 2015, 12 | "sourceType": "module" 13 | }, 14 | "rules": {} 15 | } 16 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: wbotelhos 2 | -------------------------------------------------------------------------------- /.github/workflows/tests.yml: -------------------------------------------------------------------------------- 1 | name: Tests 2 | on: [pull_request, push] 3 | 4 | jobs: 5 | tests: 6 | runs-on: ubuntu-latest 7 | 8 | steps: 9 | - name: Checkout 10 | uses: actions/checkout@v3 11 | 12 | - name: Versions 13 | run: | 14 | node -v 15 | google-chrome --version 16 | chromedriver -v 17 | 18 | - name: Yarn Install 19 | run: yarn --frozen-lockfile 20 | 21 | - name: Yarn Test 22 | uses: coactions/setup-xvfb@v1 23 | 24 | with: 25 | run: yarn test 26 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | /.idea 3 | /bower_components 4 | /node_modules 5 | /package-lock.json 6 | -------------------------------------------------------------------------------- /.hound.yml: -------------------------------------------------------------------------------- 1 | eslint: 2 | config_file: .eslintrc.json 3 | enabled: true 4 | ignore_file: .eslintignore 5 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | .babelrc 2 | .eslint* 3 | .github 4 | .gitignore 5 | .hound.yml 6 | .npmignore 7 | *.json 8 | *.lock 9 | gulpfile.js 10 | karm.conf.js 11 | node_modules 12 | spec 13 | -------------------------------------------------------------------------------- /.prettierrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "printWidth": 120, 3 | "quoteProps": "consistent", 4 | "semi": true, 5 | "singleQuote": true, 6 | "tabWidth": 2, 7 | "useTabs": false 8 | } 9 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2010 Washington Botelho 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | "Software"), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be 12 | included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Raty - A Star Rating Plugin. 2 | 3 | [![Tests](https://github.com/wbotelhos/raty/workflows/Tests/badge.svg)](https://github.com/wbotelhos/raty/actions/workflows/tests.yml) 4 | [![NPM Version](https://badge.fury.io/js/raty-js.svg)](https://badge.fury.io/js/raty-js) 5 | [![Maintainability](https://api.codeclimate.com/v1/badges/e152fa0075358ae855f1/maintainability)](https://codeclimate.com/github/wbotelhos/raty/maintainability) 6 | [![Sponsor](https://img.shields.io/badge/sponsor-%3C3-green)](https://github.com/sponsors/wbotelhos) 7 | 8 | ## Rating for Rails? 9 | 10 | It's **Rating**: https://github.com/wbotelhos/rating :star: 11 | 12 | ## Help 13 | 14 | - Check the [Tutorial](https://github.com/wbotelhos/raty/blob/main/tutorial.md) to learn about all available features. 15 | - If you're migrating from `v3` to `v4` check the [Upgrade](https://github.com/wbotelhos/raty/blob/main/UPGRADE.md) document. 16 | 17 | ## Usage with Image 18 | 19 | - raty.js 20 | - star-off.png 21 | - star-on.png 22 | 23 | ```html 24 | 25 | 26 |
27 | ``` 28 | 29 | ```js 30 | const raty = new Raty(document.querySelector('[data-raty]')); 31 | 32 | raty.init(); 33 | ``` 34 | 35 | ## Usage with Font 36 | 37 | - raty.css 38 | - raty.[eot|svg|ttf|woff] 39 | - raty.js 40 | 41 | ```html 42 | 43 | 44 | 45 | 46 |
47 | ``` 48 | 49 | ```js 50 | new Raty(document.querySelector('[data-raty]'), { starType: 'i' }); 51 | ``` 52 | 53 | ## Options 54 | 55 | | Property | Default |Description | 56 | |---------------|------------------------------------------------|-----------------------------------------------------------------| 57 | |`cancelButton` |`false` |Creates a cancel button to cancel the rating. | 58 | |`cancelClass` |`'raty-cancel'` |Name of cancel's class. | 59 | |`cancelHint` |`'Cancel this rating!'` |The cancel's button hint. | 60 | |`cancelOff` |`'cancel-off.png'` |Icon used on active cancel. | 61 | |`cancelOn` |`'cancel-on.png'` |Icon used inactive cancel. | 62 | |`cancelPlace` |`'left'` |Cancel's button position. | 63 | |`click` |`undefined` |Callback executed on rating click. | 64 | |`half` |`false` |Enables half star selection. | 65 | |`halfShow` |`true` |Enables half star display. | 66 | |`hints` |`['bad', 'poor', 'regular', 'good', 'gorgeous']`|Hints used on each star. | 67 | |`iconRange` |`undefined` |Object list with position and icon on and off to do a mixed icons| 68 | |`iconRangeSame`|`false` |All icons prior to selection will be the same as the selection. | 69 | |`mouseout` |`undefined` |Callback executed on mouseout. | 70 | |`mouseover` |`undefined` |Callback executed on mouseover. | 71 | |`noRatedMsg` |`'Not rated yet!'` |Hint for non rated elements when it's readOnly. | 72 | |`number` |`5` |The number of stars that will be presented. | 73 | |`numberMax` |`20` |Max number of stars star the option number will create. | 74 | |`path` |`undefined` |A global path where the icon will be found. | 75 | |`precision` |`false` |Enables the selection of a precise score. | 76 | |`readOnly` |`false` |Turns the rating read-only. | 77 | |`round` |`{ down: .25, full: .6, up: .76 }` |Includes value attributes to do the score rounding math. | 78 | |`score` |`undefined` |Initial rating. | 79 | |`scoreName` |`'score'` |Name of the hidden field that holds the score value. | 80 | |`single` |`false` |Enables single star selection. | 81 | |`space` |`true` |Puts space between the icons. | 82 | |`starHalf` |`'star-half.png'` |The name of the half star image. | 83 | |`starOff` |`'star-off.png'` |Name of the star image off. | 84 | |`starOn` |`'star-on.png'` |Name of the star image on. | 85 | |`target` |`undefined` |Element selector where the score will be displayed. | 86 | |`targetFormat` |`'{score}'` |Template to interpolate the score in. | 87 | |`targetKeep` |`false` |If the last rating value will be kept on mouseout. | 88 | |`targetScore` |`undefined` |Score field target avoiding hidden field creation | 89 | |`targetText` |`''` |Default text in a target. | 90 | |`targetType` |`'hint'` |Choose if target will receive a hint or the score number | 91 | |`starType` |`'img'` |Element used to represent a star. | 92 | 93 | ## Functions 94 | 95 | To call some function, first, save the Raty instance on a variable and then call the functions: 96 | 97 | ```js 98 | var raty = new Raty(document.querySelector('[data-raty]')); 99 | ``` 100 | 101 | | Function | Description | 102 | |------------------------|-----------------------------------------------------------| 103 | |`raty.score()` |Get the current score. | 104 | |`raty.score(number)` |Set a score. | 105 | |`raty.click(number)` |Click on a star. | 106 | |`raty.readOnly(boolean)`|Change the read-only state. | 107 | |`raty.cancel(boolean)` |Cancel the rating. The last param force the click callback.| 108 | |`raty.move(number)` |Move the mouse to the given score point position. | 109 | 110 | ## Build 111 | 112 | ```sh 113 | gulp 'amd' 114 | gulp 'umd' 115 | gulp 'commonjs' 116 | gulp 'systemjs' 117 | gulp 'es6' 118 | gulp 'es5' 119 | gulp 'es5-test' 120 | ``` 121 | -------------------------------------------------------------------------------- /UPGRADE.md: -------------------------------------------------------------------------------- 1 | ## From v3 to v4 2 | 3 | 1. Replace your jQuery selector to a `Raty` instance receiving a DOM element: 4 | 5 | ```js 6 | // From 7 | $('[data-raty]').raty({ cancel: true }); 8 | 9 | // To 10 | new Raty(document.querySelector('[data-raty]'), { cancel: true }); 11 | ``` 12 | 13 | 2. Replace your global configuration to a local configuration: 14 | 15 | ```js 16 | // From 17 | 18 | $.raty.path = 'assets/images'; 19 | 20 | $('[data-raty]').raty(); 21 | 22 | // To 23 | 24 | new Raty(document.querySelector('[data-raty]'), { path: 'assets/images' }); 25 | ``` 26 | 27 | 3. Replace the usage of your arguments on `click` callback: 28 | 29 | ```js 30 | // From 31 | 32 | $('[data-raty]').raty({ 33 | click: function(score, evt) { 34 | var element = this; 35 | } 36 | }); 37 | 38 | // To 39 | 40 | new Raty(document.querySelector('div'), { 41 | click: function(score, element, evt) { 42 | var objectInstance = this; 43 | } 44 | }); 45 | ``` 46 | 47 | 4. Replace the usage of your arguments on `mouseover` callback: 48 | 49 | ```js 50 | // From 51 | 52 | $('[data-raty]').raty({ 53 | mouseover: function(score, evt) { 54 | var element = this; 55 | } 56 | }); 57 | 58 | // To 59 | 60 | new Raty(document.querySelector('div'), { 61 | mouseover: function(score, element, evt) { 62 | var objectInstance = this; 63 | } 64 | }); 65 | ``` 66 | 67 | 5. Replace the usage of your arguments on `mouseout` callback: 68 | 69 | ```js 70 | // From 71 | 72 | $('[data-raty]').raty({ 73 | mouseout: function(score, evt) { 74 | var element = this; 75 | } 76 | }); 77 | 78 | // To 79 | 80 | new Raty(document.querySelector('div'), { 81 | mouseout: function(score, element, evt) { 82 | var objectInstance = this; 83 | } 84 | }); 85 | ``` 86 | 87 | 6. Replace the functions call: 88 | 89 | ```js 90 | // From 91 | 92 | $('[data-raty]').data('raty').score(); 93 | $('[data-raty]').data('raty').score(number); 94 | $('[data-raty]').data('raty').click(number); 95 | $('[data-raty]').data('raty').readOnly(boolean); 96 | $('[data-raty]').data('raty').cancel(boolean); 97 | $('[data-raty]').data('raty').move(number); 98 | 99 | // To 100 | 101 | new Raty(document.querySelector('div')).score(); 102 | new Raty(document.querySelector('div')).score(number); 103 | new Raty(document.querySelector('div')).click(number); 104 | new Raty(document.querySelector('div')).readOnly(boolean); 105 | new Raty(document.querySelector('div')).cancel(boolean); 106 | new Raty(document.querySelector('div')).move(number); 107 | ``` 108 | 109 | 7. Replace initialize callbacks: 110 | 111 | ```js 112 | // From 113 | 114 | number: function() { this == 'element' }; 115 | readOnly: function() { this == 'element' }; 116 | score: function() { this == 'element' }; 117 | scoreName: function() { this == 'element' }; 118 | target: function() { this == 'element' }; 119 | path: function() { this == 'element' }; 120 | 121 | // To 122 | 123 | number: function(element) { this == 'new Raty()'; }; 124 | readOnly: function(element) { this == 'new Raty()'; }; 125 | score: function(element) { this == 'new Raty()'; }; 126 | scoreName: function(element) { this == 'new Raty()'; }; 127 | target: function(element) { this == 'new Raty()'; }; 128 | path: function(element) { this == 'new Raty()'; }; 129 | ``` 130 | -------------------------------------------------------------------------------- /__tests__/features/cancel_class_spec.js: -------------------------------------------------------------------------------- 1 | describe('#cancelClass', () => { 2 | it('changes the class', () => { 3 | // given 4 | Helper.create('#el'); 5 | 6 | var raty = new Raty(document.querySelector('#el'), { cancelButton: true, cancelClass: 'custom-class' }); 7 | 8 | // when 9 | raty.init(); 10 | 11 | // then 12 | expect(raty.element.querySelector('.custom-class').alt).toEqual('x'); 13 | }); 14 | 15 | it('accepts data attribute', () => { 16 | // given 17 | Helper._append('div', { 'data-cancel-class': 'custom' }); 18 | 19 | // when 20 | var raty = new Raty(document.querySelector('[data-cancel-class]')).init(); 21 | 22 | // then 23 | expect(raty.opt.cancelClass).toEqual('custom'); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /__tests__/features/cancel_hint_spec.js: -------------------------------------------------------------------------------- 1 | describe('#cancelHint', () => { 2 | it('changes the cancel hint', () => { 3 | // given 4 | Helper.create('#el'); 5 | 6 | // when 7 | var raty = new Raty(document.querySelector('#el'), { 8 | cancelButton: true, 9 | cancelHint: 'double', 10 | path: '../src/images', 11 | }).init(); 12 | 13 | // then 14 | expect(raty.element.querySelector('.raty-cancel').title).toEqual('double'); 15 | }); 16 | 17 | it('accepts data attribute', () => { 18 | // given 19 | Helper._append('div', { 'data-cancel-hint': 'custom' }); 20 | 21 | // when 22 | var raty = new Raty(document.querySelector('[data-cancel-hint]'), { path: '../src/images' }).init(); 23 | 24 | // then 25 | expect(raty.opt.cancelHint).toEqual('custom'); 26 | }); 27 | }); 28 | -------------------------------------------------------------------------------- /__tests__/features/cancel_off_spec.js: -------------------------------------------------------------------------------- 1 | describe('#cancelOff', () => { 2 | it('changes the icon', () => { 3 | // given 4 | Helper.create('#el'); 5 | 6 | var raty = new Raty(document.querySelector('#el'), { 7 | cancelButton: true, 8 | cancelOff: 'star-half.png', 9 | path: '../src/images', 10 | }); 11 | 12 | // when 13 | raty.init(); 14 | 15 | // then 16 | var cancel = raty.element.querySelector('.raty-cancel'); 17 | 18 | expect(Helper.extension(cancel.src)).toEqual('star-half.png'); 19 | }); 20 | 21 | it('accepts data attribute', () => { 22 | // given 23 | Helper._append('div', { 'data-cancel-off': 'custom.png' }); 24 | 25 | var raty = new Raty(document.querySelector('[data-cancel-off]'), { cancelButton: true, path: '../src/images' }); 26 | 27 | // when 28 | raty.init(); 29 | 30 | // then 31 | var cancel = raty.element.querySelector('.raty-cancel'); 32 | 33 | expect(Helper.extension(cancel.src)).toEqual('custom.png'); 34 | }); 35 | }); 36 | -------------------------------------------------------------------------------- /__tests__/features/cancel_on_spec.js: -------------------------------------------------------------------------------- 1 | describe('#cancelOn', () => { 2 | it('changes the icon', () => { 3 | // given 4 | Helper.create('#el'); 5 | 6 | var raty = new Raty(document.querySelector('#el'), { cancelButton: true, cancelOn: 'star-half.png' }).init(); 7 | var cancel = raty.element.querySelector('.raty-cancel'); 8 | 9 | // when 10 | Helper.trigger(cancel, 'mouseover'); 11 | 12 | // then 13 | expect(Helper.extension(cancel.src)).toEqual('star-half.png'); 14 | }); 15 | 16 | it('accepts data attribute', () => { 17 | // given 18 | Helper._append('div', { 'data-cancel-on': 'custom' }); 19 | 20 | // when 21 | var raty = new Raty(document.querySelector('[data-cancel-on]')).init(); 22 | 23 | // then 24 | expect(raty.opt.cancelOn).toEqual('custom'); 25 | }); 26 | }); 27 | -------------------------------------------------------------------------------- /__tests__/features/cancel_place_spec.js: -------------------------------------------------------------------------------- 1 | describe('#cancelPlace', () => { 2 | it('accepts data attribute', () => { 3 | // given 4 | Helper._append('div', { 'data-cancel-place': 'custom' }); 5 | 6 | // when 7 | var raty = new Raty(document.querySelector('[data-cancel-place]')).init(); 8 | 9 | // then 10 | expect(raty.opt.cancelPlace).toEqual('custom'); 11 | }); 12 | 13 | context('when left', function () { 14 | it('is prepended', () => { 15 | // given 16 | Helper.create('#el'); 17 | 18 | // when 19 | var raty = new Raty(document.querySelector('#el'), { cancelButton: true, cancelPlace: 'left' }).init(); 20 | 21 | // then 22 | expect(raty.element.querySelector('img').classList.contains('raty-cancel')).toEqual(true); 23 | }); 24 | }); 25 | 26 | context('when left', function () { 27 | it('is appended', () => { 28 | // given 29 | Helper.create('#el'); 30 | 31 | // when 32 | var raty = new Raty(document.querySelector('#el'), { cancelButton: true, cancelPlace: 'right' }).init(); 33 | 34 | // then 35 | var stars = raty.element.querySelectorAll('img'); 36 | 37 | expect(stars[stars.length - 1].classList.contains('raty-cancel')).toEqual(true); 38 | }); 39 | }); 40 | }); 41 | -------------------------------------------------------------------------------- /__tests__/features/click_spec.js: -------------------------------------------------------------------------------- 1 | describe('#click', () => { 2 | beforeEach(() => { 3 | Helper.create('#el'); 4 | }); 5 | 6 | it('has "this" scope as the object instance ', () => { 7 | // given 8 | var raty = new Raty(document.querySelector('#el'), { 9 | cancelButton: true, 10 | click: function () { 11 | this.result = this; 12 | }, 13 | }).init(); 14 | 15 | var star = Helper.last(raty.element.querySelectorAll('img')); 16 | 17 | // when 18 | Helper.trigger(star, 'click'); 19 | 20 | // then 21 | expect(raty.result).toBe(raty); 22 | }); 23 | 24 | it('receives the score as integer', () => { 25 | // given 26 | var raty = new Raty(document.querySelector('#el'), { 27 | click: function (score) { 28 | this.result = score; 29 | }, 30 | }).init(); 31 | 32 | var star = Helper.last(raty.element.querySelectorAll('img')); 33 | 34 | // when 35 | Helper.trigger(star, 'click'); 36 | 37 | expect(raty.result).toEqual(5); 38 | }); 39 | 40 | it('receives the element', () => { 41 | // given 42 | var raty = new Raty(document.querySelector('#el'), { 43 | click: function (_score, element) { 44 | this.result = element; 45 | }, 46 | }).init(); 47 | 48 | var star = Helper.last(raty.element.querySelectorAll('img')); 49 | 50 | // when 51 | Helper.trigger(star, 'click'); 52 | 53 | // then 54 | expect(raty.result).toEqual(document.querySelector('#el')); 55 | }); 56 | 57 | it('receives the mouse event', () => { 58 | // given 59 | var raty = new Raty(document.querySelector('#el'), { 60 | click: function (_score, _element, evt) { 61 | this.result = evt; 62 | }, 63 | }).init(); 64 | 65 | var star = Helper.last(raty.element.querySelectorAll('img')); 66 | 67 | // when 68 | Helper.trigger(star, 'click'); 69 | 70 | // then 71 | expect(raty.result.type).toEqual('click'); 72 | }); 73 | 74 | context('with return as undefined', function () { 75 | it('executes click behavior', () => { 76 | // given 77 | var raty = new Raty(document.querySelector('#el'), { 78 | click: function () {}, 79 | }).init(); 80 | 81 | var star = Helper.last(raty.element.querySelectorAll('img')); 82 | 83 | // when 84 | Helper.trigger(star, 'click'); 85 | 86 | // then 87 | expect(raty.element.querySelector('input').value).toEqual('5'); 88 | }); 89 | 90 | it('turns on the stars', () => { 91 | // given 92 | var raty = new Raty(document.querySelector('#el'), { 93 | click: function () {}, 94 | }).init(); 95 | 96 | var stars = raty.element.querySelectorAll('img'); 97 | 98 | // when 99 | Helper.trigger(stars[0], 'click'); 100 | 101 | // then 102 | expect(Helper.extension(stars[0].src)).toEqual('star-on.png'); 103 | expect(Helper.extension(stars[1].src)).toEqual('star-off.png'); 104 | expect(Helper.extension(stars[2].src)).toEqual('star-off.png'); 105 | expect(Helper.extension(stars[3].src)).toEqual('star-off.png'); 106 | expect(Helper.extension(stars[4].src)).toEqual('star-off.png'); 107 | }); 108 | }); 109 | 110 | context('with return as true', function () { 111 | it('applies the score', () => { 112 | // given 113 | var raty = new Raty(document.querySelector('#el'), { 114 | click: function () { 115 | return true; 116 | }, 117 | }).init(); 118 | 119 | var star = Helper.last(raty.element.querySelectorAll('img')); 120 | 121 | // when 122 | Helper.trigger(star, 'click'); 123 | 124 | // then 125 | expect(raty.element.querySelector('input').value).toEqual('5'); 126 | }); 127 | 128 | it('turns on the stars', () => { 129 | // given 130 | var raty = new Raty(document.querySelector('#el'), { 131 | click: function () { 132 | return true; 133 | }, 134 | }).init(); 135 | 136 | var stars = raty.element.querySelectorAll('img'); 137 | 138 | // when 139 | Helper.trigger(stars[0], 'click'); 140 | 141 | // then 142 | expect(Helper.extension(stars[0].src)).toEqual('star-on.png'); 143 | expect(Helper.extension(stars[1].src)).toEqual('star-off.png'); 144 | expect(Helper.extension(stars[2].src)).toEqual('star-off.png'); 145 | expect(Helper.extension(stars[3].src)).toEqual('star-off.png'); 146 | expect(Helper.extension(stars[4].src)).toEqual('star-off.png'); 147 | }); 148 | }); 149 | 150 | context('with return as false', function () { 151 | it('does not applies the score', () => { 152 | // given 153 | var raty = new Raty(document.querySelector('#el'), { 154 | click: function () { 155 | return false; 156 | }, 157 | }).init(); 158 | 159 | var star = raty.element.querySelector('img'); 160 | 161 | // when 162 | Helper.trigger(star, 'click'); 163 | 164 | // then 165 | expect(raty.element.querySelector('input').value).toEqual(''); 166 | }); 167 | 168 | it('does not turns on the stars', () => { 169 | // given 170 | var raty = new Raty(document.querySelector('#el'), { 171 | click: function () { 172 | return false; 173 | }, 174 | }).init(); 175 | 176 | var stars = raty.element.querySelectorAll('img'); 177 | 178 | // when 179 | Helper.trigger(stars[0], 'click'); 180 | 181 | // then 182 | expect(Helper.extension(stars[0].src)).toEqual('star-off.png'); 183 | expect(Helper.extension(stars[1].src)).toEqual('star-off.png'); 184 | expect(Helper.extension(stars[2].src)).toEqual('star-off.png'); 185 | expect(Helper.extension(stars[3].src)).toEqual('star-off.png'); 186 | expect(Helper.extension(stars[4].src)).toEqual('star-off.png'); 187 | }); 188 | }); 189 | 190 | context('with :cancel', function () { 191 | it('has "this" scope as the object instance ', () => { 192 | // given 193 | var raty = new Raty(document.querySelector('#el'), { 194 | cancelButton: true, 195 | click: function () { 196 | this.result = this; 197 | }, 198 | }).init(); 199 | 200 | var cancel = raty.element.querySelector('.raty-cancel'); 201 | 202 | // when 203 | Helper.trigger(cancel, 'click'); 204 | 205 | // then 206 | expect(raty.result).toBe(raty); 207 | }); 208 | 209 | it('receives the score as null', () => { 210 | // given 211 | var raty = new Raty(document.querySelector('#el'), { 212 | cancelButton: true, 213 | click: function (score) { 214 | this.result = score; 215 | }, 216 | }).init(); 217 | 218 | var cancel = raty.element.querySelector('.raty-cancel'); 219 | 220 | // when 221 | Helper.trigger(cancel, 'click'); 222 | 223 | expect(raty.result).toEqual(null); 224 | }); 225 | 226 | it('receives the element', () => { 227 | // given 228 | var raty = new Raty(document.querySelector('#el'), { 229 | cancelButton: true, 230 | click: function (_score, element) { 231 | this.result = element; 232 | }, 233 | }).init(); 234 | 235 | var cancel = raty.element.querySelector('.raty-cancel'); 236 | 237 | // when 238 | Helper.trigger(cancel, 'click'); 239 | 240 | // then 241 | expect(raty.result).toEqual(document.querySelector('#el')); 242 | }); 243 | 244 | it('receives the mouse event', () => { 245 | // given 246 | var raty = new Raty(document.querySelector('#el'), { 247 | cancelButton: true, 248 | click: function (_score, _element, evt) { 249 | this.result = evt; 250 | }, 251 | }).init(); 252 | 253 | var cancel = raty.element.querySelector('.raty-cancel'); 254 | 255 | // when 256 | Helper.trigger(cancel, 'click'); 257 | 258 | // then 259 | expect(raty.result.type).toEqual('click'); 260 | }); 261 | }); 262 | 263 | context('on click without mouseover', function () { 264 | it('changes the stars to on', () => { 265 | // given 266 | var raty = new Raty(document.querySelector('#el')).init(); 267 | var stars = raty.element.querySelectorAll('img'); 268 | 269 | // when 270 | Helper.trigger(Helper.last(stars), 'click'); 271 | 272 | // then 273 | expect(Helper.extension(stars[0].src)).toEqual('star-on.png'); 274 | expect(Helper.extension(stars[1].src)).toEqual('star-on.png'); 275 | expect(Helper.extension(stars[2].src)).toEqual('star-on.png'); 276 | expect(Helper.extension(stars[3].src)).toEqual('star-on.png'); 277 | expect(Helper.extension(stars[4].src)).toEqual('star-on.png'); 278 | }); 279 | }); 280 | }); 281 | -------------------------------------------------------------------------------- /__tests__/features/fn_cancel_spec.js: -------------------------------------------------------------------------------- 1 | describe('#fn_cancel', () => { 2 | let testContext; 3 | 4 | beforeEach(() => { 5 | testContext = {}; 6 | }); 7 | 8 | beforeEach(() => { 9 | Helper.create('#el'); 10 | }); 11 | 12 | describe('with :readOnly', () => { 13 | it('does not cancel', () => { 14 | // given 15 | var raty = new Raty(document.querySelector('#el'), { readOnly: true, score: 5 }).init(); 16 | var stars = raty.element.querySelectorAll('img'); 17 | 18 | // when 19 | raty.cancel(); 20 | 21 | // then 22 | expect(Helper.extension(stars[0].src)).toEqual('star-on.png'); 23 | expect(Helper.extension(stars[1].src)).toEqual('star-on.png'); 24 | expect(Helper.extension(stars[2].src)).toEqual('star-on.png'); 25 | expect(Helper.extension(stars[3].src)).toEqual('star-on.png'); 26 | expect(Helper.extension(stars[4].src)).toEqual('star-on.png'); 27 | }); 28 | 29 | it('does not remove the score input value', () => { 30 | // given 31 | var raty = new Raty(document.querySelector('#el'), { readOnly: true, score: 5 }).init(); 32 | 33 | // when 34 | raty.cancel(); 35 | 36 | // then 37 | expect(raty.element.querySelector('input').value).toEqual('5'); 38 | }); 39 | }); 40 | 41 | context('with click trigger', function () { 42 | context('as *false', function () { 43 | it('does not triggers click callback', () => { 44 | // given 45 | var raty = new Raty(document.querySelector('#el'), { 46 | score: 1, 47 | click: function () { 48 | this.clicked = true; 49 | }, 50 | }).init(); 51 | 52 | // when 53 | raty.cancel(false); 54 | 55 | // then 56 | expect(raty.element.clicked).toEqual(undefined); 57 | }); 58 | 59 | context('with :target', function () { 60 | beforeEach(() => { 61 | testContext.target = Helper.create('#target'); 62 | }); 63 | 64 | context('and :targetKeep', function () { 65 | context('as *true', function () { 66 | it('sets the :targetText on target', () => { 67 | // given 68 | var raty = new Raty(document.querySelector('#el'), { 69 | cancel: true, 70 | target: '#target', 71 | targetKeep: true, 72 | targetText: 'targetText', 73 | }).init(); 74 | 75 | // when 76 | raty.cancel(); 77 | 78 | // then 79 | expect(document.querySelector('#target').textContent).toEqual('targetText'); 80 | }); 81 | }); 82 | }); 83 | }); 84 | }); 85 | 86 | context('as *true', function () { 87 | it('triggers the :click callback', () => { 88 | // given 89 | var raty = new Raty(document.querySelector('#el'), { 90 | score: 1, 91 | click: function () { 92 | this.clicked = true; 93 | }, 94 | }).init(); 95 | 96 | // when 97 | raty.cancel(true); 98 | 99 | // then 100 | expect(raty.clicked).toEqual(true); 101 | }); 102 | 103 | context('with :target', function () { 104 | beforeEach(() => { 105 | testContext.target = Helper.create('#target'); 106 | }); 107 | 108 | context('and :targetKeep', function () { 109 | context('as *true', function () { 110 | it('sets the :targetText on target', () => { 111 | // given 112 | var raty = new Raty(document.querySelector('#el'), { 113 | cancel: true, 114 | target: '#target', 115 | targetKeep: true, 116 | targetText: 'targetText', 117 | }).init(); 118 | 119 | // when 120 | raty.cancel(true); 121 | 122 | // then 123 | expect(testContext.target.textContent).toEqual('targetText'); 124 | }); 125 | }); 126 | }); 127 | }); 128 | }); 129 | }); 130 | }); 131 | -------------------------------------------------------------------------------- /__tests__/features/fn_click_spec.js: -------------------------------------------------------------------------------- 1 | describe('#click', () => { 2 | beforeEach(() => { 3 | var element = document.createElement('div'); 4 | element.id = 'element'; 5 | document.querySelector(`body`).appendChild(element); 6 | }); 7 | 8 | afterEach(() => { 9 | document.querySelector('#element').remove(); 10 | }); 11 | 12 | it('clicks on star', () => { 13 | // given 14 | var raty = new Raty(document.querySelector('#element'), { 15 | click: function () { 16 | this.clicked = true; 17 | }, 18 | }).init(); 19 | 20 | var stars = raty.element.querySelectorAll('img'); 21 | 22 | // when 23 | raty.click(1); 24 | 25 | // then 26 | expect(stars[0].getAttribute('src')).toEqual('star-on.png'); 27 | expect(stars[1].getAttribute('src')).toEqual('star-off.png'); 28 | expect(stars[2].getAttribute('src')).toEqual('star-off.png'); 29 | expect(stars[3].getAttribute('src')).toEqual('star-off.png'); 30 | expect(stars[4].getAttribute('src')).toEqual('star-off.png'); 31 | 32 | expect(raty.clicked).toEqual(true); 33 | }); 34 | 35 | it('receives the score', () => { 36 | // given 37 | var raty = new Raty(document.querySelector('#element'), { 38 | click: function (score) { 39 | this.result = score; 40 | }, 41 | }).init(); 42 | 43 | // when 44 | raty.click(1); 45 | 46 | // then 47 | expect(raty.result).toEqual(1); 48 | }); 49 | 50 | it('does not have an event', () => { 51 | // given 52 | var raty = new Raty(document.querySelector('#element'), { 53 | click: function (_score, _element, evt) { 54 | this.evt = evt; 55 | }, 56 | }).init(); 57 | 58 | // when 59 | raty.click(1); 60 | 61 | // then 62 | expect(raty.evt).toEqual(undefined); 63 | }); 64 | 65 | describe('with :readOnly', () => { 66 | it('does not set the score', () => { 67 | // given 68 | var raty = new Raty(document.querySelector('#element'), { readOnly: true }).init(); 69 | 70 | var stars = raty.element.querySelectorAll('img'); 71 | 72 | // when 73 | raty.click(1); 74 | 75 | // then 76 | expect(stars[0].getAttribute('src')).toEqual('star-off.png'); 77 | expect(stars[1].getAttribute('src')).toEqual('star-off.png'); 78 | expect(stars[2].getAttribute('src')).toEqual('star-off.png'); 79 | expect(stars[3].getAttribute('src')).toEqual('star-off.png'); 80 | expect(stars[4].getAttribute('src')).toEqual('star-off.png'); 81 | }); 82 | }); 83 | 84 | context('without :click', function () { 85 | it('ignores the callback', () => { 86 | // given 87 | var raty = new Raty(document.querySelector('#element')).init(); 88 | 89 | // when 90 | var lambda = function () { 91 | raty.click(1); 92 | }; 93 | 94 | // then 95 | expect(lambda).not.toThrow(); 96 | }); 97 | }); 98 | 99 | context('with :target', function () { 100 | beforeEach(() => { 101 | var hint = document.createElement('div'); 102 | hint.id = 'hint'; 103 | document.querySelector(`body`).appendChild(hint); 104 | }); 105 | 106 | afterEach(() => { 107 | document.querySelector('#hint').remove(); 108 | }); 109 | 110 | context('and :targetKeep', function () { 111 | it('sets the score on target', () => { 112 | // given 113 | var raty = new Raty(document.querySelector('#element'), { 114 | target: '#hint', 115 | targetKeep: true, 116 | click: function () {}, 117 | }).init(); 118 | 119 | // when 120 | raty.click(1); 121 | 122 | // then 123 | expect(document.querySelector('#hint').innerHTML).toEqual('bad'); 124 | }); 125 | }); 126 | }); 127 | }); 128 | -------------------------------------------------------------------------------- /__tests__/features/fn_get_score_spec.js: -------------------------------------------------------------------------------- 1 | describe('get #score', () => { 2 | beforeEach(() => { 3 | var element = document.createElement('div'); 4 | element.id = 'element'; 5 | document.querySelector(`body`).appendChild(element); 6 | }); 7 | 8 | afterEach(() => { 9 | document.querySelector('#element').remove(); 10 | }); 11 | 12 | it('accepts number as string', () => { 13 | // given 14 | var raty = new Raty(document.querySelector('#element'), { score: '1' }); 15 | 16 | // when 17 | raty.init(); 18 | 19 | // then 20 | expect(raty.element.querySelector('input').value).toEqual('1'); 21 | }); 22 | 23 | it('accepts float string', () => { 24 | // given 25 | var raty = new Raty(document.querySelector('#element'), { score: '1.5' }); 26 | 27 | // when 28 | raty.init(); 29 | 30 | // then 31 | expect(raty.element.querySelector('input').value).toEqual('1.5'); 32 | }); 33 | 34 | context('with integer score', function () { 35 | it('gets as int', () => { 36 | // given 37 | var raty = new Raty(document.querySelector('#element'), { score: 1 }).init(); 38 | 39 | // when 40 | var score = raty.score(); 41 | 42 | // then 43 | expect(score).toEqual(1); 44 | }); 45 | }); 46 | 47 | context('with float score', function () { 48 | it('gets as float', () => { 49 | // given 50 | var raty = new Raty(document.querySelector('#element'), { score: 1.5 }).init(); 51 | 52 | // when 53 | var score = raty.score(); 54 | 55 | // then 56 | expect(score).toEqual(1.5); 57 | }); 58 | }); 59 | 60 | context('with score zero', function () { 61 | it('returns an undefined value because it does not exist', () => { 62 | // given 63 | var raty = new Raty(document.querySelector('#element'), { score: 0 }).init(); 64 | 65 | // when 66 | var score = raty.score(); 67 | 68 | // then 69 | expect(score).toEqual(undefined); 70 | }); 71 | }); 72 | 73 | context('with score greater than :numberMax', function () { 74 | it('gets the max', () => { 75 | // given 76 | var raty = new Raty(document.querySelector('#element'), { number: 50, score: 50 }).init(); 77 | 78 | // when 79 | var score = raty.score(); 80 | 81 | // then 82 | expect(score).toEqual(raty.opt.numberMax); 83 | }); 84 | }); 85 | }); 86 | -------------------------------------------------------------------------------- /__tests__/features/fn_move_spec.js: -------------------------------------------------------------------------------- 1 | describe('#move', () => { 2 | jest.useFakeTimers(); 3 | 4 | let testContext; 5 | 6 | beforeEach(() => { 7 | testContext = {}; 8 | }); 9 | 10 | beforeEach(() => { 11 | Helper.create('#el'); 12 | 13 | testContext.target = Helper.create('#target'); 14 | }); 15 | 16 | it('sets *move to true then turns it false ', () => { 17 | // given 18 | var raty = new Raty(document.querySelector('#el')).init(); 19 | 20 | // when 21 | raty.move(1); 22 | 23 | // then 24 | expect(raty.isMove).toEqual(false); 25 | }); 26 | 27 | describe('with interger score', () => { 28 | it('moves to the right point', (done) => { 29 | // given 30 | var raty = new Raty(document.querySelector('#el'), { 31 | precision: true, 32 | target: '#target', 33 | targetType: 'number', 34 | }).init(); 35 | 36 | setTimeout(function () { 37 | // when 38 | raty.move(1); 39 | 40 | // then 41 | expect(testContext.target.textContent).toEqual('1.0'); 42 | 43 | done(); 44 | }, 100); 45 | 46 | jest.advanceTimersByTime(100); 47 | }); 48 | }); 49 | 50 | describe('with float score', () => { 51 | context('with one decimal', function () { 52 | it('moves to the right point', (done) => { 53 | // given 54 | var raty = new Raty(document.querySelector('#el'), { 55 | precision: true, 56 | target: '#target', 57 | targetType: 'number', 58 | }).init(); 59 | 60 | setTimeout(function () { 61 | // when 62 | raty.move(1.7); 63 | 64 | // then 65 | expect(testContext.target.textContent).toEqual('1.7'); 66 | 67 | done(); 68 | }, 100); 69 | 70 | jest.advanceTimersByTime(100); 71 | }); 72 | }); 73 | 74 | context('with two decimal', function () { 75 | it('moves to the right point', (done) => { 76 | // given 77 | var raty = new Raty(document.querySelector('#el'), { 78 | precision: true, 79 | target: '#target', 80 | targetType: 'number', 81 | }).init(); 82 | 83 | setTimeout(function () { 84 | // when 85 | raty.move(1.79); 86 | 87 | // then 88 | expect(testContext.target.textContent).toEqual('1.7'); 89 | 90 | done(); 91 | }, 100); 92 | 93 | jest.advanceTimersByTime(100); 94 | }); 95 | }); 96 | }); 97 | 98 | describe('with string score', () => { 99 | it('moves to the right point', (done) => { 100 | jest.advanceTimersByTime(100); 101 | // given 102 | var raty = new Raty(document.querySelector('#el'), { 103 | precision: true, 104 | target: '#target', 105 | targetType: 'number', 106 | }).init(); 107 | 108 | setTimeout(function () { 109 | // when 110 | raty.move('1.7'); 111 | 112 | // then 113 | expect(testContext.target.textContent).toEqual('1.7'); 114 | 115 | done(); 116 | }, 100); 117 | 118 | jest.advanceTimersByTime(100); 119 | }); 120 | }); 121 | 122 | describe('when score is bigger then the number of stars', () => { 123 | it('moves to the and of the last star', (done) => { 124 | // given 125 | var raty = new Raty(document.querySelector('#el'), { 126 | precision: true, 127 | target: '#target', 128 | targetType: 'number', 129 | }).init(); 130 | 131 | setTimeout(function () { 132 | // when 133 | raty.move(6.7); 134 | 135 | // then 136 | expect(testContext.target.textContent).toEqual('5.0'); 137 | 138 | done(); 139 | }, 100); 140 | 141 | jest.advanceTimersByTime(100); 142 | }); 143 | }); 144 | }); 145 | -------------------------------------------------------------------------------- /__tests__/features/fn_set_score_spec.js: -------------------------------------------------------------------------------- 1 | describe('#fn_setScore', () => { 2 | let testContext; 3 | 4 | beforeEach(() => { 5 | testContext = {}; 6 | }); 7 | 8 | beforeEach(() => { 9 | Helper.create('#el'); 10 | }); 11 | 12 | it('sets the score', () => { 13 | // given 14 | 15 | // when 16 | var raty = new Raty(document.querySelector('#el'), { score: 1 }).init(); 17 | 18 | // then 19 | expect(raty.score()).toEqual(1); 20 | }); 21 | 22 | describe('with :readOnly', () => { 23 | it('does not set the score', () => { 24 | // given 25 | var raty = new Raty(document.querySelector('#el'), { readOnly: true }).init(); 26 | 27 | // when 28 | raty.score(5); 29 | 30 | // then 31 | expect(raty.element.querySelector('input').value).toEqual(''); 32 | }); 33 | }); 34 | 35 | context('with :target', function () { 36 | beforeEach(() => { 37 | testContext.target = Helper.create('#target'); 38 | }); 39 | 40 | context('and :score greater then :number', function () { 41 | it('does not throw error', () => { 42 | // given 43 | var that = this; 44 | 45 | var raty = new Raty(document.querySelector('#el'), { target: '#target' }).init(); 46 | 47 | // when 48 | var lambda = function () { 49 | raty.score(6); 50 | }; 51 | 52 | // then 53 | expect(lambda).not.toThrow(); 54 | }); 55 | }); 56 | 57 | context('and :targetType', function () { 58 | context('as *score', function () { 59 | context('and :targetKeep', function () { 60 | context('as *true', function () { 61 | it('sets the value equal :number', () => { 62 | // given 63 | var raty = new Raty(document.querySelector('#el'), { 64 | target: '#target', 65 | targetType: 'score', 66 | targetKeep: true, 67 | }).init(); 68 | 69 | // when 70 | raty.score(6); 71 | 72 | // then 73 | expect(testContext.target.textContent).toEqual(raty.opt.number.toString()); 74 | }); 75 | 76 | it('sets the :score on target', () => { 77 | // given 78 | var raty = new Raty(document.querySelector('#el'), { 79 | target: '#target', 80 | targetType: 'score', 81 | targetKeep: true, 82 | }).init(); 83 | 84 | // when 85 | raty.score(1); 86 | 87 | // then 88 | expect(testContext.target.textContent).toEqual('1'); 89 | }); 90 | }); 91 | }); 92 | }); 93 | }); 94 | }); 95 | }); 96 | -------------------------------------------------------------------------------- /__tests__/features/icon_range_spec.js: -------------------------------------------------------------------------------- 1 | describe('#iconRange', () => { 2 | beforeEach(() => { 3 | var element = document.createElement('div'); 4 | element.id = 'element'; 5 | document.querySelector(`body`).appendChild(element); 6 | }); 7 | 8 | afterEach(() => { 9 | document.querySelector('#element').remove(); 10 | }); 11 | 12 | it('uses icon intervals', () => { 13 | // given 14 | var raty = new Raty(document.querySelector('#element'), { 15 | iconRange: [ 16 | { range: 2, on: 'star-off.png', off: 'star-off.png' }, 17 | { range: 3, on: 'star-off.png', off: 'cancel-off.png' }, 18 | { range: 4, on: 'star-off.png', off: 'cancel-on.png' }, 19 | { range: 5, on: 'star-off.png', off: 'star-half.png' }, 20 | ], 21 | }); 22 | 23 | // when 24 | raty.init(); 25 | 26 | // then 27 | var stars = raty.element.querySelectorAll('img'); 28 | 29 | expect(Helper.extension(stars[0].src)).toEqual('star-off.png'); 30 | expect(Helper.extension(stars[1].src)).toEqual('star-off.png'); 31 | expect(Helper.extension(stars[2].src)).toEqual('cancel-off.png'); 32 | expect(Helper.extension(stars[3].src)).toEqual('cancel-on.png'); 33 | expect(Helper.extension(stars[4].src)).toEqual('star-half.png'); 34 | }); 35 | 36 | context('when off icon is not especified', function () { 37 | it('uses the :starOff icon', () => { 38 | // given 39 | var raty = new Raty(document.querySelector('#element'), { 40 | iconRange: [ 41 | { range: 2, on: 'star-on.png', off: 'star-off.png' }, 42 | { range: 3, on: 'star-on.png', off: 'star-off.png' }, 43 | { range: 4, on: 'star-on.png', off: 'star-off.png' }, 44 | { range: 5, on: 'star-on.png' }, 45 | ], 46 | }); 47 | 48 | // when 49 | raty.init(); 50 | 51 | // then 52 | expect(Helper.extension(raty.element.querySelectorAll('img')[4].src)).toEqual('star-off.png'); 53 | }); 54 | }); 55 | 56 | context('on mouseover', function () { 57 | it('uses the on icon', () => { 58 | // given 59 | var raty = new Raty(document.querySelector('#element'), { 60 | iconRange: [ 61 | { range: 2, on: 'star-on.png', off: 'star-off.png' }, 62 | { range: 3, on: 'star-on.png', off: 'star-off.png' }, 63 | { range: 4, on: 'star-on.png', off: 'star-off.png' }, 64 | { range: 5, on: 'star-on.png', off: 'star-off.png' }, 65 | ], 66 | }).init(); 67 | 68 | var stars = raty.element.querySelectorAll('img'); 69 | 70 | // when 71 | Helper.trigger(stars[4], 'mouseover'); 72 | 73 | // then 74 | expect(Helper.extension(stars[0].src)).toEqual('star-on.png'); 75 | expect(Helper.extension(stars[1].src)).toEqual('star-on.png'); 76 | expect(Helper.extension(stars[2].src)).toEqual('star-on.png'); 77 | expect(Helper.extension(stars[3].src)).toEqual('star-on.png'); 78 | expect(Helper.extension(stars[4].src)).toEqual('star-on.png'); 79 | }); 80 | 81 | context('when on icon is not especified', function () { 82 | it('uses the :starOn icon', () => { 83 | // given 84 | var raty = new Raty(document.querySelector('#element'), { 85 | iconRange: [ 86 | { range: 2, off: 'star-off.png', on: 'star-on.png' }, 87 | { range: 3, off: 'star-off.png', on: 'star-on.png' }, 88 | { range: 4, off: 'star-off.png', on: 'star-on.png' }, 89 | { range: 5, off: 'star-off.png' }, 90 | ], 91 | }).init(); 92 | 93 | var stars = raty.element.querySelectorAll('img'); 94 | 95 | // when 96 | Helper.trigger(stars[4], 'mouseover'); 97 | 98 | // then 99 | expect(Helper.extension(stars[0].src)).toEqual('star-on.png'); 100 | expect(Helper.extension(stars[1].src)).toEqual('star-on.png'); 101 | expect(Helper.extension(stars[2].src)).toEqual('star-on.png'); 102 | expect(Helper.extension(stars[3].src)).toEqual('star-on.png'); 103 | expect(Helper.extension(stars[4].src)).toEqual('star-on.png'); 104 | }); 105 | }); 106 | }); 107 | 108 | context('on mouseout', function () { 109 | it('changes to off icons', () => { 110 | // given 111 | var raty = new Raty(document.querySelector('#element'), { 112 | iconRange: [ 113 | { range: 2, on: 'star-on.png', off: 'star-off.png' }, 114 | { range: 3, on: 'star-on.png', off: 'star-off.png' }, 115 | { range: 4, on: 'star-on.png', off: 'star-off.png' }, 116 | { range: 5, on: 'star-on.png', off: 'star-off.png' }, 117 | ], 118 | }).init(); 119 | 120 | var stars = raty.element.querySelectorAll('img'); 121 | 122 | // when 123 | Helper.trigger(stars[4], 'mouseover'); 124 | Helper.trigger(raty.element, 'mouseleave'); 125 | 126 | // then 127 | expect(Helper.extension(stars[0].src)).toEqual('star-off.png'); 128 | expect(Helper.extension(stars[1].src)).toEqual('star-off.png'); 129 | expect(Helper.extension(stars[2].src)).toEqual('star-off.png'); 130 | expect(Helper.extension(stars[3].src)).toEqual('star-off.png'); 131 | expect(Helper.extension(stars[4].src)).toEqual('star-off.png'); 132 | }); 133 | 134 | it('keeps the score value', () => { 135 | // given 136 | var raty = new Raty(document.querySelector('#element'), { 137 | iconRange: [ 138 | { range: 2, on: 'star-on.png', off: 'star-off.png' }, 139 | { range: 3, on: 'star-on.png', off: 'star-off.png' }, 140 | { range: 4, on: 'star-on.png', off: 'star-off.png' }, 141 | { range: 5, on: 'star-on.png', off: 'star-off.png' }, 142 | ], 143 | score: 1, 144 | }).init(); 145 | 146 | // when 147 | Helper.trigger(raty.element.querySelectorAll('img')[4], 'mouseover'); 148 | Helper.trigger(raty.element, 'mouseleave'); 149 | 150 | // then 151 | expect(raty.element.querySelector('input').value).toEqual('1'); 152 | }); 153 | 154 | context('when off icon is not especified', function () { 155 | it('uses the :starOff icon', () => { 156 | // given 157 | var raty = new Raty(document.querySelector('#element'), { 158 | iconRange: [ 159 | { range: 2, on: 'star-on.png', off: 'star-off.png' }, 160 | { range: 3, on: 'star-on.png', off: 'star-off.png' }, 161 | { range: 4, on: 'star-on.png', off: 'star-off.png' }, 162 | { range: 5, on: 'star-on.png' }, 163 | ], 164 | }).init(); 165 | 166 | var img = raty.element.querySelectorAll('img')[4]; 167 | 168 | // when 169 | Helper.trigger(img, 'mouseover'); 170 | Helper.trigger(raty.element, 'mouseleave'); 171 | 172 | // then 173 | expect(Helper.extension(img.src)).toEqual('star-off.png'); 174 | }); 175 | }); 176 | }); 177 | }); 178 | -------------------------------------------------------------------------------- /__tests__/features/markup_spec.js: -------------------------------------------------------------------------------- 1 | describe('markup', () => { 2 | beforeEach(() => { 3 | var element = document.createElement('div'); 4 | element.dataset.raty = undefined; 5 | var element1 = element.cloneNode(); 6 | document.querySelector(`body`).appendChild(element); 7 | document.querySelector(`body`).appendChild(element1); 8 | }); 9 | 10 | it('creates the default markup', () => { 11 | // given / when 12 | var ratys = []; 13 | 14 | document.querySelectorAll('[data-raty]').forEach(function (element) { 15 | ratys.push(new Raty(element).init()); 16 | }); 17 | 18 | // then 19 | var starsOne = ratys[0].element.querySelectorAll('img'); 20 | 21 | expect(starsOne[0].title).toEqual('bad'); 22 | expect(starsOne[1].title).toEqual('poor'); 23 | expect(starsOne[2].title).toEqual('regular'); 24 | expect(starsOne[3].title).toEqual('good'); 25 | expect(starsOne[4].title).toEqual('gorgeous'); 26 | 27 | expect(Helper.extension(starsOne[0].getAttribute('src'))).toEqual('star-off.png'); 28 | expect(Helper.extension(starsOne[1].getAttribute('src'))).toEqual('star-off.png'); 29 | expect(Helper.extension(starsOne[2].getAttribute('src'))).toEqual('star-off.png'); 30 | expect(Helper.extension(starsOne[3].getAttribute('src'))).toEqual('star-off.png'); 31 | expect(Helper.extension(starsOne[4].getAttribute('src'))).toEqual('star-off.png'); 32 | 33 | var scoreOne = ratys[0].element.querySelector('input'); 34 | 35 | expect(scoreOne.type).toEqual('hidden'); 36 | expect(scoreOne.name).toEqual('score'); 37 | expect(scoreOne.value).toEqual(''); 38 | 39 | var starsOne = ratys[1].element.querySelectorAll('img'); 40 | 41 | expect(starsOne[0].title).toEqual('bad'); 42 | expect(starsOne[1].title).toEqual('poor'); 43 | expect(starsOne[2].title).toEqual('regular'); 44 | expect(starsOne[3].title).toEqual('good'); 45 | expect(starsOne[4].title).toEqual('gorgeous'); 46 | 47 | expect(Helper.extension(starsOne[0].getAttribute('src'))).toEqual('star-off.png'); 48 | expect(Helper.extension(starsOne[1].getAttribute('src'))).toEqual('star-off.png'); 49 | expect(Helper.extension(starsOne[2].getAttribute('src'))).toEqual('star-off.png'); 50 | expect(Helper.extension(starsOne[3].getAttribute('src'))).toEqual('star-off.png'); 51 | expect(Helper.extension(starsOne[4].getAttribute('src'))).toEqual('star-off.png'); 52 | 53 | var scoreOne = ratys[0].element.querySelector('input'); 54 | 55 | expect(scoreOne.type).toEqual('hidden'); 56 | expect(scoreOne.name).toEqual('score'); 57 | expect(scoreOne.value).toEqual(''); 58 | }); 59 | }); 60 | -------------------------------------------------------------------------------- /__tests__/features/mouseout_spec.js: -------------------------------------------------------------------------------- 1 | describe('#mouseout', () => { 2 | beforeEach(() => { 3 | Helper.create('#el'); 4 | }); 5 | 6 | it('has "this" scope as the object instance ', () => { 7 | // given 8 | var raty = new Raty(document.querySelector('#el'), { 9 | mouseout: function () { 10 | this.result = this; 11 | }, 12 | }).init(); 13 | 14 | // when 15 | Helper.trigger(raty.element, 'mouseleave'); 16 | 17 | // then 18 | expect(raty.result).toBe(raty); 19 | }); 20 | 21 | it('receives the score as integer', () => { 22 | // given 23 | var raty = new Raty(document.querySelector('#el'), { 24 | mouseout: function (score) { 25 | this.result = score; 26 | }, 27 | score: 4, 28 | }).init(); 29 | 30 | // when 31 | Helper.trigger(raty.element, 'mouseleave'); 32 | 33 | expect(raty.result).toEqual(4); 34 | }); 35 | 36 | it('receives the element', () => { 37 | // given 38 | var raty = new Raty(document.querySelector('#el'), { 39 | mouseout: function (_score, element) { 40 | this.result = element; 41 | }, 42 | }).init(); 43 | 44 | // when 45 | Helper.trigger(raty.element, 'mouseleave'); 46 | 47 | // then 48 | expect(raty.result).toEqual(document.querySelector('#el')); 49 | }); 50 | 51 | it('receives the mouse event', () => { 52 | // given 53 | var raty = new Raty(document.querySelector('#el'), { 54 | mouseout: function (_score, _element, evt) { 55 | this.result = evt; 56 | }, 57 | }).init(); 58 | 59 | // when 60 | Helper.trigger(raty.element, 'mouseleave'); 61 | 62 | // then 63 | expect(raty.result.type).toEqual('mouseleave'); 64 | }); 65 | 66 | context('without score', function () { 67 | it('receives undefined', () => { 68 | // given 69 | var raty = new Raty(document.querySelector('#el'), { 70 | mouseout: function (score) { 71 | this.result = score; 72 | }, 73 | }).init(); 74 | 75 | // when 76 | Helper.trigger(raty.element, 'mouseleave'); 77 | 78 | // then 79 | expect(raty.result).toEqual(undefined); 80 | }); 81 | }); 82 | 83 | context('with score', function () { 84 | it('receives the score value as number', () => { 85 | // given 86 | var raty = new Raty(document.querySelector('#el'), { 87 | score: 1, 88 | mouseout: function (score) { 89 | this.result = score; 90 | }, 91 | }).init(); 92 | 93 | // when 94 | Helper.trigger(raty.element, 'mouseleave'); 95 | 96 | // then 97 | expect(typeof raty.result).toEqual('number'); 98 | }); 99 | }); 100 | 101 | context('when acts on :cancel', function () { 102 | it('has "this" scope as the object instance ', () => { 103 | // given 104 | var raty = new Raty(document.querySelector('#el'), { 105 | cancelButton: true, 106 | mouseout: function () { 107 | this.result = this; 108 | }, 109 | }).init(); 110 | 111 | var cancel = raty.element.querySelector('.raty-cancel'); 112 | 113 | // when 114 | Helper.trigger(cancel, 'mouseleave'); 115 | 116 | // then 117 | expect(raty.result).toBe(raty); 118 | }); 119 | 120 | context('without score', function () { 121 | it('receives undefined', () => { 122 | // given 123 | var raty = new Raty(document.querySelector('#el'), { 124 | cancelButton: true, 125 | mouseout: function (score) { 126 | this.result = score; 127 | }, 128 | }).init(); 129 | 130 | var cancel = raty.element.querySelector('.raty-cancel'); 131 | 132 | // when 133 | Helper.trigger(cancel, 'mouseleave'); 134 | 135 | // then 136 | expect(raty.result).toEqual(undefined); 137 | }); 138 | }); 139 | 140 | context('with score', function () { 141 | it('receives the score value as number', () => { 142 | // given 143 | var raty = new Raty(document.querySelector('#el'), { 144 | score: 1, 145 | cancelButton: true, 146 | mouseout: function (score) { 147 | this.result = score; 148 | }, 149 | }).init(); 150 | 151 | var cancel = raty.element.querySelector('.raty-cancel'); 152 | 153 | // when 154 | Helper.trigger(cancel, 'mouseleave'); 155 | 156 | // then 157 | expect(raty.result).toEqual(1); 158 | }); 159 | }); 160 | 161 | it('receives the element', () => { 162 | // given 163 | var raty = new Raty(document.querySelector('#el'), { 164 | cancelButton: true, 165 | mouseout: function (_score, element) { 166 | this.result = element; 167 | }, 168 | }).init(); 169 | 170 | var cancel = raty.element.querySelector('.raty-cancel'); 171 | 172 | // when 173 | Helper.trigger(cancel, 'mouseleave'); 174 | 175 | // then 176 | expect(raty.result).toEqual(document.querySelector('#el')); 177 | }); 178 | 179 | it('receives the mouse event', () => { 180 | // given 181 | var raty = new Raty(document.querySelector('#el'), { 182 | cancelButton: true, 183 | mouseout: function (_score, _element, evt) { 184 | this.result = evt; 185 | }, 186 | }).init(); 187 | 188 | var cancel = raty.element.querySelector('.raty-cancel'); 189 | 190 | // when 191 | Helper.trigger(cancel, 'mouseleave'); 192 | 193 | // then 194 | expect(raty.result.type).toEqual('mouseleave'); 195 | }); 196 | }); 197 | }); 198 | -------------------------------------------------------------------------------- /__tests__/features/mouseover_spec.js: -------------------------------------------------------------------------------- 1 | describe('#mouseover', () => { 2 | beforeEach(() => { 3 | Helper.create('#el'); 4 | }); 5 | 6 | it('has "this" scope as the object instance ', () => { 7 | // given 8 | var raty = new Raty(document.querySelector('#el'), { 9 | cancelButton: true, 10 | mouseover: function () { 11 | this.result = this; 12 | }, 13 | }).init(); 14 | 15 | var star = Helper.last(raty.element.querySelectorAll('img')); 16 | 17 | // when 18 | Helper.trigger(star, 'mouseover'); 19 | 20 | // then 21 | expect(raty.result).toBe(raty); 22 | }); 23 | 24 | it('receives the score as integer', () => { 25 | // given 26 | var raty = new Raty(document.querySelector('#el'), { 27 | mouseover: function (score) { 28 | this.result = score; 29 | }, 30 | }).init(); 31 | 32 | var star = Helper.last(raty.element.querySelectorAll('img')); 33 | 34 | // when 35 | Helper.trigger(star, 'mouseover'); 36 | 37 | expect(raty.result).toEqual(5); 38 | }); 39 | 40 | it('receives the element', () => { 41 | // given 42 | var raty = new Raty(document.querySelector('#el'), { 43 | mouseover: function (_score, element) { 44 | this.result = element; 45 | }, 46 | }).init(); 47 | 48 | var star = Helper.last(raty.element.querySelectorAll('img')); 49 | 50 | // when 51 | Helper.trigger(star, 'mouseover'); 52 | 53 | // then 54 | expect(raty.result).toEqual(document.querySelector('#el')); 55 | }); 56 | 57 | it('receives the mouse event', () => { 58 | // given 59 | var raty = new Raty(document.querySelector('#el'), { 60 | mouseover: function (_score, _element, evt) { 61 | this.result = evt; 62 | }, 63 | }).init(); 64 | 65 | var star = Helper.last(raty.element.querySelectorAll('img')); 66 | 67 | // when 68 | Helper.trigger(star, 'mouseover'); 69 | 70 | // then 71 | expect(raty.result.type).toEqual('mouseover'); 72 | }); 73 | 74 | context('with return as undefined', function () { 75 | it('executes mouseover behavior', () => { 76 | // given 77 | var raty = new Raty(document.querySelector('#el'), { 78 | mouseover: function () {}, 79 | }).init(); 80 | 81 | var stars = raty.element.querySelectorAll('img'); 82 | 83 | // when 84 | Helper.trigger(stars[0], 'mouseover'); 85 | 86 | // then 87 | expect(Helper.extension(stars[0].src)).toEqual('star-on.png'); 88 | expect(Helper.extension(stars[1].src)).toEqual('star-off.png'); 89 | expect(Helper.extension(stars[2].src)).toEqual('star-off.png'); 90 | expect(Helper.extension(stars[3].src)).toEqual('star-off.png'); 91 | expect(Helper.extension(stars[4].src)).toEqual('star-off.png'); 92 | }); 93 | 94 | it('turns on the stars', () => { 95 | // given 96 | var raty = new Raty(document.querySelector('#el'), { 97 | mouseover: function () {}, 98 | }).init(); 99 | 100 | var stars = raty.element.querySelectorAll('img'); 101 | 102 | // when 103 | Helper.trigger(stars[0], 'mouseover'); 104 | 105 | // then 106 | expect(Helper.extension(stars[0].src)).toEqual('star-on.png'); 107 | expect(Helper.extension(stars[1].src)).toEqual('star-off.png'); 108 | expect(Helper.extension(stars[2].src)).toEqual('star-off.png'); 109 | expect(Helper.extension(stars[3].src)).toEqual('star-off.png'); 110 | expect(Helper.extension(stars[4].src)).toEqual('star-off.png'); 111 | }); 112 | }); 113 | 114 | context('with :cancel', function () { 115 | it('has "this" scope as the object instance ', () => { 116 | // given 117 | var raty = new Raty(document.querySelector('#el'), { 118 | cancelButton: true, 119 | mouseover: function () { 120 | this.result = this; 121 | }, 122 | }).init(); 123 | 124 | var cancel = raty.element.querySelector('.raty-cancel'); 125 | 126 | // when 127 | Helper.trigger(cancel, 'mouseover'); 128 | 129 | // then 130 | expect(raty.result).toBe(raty); 131 | }); 132 | 133 | it('receives the score as null', () => { 134 | // given 135 | var raty = new Raty(document.querySelector('#el'), { 136 | cancelButton: true, 137 | mouseover: function (score) { 138 | this.result = score; 139 | }, 140 | }).init(); 141 | 142 | var cancel = raty.element.querySelector('.raty-cancel'); 143 | 144 | // when 145 | Helper.trigger(cancel, 'mouseover'); 146 | 147 | expect(raty.result).toEqual(null); 148 | }); 149 | 150 | it('receives the element', () => { 151 | // given 152 | var raty = new Raty(document.querySelector('#el'), { 153 | cancelButton: true, 154 | mouseover: function (_score, element) { 155 | this.result = element; 156 | }, 157 | }).init(); 158 | 159 | var cancel = raty.element.querySelector('.raty-cancel'); 160 | 161 | // when 162 | Helper.trigger(cancel, 'mouseover'); 163 | 164 | // then 165 | expect(raty.result).toEqual(document.querySelector('#el')); 166 | }); 167 | 168 | it('receives the mouse event', () => { 169 | // given 170 | var raty = new Raty(document.querySelector('#el'), { 171 | cancelButton: true, 172 | mouseover: function (_score, _element, evt) { 173 | this.result = evt; 174 | }, 175 | }).init(); 176 | 177 | var cancel = raty.element.querySelector('.raty-cancel'); 178 | 179 | // when 180 | Helper.trigger(cancel, 'mouseover'); 181 | 182 | // then 183 | expect(raty.result.type).toEqual('mouseover'); 184 | }); 185 | }); 186 | 187 | context('on mouseover without mouseover', function () { 188 | it('changes the stars to on', () => { 189 | // given 190 | var raty = new Raty(document.querySelector('#el')).init(); 191 | var stars = raty.element.querySelectorAll('img'); 192 | 193 | // when 194 | Helper.trigger(Helper.last(stars), 'mouseover'); 195 | 196 | // then 197 | expect(Helper.extension(stars[0].src)).toEqual('star-on.png'); 198 | expect(Helper.extension(stars[1].src)).toEqual('star-on.png'); 199 | expect(Helper.extension(stars[2].src)).toEqual('star-on.png'); 200 | expect(Helper.extension(stars[3].src)).toEqual('star-on.png'); 201 | expect(Helper.extension(stars[4].src)).toEqual('star-on.png'); 202 | }); 203 | }); 204 | }); 205 | -------------------------------------------------------------------------------- /__tests__/features/number_max_spec.js: -------------------------------------------------------------------------------- 1 | describe('#numberMax', () => { 2 | beforeEach(() => { 3 | Helper.create('#el'); 4 | }); 5 | 6 | it('limits the max of "number" option', () => { 7 | // given 8 | var raty = new Raty(document.querySelector('#el'), { number: 2, numberMax: 1 }); 9 | 10 | // when 11 | raty.init(); 12 | 13 | // then 14 | expect(raty.opt.number).toEqual(1); 15 | }); 16 | 17 | it('limits the min of "number" option', () => { 18 | // given 19 | var raty = new Raty(document.querySelector('#el'), { number: -1 }); 20 | 21 | // when 22 | raty.init(); 23 | 24 | // then 25 | expect(raty.opt.number).toEqual(1); 26 | }); 27 | }); 28 | -------------------------------------------------------------------------------- /__tests__/features/number_spec.js: -------------------------------------------------------------------------------- 1 | describe('#number', () => { 2 | it('accepts callback return and has the correct arguments', () => { 3 | // given 4 | Helper.create('#el'); 5 | 6 | var raty = new Raty(document.querySelector('#el'), { 7 | number: function (element) { 8 | this._this = this; 9 | this._element = element; 10 | 11 | return 10; 12 | }, 13 | }); 14 | 15 | // when 16 | raty.init(); 17 | 18 | // then 19 | expect(raty.element.querySelectorAll('img').length).toEqual(10); 20 | expect(raty._this).toBe(raty); 21 | expect(raty._element).toEqual(document.querySelector('#el')); 22 | }); 23 | 24 | it('changes the number of stars', () => { 25 | // given 26 | Helper.create('#el'); 27 | 28 | var raty = new Raty(document.querySelector('#el'), { number: 1 }); 29 | 30 | // when 31 | raty.init(); 32 | 33 | // then 34 | expect(raty.element.querySelectorAll('img').length).toEqual(1); 35 | }); 36 | 37 | it('accepts number as string', () => { 38 | // given 39 | Helper.create('#el'); 40 | 41 | var raty = new Raty(document.querySelector('#el'), { number: '1' }); 42 | 43 | // when 44 | raty.init(); 45 | 46 | // then 47 | expect(raty.element.querySelectorAll('img').length).toEqual(1); 48 | }); 49 | 50 | it('accepts callback', () => { 51 | // given 52 | Helper.create('#el'); 53 | 54 | var raty = new Raty(document.querySelector('#el'), { 55 | number: function () { 56 | return 1; 57 | }, 58 | }); 59 | 60 | // when 61 | raty.init(); 62 | 63 | // then 64 | expect(raty.opt.number).toEqual(1); 65 | }); 66 | 67 | it('accepts data attribute', () => { 68 | // given 69 | Helper._append('div', { 'data-number': 3 }); 70 | 71 | var raty = new Raty(document.querySelector('[data-number]')); 72 | 73 | // when 74 | raty.init(); 75 | 76 | // then 77 | expect(raty.opt.number).toEqual(3); 78 | }); 79 | }); 80 | -------------------------------------------------------------------------------- /__tests__/features/path_spec.js: -------------------------------------------------------------------------------- 1 | describe('#path', () => { 2 | beforeEach(() => { 3 | Helper.create('#el'); 4 | }); 5 | 6 | it('accepts callback return and has the correct arguments', () => { 7 | // given 8 | var raty = new Raty(document.querySelector('#el'), { 9 | path: function (element) { 10 | this._this = this; 11 | this._element = element; 12 | 13 | return 'path'; 14 | }, 15 | }); 16 | 17 | // when 18 | raty.init(); 19 | 20 | // then 21 | expect(raty.opt.path).toEqual('path/'); 22 | expect(raty._this).toBe(raty); 23 | expect(raty._element).toEqual(document.querySelector('#el')); 24 | }); 25 | 26 | it('changes the path', () => { 27 | // given 28 | var raty = new Raty(document.querySelector('#el'), { path: '../demo/images' }); 29 | 30 | // when 31 | raty.init(); 32 | 33 | // then 34 | var stars = raty.element.querySelectorAll('img'); 35 | 36 | expect(stars[0].getAttribute('src')).toEqual('../demo/images/star-off.png'); 37 | expect(stars[1].getAttribute('src')).toEqual('../demo/images/star-off.png'); 38 | expect(stars[2].getAttribute('src')).toEqual('../demo/images/star-off.png'); 39 | expect(stars[3].getAttribute('src')).toEqual('../demo/images/star-off.png'); 40 | expect(stars[4].getAttribute('src')).toEqual('../demo/images/star-off.png'); 41 | }); 42 | 43 | it('accepts data attribute', () => { 44 | // given 45 | Helper._append('div', { 'data-path': 'custom' }); 46 | 47 | var raty = new Raty(document.querySelector('[data-path]')); 48 | 49 | // when 50 | raty.init(); 51 | 52 | // then 53 | expect(raty.opt.path).toEqual('custom/'); 54 | }); 55 | 56 | context('without slash on the final', function () { 57 | it('receives the slash', () => { 58 | // given 59 | var raty = new Raty(document.querySelector('#el'), { path: '../demo/images' }); 60 | 61 | // when 62 | raty.init(); 63 | 64 | // then 65 | expect(raty.opt.path).toEqual('../demo/images/'); 66 | }); 67 | }); 68 | 69 | context('with slash on the final', function () { 70 | it('is keeped', () => { 71 | // given 72 | var raty = new Raty(document.querySelector('#el'), { path: '../demo/images/' }); 73 | 74 | // when 75 | raty.init(); 76 | 77 | // then 78 | expect(raty.opt.path).toEqual('../demo/images/'); 79 | }); 80 | }); 81 | 82 | context('as null', function () { 83 | it('replace to an empty string', () => { 84 | // given 85 | var raty = new Raty(document.querySelector('#el'), { path: null }); 86 | 87 | // when 88 | raty.init(); 89 | 90 | // then 91 | var stars = raty.element.querySelectorAll('img'); 92 | 93 | expect(stars[0].getAttribute('src')).toEqual('star-off.png'); 94 | expect(stars[1].getAttribute('src')).toEqual('star-off.png'); 95 | expect(stars[2].getAttribute('src')).toEqual('star-off.png'); 96 | expect(stars[3].getAttribute('src')).toEqual('star-off.png'); 97 | expect(stars[4].getAttribute('src')).toEqual('star-off.png'); 98 | }); 99 | }); 100 | 101 | context('as undefined', function () { 102 | it('replace to an empty string', () => { 103 | // given 104 | var raty = new Raty(document.querySelector('#el')); 105 | 106 | // when 107 | raty.init(); 108 | 109 | // then 110 | var stars = raty.element.querySelectorAll('img'); 111 | 112 | expect(stars[0].getAttribute('src')).toEqual('star-off.png'); 113 | expect(stars[1].getAttribute('src')).toEqual('star-off.png'); 114 | expect(stars[2].getAttribute('src')).toEqual('star-off.png'); 115 | expect(stars[3].getAttribute('src')).toEqual('star-off.png'); 116 | expect(stars[4].getAttribute('src')).toEqual('star-off.png'); 117 | }); 118 | }); 119 | 120 | context('with :cancel', function () { 121 | it('changes the path', () => { 122 | // given 123 | var raty = new Raty(document.querySelector('#el'), { cancelButton: true, path: '../demo/images' }); 124 | 125 | // when 126 | raty.init(); 127 | 128 | // then 129 | expect(raty.element.querySelector('.raty-cancel').getAttribute('src')).toEqual('../demo/images/cancel-off.png'); 130 | }); 131 | }); 132 | 133 | context('with :iconRange', function () { 134 | it('changes the path', () => { 135 | // given 136 | var raty = new Raty(document.querySelector('#el'), { iconRange: [{ range: 1 }], path: '../demo/images' }); 137 | 138 | // when 139 | raty.init(); 140 | 141 | // then 142 | expect(raty.element.querySelector('img').getAttribute('src')).toEqual('../demo/images/star-off.png'); 143 | }); 144 | }); 145 | }); 146 | -------------------------------------------------------------------------------- /__tests__/features/score_name_spec.js: -------------------------------------------------------------------------------- 1 | describe('#scoreName', () => { 2 | it('changes the score field name', () => { 3 | // given 4 | Helper.create('#el'); 5 | 6 | var raty = new Raty(document.querySelector('#el'), { scoreName: 'double' }); 7 | 8 | // when 9 | raty.init(); 10 | 11 | // then 12 | expect(raty.element.querySelector('input').name).toEqual('double'); 13 | }); 14 | 15 | it('accepts callback return and has the correct arguments', () => { 16 | // given 17 | Helper.create('#el'); 18 | 19 | var raty = new Raty(document.querySelector('#el'), { 20 | scoreName: function (element) { 21 | this._this = this; 22 | this._element = element; 23 | 24 | return 'name'; 25 | }, 26 | }); 27 | 28 | // when 29 | raty.init(); 30 | 31 | // then 32 | expect(raty.opt.scoreName).toEqual('name'); 33 | expect(raty._this).toBe(raty); 34 | expect(raty._element).toEqual(document.querySelector('#el')); 35 | }); 36 | }); 37 | -------------------------------------------------------------------------------- /__tests__/features/score_spec.js: -------------------------------------------------------------------------------- 1 | describe('#score', () => { 2 | it('can be initialized on bind', () => { 3 | // given 4 | Helper.create('#el'); 5 | 6 | var raty = new Raty(document.querySelector('#el'), { score: 1 }); 7 | 8 | // when 9 | raty.init(); 10 | 11 | // then 12 | expect(raty.element.querySelector('input').value).toEqual('1'); 13 | }); 14 | 15 | it('turns on stars', () => { 16 | // given 17 | Helper.create('#el'); 18 | 19 | var raty = new Raty(document.querySelector('#el'), { score: 5 }); 20 | 21 | // when 22 | raty.init(); 23 | 24 | // then 25 | expect(Helper.extension(raty.element.querySelector('img').src)).toEqual('star-on.png'); 26 | }); 27 | 28 | it('accepts callback return and has the correct arguments', () => { 29 | // given 30 | Helper.create('#el'); 31 | 32 | var raty = new Raty(document.querySelector('#el'), { 33 | score: function (element) { 34 | this._this = this; 35 | this._element = element; 36 | 37 | return 1; 38 | }, 39 | }); 40 | 41 | // when 42 | raty.init(); 43 | 44 | // then 45 | expect(raty.opt.score).toEqual(1); 46 | expect(raty._this).toBe(raty); 47 | expect(raty._element).toEqual(document.querySelector('#el')); 48 | }); 49 | 50 | it('accepts data attribute', () => { 51 | // given 52 | Helper._append('div', { 'data-score': 3 }); 53 | 54 | // when 55 | var raty = new Raty(document.querySelector('[data-score]')); 56 | 57 | // then 58 | expect(raty.opt.score).toEqual(3); 59 | }); 60 | 61 | context('with negative number', function () { 62 | it('does not set the score', () => { 63 | // given 64 | Helper.create('#el'); 65 | 66 | var raty = new Raty(document.querySelector('#el'), { score: -1 }); 67 | 68 | // when 69 | raty.init(); 70 | 71 | // then 72 | expect(raty.element.querySelector('input').value).toEqual(''); 73 | }); 74 | }); 75 | 76 | context('with :readOnly', function () { 77 | it('becomes readOnly too', () => { 78 | // given 79 | Helper.create('#el'); 80 | 81 | var raty = new Raty(document.querySelector('#el'), { readOnly: true }); 82 | 83 | // when 84 | raty.init(); 85 | 86 | // then 87 | expect(raty.element.querySelector('input').readOnly).toEqual(true); 88 | }); 89 | }); 90 | 91 | context('with value greater then numbers', function () { 92 | it('receives the number of star as value', () => { 93 | // given 94 | Helper.create('#el'); 95 | 96 | var raty = new Raty(document.querySelector('#el'), { score: 100 }); 97 | 98 | // when 99 | raty.init(); 100 | 101 | // then 102 | expect(raty.opt.score).toEqual(raty.opt.number); 103 | }); 104 | }); 105 | }); 106 | -------------------------------------------------------------------------------- /__tests__/features/single_spec.js: -------------------------------------------------------------------------------- 1 | describe('#single', () => { 2 | beforeEach(() => { 3 | var element = document.createElement('div'); 4 | element.id = 'element'; 5 | document.querySelector(`body`).appendChild(element); 6 | }); 7 | 8 | afterEach(() => { 9 | document.querySelector('#element').remove(); 10 | }); 11 | 12 | context('on mouseover', function () { 13 | it('turns on just one icon', () => { 14 | // given 15 | var raty = new Raty(document.querySelector('#element'), { single: true }).init(); 16 | var stars = raty.element.querySelectorAll('img'); 17 | 18 | // when 19 | Helper.trigger(stars[2], 'mouseover'); 20 | 21 | // then 22 | expect(Helper.extension(stars[0].src)).toEqual('star-off.png'); 23 | expect(Helper.extension(stars[1].src)).toEqual('star-off.png'); 24 | expect(Helper.extension(stars[2].src)).toEqual('star-on.png'); 25 | expect(Helper.extension(stars[3].src)).toEqual('star-off.png'); 26 | expect(Helper.extension(stars[4].src)).toEqual('star-off.png'); 27 | }); 28 | 29 | context('with :iconRange', function () { 30 | it('shows just on icon', () => { 31 | // given 32 | var raty = new Raty(document.querySelector('#element'), { 33 | iconRange: [ 34 | { range: 2, on: 'star-on.png', off: 'star-off.png' }, 35 | { range: 3, on: 'star-on.png', off: 'star-off.png' }, 36 | { range: 4, on: 'star-on.png', off: 'star-off.png' }, 37 | { range: 5, on: 'star-on.png', off: 'star-off.png' }, 38 | ], 39 | single: true, 40 | }).init(); 41 | 42 | var stars = raty.element.querySelectorAll('img'); 43 | 44 | // when 45 | Helper.trigger(stars[3], 'mouseover'); 46 | 47 | // then 48 | expect(Helper.extension(stars[0].src)).toEqual('star-off.png'); 49 | expect(Helper.extension(stars[1].src)).toEqual('star-off.png'); 50 | expect(Helper.extension(stars[2].src)).toEqual('star-off.png'); 51 | expect(Helper.extension(stars[3].src)).toEqual('star-on.png'); 52 | expect(Helper.extension(stars[4].src)).toEqual('star-off.png'); 53 | }); 54 | }); 55 | }); 56 | 57 | context('on click', function () { 58 | it('turns on the star', () => { 59 | // given 60 | var raty = new Raty(document.querySelector('#element'), { single: true }).init(); 61 | var stars = raty.element.querySelectorAll('img'); 62 | 63 | // when 64 | Helper.trigger(stars[2], 'mouseover'); 65 | Helper.trigger(stars[2], 'click'); 66 | 67 | // then 68 | expect(Helper.extension(stars[0].src)).toEqual('star-off.png'); 69 | expect(Helper.extension(stars[1].src)).toEqual('star-off.png'); 70 | expect(Helper.extension(stars[2].src)).toEqual('star-on.png'); 71 | expect(Helper.extension(stars[3].src)).toEqual('star-off.png'); 72 | expect(Helper.extension(stars[4].src)).toEqual('star-off.png'); 73 | }); 74 | 75 | context('on mouseout', function () { 76 | it('keeps the score', () => { 77 | // given 78 | var raty = new Raty(document.querySelector('#element'), { single: true }).init(); 79 | var stars = raty.element.querySelectorAll('img'); 80 | 81 | // when 82 | Helper.trigger(stars[2], 'mouseover'); 83 | Helper.trigger(stars[2], 'click'); 84 | Helper.trigger(stars[2], 'mouseleave'); 85 | 86 | // then 87 | expect(Helper.extension(stars[0].src)).toEqual('star-off.png'); 88 | expect(Helper.extension(stars[1].src)).toEqual('star-off.png'); 89 | expect(Helper.extension(stars[2].src)).toEqual('star-on.png'); 90 | expect(Helper.extension(stars[3].src)).toEqual('star-off.png'); 91 | expect(Helper.extension(stars[4].src)).toEqual('star-off.png'); 92 | }); 93 | 94 | context('and :iconRange', function () { 95 | it('keeps the score', () => { 96 | // given 97 | var raty = new Raty(document.querySelector('#element'), { 98 | single: true, 99 | iconRange: [ 100 | { range: 2, on: 'a.png', off: 'a-off.png' }, 101 | { range: 3, on: 'b.png', off: 'b-off.png' }, 102 | { range: 4, on: 'c.png', off: 'c-off.png' }, 103 | { range: 5, on: 'd.png', off: 'd-off.png' }, 104 | ], 105 | }).init(); 106 | 107 | var stars = raty.element.querySelectorAll('img'); 108 | 109 | // when 110 | Helper.trigger(stars[3], 'mouseover'); 111 | Helper.trigger(stars[3], 'click'); 112 | Helper.trigger(stars[3], 'mouseleave'); 113 | 114 | // then 115 | expect(Helper.extension(stars[0].src)).toEqual('a-off.png'); 116 | expect(Helper.extension(stars[1].src)).toEqual('a-off.png'); 117 | expect(Helper.extension(stars[2].src)).toEqual('b-off.png'); 118 | expect(Helper.extension(stars[3].src)).toEqual('c.png'); 119 | expect(Helper.extension(stars[4].src)).toEqual('d-off.png'); 120 | }); 121 | }); 122 | }); 123 | }); 124 | }); 125 | -------------------------------------------------------------------------------- /__tests__/features/space_spec.js: -------------------------------------------------------------------------------- 1 | describe('#space', () => { 2 | beforeEach(() => { 3 | var element = document.createElement('div'); 4 | element.id = 'element'; 5 | document.querySelector(`body`).appendChild(element); 6 | }); 7 | 8 | afterEach(() => { 9 | document.querySelector('#element').remove(); 10 | }); 11 | 12 | context('when off', function () { 13 | it('keeps the spaces', () => { 14 | // given 15 | var raty = new Raty(document.querySelector('#element'), { space: true }); 16 | 17 | // when 18 | raty.init(); 19 | 20 | // then 21 | expect(raty.element.textContent.length).toEqual(4); 22 | }); 23 | 24 | context('with :cancel', function () { 25 | it('adds on more space', () => { 26 | // given 27 | var raty = new Raty(document.querySelector('#element'), { cancelButton: true, space: true }); 28 | 29 | // when 30 | raty.init(); 31 | 32 | // then 33 | expect(raty.element.textContent.length).toEqual(5); 34 | }); 35 | }); 36 | }); 37 | 38 | context('when off', function () { 39 | it('takes off the spaces', () => { 40 | // given 41 | var raty = new Raty(document.querySelector('#element'), { space: false }); 42 | 43 | // when 44 | raty.init(); 45 | 46 | // then 47 | expect(raty.element.textContent.length).toEqual(0); 48 | }); 49 | 50 | context('with :cancel', function () { 51 | it('keeps the cancel space', () => { 52 | // given 53 | var raty = new Raty(document.querySelector('#element'), { cancelButton: true, space: false }); 54 | 55 | // when 56 | raty.init(); 57 | 58 | // then 59 | expect(raty.element.textContent.length).toEqual(1); 60 | }); 61 | }); 62 | }); 63 | }); 64 | -------------------------------------------------------------------------------- /__tests__/features/star_off_spec.js: -------------------------------------------------------------------------------- 1 | describe('#starOff', () => { 2 | it('changes the stars off', () => { 3 | // given 4 | Helper.create('#el'); 5 | 6 | var raty = new Raty(document.querySelector('#el'), { starOff: 'star-half.png' }); 7 | 8 | // when 9 | raty.init(); 10 | 11 | // then 12 | var stars = raty.element.querySelectorAll('img'); 13 | 14 | expect(Helper.extension(stars[0].src)).toEqual('star-half.png'); 15 | expect(Helper.extension(stars[1].src)).toEqual('star-half.png'); 16 | expect(Helper.extension(stars[2].src)).toEqual('star-half.png'); 17 | expect(Helper.extension(stars[3].src)).toEqual('star-half.png'); 18 | expect(Helper.extension(stars[4].src)).toEqual('star-half.png'); 19 | }); 20 | 21 | it('accepts data attribute', () => { 22 | // given 23 | Helper._append('div', { 'data-star-off': 'custom' }); 24 | 25 | // when 26 | var raty = new Raty(document.querySelector('[data-star-off]')); 27 | 28 | // then 29 | expect(raty.opt.starOff).toEqual('custom'); 30 | }); 31 | 32 | context('with :starType', function () { 33 | it('uses the given element', () => { 34 | // given 35 | Helper.create('#el'); 36 | 37 | var raty = new Raty(document.querySelector('#el'), { starType: 'i' }); 38 | 39 | // when 40 | raty.init(); 41 | 42 | // then 43 | var stars = raty.element.querySelectorAll('i'); 44 | 45 | expect(stars[0].tagName).toEqual('I'); 46 | expect(stars[1].tagName).toEqual('I'); 47 | expect(stars[2].tagName).toEqual('I'); 48 | expect(stars[3].tagName).toEqual('I'); 49 | expect(stars[4].tagName).toEqual('I'); 50 | }); 51 | 52 | it('normalizes the class name', () => { 53 | // given 54 | Helper.create('#el'); 55 | 56 | var raty = new Raty(document.querySelector('#el'), { starType: 'i' }); 57 | 58 | // when 59 | raty.init(); 60 | 61 | // then 62 | var stars = raty.element.querySelectorAll('i'); 63 | 64 | expect(stars[0].classList.contains('star-off-png')).toEqual(true); 65 | expect(stars[1].classList.contains('star-off-png')).toEqual(true); 66 | expect(stars[2].classList.contains('star-off-png')).toEqual(true); 67 | expect(stars[3].classList.contains('star-off-png')).toEqual(true); 68 | expect(stars[4].classList.contains('star-off-png')).toEqual(true); 69 | }); 70 | 71 | it('does not create the "src" attribute', () => { 72 | // given 73 | Helper.create('#el'); 74 | 75 | var raty = new Raty(document.querySelector('#el'), { starType: 'i' }); 76 | 77 | // when 78 | raty.init(); 79 | 80 | // then 81 | var stars = raty.element.querySelectorAll('i'); 82 | 83 | expect(stars[0].src).toEqual(undefined); 84 | expect(stars[1].src).toEqual(undefined); 85 | expect(stars[2].src).toEqual(undefined); 86 | expect(stars[3].src).toEqual(undefined); 87 | expect(stars[4].src).toEqual(undefined); 88 | }); 89 | 90 | it('creates the "data-alt" attribute', () => { 91 | // given 92 | Helper.create('#el'); 93 | 94 | var raty = new Raty(document.querySelector('#el'), { starType: 'i' }); 95 | 96 | // when 97 | raty.init(); 98 | 99 | // then 100 | var stars = raty.element.querySelectorAll('i'); 101 | 102 | expect(stars[0].getAttribute('data-alt')).toEqual('1'); 103 | expect(stars[1].getAttribute('data-alt')).toEqual('2'); 104 | expect(stars[2].getAttribute('data-alt')).toEqual('3'); 105 | expect(stars[3].getAttribute('data-alt')).toEqual('4'); 106 | expect(stars[4].getAttribute('data-alt')).toEqual('5'); 107 | }); 108 | 109 | it('does not create the "alt" attribute', () => { 110 | // given 111 | Helper.create('#el'); 112 | 113 | var raty = new Raty(document.querySelector('#el'), { starType: 'i' }); 114 | 115 | // when 116 | raty.init(); 117 | 118 | // then 119 | var stars = raty.element.querySelectorAll('i'); 120 | 121 | expect(stars[0].alt).toEqual(undefined); 122 | expect(stars[1].alt).toEqual(undefined); 123 | expect(stars[2].alt).toEqual(undefined); 124 | expect(stars[3].alt).toEqual(undefined); 125 | expect(stars[4].alt).toEqual(undefined); 126 | }); 127 | }); 128 | }); 129 | -------------------------------------------------------------------------------- /__tests__/features/star_on_spec.js: -------------------------------------------------------------------------------- 1 | describe('#starOn', () => { 2 | it('accepts data attribute', () => { 3 | // given 4 | Helper._append('div', { 'data-star-on': 'custom' }); 5 | 6 | // when 7 | var raty = new Raty(document.querySelector('[data-star-on]')).init(); 8 | 9 | // then 10 | expect(raty.opt.starOn).toEqual('custom'); 11 | }); 12 | 13 | context('on mouseover', function () { 14 | beforeEach(() => { 15 | Helper.create('#el'); 16 | }); 17 | 18 | it('changes the stars on', () => { 19 | // given 20 | var raty = new Raty(document.querySelector('#el'), { starOn: 'star-half.png' }).init(); 21 | var stars = raty.element.querySelectorAll('img'); 22 | 23 | // when 24 | Helper.trigger(Helper.last(stars), 'mouseover'); 25 | 26 | // then 27 | expect(Helper.extension(stars[0].src)).toEqual('star-half.png'); 28 | expect(Helper.extension(stars[1].src)).toEqual('star-half.png'); 29 | expect(Helper.extension(stars[2].src)).toEqual('star-half.png'); 30 | expect(Helper.extension(stars[3].src)).toEqual('star-half.png'); 31 | expect(Helper.extension(stars[4].src)).toEqual('star-half.png'); 32 | }); 33 | 34 | context('with :starType', function () { 35 | it('uses the given element', () => { 36 | // given 37 | var raty = new Raty(document.querySelector('#el'), { starType: 'i' }).init(); 38 | var stars = raty.element.querySelectorAll('i'); 39 | 40 | // when 41 | Helper.trigger(Helper.last(stars), 'mouseover'); 42 | 43 | // then 44 | expect(stars[0].tagName).toEqual('I'); 45 | expect(stars[1].tagName).toEqual('I'); 46 | expect(stars[2].tagName).toEqual('I'); 47 | expect(stars[3].tagName).toEqual('I'); 48 | expect(stars[4].tagName).toEqual('I'); 49 | }); 50 | 51 | it('normalizes the class name', () => { 52 | // given 53 | var raty = new Raty(document.querySelector('#el'), { starType: 'i' }).init(); 54 | var stars = raty.element.querySelectorAll('i'); 55 | 56 | // when 57 | Helper.trigger(Helper.last(stars), 'mouseover'); 58 | 59 | // then 60 | stars.forEach((element) => { 61 | expect(element).toHaveClass('star-on-png'); 62 | }); 63 | }); 64 | 65 | it('does not create "src" attribute', () => { 66 | // given 67 | var raty = new Raty(document.querySelector('#el'), { starType: 'i' }).init(); 68 | var stars = raty.element.querySelectorAll('i'); 69 | 70 | // when 71 | Helper.trigger(Helper.last(stars), 'mouseover'); 72 | 73 | // then 74 | stars.forEach((element) => { 75 | expect(element).not.toHaveAttribute('src'); 76 | }); 77 | }); 78 | 79 | it('creates "data-alt" attribute', () => { 80 | // given 81 | var raty = new Raty(document.querySelector('#el'), { starType: 'i' }).init(); 82 | var stars = raty.element.querySelectorAll('i'); 83 | 84 | // when 85 | Helper.trigger(Helper.last(stars), 'mouseover'); 86 | 87 | // then 88 | stars.forEach((element) => { 89 | expect(element).toHaveAttribute('data-alt'); 90 | }); 91 | }); 92 | 93 | it('does not create "alt" attribute', () => { 94 | // given 95 | var raty = new Raty(document.querySelector('#el'), { starType: 'i' }).init(); 96 | var stars = raty.element.querySelectorAll('i'); 97 | 98 | // when 99 | Helper.trigger(Helper.last(stars), 'mouseover'); 100 | 101 | // then 102 | stars.forEach((element) => { 103 | expect(element).not.toHaveAttribute('alt'); 104 | }); 105 | }); 106 | }); 107 | }); 108 | }); 109 | -------------------------------------------------------------------------------- /__tests__/features/star_type_spec.js: -------------------------------------------------------------------------------- 1 | describe('#starType', () => { 2 | context('when actived', function () { 3 | it('disable the width property', () => { 4 | // given 5 | Helper.create('#el'); 6 | 7 | var raty = new Raty(document.querySelector('#el'), { starType: 'i' }).init(); 8 | 9 | // when 10 | raty.init(); 11 | 12 | // then 13 | expect(raty.element.style.width).toEqual(''); 14 | }); 15 | }); 16 | 17 | it('accepts data attribute', () => { 18 | // given 19 | Helper._append('div', { 'data-star-type': 'b' }); 20 | 21 | var raty = new Raty(document.querySelector('[data-star-type]')).init(); 22 | 23 | // when 24 | raty.init(); 25 | 26 | // then 27 | expect(raty.opt.starType).toEqual('b'); 28 | }); 29 | 30 | context('when is "img"', function () { 31 | it('does not changes the :path to blank', () => { 32 | // given 33 | Helper.create('#el'); 34 | 35 | var raty = new Raty(document.querySelector('#el'), { path: 'path', starType: 'img' }); 36 | 37 | // when 38 | raty.init(); 39 | 40 | // then 41 | expect(raty.opt.path).toEqual('path/'); 42 | }); 43 | 44 | it('creates the default markup', () => { 45 | // given 46 | Helper.create('#el'); 47 | 48 | // when 49 | var raty = new Raty(document.querySelector('#el'), { path: 'path', starType: 'img' }).init(); 50 | 51 | // then 52 | var stars = raty.element.querySelectorAll('img'); 53 | var score = raty.element.querySelector('input'); 54 | 55 | expect(stars[0].title).toEqual('bad'); 56 | expect(stars[1].title).toEqual('poor'); 57 | expect(stars[2].title).toEqual('regular'); 58 | expect(stars[3].title).toEqual('good'); 59 | expect(stars[4].title).toEqual('gorgeous'); 60 | 61 | expect(stars[0].alt).toEqual('1'); 62 | expect(stars[1].alt).toEqual('2'); 63 | expect(stars[2].alt).toEqual('3'); 64 | expect(stars[3].alt).toEqual('4'); 65 | expect(stars[4].alt).toEqual('5'); 66 | 67 | expect(Helper.extension(stars[0].src)).toEqual('star-off.png'); 68 | expect(Helper.extension(stars[1].src)).toEqual('star-off.png'); 69 | expect(Helper.extension(stars[2].src)).toEqual('star-off.png'); 70 | expect(Helper.extension(stars[3].src)).toEqual('star-off.png'); 71 | expect(Helper.extension(stars[4].src)).toEqual('star-off.png'); 72 | 73 | expect(score.type).toEqual('hidden'); 74 | expect(score.name).toEqual('score'); 75 | expect(score.value).toEqual(''); 76 | }); 77 | }); 78 | 79 | context('when is other element', function () { 80 | it('changes the :path to blank', () => { 81 | // given 82 | Helper.create('#el'); 83 | 84 | // when 85 | var raty = new Raty(document.querySelector('#el'), { path: 'path', starType: 'i' }).init(); 86 | 87 | // then 88 | expect(raty.opt.path).toEqual(''); 89 | }); 90 | 91 | it('creates the default markup', () => { 92 | // given 93 | Helper.create('#el'); 94 | 95 | // when 96 | var raty = new Raty(document.querySelector('#el'), { starType: 'i' }).init(); 97 | 98 | // then 99 | var stars = raty.element.querySelectorAll('i'); 100 | var score = raty.element.querySelector('input'); 101 | 102 | expect(stars[0].title).toEqual('bad'); 103 | expect(stars[1].title).toEqual('poor'); 104 | expect(stars[2].title).toEqual('regular'); 105 | expect(stars[3].title).toEqual('good'); 106 | expect(stars[4].title).toEqual('gorgeous'); 107 | 108 | expect(stars[0].dataset.alt).toEqual('1'); 109 | expect(stars[1].dataset.alt).toEqual('2'); 110 | expect(stars[2].dataset.alt).toEqual('3'); 111 | expect(stars[3].dataset.alt).toEqual('4'); 112 | expect(stars[4].dataset.alt).toEqual('5'); 113 | 114 | stars.forEach((element) => { 115 | expect(element).not.toHaveAttribute('alt'); 116 | expect(element).not.toHaveAttribute('src'); 117 | }); 118 | 119 | expect(score.type).toEqual('hidden'); 120 | expect(score.name).toEqual('score'); 121 | expect(score.value).toEqual(''); 122 | }); 123 | 124 | context('with :half true', function () { 125 | it('fills half star', () => { 126 | // given 127 | Helper.create('#el'); 128 | 129 | var raty = new Raty(document.querySelector('#el'), { half: true, starType: 'i' }).init(); 130 | var stars = raty.element.querySelectorAll('i'); 131 | 132 | // when 133 | raty.move(4.5); 134 | 135 | // then 136 | expect(stars[0].classList.contains('star-on-png')).toEqual(true); 137 | expect(stars[1].classList.contains('star-on-png')).toEqual(true); 138 | expect(stars[2].classList.contains('star-on-png')).toEqual(true); 139 | expect(stars[3].classList.contains('star-on-png')).toEqual(true); 140 | expect(stars[4].classList.contains('star-half-png')).toEqual(true); 141 | }); 142 | }); 143 | }); 144 | }); 145 | -------------------------------------------------------------------------------- /__tests__/features/stars_spec.js: -------------------------------------------------------------------------------- 1 | describe('stars', () => { 2 | beforeEach(() => { 3 | Helper.create('#el'); 4 | }); 5 | 6 | it('starts all off', () => { 7 | // given / when 8 | var raty = new Raty(document.querySelector('#el')).init(); 9 | 10 | // then 11 | expect(Helper.extension(raty.element.querySelector('img').src)).toEqual('star-off.png'); 12 | }); 13 | 14 | context('on click', function () { 15 | it('changes the score', () => { 16 | // given 17 | var raty = new Raty(document.querySelector('#el')).init(); 18 | var stars = raty.element.querySelectorAll('img'); 19 | 20 | // when 21 | Helper.trigger(Helper.last(stars), 'click'); 22 | 23 | // then 24 | expect(raty.element.querySelector('input').value).toEqual('5'); 25 | }); 26 | }); 27 | 28 | context('on mouseover', function () { 29 | it('turns on the stars', () => { 30 | // given 31 | var raty = new Raty(document.querySelector('#el')).init(); 32 | var stars = raty.element.querySelectorAll('img'); 33 | 34 | // when 35 | Helper.trigger(Helper.last(stars), 'mouseover'); 36 | 37 | // then 38 | expect(Helper.extension(stars[0].src)).toEqual('star-on.png'); 39 | expect(Helper.extension(stars[1].src)).toEqual('star-on.png'); 40 | expect(Helper.extension(stars[2].src)).toEqual('star-on.png'); 41 | expect(Helper.extension(stars[3].src)).toEqual('star-on.png'); 42 | expect(Helper.extension(stars[4].src)).toEqual('star-on.png'); 43 | }); 44 | 45 | context('and mouseout', function () { 46 | it('turns off all stars', () => { 47 | // given 48 | var raty = new Raty(document.querySelector('#el')).init(); 49 | var stars = raty.element.querySelectorAll('img'); 50 | 51 | // when 52 | Helper.trigger(raty.element, 'mouseover'); 53 | Helper.trigger(raty.element, 'mouseout'); 54 | 55 | // then 56 | expect(Helper.extension(stars[0].src)).toEqual('star-off.png'); 57 | expect(Helper.extension(stars[1].src)).toEqual('star-off.png'); 58 | expect(Helper.extension(stars[2].src)).toEqual('star-off.png'); 59 | expect(Helper.extension(stars[3].src)).toEqual('star-off.png'); 60 | expect(Helper.extension(stars[4].src)).toEqual('star-off.png'); 61 | }); 62 | }); 63 | 64 | context('and click', function () { 65 | it('changes the score', () => { 66 | // given 67 | var raty = new Raty(document.querySelector('#el')).init(); 68 | var stars = raty.element.querySelectorAll('img'); 69 | var star = Helper.last(stars); 70 | 71 | // when 72 | Helper.trigger(star, 'mouseover'); 73 | Helper.trigger(star, 'click'); 74 | 75 | // then 76 | expect(raty.element.querySelector('input').value).toEqual('5'); 77 | }); 78 | 79 | context('and mouseout', function () { 80 | it('keeps the stars on', () => { 81 | // given 82 | var raty = new Raty(document.querySelector('#el')).init(); 83 | var stars = raty.element.querySelectorAll('img'); 84 | var star = Helper.last(stars); 85 | 86 | // when 87 | Helper.trigger(star, 'mouseover'); 88 | Helper.trigger(star, 'click'); 89 | Helper.trigger(star, 'mouseout'); 90 | 91 | // then 92 | expect(Helper.extension(stars[0].src)).toEqual('star-on.png'); 93 | expect(Helper.extension(stars[1].src)).toEqual('star-on.png'); 94 | expect(Helper.extension(stars[2].src)).toEqual('star-on.png'); 95 | expect(Helper.extension(stars[3].src)).toEqual('star-on.png'); 96 | expect(Helper.extension(stars[4].src)).toEqual('star-on.png'); 97 | }); 98 | }); 99 | }); 100 | }); 101 | }); 102 | -------------------------------------------------------------------------------- /__tests__/features/target_format_spec.js: -------------------------------------------------------------------------------- 1 | describe('#targetFormat', () => { 2 | beforeEach(() => { 3 | var element = document.createElement('div'); 4 | element.id = 'element'; 5 | var hint = document.createElement('div'); 6 | hint.id = 'hint'; 7 | document.querySelector(`body`).appendChild(element); 8 | document.querySelector(`body`).appendChild(hint); 9 | }); 10 | 11 | afterEach(() => { 12 | document.querySelector('#element').remove(); 13 | document.querySelector('#hint').remove(); 14 | }); 15 | 16 | it('stars empty', () => { 17 | // given 18 | var raty = new Raty(document.querySelector('#element', { target: '#hint', targetFormat: 'score: {score}' })).init(); 19 | 20 | // when 21 | raty.init(); 22 | 23 | // then 24 | expect(document.querySelector('#hint').innerHTML).toEqual(''); 25 | }); 26 | 27 | context('on mouseover', function () { 28 | it('set target with format on mouseover', () => { 29 | // given 30 | var raty = new Raty(document.querySelector('#element'), { 31 | target: '#hint', 32 | targetFormat: 'score: {score}', 33 | }).init(); 34 | 35 | // when 36 | Helper.trigger(raty.element.querySelector('img'), 'mouseover'); 37 | 38 | // then 39 | expect(document.querySelector('#hint').innerHTML).toEqual('score: bad'); 40 | }); 41 | }); 42 | 43 | context('on mouseout', function () { 44 | it('clears the target', () => { 45 | // given 46 | var raty = new Raty(document.querySelector('#element'), { 47 | target: '#hint', 48 | targetFormat: 'score: {score}', 49 | }).init(); 50 | 51 | // when 52 | Helper.trigger(raty.element, 'mouseover'); 53 | Helper.trigger(raty.element, 'mouseleave'); 54 | 55 | // then 56 | expect(document.querySelector('#hint').textContent).toEqual(''); 57 | }); 58 | 59 | context('with :targetKeep', function () { 60 | context('without score', function () { 61 | it('clears the target', () => { 62 | // given 63 | var raty = new Raty(document.querySelector('#element'), { 64 | target: '#hint', 65 | targetFormat: 'score: {score}', 66 | targetKeep: true, 67 | }).init(); 68 | 69 | // when 70 | Helper.trigger(raty.element, 'mouseover'); 71 | Helper.trigger(raty.element, 'mouseleave'); 72 | 73 | // then 74 | expect(document.querySelector('#hint').innerHTML).toEqual(''); 75 | }); 76 | }); 77 | 78 | context('with score', function () { 79 | it('keeps the template', () => { 80 | // given 81 | var raty = new Raty(document.querySelector('#element'), { 82 | score: 1, 83 | target: '#hint', 84 | targetFormat: 'score: {score}', 85 | targetKeep: true, 86 | }).init(); 87 | 88 | // when 89 | Helper.trigger(raty.element, 'mouseover'); 90 | Helper.trigger(raty.element, 'mouseleave'); 91 | 92 | // then 93 | expect(document.querySelector('#hint').innerHTML).toEqual('score: bad'); 94 | }); 95 | }); 96 | }); 97 | }); 98 | }); 99 | -------------------------------------------------------------------------------- /__tests__/features/target_score_spec.js: -------------------------------------------------------------------------------- 1 | describe('#targetScore', () => { 2 | let testContext; 3 | 4 | beforeEach(() => { 5 | testContext = {}; 6 | }); 7 | 8 | beforeEach(() => { 9 | var element = document.createElement('div'); 10 | element.id = 'element'; 11 | 12 | const body = document.querySelector(`body`); 13 | 14 | body.appendChild(element); 15 | 16 | var score = document.createElement('input'); 17 | score.type = 'text'; 18 | score.id = 'score'; 19 | 20 | body.appendChild(score); 21 | 22 | testContext.scoreField = score; 23 | }); 24 | 25 | afterEach(() => { 26 | document.querySelector('#element').remove(); 27 | 28 | testContext.scoreField.remove(); 29 | }); 30 | 31 | it('avoids the creation of default score field', () => { 32 | // given 33 | var raty = new Raty(document.querySelector('#element'), { targetScore: '#score' }); 34 | 35 | // when 36 | raty.init(); 37 | 38 | // then 39 | expect(raty.element.querySelector('input')).toEqual(null); 40 | }); 41 | 42 | it('changes the place where score will be setted', () => { 43 | // given 44 | var raty = new Raty(document.querySelector('#element'), { targetScore: '#score' }).init(); 45 | var star = raty.element.querySelector('img'); 46 | 47 | // when 48 | Helper.trigger(star, 'click'); 49 | 50 | // then 51 | expect(document.querySelector('#score').value).toEqual('1'); 52 | }); 53 | }); 54 | -------------------------------------------------------------------------------- /__tests__/features/target_spec.js: -------------------------------------------------------------------------------- 1 | describe('#target', () => { 2 | let testContext; 3 | 4 | beforeEach(() => { 5 | testContext = {}; 6 | }); 7 | 8 | beforeEach(() => { 9 | Helper.create('#el'); 10 | }); 11 | 12 | it('accepts callback return and has the correct arguments', () => { 13 | // given 14 | Helper.create('#target'); 15 | 16 | var raty = new Raty(document.querySelector('#el'), { 17 | target: function (element) { 18 | this._this = this; 19 | this._element = element; 20 | 21 | return '#target'; 22 | }, 23 | }); 24 | 25 | // when 26 | raty.init(); 27 | 28 | // then 29 | expect(raty.opt.target).toEqual('#target'); 30 | expect(raty._this).toBe(raty); 31 | expect(raty._element).toEqual(document.querySelector('#el')); 32 | }); 33 | 34 | context('on mouseover', function () { 35 | context('as div', function () { 36 | beforeEach(() => { 37 | testContext.target = Helper.target('#target'); 38 | }); 39 | 40 | it('sets the hint', () => { 41 | // given 42 | var raty = new Raty(document.querySelector('#el'), { target: '#' + testContext.target.id }).init(); 43 | var star = Helper.last(raty.element.querySelectorAll('img')); 44 | 45 | // when 46 | Helper.trigger(star, 'mouseover'); 47 | 48 | // then 49 | expect(testContext.target.innerHTML).toEqual('gorgeous'); 50 | }); 51 | }); 52 | 53 | context('as input', function () { 54 | beforeEach(() => { 55 | testContext.target = Helper.target('#target', 'input'); 56 | }); 57 | 58 | it('sets the hint', () => { 59 | // given 60 | var raty = new Raty(document.querySelector('#el'), { target: '#' + testContext.target.id }).init(); 61 | var star = Helper.last(raty.element.querySelectorAll('img')); 62 | 63 | // when 64 | Helper.trigger(star, 'mouseover'); 65 | 66 | // then 67 | expect(document.querySelector('#target').value).toEqual('gorgeous'); 68 | }); 69 | }); 70 | 71 | context('as textarea', function () { 72 | beforeEach(() => { 73 | testContext.target = Helper.target('#target', 'textarea'); 74 | }); 75 | 76 | it('sets the hint', () => { 77 | // given 78 | var raty = new Raty(document.querySelector('#el'), { target: '#' + testContext.target.id }).init(); 79 | var star = Helper.last(raty.element.querySelectorAll('img')); 80 | 81 | // when 82 | Helper.trigger(star, 'mouseover'); 83 | 84 | // then 85 | expect(document.querySelector('#target').value).toEqual('gorgeous'); 86 | }); 87 | }); 88 | 89 | context('as select', function () { 90 | beforeEach(() => { 91 | testContext.target = Helper.target('#target', 'select'); 92 | }); 93 | 94 | it('sets the hint', () => { 95 | // given 96 | var raty = new Raty(document.querySelector('#el'), { target: '#' + testContext.target.id }).init(); 97 | var star = Helper.last(raty.element.querySelectorAll('img')); 98 | 99 | // when 100 | Helper.trigger(star, 'mouseover'); 101 | 102 | // then 103 | expect(document.querySelector('#target').value).toEqual('gorgeous'); 104 | }); 105 | }); 106 | 107 | context('and mouseout', function () { 108 | context('as div', function () { 109 | beforeEach(() => { 110 | testContext.target = Helper.target('#target'); 111 | }); 112 | 113 | it('gets clear', () => { 114 | // given 115 | var raty = new Raty(document.querySelector('#el'), { target: '#' + testContext.target.id }).init(); 116 | 117 | // when 118 | Helper.trigger(raty.element, 'mouseover'); 119 | Helper.trigger(raty.element, 'mouseout'); 120 | 121 | // then 122 | expect(testContext.target.innerHTML).toEqual(''); 123 | }); 124 | }); 125 | 126 | context('as textarea', function () { 127 | beforeEach(() => { 128 | testContext.target = Helper.target('#textarea'); 129 | }); 130 | 131 | it('gets clear', () => { 132 | // given 133 | var raty = new Raty(document.querySelector('#el'), { target: '#' + testContext.target.id }).init(); 134 | 135 | // when 136 | Helper.trigger(raty.element, 'mouseover'); 137 | Helper.trigger(raty.element, 'mouseout'); 138 | 139 | // then 140 | expect(testContext.target.innerHTML).toEqual(''); 141 | }); 142 | }); 143 | 144 | context('as input', function () { 145 | beforeEach(() => { 146 | testContext.target = Helper.target('#target', 'input'); 147 | }); 148 | 149 | it('gets clear', () => { 150 | // given 151 | var raty = new Raty(document.querySelector('#el'), { target: '#' + testContext.target.id }).init(); 152 | 153 | // when 154 | Helper.trigger(raty.element, 'mouseover'); 155 | 156 | // then 157 | expect(testContext.target.innerHTML).toEqual(''); 158 | }); 159 | }); 160 | 161 | context('as select', function () { 162 | beforeEach(() => { 163 | testContext.target = Helper.target('#select'); 164 | }); 165 | 166 | it('gets clear', () => { 167 | // given 168 | var raty = new Raty(document.querySelector('#el'), { target: '#' + testContext.target.id }).init(); 169 | 170 | // when 171 | Helper.trigger(raty.element, 'mouseout'); 172 | 173 | // then 174 | expect(testContext.target.innerHTML).toEqual(''); 175 | }); 176 | }); 177 | }); 178 | 179 | context('and click', function () { 180 | context('and mouseout', function () { 181 | context('as div', function () { 182 | beforeEach(() => { 183 | testContext.target = Helper.target('#target'); 184 | }); 185 | 186 | it('gets clear', () => { 187 | // given 188 | var raty = new Raty(document.querySelector('#el'), { target: '#' + testContext.target.id }).init(); 189 | 190 | // when 191 | Helper.trigger(raty.element, 'mouseover'); 192 | Helper.trigger(raty.element, 'click'); 193 | Helper.trigger(raty.element, 'mouseout'); 194 | 195 | // then 196 | expect(testContext.target.innerHTML).toEqual(''); 197 | }); 198 | }); 199 | 200 | context('as textarea', function () { 201 | beforeEach(() => { 202 | testContext.target = Helper.target('#textarea'); 203 | }); 204 | 205 | it('gets clear', () => { 206 | // given 207 | var raty = new Raty(document.querySelector('#el'), { target: '#' + testContext.target.id }).init(); 208 | 209 | // when 210 | Helper.trigger(raty.element, 'mouseover'); 211 | Helper.trigger(raty.element, 'click'); 212 | Helper.trigger(raty.element, 'mouseout'); 213 | 214 | // then 215 | expect(testContext.target.innerHTML).toEqual(''); 216 | }); 217 | }); 218 | 219 | context('as input', function () { 220 | beforeEach(() => { 221 | testContext.target = Helper.target('#target', 'input'); 222 | }); 223 | 224 | it('gets clear', () => { 225 | // given 226 | var raty = new Raty(document.querySelector('#el'), { target: '#' + testContext.target.id }).init(); 227 | 228 | var star = Helper.last(raty.element.querySelectorAll('img')); 229 | 230 | // when 231 | Helper.trigger(raty.element, 'mouseover'); 232 | Helper.trigger(raty.element, 'click'); 233 | Helper.trigger(raty.element, 'mouseout'); 234 | 235 | // then 236 | expect(testContext.target.innerHTML).toEqual(''); 237 | }); 238 | }); 239 | 240 | context('as select', function () { 241 | beforeEach(() => { 242 | testContext.target = Helper.target('#select'); 243 | }); 244 | 245 | it('gets clear', () => { 246 | // given 247 | var raty = new Raty(document.querySelector('#el'), { target: '#' + testContext.target.id }).init(); 248 | 249 | // when 250 | Helper.trigger(raty.element, 'mouseover'); 251 | Helper.trigger(raty.element, 'click'); 252 | Helper.trigger(raty.element, 'mouseout'); 253 | 254 | // then 255 | expect(testContext.target.innerHTML).toEqual(''); 256 | }); 257 | }); 258 | }); 259 | }); 260 | }); 261 | }); 262 | -------------------------------------------------------------------------------- /__tests__/features/target_text_spec.js: -------------------------------------------------------------------------------- 1 | describe('#targetText', () => { 2 | beforeEach(() => { 3 | var element = document.createElement('div'); 4 | element.id = 'element'; 5 | var hint = document.createElement('div'); 6 | hint.id = 'hint'; 7 | document.querySelector(`body`).appendChild(element); 8 | document.querySelector(`body`).appendChild(hint); 9 | }); 10 | 11 | it('set target with none value', () => { 12 | // given 13 | var raty = new Raty(document.querySelector('#element'), { target: '#hint', targetText: 'none' }); 14 | 15 | // when 16 | raty.init(); 17 | 18 | // then 19 | expect(document.querySelector('#hint').innerHTML).toEqual('none'); 20 | }); 21 | }); 22 | -------------------------------------------------------------------------------- /__tests__/features/target_type_spec.js: -------------------------------------------------------------------------------- 1 | describe('#targetType', () => { 2 | let testContext; 3 | 4 | beforeEach(() => { 5 | testContext = {}; 6 | }); 7 | 8 | beforeEach(() => { 9 | Helper.create('#el'); 10 | 11 | testContext.target = Helper.target('#target'); 12 | }); 13 | 14 | context('target missing', function () { 15 | it('throws error', () => { 16 | // given 17 | var that = this; 18 | 19 | // when 20 | var lambda = function () { 21 | var raty = new Raty(document.querySelector('#el'), { target: '#missing' }).init(); 22 | }; 23 | 24 | // then 25 | expect(lambda).toThrow(new Error('Target selector invalid or missing!')); 26 | }); 27 | }); 28 | 29 | context('as *hint', function () { 30 | it('receives the hint', () => { 31 | // given 32 | var raty = new Raty(document.querySelector('#el'), { 33 | target: '#' + testContext.target.id, 34 | targetType: 'hint', 35 | }).init(); 36 | 37 | var star = Helper.last(raty.element.querySelectorAll('img')); 38 | 39 | // when 40 | Helper.trigger(star, 'mouseover'); 41 | 42 | // then 43 | expect(testContext.target.innerHTML).toEqual('gorgeous'); 44 | }); 45 | 46 | context('with :cancel', function () { 47 | it('receives the :cancelHint', () => { 48 | // given 49 | var raty = new Raty(document.querySelector('#el'), { 50 | cancelButton: true, 51 | target: '#' + testContext.target.id, 52 | targetType: 'hint', 53 | }).init(); 54 | 55 | var cancel = raty.element.querySelector('.raty-cancel'); 56 | 57 | // when 58 | Helper.trigger(cancel, 'mouseover'); 59 | 60 | // then 61 | expect(testContext.target.innerHTML).toEqual('Cancel this rating!'); 62 | }); 63 | }); 64 | }); 65 | 66 | context('as *score', function () { 67 | it('receives the score', () => { 68 | // given 69 | var raty = new Raty(document.querySelector('#el'), { 70 | target: '#' + testContext.target.id, 71 | targetType: 'score', 72 | }).init(); 73 | 74 | var star = Helper.last(raty.element.querySelectorAll('img')); 75 | 76 | // when 77 | Helper.trigger(star, 'mouseover'); 78 | 79 | // then 80 | expect(testContext.target).toContainHTML('5'); 81 | }); 82 | 83 | context('with :cancel', function () { 84 | it('receives the :cancelHint', () => { 85 | // given 86 | var raty = new Raty(document.querySelector('#el'), { 87 | cancelButton: true, 88 | target: '#' + testContext.target.id, 89 | targetType: 'score', 90 | }).init(); 91 | 92 | var cancel = raty.element.querySelector('.raty-cancel'); 93 | 94 | // when 95 | Helper.trigger(cancel, 'mouseover'); 96 | 97 | // then 98 | expect(testContext.target.innerHTML).toEqual('Cancel this rating!'); 99 | }); 100 | }); 101 | }); 102 | }); 103 | -------------------------------------------------------------------------------- /__tests__/models/_adjustHintsSpec.js: -------------------------------------------------------------------------------- 1 | describe('#_adjustHints', () => { 2 | beforeEach(() => { 3 | Helper.create('#el'); 4 | }); 5 | 6 | context('when :halfShow and :half is false', function () { 7 | var half = false; 8 | var halfShow = false; 9 | 10 | context('and hints is null', function () { 11 | var hints = null; 12 | 13 | it('receives an empty array', () => { 14 | // given 15 | var options = { half: half, halfShow: halfShow, hints: hints }; 16 | var raty = new Raty(document.querySelector('#el'), options); 17 | 18 | // when 19 | raty._adjustHints(); 20 | 21 | // then 22 | expect(raty.opt.hints).toEqual([]); 23 | }); 24 | }); 25 | 26 | context('and hints is empty', function () { 27 | var hints = ''; 28 | 29 | it('receives an empty array', () => { 30 | // given 31 | var options = { half: half, halfShow: halfShow, hints: hints }; 32 | var raty = new Raty(document.querySelector('#el'), options); 33 | 34 | // when 35 | raty._adjustHints(); 36 | 37 | // then 38 | expect(raty.opt.hints).toEqual([]); 39 | }); 40 | }); 41 | 42 | context('and hints is undefined', function () { 43 | it('receives an empty array', () => { 44 | // given 45 | var options = { half: half, halfShow: halfShow }; 46 | var raty = new Raty(document.querySelector('#el'), options); 47 | 48 | delete raty.opt.hints; 49 | 50 | // when 51 | raty._adjustHints(); 52 | 53 | // then 54 | expect(raty.opt.hints).toEqual([]); 55 | }); 56 | }); 57 | }); 58 | 59 | context('when :halfShow is true', function () { 60 | var halfShow = true; 61 | 62 | context('and hints is string or number', function () { 63 | var hints = [1, '2', 3, '4', 5]; 64 | 65 | it('uses the hint on the first and second position', () => { 66 | // given 67 | var options = { halfShow: halfShow, hints: hints }; 68 | var raty = new Raty(document.querySelector('#el'), options); 69 | 70 | // when 71 | raty._adjustHints(); 72 | 73 | // then 74 | var expected = [ 75 | [1, 1], 76 | ['2', '2'], 77 | [3, 3], 78 | ['4', '4'], 79 | [5, 5], 80 | ]; 81 | 82 | expect(raty.opt.hints).toEqual(expected); 83 | }); 84 | }); 85 | 86 | context('and hints is an array of one position of string or number', function () { 87 | var hints = [[1], ['2'], [3], ['4'], [5]]; 88 | 89 | it('replicates the first position to second one', () => { 90 | // given 91 | var options = { halfShow: halfShow, hints: hints }; 92 | var raty = new Raty(document.querySelector('#el'), options); 93 | 94 | // when 95 | raty._adjustHints(); 96 | 97 | // then 98 | var expected = [ 99 | [1, 1], 100 | ['2', '2'], 101 | [3, 3], 102 | ['4', '4'], 103 | [5, 5], 104 | ]; 105 | 106 | expect(raty.opt.hints).toEqual(expected); 107 | }); 108 | }); 109 | 110 | context('and hints is an array of two positions of string or number', function () { 111 | var hints = [ 112 | [0.5, 1], 113 | ['1.5', '2'], 114 | [2.5, 3], 115 | ['3.5', '4'], 116 | [4.5, 5], 117 | ]; 118 | 119 | it('keeps the original values', () => { 120 | // given 121 | var options = { halfShow: halfShow, hints: hints }; 122 | var raty = new Raty(document.querySelector('#el'), options); 123 | 124 | // when 125 | raty._adjustHints(); 126 | 127 | // then 128 | expect(raty.opt.hints).toEqual(hints); 129 | }); 130 | }); 131 | 132 | context('and hints is an array of three or more positions of string or number', function () { 133 | var hints = [ 134 | [0.5, 1, 'extra'], 135 | ['1.5', '2', 'extra'], 136 | [2.5, 3, 'extra'], 137 | ['3.5', '4', 'extra'], 138 | [4.5, 5, 'extra'], 139 | ]; 140 | 141 | it('removes the extra hints', () => { 142 | // given 143 | var options = { halfShow: halfShow, hints: hints }; 144 | var raty = new Raty(document.querySelector('#el'), options); 145 | 146 | // when 147 | raty._adjustHints(); 148 | 149 | // then 150 | var expected = [ 151 | [0.5, 1], 152 | ['1.5', '2'], 153 | [2.5, 3], 154 | ['3.5', '4'], 155 | [4.5, 5], 156 | ]; 157 | 158 | expect(raty.opt.hints).toEqual(expected); 159 | }); 160 | }); 161 | }); 162 | }); 163 | -------------------------------------------------------------------------------- /__tests__/models/_adjustNumberSpec.js: -------------------------------------------------------------------------------- 1 | describe('#_adjustNumber', () => { 2 | beforeEach(() => { 3 | Helper.create('#el'); 4 | }); 5 | 6 | context('when :number is less than 1', function () { 7 | it('receives 1', () => { 8 | // given 9 | 10 | var options = { number: 0 }; 11 | var raty = new Raty(document.querySelector('#el'), options); 12 | 13 | // when 14 | raty._adjustNumber(); 15 | 16 | // then 17 | expect(raty.opt.number).toEqual(1); 18 | }); 19 | }); 20 | 21 | context('when :number is more than :numberMax', function () { 22 | it('returns the max', () => { 23 | // given 24 | 25 | var options = { number: 5, numberMax: 2 }; 26 | var raty = new Raty(document.querySelector('#el'), options); 27 | 28 | // when 29 | raty._adjustNumber(); 30 | 31 | // then 32 | expect(raty.opt.number).toEqual(2); 33 | }); 34 | }); 35 | }); 36 | -------------------------------------------------------------------------------- /__tests__/models/_adjustPrecisionSpec.js: -------------------------------------------------------------------------------- 1 | describe('#_adjustPrecision', () => { 2 | beforeEach(() => { 3 | Helper.create('#el'); 4 | }); 5 | 6 | it('sets *half to true', () => { 7 | // given 8 | 9 | var options = { half: false }; 10 | var raty = new Raty(document.querySelector('#el'), options); 11 | 12 | // when 13 | raty._adjustPrecision(); 14 | 15 | // then 16 | expect(raty.opt.half).toEqual(true); 17 | }); 18 | }); 19 | -------------------------------------------------------------------------------- /__tests__/models/_adjustStarNameSpec.js: -------------------------------------------------------------------------------- 1 | describe('#_adjustStarName', () => { 2 | beforeEach(() => { 3 | Helper.create('#el'); 4 | }); 5 | 6 | it('set *path to empty', () => { 7 | // given 8 | 9 | var options = { path: 'path' }; 10 | var raty = new Raty(document.querySelector('#el'), options); 11 | 12 | // when 13 | raty._adjustStarName(); 14 | 15 | // then 16 | expect(raty.opt.path).toEqual(''); 17 | }); 18 | 19 | it('replaces "." to "-" on stars name', () => { 20 | // given 21 | 22 | var options = { 23 | cancelOff: 'x.x', 24 | cancelOn: 'x.x', 25 | starHalf: 'x.x', 26 | starOff: 'x.x', 27 | starOn: 'x.x', 28 | }; 29 | var raty = new Raty(document.querySelector('#el'), options); 30 | 31 | // when 32 | raty._adjustStarName(); 33 | 34 | // then 35 | expect(raty.opt.cancelOff).toEqual('x-x'); 36 | expect(raty.opt.cancelOn).toEqual('x-x'); 37 | expect(raty.opt.starHalf).toEqual('x-x'); 38 | expect(raty.opt.starOff).toEqual('x-x'); 39 | expect(raty.opt.starOn).toEqual('x-x'); 40 | }); 41 | }); 42 | -------------------------------------------------------------------------------- /__tests__/models/_adjustedScoreSpec.js: -------------------------------------------------------------------------------- 1 | describe('#_adjustedScore', () => { 2 | beforeEach(() => { 3 | Helper.create('#el'); 4 | }); 5 | 6 | context('when score is null', function () { 7 | it('returns undefined', () => { 8 | // given 9 | var options = {}; 10 | var score = null; 11 | var raty = new Raty(document.querySelector('#el'), options); 12 | 13 | // when 14 | var value = raty._adjustedScore(score); 15 | 16 | // then 17 | expect(value).toEqual(undefined); 18 | }); 19 | }); 20 | 21 | context('when score is undefined', function () { 22 | it('returns undefined', () => { 23 | // given 24 | var options = {}; 25 | var score = undefined; 26 | var raty = new Raty(document.querySelector('#el'), options); 27 | 28 | // when 29 | var value = raty._adjustedScore(score); 30 | 31 | // then 32 | expect(value).toEqual(undefined); 33 | }); 34 | }); 35 | 36 | context('when score is less than zero', function () { 37 | it('returns the zero', () => { 38 | // given 39 | var options = { number: 1 }; 40 | var score = -1; 41 | var raty = new Raty(document.querySelector('#el'), options); 42 | 43 | // when 44 | var value = raty._adjustedScore(score); 45 | 46 | // then 47 | expect(value).toEqual(0); 48 | }); 49 | }); 50 | 51 | context('when score is equal zero', function () { 52 | it('returns the zero', () => { 53 | // given 54 | var options = { number: 1 }; 55 | var score = 0; 56 | var raty = new Raty(document.querySelector('#el'), options); 57 | 58 | // when 59 | var value = raty._adjustedScore(score); 60 | 61 | // then 62 | expect(value).toEqual(0); 63 | }); 64 | }); 65 | 66 | context('when score is more than *number', function () { 67 | it('returns the number', () => { 68 | // given 69 | var options = { number: 1 }; 70 | var score = 2; 71 | var raty = new Raty(document.querySelector('#el'), options); 72 | 73 | // when 74 | var value = raty._adjustedScore(score); 75 | 76 | // then 77 | expect(value).toEqual(1); 78 | }); 79 | }); 80 | }); 81 | -------------------------------------------------------------------------------- /__tests__/models/_attributesForIndexSpec.js: -------------------------------------------------------------------------------- 1 | describe('#_attributesForIndex', () => { 2 | beforeEach(() => { 3 | Helper.create('#el'); 4 | }); 5 | 6 | context('when :starType is img', function () { 7 | it('uses alt attribute with given index', () => { 8 | // given 9 | 10 | var options = { starType: 'img' }; 11 | var index = 1; 12 | var raty = new Raty(document.querySelector('#el'), options); 13 | 14 | // when 15 | var attributes = raty._attributesForIndex(index); 16 | 17 | // then 18 | expect(attributes.alt).toEqual(index); 19 | }); 20 | 21 | it('uses src with :path and returned _nameForIndex', () => { 22 | // given 23 | 24 | var name = 'starOff'; 25 | var options = { path: 'path', starOff: 'starOff', starType: 'img' }; 26 | var index = 1; 27 | var raty = new Raty(document.querySelector('#el'), options); 28 | 29 | jest.spyOn(raty, '_nameForIndex').mockImplementationOnce(() => name); 30 | 31 | // when 32 | var attributes = raty._attributesForIndex(index); 33 | 34 | // then 35 | expect(attributes.src).toEqual('pathstarOff'); 36 | }); 37 | 38 | it('does not use data-alt', () => { 39 | // given 40 | 41 | var options = { starType: 'img' }; 42 | var index = 1; 43 | var raty = new Raty(document.querySelector('#el'), options); 44 | 45 | // when 46 | var attributes = raty._attributesForIndex(index); 47 | 48 | // then 49 | expect(attributes['data-alt']).toEqual(undefined); 50 | }); 51 | 52 | it('does not use class', () => { 53 | // given 54 | 55 | var options = { starType: 'img' }; 56 | var index = 1; 57 | var raty = new Raty(document.querySelector('#el'), options); 58 | 59 | // when 60 | var attributes = raty._attributesForIndex(index); 61 | 62 | // then 63 | expect(attributes['class']).toEqual(undefined); 64 | }); 65 | 66 | it('sets title with _getHint and given index', () => { 67 | // given 68 | 69 | var hint = 'double'; 70 | var options = { starType: 'img' }; 71 | var index = 1; 72 | var raty = new Raty(document.querySelector('#el'), options); 73 | 74 | raty.init(); 75 | 76 | jest.spyOn(raty, '_getHint').mockImplementationOnce(() => hint); 77 | 78 | // when 79 | var attributes = raty._attributesForIndex(index); 80 | 81 | // then 82 | expect(attributes.title).toEqual(hint); 83 | }); 84 | }); 85 | 86 | context('when :starType is not img', function () { 87 | it('uses data-alt attribute with given index', () => { 88 | // given 89 | 90 | var options = { starType: 'i' }; 91 | var index = 1; 92 | var raty = new Raty(document.querySelector('#el'), options); 93 | 94 | // when 95 | var attributes = raty._attributesForIndex(index); 96 | 97 | // then 98 | expect(attributes['data-alt']).toEqual(index); 99 | }); 100 | 101 | it('uses class with property name returned _nameForIndex', () => { 102 | // given 103 | 104 | var name = 'starOff'; 105 | var options = { starType: 'i' }; 106 | var index = 1; 107 | var raty = new Raty(document.querySelector('#el'), options); 108 | 109 | raty.init(); 110 | 111 | jest.spyOn(raty, '_nameForIndex').mockImplementationOnce(() => name); 112 | 113 | // when 114 | var attributes = raty._attributesForIndex(index); 115 | 116 | // then 117 | expect(attributes['class']).toEqual(raty.opt.starOff); 118 | }); 119 | 120 | it('does not use alt', () => { 121 | // given 122 | 123 | var options = { starType: 'i' }; 124 | var index = 1; 125 | var raty = new Raty(document.querySelector('#el'), options); 126 | 127 | // when 128 | var attributes = raty._attributesForIndex(index); 129 | 130 | // then 131 | expect(attributes.alt).toEqual(undefined); 132 | }); 133 | 134 | it('does not use src', () => { 135 | // given 136 | 137 | var options = { starType: 'i' }; 138 | var index = 1; 139 | var raty = new Raty(document.querySelector('#el'), options); 140 | 141 | // when 142 | var attributes = raty._attributesForIndex(index); 143 | 144 | // then 145 | expect(attributes.src).toEqual(undefined); 146 | }); 147 | 148 | it('sets title with _getHint and given index', () => { 149 | // given 150 | 151 | var hint = 'double'; 152 | var options = { starType: 'i' }; 153 | var index = 1; 154 | var raty = new Raty(document.querySelector('#el'), options); 155 | 156 | raty.init(); 157 | 158 | jest.spyOn(raty, '_getHint').mockImplementationOnce(() => hint); 159 | 160 | // when 161 | var attributes = raty._attributesForIndex(index); 162 | 163 | // then 164 | expect(attributes.title).toEqual(hint); 165 | }); 166 | }); 167 | }); 168 | -------------------------------------------------------------------------------- /__tests__/models/_betweenSpec.js: -------------------------------------------------------------------------------- 1 | describe('#_between', () => { 2 | beforeEach(() => { 3 | Helper.create('#el'); 4 | }); 5 | 6 | context('when value is less than min', function () { 7 | var max = 2; 8 | var min = 1; 9 | var number = 0; 10 | 11 | it('returns the min', () => { 12 | // given 13 | 14 | var options = {}; 15 | var raty = new Raty(document.querySelector('#el'), options); 16 | 17 | // when 18 | var result = raty._between(number, min, max); 19 | 20 | // then 21 | expect(result).toEqual(1); 22 | }); 23 | }); 24 | 25 | context('when value is more than max', function () { 26 | var max = 2; 27 | var min = 1; 28 | var number = 3; 29 | 30 | it('returns the min', () => { 31 | // given 32 | 33 | var options = {}; 34 | var raty = new Raty(document.querySelector('#el'), options); 35 | 36 | // when 37 | var result = raty._between(number, min, max); 38 | 39 | // then 40 | expect(result).toEqual(2); 41 | }); 42 | }); 43 | }); 44 | -------------------------------------------------------------------------------- /__tests__/models/_createStarsSpec.js: -------------------------------------------------------------------------------- 1 | describe('#_createStars', () => { 2 | beforeEach(() => { 3 | Helper.create('#el'); 4 | }); 5 | 6 | context('with :number as 3', function () { 7 | it('creates 3 stars', () => { 8 | // given 9 | 10 | var options = { number: 3 }; 11 | var raty = new Raty(document.querySelector('#el'), options); 12 | 13 | // when 14 | raty._createStars(); 15 | 16 | // then 17 | expect(raty.element.querySelectorAll(raty.opt.starType).length).toEqual(3); 18 | }); 19 | 20 | it('sets the right attributes', () => { 21 | // given 22 | var options = {}; 23 | var raty = new Raty(document.querySelector('#el'), options); 24 | 25 | jest.spyOn(raty, '_attributesForIndex').mockImplementation(() => ({ 26 | alt: 'alt', 27 | })); 28 | 29 | // when 30 | raty._createStars(); 31 | 32 | // then 33 | raty.element.querySelectorAll(raty.opt.starType).forEach((element) => 34 | expect(element).toHaveAttribute('alt', 'alt') 35 | ); 36 | }); 37 | 38 | it('uses the :starType to build the star', () => { 39 | // given 40 | 41 | var options = { starType: 'li' }; 42 | var raty = new Raty(document.querySelector('#el'), options); 43 | 44 | // when 45 | raty._createStars(); 46 | 47 | // then 48 | var stars = raty.element.querySelectorAll(raty.opt.starType); 49 | 50 | expect(stars[0].tagName).toEqual('LI'); 51 | expect(stars[1].tagName).toEqual('LI'); 52 | expect(stars[2].tagName).toEqual('LI'); 53 | expect(stars[3].tagName).toEqual('LI'); 54 | expect(stars[4].tagName).toEqual('LI'); 55 | }); 56 | 57 | context('with :space as true', function () { 58 | it('puts one space between the stars', () => { 59 | // given 60 | var options = { number: 2, space: true }; 61 | var raty = new Raty(document.querySelector('#el'), options); 62 | var regex = /.+ .+/; 63 | 64 | jest.spyOn(raty, '_attributesForIndex').mockImplementationOnce(() => ({})); 65 | 66 | // when 67 | raty._createStars(); 68 | 69 | // then 70 | expect(regex.test(raty.element.innerHTML)).toEqual(true); 71 | }); 72 | }); 73 | 74 | context('with :space as false', function () { 75 | it('does not puts space between the stars', () => { 76 | // given 77 | var options = { number: 2, space: true }; 78 | var raty = new Raty(document.querySelector('#el'), options); 79 | var regex = /.+ .+/; 80 | 81 | jest.spyOn(raty, '_attributesForIndex').mockImplementationOnce(() => ({})); 82 | 83 | // when 84 | raty._createStars(); 85 | 86 | // then 87 | expect(regex.test(raty.element.innerHTML)).toEqual(true); 88 | }); 89 | }); 90 | 91 | it('saves the stars on raty', () => { 92 | // given 93 | 94 | var options = {}; 95 | var raty = new Raty(document.querySelector('#el'), options); 96 | 97 | // when 98 | raty._createStars(); 99 | 100 | // then 101 | expect(raty.stars).toEqual(raty.element.querySelectorAll(raty.opt.starType)); 102 | }); 103 | }); 104 | }); 105 | -------------------------------------------------------------------------------- /__tests__/models/_executeCallbacksSpec.js: -------------------------------------------------------------------------------- 1 | describe('#_executeCallbacks', () => { 2 | beforeEach(() => { 3 | Helper.create('#el'); 4 | }); 5 | 6 | context('when options should compute, not evaluate at runtime, the return and it is a function', function () { 7 | it('uses the given return', () => { 8 | // given 9 | var raty = new Raty(document.querySelector('#el'), { 10 | number: function () { 11 | return 36; 12 | }, 13 | }); 14 | 15 | // when 16 | raty._executeCallbacks(); 17 | 18 | // then 19 | expect(raty.opt.number).toEqual(36); 20 | }); 21 | 22 | context('whe there is not return', function () { 23 | it('is undefined', () => { 24 | // given 25 | var raty = new Raty(document.querySelector('#el'), { number: function () {} }); 26 | 27 | // when 28 | raty._executeCallbacks(); 29 | 30 | // then 31 | expect(raty.opt.number).toEqual(undefined); 32 | }); 33 | }); 34 | 35 | context('when options is not a function', function () { 36 | it('keeps the given value', () => { 37 | // given 38 | var raty = new Raty(document.querySelector('#el'), { number: 16 }); 39 | 40 | // when 41 | raty._executeCallbacks(); 42 | 43 | // then 44 | expect(raty.opt.number).toEqual(16); 45 | }); 46 | }); 47 | }); 48 | 49 | context('when options is not no allow list', function () { 50 | it('keeps the given value', () => { 51 | // given 52 | 53 | var raty = new Raty(document.querySelector('#el'), { denied: 'default' }); 54 | 55 | // when 56 | raty._executeCallbacks(); 57 | 58 | // then 59 | expect(raty.opt.denied).toEqual('default'); 60 | }); 61 | }); 62 | }); 63 | -------------------------------------------------------------------------------- /__tests__/models/_getDecimalSpec.js: -------------------------------------------------------------------------------- 1 | describe('#_getDecimal', () => { 2 | beforeEach(() => { 3 | Helper.create('#el'); 4 | }); 5 | 6 | context('when number is an integer', function () { 7 | var number = 0; 8 | 9 | it('returns the first fraction', () => { 10 | // given 11 | 12 | var options = {}; 13 | var raty = new Raty(document.querySelector('#el'), options); 14 | 15 | // when 16 | var decimal = raty._getDecimal(number, 1); 17 | 18 | // then 19 | expect(decimal).toEqual(0); 20 | }); 21 | }); 22 | 23 | context('when number is a float', function () { 24 | context('with 1 fraction', function () { 25 | var number = 0.1; 26 | 27 | it('returns the first fraction', () => { 28 | // given 29 | var options = {}; 30 | var raty = new Raty(document.querySelector('#el'), options); 31 | 32 | // when 33 | var decimal = raty._getDecimal(number, 1); 34 | 35 | // then 36 | expect(decimal).toEqual(1); 37 | }); 38 | 39 | context('when has four 9 consecutives', function () { 40 | var number = 0.19999; 41 | 42 | it('increments the first decimal', () => { 43 | // given 44 | var options = {}; 45 | var raty = new Raty(document.querySelector('#el'), options); 46 | 47 | // when 48 | var decimal = raty._getDecimal(number, 1); 49 | 50 | // then 51 | expect(decimal).toEqual(2); 52 | }); 53 | }); 54 | }); 55 | 56 | context('with 2 fraction', function () { 57 | var number = 0.12; 58 | 59 | it('returns the first fraction', () => { 60 | // given 61 | var options = {}; 62 | var raty = new Raty(document.querySelector('#el'), options); 63 | 64 | // when 65 | var decimal = raty._getDecimal(number, 2); 66 | 67 | // then 68 | expect(decimal).toEqual(12); 69 | }); 70 | 71 | context('when has four 9 consecutives', function () { 72 | var number = 0.19999; 73 | 74 | it('increments the first decimal', () => { 75 | // given 76 | var options = {}; 77 | var raty = new Raty(document.querySelector('#el'), options); 78 | 79 | // when 80 | var decimal = raty._getDecimal(number, 2); 81 | 82 | // then 83 | expect(decimal).toEqual(20); 84 | }); 85 | }); 86 | }); 87 | }); 88 | }); 89 | -------------------------------------------------------------------------------- /__tests__/models/_isReadOnlySpec.js: -------------------------------------------------------------------------------- 1 | describe('#_isReadOnly', () => { 2 | it('returns true when read only value is true', () => { 3 | // given 4 | Helper.create('#el'); 5 | 6 | var raty = new Raty(document.querySelector('#el')).init(); 7 | 8 | // when 9 | raty.element.dataset.readOnly = true; 10 | 11 | // then 12 | expect(raty._isReadOnly()).toEqual(true); 13 | }); 14 | 15 | it('returns "true" when read only value is true', () => { 16 | // given 17 | Helper.create('#el'); 18 | 19 | var raty = new Raty(document.querySelector('#el')).init(); 20 | 21 | // when 22 | raty.element.dataset.readOnly = 'true'; 23 | 24 | // then 25 | expect(raty._isReadOnly()).toEqual(true); 26 | }); 27 | 28 | it('returns false when read only value is false', () => { 29 | // given 30 | Helper.create('#el'); 31 | 32 | var raty = new Raty(document.querySelector('#el')).init(); 33 | 34 | // when 35 | raty.element.dataset.readOnly = false; 36 | 37 | // then 38 | expect(raty._isReadOnly()).toEqual(false); 39 | }); 40 | 41 | it('returns false when read only value is undefined', () => { 42 | // given 43 | Helper.create('#el'); 44 | 45 | var raty = new Raty(document.querySelector('#el')).init(); 46 | 47 | // when 48 | raty.element.dataset.readOnly = undefined; 49 | 50 | // then 51 | expect(raty._isReadOnly()).toEqual(false); 52 | }); 53 | 54 | it('returns false when read only value is null', () => { 55 | // given 56 | Helper.create('#el'); 57 | 58 | var raty = new Raty(document.querySelector('#el')).init(); 59 | 60 | // when 61 | raty.element.dataset.readOnly = null; 62 | 63 | // then 64 | expect(raty._isReadOnly()).toEqual(false); 65 | }); 66 | 67 | it('returns false when read only value is empty', () => { 68 | // given 69 | Helper.create('#el'); 70 | 71 | var raty = new Raty(document.querySelector('#el')).init(); 72 | 73 | // when 74 | raty.element.dataset.readOnly = ''; 75 | 76 | // then 77 | expect(raty._isReadOnly()).toEqual(false); 78 | }); 79 | }); 80 | -------------------------------------------------------------------------------- /__tests__/models/_nameForIndexSpec.js: -------------------------------------------------------------------------------- 1 | describe('#_nameForIndex', () => { 2 | beforeEach(() => { 3 | Helper.create('#el'); 4 | }); 5 | 6 | context('when score is null', function () { 7 | it('returns :starOff', () => { 8 | // given 9 | 10 | var options = {}; 11 | var index = 'double'; 12 | var raty = new Raty(document.querySelector('#el'), options); 13 | 14 | raty.opt.score = null; 15 | 16 | // when 17 | var name = raty._nameForIndex(index); 18 | 19 | // then 20 | expect(name).toEqual('starOff'); 21 | }); 22 | }); 23 | 24 | context('when score is undefined', function () { 25 | it('returns :starOff', () => { 26 | // given 27 | 28 | var options = {}; 29 | var index = 'double'; 30 | var raty = new Raty(document.querySelector('#el'), options); 31 | 32 | delete raty.opt.score; 33 | 34 | // when 35 | var name = raty._nameForIndex(index); 36 | 37 | // then 38 | expect(name).toEqual('starOff'); 39 | }); 40 | }); 41 | 42 | context('when has score', function () { 43 | context('and score is less than index', function () { 44 | var index = 2; 45 | var score = 1; 46 | 47 | it('returns :starOff', () => { 48 | // given 49 | var options = {}; 50 | var raty = new Raty(document.querySelector('#el'), options); 51 | 52 | raty.opt.score = score; 53 | 54 | // when 55 | var name = raty._nameForIndex(index); 56 | 57 | // then 58 | expect(name).toEqual('starOff'); 59 | }); 60 | }); 61 | 62 | context('and score is equal index', function () { 63 | var index = 1; 64 | var score = 1; 65 | 66 | it('returns :starOff', () => { 67 | // given 68 | var options = {}; 69 | var raty = new Raty(document.querySelector('#el'), options); 70 | 71 | raty.opt.score = score; 72 | 73 | // when 74 | var name = raty._nameForIndex(index); 75 | 76 | // then 77 | expect(name).toEqual('starOn'); 78 | }); 79 | }); 80 | 81 | context('and score is greater then index', function () { 82 | var index = 1; 83 | var score = 2; 84 | 85 | it('returns :starOff', () => { 86 | // given 87 | var options = {}; 88 | var raty = new Raty(document.querySelector('#el'), options); 89 | 90 | raty.opt.score = score; 91 | 92 | // when 93 | var name = raty._nameForIndex(index); 94 | 95 | // then 96 | expect(name).toEqual('starOn'); 97 | }); 98 | }); 99 | }); 100 | }); 101 | -------------------------------------------------------------------------------- /__tests__/models/_parseOptionsSpec.js: -------------------------------------------------------------------------------- 1 | describe('#_parseOptions', () => { 2 | it('parses options', () => { 3 | // given 4 | Helper.create('#el'); 5 | 6 | var raty = new Raty(document.querySelector('#el')); 7 | 8 | // when 9 | 10 | var options = raty._parseOptions({ 11 | param1: 'true', 12 | param2: 'false', 13 | param3: '', 14 | param4: 'b', 15 | param5: '3', 16 | }); 17 | 18 | // then 19 | expect(options).toEqual({ 20 | param1: true, 21 | param2: false, 22 | param3: '', 23 | param4: 'b', 24 | param5: 3, 25 | }); 26 | }); 27 | }); 28 | -------------------------------------------------------------------------------- /__tests__/models/_setPathSpec.js: -------------------------------------------------------------------------------- 1 | describe('#_setPath', () => { 2 | beforeEach(() => { 3 | Helper.create('#el'); 4 | }); 5 | 6 | context('when path is null', function () { 7 | it('sets to an empty string', () => { 8 | // given 9 | 10 | var options = {}; 11 | var raty = new Raty(document.querySelector('#el'), options); 12 | 13 | raty.opt.path = null; 14 | 15 | // when 16 | raty._setPath(); 17 | 18 | // then 19 | expect(raty.opt.path).toEqual(''); 20 | }); 21 | }); 22 | 23 | context('when path is undefined', function () { 24 | it('sets to an empty string', () => { 25 | // given 26 | 27 | var options = {}; 28 | var raty = new Raty(document.querySelector('#el'), options); 29 | 30 | delete raty.opt.path; 31 | 32 | // when 33 | raty._setPath(); 34 | 35 | // then 36 | expect(raty.opt.path).toEqual(''); 37 | }); 38 | }); 39 | 40 | context('when path is defined', function () { 41 | context('with a slash at end', function () { 42 | it('keeps the same value', () => { 43 | // given 44 | var options = {}; 45 | var raty = new Raty(document.querySelector('#el'), options); 46 | 47 | raty.opt.path = 'path/'; 48 | 49 | // when 50 | raty._setPath(); 51 | 52 | // then 53 | expect(raty.opt.path).toEqual('path/'); 54 | }); 55 | }); 56 | 57 | context('without a slash at end', function () { 58 | it('appends a slash', () => { 59 | // given 60 | var options = {}; 61 | var raty = new Raty(document.querySelector('#el'), options); 62 | 63 | raty.opt.path = 'path/'; 64 | 65 | // when 66 | raty._setPath(); 67 | 68 | // then 69 | expect(raty.opt.path).toEqual('path/'); 70 | }); 71 | }); 72 | }); 73 | }); 74 | -------------------------------------------------------------------------------- /__tests__/models/initSpec.js: -------------------------------------------------------------------------------- 1 | describe('#init', () => { 2 | beforeEach(() => { 3 | Helper.create('#el'); 4 | }); 5 | 6 | it('calls all necessary methods', () => { 7 | // given 8 | 9 | var raty = new Raty(document.querySelector('#el'), { score: 1 }); 10 | 11 | jest.spyOn(raty, '_executeCallbacks'); 12 | jest.spyOn(raty, '_adjustNumber'); 13 | jest.spyOn(raty, '_adjustHints'); 14 | jest.spyOn(raty, '_adjustedScore').mockImplementationOnce(()=>''); 15 | jest.spyOn(raty, '_setPath'); 16 | jest.spyOn(raty, '_createStars'); 17 | jest.spyOn(raty, '_createScore'); 18 | jest.spyOn(raty, '_apply'); 19 | jest.spyOn(raty, '_setTitle'); 20 | jest.spyOn(raty, '_target'); 21 | jest.spyOn(raty, '_binds'); 22 | 23 | // when 24 | raty.init(); 25 | 26 | // then 27 | expect(raty._executeCallbacks).toHaveBeenCalled(); 28 | expect(raty._adjustNumber).toHaveBeenCalled(); 29 | expect(raty._adjustHints).toHaveBeenCalled(); 30 | expect(raty._adjustedScore).toHaveBeenCalledWith(1); 31 | expect(raty._setPath).toHaveBeenCalled(); 32 | expect(raty._createStars).toHaveBeenCalled(); 33 | expect(raty._createScore).toHaveBeenCalled(); 34 | expect(raty._apply).toHaveBeenCalledWith(''); 35 | expect(raty._setTitle).toHaveBeenCalledWith(''); 36 | expect(raty._target).toHaveBeenCalledWith(''); 37 | expect(raty._binds).toHaveBeenCalled(); 38 | 39 | expect(raty.element.style.cursor).toEqual('pointer'); 40 | }); 41 | 42 | it('returns the raty instance', () => { 43 | // given 44 | var raty = new Raty(document.querySelector('#el'), { score: 1 }); 45 | 46 | // when 47 | var result = raty.init(); 48 | 49 | // then 50 | expect(result).toEqual(raty); 51 | }); 52 | 53 | context('when *starType is "img"', function () { 54 | it('does not calls :_adjustStarName', () => { 55 | // given 56 | var raty = new Raty(document.querySelector('#el'), { starType: 'img' }); 57 | 58 | jest.spyOn(raty, '_adjustStarName'); 59 | 60 | // when 61 | raty.init(); 62 | 63 | // then 64 | expect(raty._adjustStarName).not.toHaveBeenCalled(); 65 | }); 66 | }); 67 | 68 | context('when *starType is not "img"', function () { 69 | it('calls :_adjustStarName', () => { 70 | // given 71 | 72 | var options = { starType: 'i' }; 73 | var raty = new Raty(document.querySelector('#el'), options); 74 | 75 | jest.spyOn(raty, '_adjustStarName'); 76 | 77 | // when 78 | raty.init(); 79 | 80 | // then 81 | expect(raty._adjustStarName).toHaveBeenCalled(); 82 | }); 83 | }); 84 | 85 | context('when *cancel is true', function () { 86 | it('does not calls :_createCancel', () => { 87 | // given 88 | 89 | var options = { cancelButton: true }; 90 | var raty = new Raty(document.querySelector('#el'), options); 91 | 92 | jest.spyOn(raty, '_createCancel'); 93 | 94 | // when 95 | raty.init(); 96 | 97 | // then 98 | expect(raty._createCancel).toHaveBeenCalled(); 99 | }); 100 | }); 101 | 102 | context('when *cancel is false', function () { 103 | it('calls :_createCancel', () => { 104 | // given 105 | 106 | var options = { cancelButton: false }; 107 | var raty = new Raty(document.querySelector('#el'), options); 108 | 109 | jest.spyOn(raty, '_createCancel'); 110 | 111 | // when 112 | raty.init(); 113 | 114 | // then 115 | expect(raty._createCancel).not.toHaveBeenCalled(); 116 | }); 117 | }); 118 | 119 | context('when *precision is true', function () { 120 | it('does not calls :_adjustPrecision', () => { 121 | // given 122 | 123 | var options = { precision: true }; 124 | var raty = new Raty(document.querySelector('#el'), options); 125 | 126 | jest.spyOn(raty, '_adjustPrecision'); 127 | 128 | // when 129 | raty.init(); 130 | 131 | // then 132 | expect(raty._adjustPrecision).toHaveBeenCalled(); 133 | }); 134 | }); 135 | 136 | context('when *precision is false', function () { 137 | it('calls :_adjustPrecision', () => { 138 | // given 139 | 140 | var options = { precision: false }; 141 | var raty = new Raty(document.querySelector('#el'), options); 142 | 143 | jest.spyOn(raty, '_adjustPrecision'); 144 | 145 | // when 146 | raty.init(); 147 | 148 | // then 149 | expect(raty._adjustPrecision).not.toHaveBeenCalled(); 150 | }); 151 | }); 152 | 153 | context('when *readOnly is true', function () { 154 | it('calls :_lock', () => { 155 | // given 156 | 157 | var raty = new Raty(document.querySelector('#el'), { readOnly: true }); 158 | 159 | jest.spyOn(raty, '_lock'); 160 | 161 | // when 162 | raty.init(); 163 | 164 | // then 165 | expect(raty._lock).toHaveBeenCalled(); 166 | }); 167 | 168 | it('does not call :_binds', () => { 169 | // given 170 | 171 | var raty = new Raty(document.querySelector('#el'), { readOnly: true }); 172 | 173 | jest.spyOn(raty, '_binds'); 174 | 175 | // when 176 | raty.init(); 177 | 178 | // then 179 | expect(raty._binds).not.toHaveBeenCalled(); 180 | }); 181 | 182 | it('does not set cursor style to pointer', () => { 183 | // given 184 | 185 | var raty = new Raty(document.querySelector('#el'), { readOnly: true }); 186 | 187 | // when 188 | raty.init(); 189 | 190 | // then 191 | expect(raty.element.style.cursor).not.toEqual('pointer'); 192 | }); 193 | }); 194 | 195 | context('when *readOnly is false', function () { 196 | it('does not call :_lock', () => { 197 | // given 198 | 199 | var raty = new Raty(document.querySelector('#el'), { readOnly: false }); 200 | 201 | jest.spyOn(raty, '_lock'); 202 | 203 | // when 204 | raty.init(); 205 | 206 | // then 207 | expect(raty._lock).not.toHaveBeenCalled(); 208 | }); 209 | 210 | it('calls :_binds', () => { 211 | // given 212 | 213 | var raty = new Raty(document.querySelector('#el'), { readOnly: false }); 214 | 215 | jest.spyOn(raty, '_binds'); 216 | 217 | // when 218 | raty.init(); 219 | 220 | // then 221 | expect(raty._binds).toHaveBeenCalled(); 222 | }); 223 | 224 | it('sets cursor style to pointer', () => { 225 | // given 226 | 227 | var raty = new Raty(document.querySelector('#el'), { readOnly: false }); 228 | 229 | // when 230 | raty.init(); 231 | 232 | // then 233 | expect(raty.element.style.cursor).toEqual('pointer'); 234 | }); 235 | }); 236 | }); 237 | -------------------------------------------------------------------------------- /__tests__/models/optionsSpec.js: -------------------------------------------------------------------------------- 1 | describe('options', () => { 2 | beforeEach(() => { 3 | Helper.create('#el'); 4 | }); 5 | 6 | it('has the right default values', () => { 7 | // given 8 | var raty = new Raty(document.querySelector('#el')); 9 | 10 | // when 11 | var opt = raty.opt; 12 | 13 | // then 14 | expect(opt.cancelButton).toEqual(false); 15 | expect(opt.cancelClass).toEqual('raty-cancel'); 16 | expect(opt.cancelHint).toEqual('Cancel this rating!'); 17 | expect(opt.cancelOff).toEqual('cancel-off.png'); 18 | expect(opt.cancelOn).toEqual('cancel-on.png'); 19 | expect(opt.cancelPlace).toEqual('left'); 20 | expect(opt.click).toEqual(undefined); 21 | expect(opt.half).toEqual(false); 22 | expect(opt.halfShow).toEqual(true); 23 | expect(opt.hints).toEqual(['bad', 'poor', 'regular', 'good', 'gorgeous']); 24 | expect(opt.iconRange).toEqual(undefined); 25 | expect(opt.mouseover).toEqual(undefined); 26 | expect(opt.noRatedMsg).toEqual('Not rated yet!'); 27 | expect(opt.number).toBe(5); 28 | expect(opt.path).toEqual(undefined); 29 | expect(opt.precision).toEqual(false); 30 | expect(opt.readOnly).toEqual(false); 31 | expect(opt.round.down).toEqual(0.25); 32 | expect(opt.round.full).toEqual(0.6); 33 | expect(opt.round.up).toEqual(0.76); 34 | expect(opt.score).toEqual(undefined); 35 | expect(opt.scoreName).toEqual('score'); 36 | expect(opt.single).toEqual(false); 37 | expect(opt.space).toEqual(true); 38 | expect(opt.starHalf).toEqual('star-half.png'); 39 | expect(opt.starOff).toEqual('star-off.png'); 40 | expect(opt.starOn).toEqual('star-on.png'); 41 | expect(opt.target).toEqual(undefined); 42 | expect(opt.targetFormat).toEqual('{score}'); 43 | expect(opt.targetKeep).toEqual(false); 44 | expect(opt.targetText).toEqual(''); 45 | expect(opt.targetType).toEqual('hint'); 46 | expect(opt.width).toEqual(undefined); 47 | }); 48 | }); 49 | -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "Washington Botelho (https://www.wbotelhos.com)" 4 | ], 5 | "description": "Raty - A Star Rating Plugin", 6 | "homepage": "https://github.com/wbotelhos/raty", 7 | "ignore": [ 8 | "**/.*", 9 | "node_modules", 10 | "spec", 11 | "vendor" 12 | ], 13 | "keywords": [ 14 | "classificacao", 15 | "classificar", 16 | "javascript", 17 | "library", 18 | "plugin", 19 | "rating", 20 | "raty", 21 | "star", 22 | "staring", 23 | "votar", 24 | "voto" 25 | ], 26 | "license": "MIT", 27 | "main": [ 28 | "src/raty.js", 29 | "src/raty.css", 30 | "src/fonts/*", 31 | "src/images/*" 32 | ], 33 | "name": "raty" 34 | } 35 | -------------------------------------------------------------------------------- /build/raty.amd.min.js: -------------------------------------------------------------------------------- 1 | define(["exports"],function(t){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;t.default=class{constructor(t,e={}){this.element=t,this.opt={...this.defaultOptions(),...e,...this._parseOptions(t.dataset)}}defaultOptions(){return{cancelButton:!1,cancelClass:"raty-cancel",cancelHint:"Cancel this rating!",cancelOff:"cancel-off.png",cancelOn:"cancel-on.png",cancelPlace:"left",click:void 0,half:!1,halfShow:!0,hints:["bad","poor","regular","good","gorgeous"],iconRange:void 0,iconRangeSame:!1,mouseout:void 0,mouseover:void 0,noRatedMsg:"Not rated yet!",number:5,numberMax:20,path:void 0,precision:!1,readOnly:!1,round:{down:.25,full:.6,up:.76},score:void 0,scoreName:"score",single:!1,space:!0,starHalf:"star-half.png",starOff:"star-off.png",starOn:"star-on.png",starType:"img",target:void 0,targetFormat:"{score}",targetKeep:!1,targetScore:void 0,targetText:"",targetType:"hint"}}cancel(t){this._isReadOnly()||(this[t?"click":"score"](null),this.scoreField.removeAttribute("value"))}click(t){this._isReadOnly()||(t=this._adjustedScore(t),this._apply(t),this.opt.click&&this.opt.click.call(this,t,this.element),this._target(t))}move(t){var e=parseInt(t,10),t=this._getDecimal(t,1),s=(e>=this.opt.number&&(e=this.opt.number-1,t=10),this._getWidth()),e=this.stars[e],s=e.offsetLeft+s/10*t,t=new Event("mousemove");t.pageX=s,this.isMove=!0,e.dispatchEvent(t),this.isMove=!1}readOnly(t){this._isReadOnly()!==t&&(t?this._lock():(this._binds(),this._unlock()),this.element.dataset.readOnly=t)}score(){return arguments.length?this.setScore(arguments[0]):this.getScore()}setScore(t){this._isReadOnly()||(t=this._adjustedScore(t),this._apply(t),this._target(t))}getScore(){var t=[],e=this.scoreField.value;return t.push(e?+e:void 0),1{i.addEventListener("click",s=>{if(!this._isReadOnly()){let t,e=this.opt.half||this.opt.precision?this.element.dataset.score:i.alt||i.dataset.alt;this.opt.half&&!this.opt.precision&&(e=this._roundHalfScore(e)),!(t=this.opt.click?this.opt.click.call(this,+e,this.element,s):t)&&void 0!==t||this._apply(+e)}})})}_bindClickCancel(){this.cancelButton.addEventListener("click",t=>{this.scoreField.removeAttribute("value"),this.opt.click&&this.opt.click.call(this,null,this.element,t)})}_bindOut(){this.element.addEventListener("mouseleave",t=>{var e=+this.scoreField.value||void 0;this._apply(e),this._target(e,t),this._resetTitle(),this.opt.mouseout&&this.opt.mouseout.call(this,e,this.element,t)})}_bindOutCancel(){this.cancelButton.addEventListener("mouseleave",t=>{let e=this.opt.cancelOff;var s;"img"!==this.opt.starType&&(e=this.opt.cancelClass+" "+e),this._setIcon(this.cancelButton,e),this.opt.mouseout&&(s=+this.scoreField.value||void 0,this.opt.mouseout.call(this,s,this.element,t))})}_bindOver(){const t=this.opt.half?"mousemove":"mouseover";this.stars.forEach(s=>{s.addEventListener(t,t=>{var e=this._getScoreByPosition(t,s);this._fill(e),this.opt.half&&(this._roundStars(e,t),this._setTitle(e,t),this.element.dataset.score=e),this._target(e,t),this.opt.mouseover&&this.opt.mouseover.call(this,e,this.element,t)})})}_bindOverCancel(){this.cancelButton.addEventListener("mouseover",e=>{if(!this._isReadOnly()){const s=this.opt.path+this.opt.starOff;let t=this.opt.cancelOn;"img"===this.opt.starType?this.stars.forEach(t=>{t.src=s}):(t=this.opt.cancelClass+" "+t,this.stars.forEach(t=>{t.className=s})),this._setIcon(this.cancelButton,t),this._target(null,e),this.opt.mouseover&&this.opt.mouseover.call(this,null,this.element,e)}})}_buildScoreField(){var t=document.createElement("input");return t.name=this.opt.scoreName,t.type="hidden",this.element.appendChild(t),t}_createCancel(){var t=document.createElement(this.opt.starType),e=this.opt.path+this.opt.cancelOff;t.setAttribute("class",this.opt.cancelClass),t.setAttribute("title",this.opt.cancelHint),"img"===this.opt.starType?(t.setAttribute("alt","x"),t.setAttribute("src",e)):(t.classList.add(e),t.setAttribute("data-alt","x")),"left"===this.opt.cancelPlace?(this.element.prepend(" "),this.element.prepend(t)):(this.element.append(" "),this.element.appendChild(t)),this.cancelButton=t}_createScore(){this.scoreField=document.querySelector(this.opt.targetScore)||this._buildScoreField()}_createStars(){for(let t=1;t<=this.opt.number;t++){var e=this._attributesForIndex(t),s=document.createElement(this.opt.starType);for(const i in e)s.setAttribute(i,e[i]);this.element.appendChild(s),this.opt.space&&ti?(a=this.opt.iconRange[i],t=this._getRangeIcon(a,r),e<=a.range&&this._setIcon(o,t),e===a.range&&i++):(t=this.opt[r?"starOn":"starOff"],this._setIcon(o,t))}}_getDecimal(t,e){t=t.toString().split(".")[1];let s=0;return t&&(s=parseInt(t.slice(0,e),10),"9999"===t.slice(1,5))&&s++,s}_getRangeIcon(t,e){return e?t.on||this.opt.starOn:t.off||this.opt.starOff}_getScoreByPosition(t,e){let s=parseInt(e.alt||e.getAttribute("data-alt"),10);var i;return this.opt.half&&(i=this._getWidth(),t=parseFloat((t.pageX-e.getBoundingClientRect().x)/i),s=s-1+t),s}_getHint(t,e){if(0!==t&&!t)return this.opt.noRatedMsg;var s=Math.ceil(t),s=this.opt.hints[(s||1)-1],e=!e||this.isMove;let i=this._getDecimal(t,1),a=s;return this.opt.precision?(e&&(i=0===i?9:i-1),a=s[i]):(this.opt.halfShow||this.opt.half)&&(i=e&&0===i||5{t.title=e}),this.cancelButton&&(this.cancelButton.style.display="none"),this.element.dataset.readOnly=!0}_nameForIndex(t){return this.opt.score&&this.opt.score>=t?"starOn":"starOff"}_resetTitle(){for(let t=0;t{let s={true:!0,false:!1}[i[e]];return s=null!==s&&void 0!==s?s:i[e],!isNaN(s)&&Number.isInteger(parseFloat(s))&&(s=Number(s)),t[e]=s,t},{})}_roundHalfScore(t){var e=parseInt(t,10);let s=this._getDecimal(t,1);return e+(s=0!==s?5=this.opt.number&&(e=this.opt.number-1,t=10),this._getWidth()),e=this.stars[e],s=e.offsetLeft+s/10*t,t=new Event("mousemove");t.pageX=s,this.isMove=!0,e.dispatchEvent(t),this.isMove=!1}readOnly(t){this._isReadOnly()!==t&&(t?this._lock():(this._binds(),this._unlock()),this.element.dataset.readOnly=t)}score(){return arguments.length?this.setScore(arguments[0]):this.getScore()}setScore(t){this._isReadOnly()||(t=this._adjustedScore(t),this._apply(t),this._target(t))}getScore(){var t=[],e=this.scoreField.value;return t.push(e?+e:void 0),1{i.addEventListener("click",s=>{if(!this._isReadOnly()){let t,e=this.opt.half||this.opt.precision?this.element.dataset.score:i.alt||i.dataset.alt;this.opt.half&&!this.opt.precision&&(e=this._roundHalfScore(e)),!(t=this.opt.click?this.opt.click.call(this,+e,this.element,s):t)&&void 0!==t||this._apply(+e)}})})}_bindClickCancel(){this.cancelButton.addEventListener("click",t=>{this.scoreField.removeAttribute("value"),this.opt.click&&this.opt.click.call(this,null,this.element,t)})}_bindOut(){this.element.addEventListener("mouseleave",t=>{var e=+this.scoreField.value||void 0;this._apply(e),this._target(e,t),this._resetTitle(),this.opt.mouseout&&this.opt.mouseout.call(this,e,this.element,t)})}_bindOutCancel(){this.cancelButton.addEventListener("mouseleave",t=>{let e=this.opt.cancelOff;var s;"img"!==this.opt.starType&&(e=this.opt.cancelClass+" "+e),this._setIcon(this.cancelButton,e),this.opt.mouseout&&(s=+this.scoreField.value||void 0,this.opt.mouseout.call(this,s,this.element,t))})}_bindOver(){const t=this.opt.half?"mousemove":"mouseover";this.stars.forEach(s=>{s.addEventListener(t,t=>{var e=this._getScoreByPosition(t,s);this._fill(e),this.opt.half&&(this._roundStars(e,t),this._setTitle(e,t),this.element.dataset.score=e),this._target(e,t),this.opt.mouseover&&this.opt.mouseover.call(this,e,this.element,t)})})}_bindOverCancel(){this.cancelButton.addEventListener("mouseover",e=>{if(!this._isReadOnly()){const s=this.opt.path+this.opt.starOff;let t=this.opt.cancelOn;"img"===this.opt.starType?this.stars.forEach(t=>{t.src=s}):(t=this.opt.cancelClass+" "+t,this.stars.forEach(t=>{t.className=s})),this._setIcon(this.cancelButton,t),this._target(null,e),this.opt.mouseover&&this.opt.mouseover.call(this,null,this.element,e)}})}_buildScoreField(){var t=document.createElement("input");return t.name=this.opt.scoreName,t.type="hidden",this.element.appendChild(t),t}_createCancel(){var t=document.createElement(this.opt.starType),e=this.opt.path+this.opt.cancelOff;t.setAttribute("class",this.opt.cancelClass),t.setAttribute("title",this.opt.cancelHint),"img"===this.opt.starType?(t.setAttribute("alt","x"),t.setAttribute("src",e)):(t.classList.add(e),t.setAttribute("data-alt","x")),"left"===this.opt.cancelPlace?(this.element.prepend(" "),this.element.prepend(t)):(this.element.append(" "),this.element.appendChild(t)),this.cancelButton=t}_createScore(){this.scoreField=document.querySelector(this.opt.targetScore)||this._buildScoreField()}_createStars(){for(let t=1;t<=this.opt.number;t++){var e=this._attributesForIndex(t),s=document.createElement(this.opt.starType);for(const i in e)s.setAttribute(i,e[i]);this.element.appendChild(s),this.opt.space&&ti?(a=this.opt.iconRange[i],t=this._getRangeIcon(a,r),e<=a.range&&this._setIcon(o,t),e===a.range&&i++):(t=this.opt[r?"starOn":"starOff"],this._setIcon(o,t))}}_getDecimal(t,e){t=t.toString().split(".")[1];let s=0;return t&&(s=parseInt(t.slice(0,e),10),"9999"===t.slice(1,5))&&s++,s}_getRangeIcon(t,e){return e?t.on||this.opt.starOn:t.off||this.opt.starOff}_getScoreByPosition(t,e){let s=parseInt(e.alt||e.getAttribute("data-alt"),10);var i;return this.opt.half&&(i=this._getWidth(),t=parseFloat((t.pageX-e.getBoundingClientRect().x)/i),s=s-1+t),s}_getHint(t,e){if(0!==t&&!t)return this.opt.noRatedMsg;var s=Math.ceil(t),s=this.opt.hints[(s||1)-1],e=!e||this.isMove;let i=this._getDecimal(t,1),a=s;return this.opt.precision?(e&&(i=0===i?9:i-1),a=s[i]):(this.opt.halfShow||this.opt.half)&&(i=e&&0===i||5{t.title=e}),this.cancelButton&&(this.cancelButton.style.display="none"),this.element.dataset.readOnly=!0}_nameForIndex(t){return this.opt.score&&this.opt.score>=t?"starOn":"starOff"}_resetTitle(){for(let t=0;t{let s={true:!0,false:!1}[i[e]];return s=null!==s&&void 0!==s?s:i[e],!isNaN(s)&&Number.isInteger(parseFloat(s))&&(s=Number(s)),t[e]=s,t},{})}_roundHalfScore(t){var e=parseInt(t,10);let s=this._getDecimal(t,1);return e+(s=0!==s?5=this.opt.number&&(e=this.opt.number-1,t=10),this._getWidth()),e=this.stars[e],s=e.offsetLeft+s/10*t,t=new Event("mousemove");t.pageX=s,this.isMove=!0,e.dispatchEvent(t),this.isMove=!1}readOnly(t){this._isReadOnly()!==t&&(t?this._lock():(this._binds(),this._unlock()),this.element.dataset.readOnly=t)}score(){return arguments.length?this.setScore(arguments[0]):this.getScore()}setScore(t){this._isReadOnly()||(t=this._adjustedScore(t),this._apply(t),this._target(t))}getScore(){var t=[],e=this.scoreField.value;return t.push(e?+e:void 0),1{i.addEventListener("click",s=>{if(!this._isReadOnly()){let t,e=this.opt.half||this.opt.precision?this.element.dataset.score:i.alt||i.dataset.alt;this.opt.half&&!this.opt.precision&&(e=this._roundHalfScore(e)),!(t=this.opt.click?this.opt.click.call(this,+e,this.element,s):t)&&void 0!==t||this._apply(+e)}})})}_bindClickCancel(){this.cancelButton.addEventListener("click",t=>{this.scoreField.removeAttribute("value"),this.opt.click&&this.opt.click.call(this,null,this.element,t)})}_bindOut(){this.element.addEventListener("mouseleave",t=>{var e=+this.scoreField.value||void 0;this._apply(e),this._target(e,t),this._resetTitle(),this.opt.mouseout&&this.opt.mouseout.call(this,e,this.element,t)})}_bindOutCancel(){this.cancelButton.addEventListener("mouseleave",t=>{let e=this.opt.cancelOff;var s;"img"!==this.opt.starType&&(e=this.opt.cancelClass+" "+e),this._setIcon(this.cancelButton,e),this.opt.mouseout&&(s=+this.scoreField.value||void 0,this.opt.mouseout.call(this,s,this.element,t))})}_bindOver(){const t=this.opt.half?"mousemove":"mouseover";this.stars.forEach(s=>{s.addEventListener(t,t=>{var e=this._getScoreByPosition(t,s);this._fill(e),this.opt.half&&(this._roundStars(e,t),this._setTitle(e,t),this.element.dataset.score=e),this._target(e,t),this.opt.mouseover&&this.opt.mouseover.call(this,e,this.element,t)})})}_bindOverCancel(){this.cancelButton.addEventListener("mouseover",e=>{if(!this._isReadOnly()){const s=this.opt.path+this.opt.starOff;let t=this.opt.cancelOn;"img"===this.opt.starType?this.stars.forEach(t=>{t.src=s}):(t=this.opt.cancelClass+" "+t,this.stars.forEach(t=>{t.className=s})),this._setIcon(this.cancelButton,t),this._target(null,e),this.opt.mouseover&&this.opt.mouseover.call(this,null,this.element,e)}})}_buildScoreField(){var t=document.createElement("input");return t.name=this.opt.scoreName,t.type="hidden",this.element.appendChild(t),t}_createCancel(){var t=document.createElement(this.opt.starType),e=this.opt.path+this.opt.cancelOff;t.setAttribute("class",this.opt.cancelClass),t.setAttribute("title",this.opt.cancelHint),"img"===this.opt.starType?(t.setAttribute("alt","x"),t.setAttribute("src",e)):(t.classList.add(e),t.setAttribute("data-alt","x")),"left"===this.opt.cancelPlace?(this.element.prepend(" "),this.element.prepend(t)):(this.element.append(" "),this.element.appendChild(t)),this.cancelButton=t}_createScore(){this.scoreField=document.querySelector(this.opt.targetScore)||this._buildScoreField()}_createStars(){for(let t=1;t<=this.opt.number;t++){var e=this._attributesForIndex(t),s=document.createElement(this.opt.starType);for(const i in e)s.setAttribute(i,e[i]);this.element.appendChild(s),this.opt.space&&ti?(a=this.opt.iconRange[i],t=this._getRangeIcon(a,r),e<=a.range&&this._setIcon(o,t),e===a.range&&i++):(t=this.opt[r?"starOn":"starOff"],this._setIcon(o,t))}}_getDecimal(t,e){t=t.toString().split(".")[1];let s=0;return t&&(s=parseInt(t.slice(0,e),10),"9999"===t.slice(1,5))&&s++,s}_getRangeIcon(t,e){return e?t.on||this.opt.starOn:t.off||this.opt.starOff}_getScoreByPosition(t,e){let s=parseInt(e.alt||e.getAttribute("data-alt"),10);var i;return this.opt.half&&(i=this._getWidth(),t=parseFloat((t.pageX-e.getBoundingClientRect().x)/i),s=s-1+t),s}_getHint(t,e){if(0!==t&&!t)return this.opt.noRatedMsg;var s=Math.ceil(t),s=this.opt.hints[(s||1)-1],e=!e||this.isMove;let i=this._getDecimal(t,1),a=s;return this.opt.precision?(e&&(i=0===i?9:i-1),a=s[i]):(this.opt.halfShow||this.opt.half)&&(i=e&&0===i||5{t.title=e}),this.cancelButton&&(this.cancelButton.style.display="none"),this.element.dataset.readOnly=!0}_nameForIndex(t){return this.opt.score&&this.opt.score>=t?"starOn":"starOff"}_resetTitle(){for(let t=0;t{let s={true:!0,false:!1}[i[e]];return s=null!==s&&void 0!==s?s:i[e],!isNaN(s)&&Number.isInteger(parseFloat(s))&&(s=Number(s)),t[e]=s,t},{})}_roundHalfScore(t){var e=parseInt(t,10);let s=this._getDecimal(t,1);return e+(s=0!==s?5=this.opt.number&&(e=this.opt.number-1,t=10),this._getWidth()),e=this.stars[e],s=e.offsetLeft+s/10*t,t=new Event("mousemove");t.pageX=s,this.isMove=!0,e.dispatchEvent(t),this.isMove=!1}readOnly(t){this._isReadOnly()!==t&&(t?this._lock():(this._binds(),this._unlock()),this.element.dataset.readOnly=t)}score(){return arguments.length?this.setScore(arguments[0]):this.getScore()}setScore(t){this._isReadOnly()||(t=this._adjustedScore(t),this._apply(t),this._target(t))}getScore(){var t=[],e=this.scoreField.value;return t.push(e?+e:void 0),1{i.addEventListener("click",s=>{if(!this._isReadOnly()){let t,e=this.opt.half||this.opt.precision?this.element.dataset.score:i.alt||i.dataset.alt;this.opt.half&&!this.opt.precision&&(e=this._roundHalfScore(e)),!(t=this.opt.click?this.opt.click.call(this,+e,this.element,s):t)&&void 0!==t||this._apply(+e)}})})}_bindClickCancel(){this.cancelButton.addEventListener("click",t=>{this.scoreField.removeAttribute("value"),this.opt.click&&this.opt.click.call(this,null,this.element,t)})}_bindOut(){this.element.addEventListener("mouseleave",t=>{var e=+this.scoreField.value||void 0;this._apply(e),this._target(e,t),this._resetTitle(),this.opt.mouseout&&this.opt.mouseout.call(this,e,this.element,t)})}_bindOutCancel(){this.cancelButton.addEventListener("mouseleave",t=>{let e=this.opt.cancelOff;var s;"img"!==this.opt.starType&&(e=this.opt.cancelClass+" "+e),this._setIcon(this.cancelButton,e),this.opt.mouseout&&(s=+this.scoreField.value||void 0,this.opt.mouseout.call(this,s,this.element,t))})}_bindOver(){const t=this.opt.half?"mousemove":"mouseover";this.stars.forEach(s=>{s.addEventListener(t,t=>{var e=this._getScoreByPosition(t,s);this._fill(e),this.opt.half&&(this._roundStars(e,t),this._setTitle(e,t),this.element.dataset.score=e),this._target(e,t),this.opt.mouseover&&this.opt.mouseover.call(this,e,this.element,t)})})}_bindOverCancel(){this.cancelButton.addEventListener("mouseover",e=>{if(!this._isReadOnly()){const s=this.opt.path+this.opt.starOff;let t=this.opt.cancelOn;"img"===this.opt.starType?this.stars.forEach(t=>{t.src=s}):(t=this.opt.cancelClass+" "+t,this.stars.forEach(t=>{t.className=s})),this._setIcon(this.cancelButton,t),this._target(null,e),this.opt.mouseover&&this.opt.mouseover.call(this,null,this.element,e)}})}_buildScoreField(){var t=document.createElement("input");return t.name=this.opt.scoreName,t.type="hidden",this.element.appendChild(t),t}_createCancel(){var t=document.createElement(this.opt.starType),e=this.opt.path+this.opt.cancelOff;t.setAttribute("class",this.opt.cancelClass),t.setAttribute("title",this.opt.cancelHint),"img"===this.opt.starType?(t.setAttribute("alt","x"),t.setAttribute("src",e)):(t.classList.add(e),t.setAttribute("data-alt","x")),"left"===this.opt.cancelPlace?(this.element.prepend(" "),this.element.prepend(t)):(this.element.append(" "),this.element.appendChild(t)),this.cancelButton=t}_createScore(){this.scoreField=document.querySelector(this.opt.targetScore)||this._buildScoreField()}_createStars(){for(let t=1;t<=this.opt.number;t++){var e=this._attributesForIndex(t),s=document.createElement(this.opt.starType);for(const i in e)s.setAttribute(i,e[i]);this.element.appendChild(s),this.opt.space&&ti?(a=this.opt.iconRange[i],t=this._getRangeIcon(a,r),e<=a.range&&this._setIcon(o,t),e===a.range&&i++):(t=this.opt[r?"starOn":"starOff"],this._setIcon(o,t))}}_getDecimal(t,e){t=t.toString().split(".")[1];let s=0;return t&&(s=parseInt(t.slice(0,e),10),"9999"===t.slice(1,5))&&s++,s}_getRangeIcon(t,e){return e?t.on||this.opt.starOn:t.off||this.opt.starOff}_getScoreByPosition(t,e){let s=parseInt(e.alt||e.getAttribute("data-alt"),10);var i;return this.opt.half&&(i=this._getWidth(),t=parseFloat((t.pageX-e.getBoundingClientRect().x)/i),s=s-1+t),s}_getHint(t,e){if(0!==t&&!t)return this.opt.noRatedMsg;var s=Math.ceil(t),s=this.opt.hints[(s||1)-1],e=!e||this.isMove;let i=this._getDecimal(t,1),a=s;return this.opt.precision?(e&&(i=0===i?9:i-1),a=s[i]):(this.opt.halfShow||this.opt.half)&&(i=e&&0===i||5{t.title=e}),this.cancelButton&&(this.cancelButton.style.display="none"),this.element.dataset.readOnly=!0}_nameForIndex(t){return this.opt.score&&this.opt.score>=t?"starOn":"starOff"}_resetTitle(){for(let t=0;t{let s={true:!0,false:!1}[i[e]];return s=null!==s&&void 0!==s?s:i[e],!isNaN(s)&&Number.isInteger(parseFloat(s))&&(s=Number(s)),t[e]=s,t},{})}_roundHalfScore(t){var e=parseInt(t,10);let s=this._getDecimal(t,1);return e+(s=0!==s?5 { 8 | source 9 | .pipe(babel({ plugins: ['@babel/plugin-transform-modules-amd'] })) 10 | .pipe(uglifyJS()) 11 | .pipe(rename('raty.amd.min.js')) 12 | .pipe(gulp.dest('./build/', { overwrite: true })); 13 | }); 14 | 15 | gulp.task('umd', async () => { 16 | source 17 | .pipe(babel({ plugins: ['@babel/plugin-transform-modules-umd'] })) 18 | .pipe(uglifyJS()) 19 | .pipe(rename('raty.umd.min.js')) 20 | .pipe(gulp.dest('./build/', { overwrite: true })); 21 | }); 22 | 23 | gulp.task('commonjs', async () => { 24 | source 25 | .pipe(babel({ plugins: ['@babel/plugin-transform-modules-commonjs'] })) 26 | .pipe(uglifyJS()) 27 | .pipe(rename('raty.commonjs.min.js')) 28 | .pipe(gulp.dest('./build/', { overwrite: true })); 29 | }); 30 | 31 | gulp.task('systemjs', async () => { 32 | source 33 | .pipe(babel({ plugins: ['@babel/plugin-transform-modules-systemjs'] })) 34 | .pipe(uglifyJS()) 35 | .pipe(rename('raty.systemjs.min.js')) 36 | .pipe(gulp.dest('./build/', { overwrite: true })); 37 | }); 38 | 39 | gulp.task('es6', async () => { 40 | source 41 | .pipe(babel()) 42 | .pipe(uglifyJS()) 43 | .pipe(rename('raty.module.min.js')) 44 | .pipe(gulp.dest('./build/', { overwrite: true })); 45 | }); 46 | 47 | gulp.task('es5', async () => { 48 | source 49 | .pipe(babel({ plugins: ['babel-plugin-remove-import-export'] })) 50 | .pipe(uglifyJS()) 51 | .pipe(rename('raty.min.js')) 52 | .pipe(gulp.dest('./build/', { overwrite: true })); 53 | }); 54 | 55 | gulp.task('es5-test', async () => { 56 | source 57 | .pipe(babel({ plugins: ['babel-plugin-remove-import-export'] })) 58 | .pipe(rename('raty.js')) 59 | .pipe(gulp.dest('./build/', { overwrite: true })); 60 | }); 61 | 62 | const tasks = gulp.parallel(['amd', 'umd', 'commonjs', 'systemjs', 'es6', 'es5', 'es5-test']); 63 | 64 | gulp.task('build', tasks); 65 | 66 | gulp.task('watch', async () => { 67 | gulp.watch(['src/*.js', '!build/*.js'], { awaitWriteFinish: true, ignoreInitial: false }, tasks); 68 | }); 69 | -------------------------------------------------------------------------------- /jest.config.js: -------------------------------------------------------------------------------- 1 | /* 2 | * For a detailed explanation regarding each configuration property, visit: 3 | * https://jestjs.io/docs/configuration 4 | */ 5 | 6 | /** @type {import('jest').Config} */ 7 | module.exports = { 8 | // All imported modules in your tests should be mocked automatically 9 | // automock: false, 10 | 11 | // Stop running tests after `n` failures 12 | // bail: 0, 13 | 14 | // The directory where Jest should store its cached dependency information 15 | // cacheDirectory: "/private/var/folders/rb/lw6k043j1758g_0hvsd2vql40000gn/T/jest_dx", 16 | 17 | // Automatically clear mock calls, instances, contexts and results before every test 18 | clearMocks: true, 19 | 20 | // Indicates whether the coverage information should be collected while executing the test 21 | // collectCoverage: false, 22 | 23 | // An array of glob patterns indicating a set of files for which coverage information should be collected 24 | // collectCoverageFrom: undefined, 25 | 26 | // The directory where Jest should output its coverage files 27 | // coverageDirectory: undefined, 28 | 29 | // An array of regexp pattern strings used to skip coverage collection 30 | // coveragePathIgnorePatterns: [ 31 | // "/node_modules/" 32 | // ], 33 | 34 | // Indicates which provider should be used to instrument code for coverage 35 | // coverageProvider: "babel", 36 | 37 | // A list of reporter names that Jest uses when writing coverage reports 38 | // coverageReporters: [ 39 | // "json", 40 | // "text", 41 | // "lcov", 42 | // "clover" 43 | // ], 44 | 45 | // An object that configures minimum threshold enforcement for coverage results 46 | // coverageThreshold: undefined, 47 | 48 | // A path to a custom dependency extractor 49 | // dependencyExtractor: undefined, 50 | 51 | // Make calling deprecated APIs throw helpful error messages 52 | // errorOnDeprecated: false, 53 | 54 | // The default configuration for fake timers 55 | // fakeTimers: { 56 | // "enableGlobally": false 57 | // }, 58 | 59 | // Force coverage collection from ignored files using an array of glob patterns 60 | // forceCoverageMatch: [], 61 | 62 | // A path to a module which exports an async function that is triggered once before all test suites 63 | // globalSetup: undefined, 64 | 65 | // A path to a module which exports an async function that is triggered once after all test suites 66 | // globalTeardown: undefined, 67 | 68 | // A set of global variables that need to be available in all test environments 69 | // globals: {}, 70 | 71 | // The maximum amount of workers used to run your tests. Can be specified as % or a number. E.g. maxWorkers: 10% will use 10% of your CPU amount + 1 as the maximum worker number. maxWorkers: 2 will use a maximum of 2 workers. 72 | // maxWorkers: "50%", 73 | 74 | // An array of directory names to be searched recursively up from the requiring module's location 75 | // moduleDirectories: [ 76 | // "node_modules" 77 | // ], 78 | 79 | // An array of file extensions your modules use 80 | // moduleFileExtensions: [ 81 | // "js", 82 | // "mjs", 83 | // "cjs", 84 | // "jsx", 85 | // "ts", 86 | // "tsx", 87 | // "json", 88 | // "node" 89 | // ], 90 | 91 | // A map from regular expressions to module names or to arrays of module names that allow to stub out resources with a single module 92 | // moduleNameMapper: {}, 93 | 94 | // An array of regexp pattern strings, matched against all module paths before considered 'visible' to the module loader 95 | // modulePathIgnorePatterns: [], 96 | 97 | // Activates notifications for test results 98 | // notify: false, 99 | 100 | // An enum that specifies notification mode. Requires { notify: true } 101 | // notifyMode: "failure-change", 102 | 103 | // A preset that is used as a base for Jest's configuration 104 | // preset: undefined, 105 | 106 | // Run tests from one or more projects 107 | // projects: undefined, 108 | 109 | // Use this configuration option to add custom reporters to Jest 110 | // reporters: undefined, 111 | 112 | // Automatically reset mock state before every test 113 | // resetMocks: false, 114 | 115 | // Reset the module registry before running each individual test 116 | // resetModules: false, 117 | 118 | // A path to a custom resolver 119 | // resolver: undefined, 120 | 121 | // Automatically restore mock state and implementation before every test 122 | // restoreMocks: false, 123 | 124 | // The root directory that Jest should scan for tests and modules within 125 | rootDir: '.', 126 | 127 | // A list of paths to directories that Jest should use to search for files in 128 | // roots: [ 129 | // "" 130 | // ], 131 | 132 | // Allows you to use a custom runner instead of Jest's default test runner 133 | // runner: "jest-runner", 134 | 135 | // The paths to modules that run some code to configure or set up the testing environment before each test 136 | // setupFiles: ['./__tests__/helper.js'], 137 | 138 | // A list of paths to modules that run some code to configure or set up the testing framework before each test 139 | setupFilesAfterEnv: ['./test-helper/index.js'], 140 | 141 | // The number of seconds after which a test is considered as slow and reported as such in the results. 142 | // slowTestThreshold: 5, 143 | 144 | // A list of paths to snapshot serializer modules Jest should use for snapshot testing 145 | // snapshotSerializers: [], 146 | 147 | // The test environment that will be used for testing 148 | testEnvironment: 'jsdom', 149 | 150 | // Options that will be passed to the testEnvironment 151 | // testEnvironmentOptions: {}, 152 | 153 | // Adds a location field to test results 154 | // testLocationInResults: false, 155 | 156 | // The glob patterns Jest uses to detect test files 157 | // testMatch: [ 158 | // './__tests__/**/*[sS]pec.js' 159 | // ], 160 | 161 | // An array of regexp pattern strings that are matched against all test paths, matched tests are skipped 162 | testPathIgnorePatterns: ['/node_modules/'], 163 | 164 | // The regexp pattern or array of patterns that Jest uses to detect test files 165 | // testRegex: [], 166 | 167 | // This option allows the use of a custom results processor 168 | // testResultsProcessor: undefined, 169 | 170 | // This option allows use of a custom test runner 171 | // testRunner: "jest-circus/runner", 172 | 173 | // A map from regular expressions to paths to transformers 174 | // transform: undefined, 175 | 176 | // An array of regexp pattern strings that are matched against all source file paths, matched files will skip transformation 177 | // transformIgnorePatterns: [ 178 | // "/node_modules/" 179 | // ], 180 | 181 | // An array of regexp pattern strings that are matched against all modules before the module loader will automatically return a mock for them 182 | // unmockedModulePathPatterns: undefined, 183 | 184 | // Indicates whether each individual test should be reported during the run 185 | // verbose: undefined, 186 | 187 | // An array of regexp patterns that are matched against all source file paths before re-running tests in watch mode 188 | // watchPathIgnorePatterns: ['__tests__/features/*.js'], 189 | 190 | // Whether to use watchman for file crawling 191 | // watchman: true, 192 | }; 193 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "author": "Washington Botelho", 3 | "bugs": { 4 | "url": "https://github.com/wbotelhos/raty/issues" 5 | }, 6 | "contributors": [ 7 | "Washington Botelho (https://www.wbotelhos.com)" 8 | ], 9 | "description": "Raty - A Star Rating Plugin", 10 | "devDependencies": { 11 | "@babel/core": "^7.24.4", 12 | "@babel/plugin-transform-modules-amd": "^7.24.1", 13 | "@babel/plugin-transform-modules-commonjs": "^7.24.1", 14 | "@babel/plugin-transform-modules-systemjs": "^7.24.1", 15 | "@babel/plugin-transform-modules-umd": "^7.24.1", 16 | "@babel/preset-env": "^7.24.4", 17 | "@babel/register": "^7.23.7", 18 | "@testing-library/jest-dom": "^6.4.2", 19 | "@types/jest": "^29.5.12", 20 | "babel-jest": "^29.7.0", 21 | "babel-plugin-remove-import-export": "^1.1.1", 22 | "babel-preset-minify": "^0.5.2", 23 | "eslint": "^9.1.1", 24 | "gulp": "^5.0.0", 25 | "gulp-babel": "^8.0.0", 26 | "gulp-rename": "^2.0.0", 27 | "gulp-uglify": "^3.0.2", 28 | "jest": "^29.7.0", 29 | "jest-environment-jsdom": "^29.7.0", 30 | "jest-extended": "^4.0.2" 31 | }, 32 | "directories": { 33 | "lib": "src", 34 | "test": "__tests__" 35 | }, 36 | "homepage": "https://github.com/wbotelhos/raty", 37 | "keywords": [ 38 | "classificacao", 39 | "classificar", 40 | "javascript", 41 | "library", 42 | "plugin", 43 | "rating", 44 | "raty", 45 | "star", 46 | "staring", 47 | "votar", 48 | "voto" 49 | ], 50 | "license": "MIT", 51 | "main": "src/raty.js", 52 | "types": "src/raty.d.ts", 53 | "maintainers": [ 54 | "Washington Botelho (https://www.wbotelhos.com)" 55 | ], 56 | "name": "raty-js", 57 | "repository": { 58 | "type": "git", 59 | "url": "https://github.com/wbotelhos/raty" 60 | }, 61 | "scripts": { 62 | "build": "gulp build", 63 | "test": "jest", 64 | "watch": "gulp watch" 65 | }, 66 | "version": "4.3.0" 67 | } 68 | -------------------------------------------------------------------------------- /src/fonts/raty.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wbotelhos/raty/d55ead044ab1466acd5ed02cb6b58a1e756ca175/src/fonts/raty.eot -------------------------------------------------------------------------------- /src/fonts/raty.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Generated by IcoMoon 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /src/fonts/raty.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wbotelhos/raty/d55ead044ab1466acd5ed02cb6b58a1e756ca175/src/fonts/raty.ttf -------------------------------------------------------------------------------- /src/fonts/raty.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wbotelhos/raty/d55ead044ab1466acd5ed02cb6b58a1e756ca175/src/fonts/raty.woff -------------------------------------------------------------------------------- /src/images/cancel-off.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wbotelhos/raty/d55ead044ab1466acd5ed02cb6b58a1e756ca175/src/images/cancel-off.png -------------------------------------------------------------------------------- /src/images/cancel-on.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wbotelhos/raty/d55ead044ab1466acd5ed02cb6b58a1e756ca175/src/images/cancel-on.png -------------------------------------------------------------------------------- /src/images/star-half.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wbotelhos/raty/d55ead044ab1466acd5ed02cb6b58a1e756ca175/src/images/star-half.png -------------------------------------------------------------------------------- /src/images/star-off.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wbotelhos/raty/d55ead044ab1466acd5ed02cb6b58a1e756ca175/src/images/star-off.png -------------------------------------------------------------------------------- /src/images/star-on.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wbotelhos/raty/d55ead044ab1466acd5ed02cb6b58a1e756ca175/src/images/star-on.png -------------------------------------------------------------------------------- /src/raty.css: -------------------------------------------------------------------------------- 1 | .cancel-on-png, .cancel-off-png, .star-on-png, .star-off-png, .star-half-png { 2 | font-size: 2em; 3 | } 4 | 5 | @font-face { 6 | font-family: "raty"; 7 | font-style: normal; 8 | font-weight: normal; 9 | src: url("./fonts/raty.eot"); 10 | src: url("./fonts/raty.eot?#iefix") format("embedded-opentype"); 11 | src: url("./fonts/raty.svg#raty") format("svg"); 12 | src: url("./fonts/raty.ttf") format("truetype"); 13 | src: url("./fonts/raty.woff") format("woff"); 14 | } 15 | 16 | .cancel-on-png, .cancel-off-png, .star-on-png, .star-off-png, .star-half-png { 17 | -moz-osx-font-smoothing: grayscale; 18 | -webkit-font-smoothing: antialiased; 19 | font-family: "raty"; 20 | font-style: normal; 21 | font-variant: normal; 22 | font-weight: normal; 23 | line-height: 1; 24 | speak: none; 25 | text-transform: none; 26 | } 27 | 28 | .cancel-on-png:before { 29 | content: "\e600"; 30 | } 31 | 32 | .cancel-off-png:before { 33 | content: "\e601"; 34 | } 35 | 36 | .star-on-png:before { 37 | content: "\f005"; 38 | } 39 | 40 | .star-off-png:before { 41 | content: "\f006"; 42 | } 43 | 44 | .star-half-png:before { 45 | content: "\f123"; 46 | } 47 | -------------------------------------------------------------------------------- /src/raty.d.ts: -------------------------------------------------------------------------------- 1 | export interface RatyOptions { 2 | cancelButton: boolean; 3 | cancelClass: string; 4 | cancelHint: string; 5 | cancelOff: string; 6 | cancelOn: string; 7 | cancelPlace: string; 8 | click: (score: number, element: HTMLElement, evt: MouseEvent) => void; 9 | half: boolean; 10 | halfShow: boolean; 11 | hints: string[]; 12 | iconRange: { range: number; on: string; off: string }[]; 13 | iconRangeSame: boolean; 14 | mouseout: (score: number, element: HTMLElement, evt: MouseEvent) => void; 15 | mouseover: (score: number, element: HTMLElement, evt: MouseEvent) => void; 16 | noRatedMsg: string; 17 | number: () => number | number; 18 | numberMax: number; 19 | path: () => string | string; 20 | precision: boolean; 21 | readOnly: () => boolean | boolean; 22 | round: { down: number; full: number; up: number }; 23 | score: () => number | number; 24 | scoreName: string; 25 | single: boolean; 26 | space: boolean; 27 | starHalf: string; 28 | starOff: string; 29 | starOn: string; 30 | starType: string; 31 | target: string; 32 | targetFormat: string; 33 | targetKeep: boolean; 34 | targetScore: string; 35 | targetText: string; 36 | targetType: string; 37 | } 38 | 39 | export declare class Raty { 40 | constructor(element: HTMLElement, options?: Partial); 41 | 42 | defaultOptions(): Partial; 43 | 44 | cancel(click: boolean); 45 | 46 | click(score: number): void; 47 | 48 | move(score: number): void; 49 | 50 | readOnly(readOnly: boolean): void; 51 | 52 | score(): number; 53 | score(score: number): void 54 | 55 | setScore(score: number): void; 56 | getScore(): number; 57 | 58 | init(): Raty 59 | } 60 | -------------------------------------------------------------------------------- /test-helper/index.js: -------------------------------------------------------------------------------- 1 | require('@testing-library/jest-dom'); 2 | 3 | global.Raty = require('../src/raty').default; 4 | 5 | global.context = function context(description, spec) { 6 | // eslint-disable-line no-redeclare, no-unused-vars 7 | describe(description, spec); 8 | }; 9 | 10 | global.xcontext = function xcontext(description, spec) { 11 | // eslint-disable-line no-redeclare, no-unused-vars 12 | xdescribe(description, spec); 13 | }; 14 | 15 | afterEach(() => { 16 | document.body.innerHTML = ''; 17 | }); 18 | 19 | function camelize(str) { 20 | return str.toLowerCase().replace(/[^a-zA-Z0-9]+(.)/g, (m, chr) => chr.toUpperCase()); 21 | } 22 | 23 | function setAttributes(el, attrs) { 24 | for (var key in attrs) { 25 | if (key.startsWith('data-')) { 26 | el.dataset[camelize(key.replace('data-', ''))] = attrs[key]; 27 | } else el.setAttribute(key, attrs[key]); 28 | } 29 | } 30 | 31 | global.Helper = { 32 | clear: function () { 33 | if (this.ids) { 34 | for (var i = 0; i < this.ids.length; i++) { 35 | document.querySelector(this.ids[i]).remove(); 36 | } 37 | } 38 | }, 39 | 40 | // Creates an element for the test document to be used on the tests. 41 | create: function (id, type, options) { 42 | type = type || 'div'; 43 | 44 | var data = this._data(id); 45 | var attrs = this._attrs(data, options); 46 | 47 | return this._append(type, attrs); 48 | }, 49 | 50 | click: function (el, integer, decimal) { 51 | this.mouseTrigger('mousemove', el, integer, decimal); 52 | this.mouseTrigger('click', el, integer, decimal); 53 | }, 54 | 55 | extension: function (elements) { 56 | var items; 57 | 58 | if (Object.prototype.toString.call(items) === '[object Array]') { 59 | items = elements; 60 | } else { 61 | items = [elements]; 62 | } 63 | 64 | var extensions = []; 65 | 66 | items.forEach((item) => { 67 | var paths = item.split('/'); 68 | 69 | extensions.push(paths[paths.length - 1]); 70 | }); 71 | 72 | return extensions.length === 1 ? extensions[0] : extensions; 73 | }, 74 | 75 | last: function (items) { 76 | var size = items.length; 77 | 78 | return items[size - 1]; 79 | }, 80 | 81 | mouseData: function (el, integer, decimal) { 82 | var stars = el.querySelectorAll('img:not(.raty-cancel)'); 83 | var star = stars[integer]; 84 | var width = star.offsetWidth || parseFloat(getComputedStyle(star).fontSize); 85 | var fraction = width / 10; 86 | var left = start.getBoundingClientRect().left + window.scrollX; 87 | var pageX = left + fraction * decimal + 0.1; 88 | 89 | // if (console && console.log) { 90 | // console.debug( 91 | // integer + '.' + decimal, 92 | // ':', 93 | // 'left:', 94 | // left, 95 | // 'width:', 96 | // width, 97 | // 'fraction (width/10):', 98 | // fraction, 99 | // 'pageX:', 100 | // pageX, 101 | // 'fractions (decimal * fraction)', 102 | // decimal * fraction 103 | // ); 104 | // } 105 | 106 | return { el: star, pageX: pageX }; 107 | }, 108 | 109 | mouseTrigger: function (action, el, integer, decimal) { 110 | var data = this.mouseData(el, integer, decimal); 111 | const evt = new Event(action, { pageX: data.pageX }); 112 | 113 | data.el.trigger(evt); 114 | }, 115 | 116 | mousemove: function (el, integer, decimal) { 117 | this.mouseTrigger('mousemove', el, integer, decimal); 118 | }, 119 | 120 | target: function (id, type, options) { 121 | type = type || 'div'; 122 | 123 | var data = this._data(id); 124 | var attrs = this._attrs(data, options); 125 | 126 | const element = this._append(type, attrs); 127 | 128 | if (type === 'select') { 129 | element.insertAdjacentHTML('beforeend', this._select()); 130 | } 131 | 132 | return element; 133 | }, 134 | 135 | trigger: function (el, eventName) { 136 | el.dispatchEvent(new Event(eventName)); 137 | }, 138 | 139 | // private 140 | 141 | // eslint-disable-line no-redeclare, no-unused-vars 142 | // Appends the element into the test document body using the mounted attrs. 143 | _append: function (type, attrs) { 144 | const element = document.createElement(type); 145 | setAttributes(element, attrs); 146 | 147 | document.querySelector(`body`).appendChild(element); 148 | 149 | return element; 150 | }, 151 | 152 | // Build ID and class attribute for the created element like `
`. 153 | _attrs: function (data, options) { 154 | var attrs = options || {}; 155 | 156 | if (data.prefix === '#') { 157 | attrs.id = data.id; 158 | } else { 159 | attrs['class'] = data.id; 160 | } 161 | 162 | return attrs; 163 | }, 164 | 165 | // Collects the identificator of the element and the prefix that indicates an ID or class. 166 | _data: function (id) { 167 | var data = { prefix: id.charAt(0), id: id.slice(1) }; 168 | 169 | this.ids = this.ids || []; 170 | 171 | this.ids.push(id); 172 | 173 | return data; 174 | }, 175 | 176 | _select: function () { 177 | return ( 178 | '' + 179 | '' + 180 | '' + 181 | '' + 182 | '' + 183 | '' + 184 | '' + 185 | '' + 186 | '' 187 | ); 188 | }, 189 | }; 190 | --------------------------------------------------------------------------------