├── .browserslistrc
├── .eslintrc.js
├── .gitignore
├── .npmignore
├── .prettierrc
├── CHANGELOG.md
├── LICENSE
├── README.md
├── babel.config.js
├── package.json
├── postcss.config.js
├── public
└── index.html
├── resources
├── data.json
├── header.png
└── histogram-slider-demo.gif
├── src
├── App.vue
├── lib
│ ├── HistogramSlider.vue
│ ├── props.js
│ └── range-slider.js
└── main.js
├── vue.config.js
└── yarn.lock
/.browserslistrc:
--------------------------------------------------------------------------------
1 | > 1%
2 | last 2 versions
3 |
--------------------------------------------------------------------------------
/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | root: true,
3 | env: {
4 | node: true
5 | },
6 | extends: ['plugin:vue/essential', '@vue/prettier'],
7 | rules: {
8 | 'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'off',
9 | 'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off'
10 | },
11 | parserOptions: {
12 | parser: 'babel-eslint'
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules
3 | /dist
4 |
5 | # local env files
6 | .env.local
7 | .env.*.local
8 |
9 | # Log files
10 | npm-debug.log*
11 | yarn-debug.log*
12 | yarn-error.log*
13 |
14 | # Editor directories and files
15 | .idea
16 | .vscode
17 | *.suo
18 | *.ntvs*
19 | *.njsproj
20 | *.sln
21 | *.sw?
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | resources
2 | public
3 |
--------------------------------------------------------------------------------
/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "printWidth": 100,
3 | "tabWidth": 2,
4 | "useTabs": false,
5 | "semi": false,
6 | "singleQuote": true,
7 | "trailingComma": "none",
8 | "bracketSpacing": true,
9 | "jsxBracketSameLine": false,
10 | "fluid": false
11 | }
12 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # ChangeLog
2 |
3 | ## v0.3.5
4 |
5 | ### New Features
6 | - Added handle size prop
7 |
8 | ## v0.3.3
9 |
10 | ### Bug Fix
11 | - Fixed hist color issue
12 |
13 | ## v0.3.2
14 |
15 | ### Bug Fix
16 | - Performance improvements
17 |
18 | ## v0.3.1
19 |
20 | ### Bug Fix
21 | - Histogram clip issue fixed
22 |
23 | ## v0.3.0
24 |
25 | ### New Features
26 | - Add histogram clip
27 |
28 | ## v0.2.1
29 |
30 | ### Bug Fix
31 | - First and lash histogram bar color not change problem fixed
32 |
33 | ## v0.2.0
34 |
35 | ### New Features
36 | - `min`, `max` props are not required
37 | - `type` 'single' option is completed
38 |
39 | ## v0.1.0
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2020 Oguzhan Inan
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Range slider with histogram for Vue
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 | ## 🚀 Quick Start
16 | If you are a try and learn developer, you can start trying the vue-histogram-slider now using codesandbox.io.
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 | ## 📦 Installation
28 | ### yarn
29 | `yarn add vue-histogram-slider`
30 |
31 | ### npm
32 | `npm i vue-histogram-slider`
33 |
34 | ## 🔧 Usage
35 | ```js
36 | import Vue from 'vue';
37 | import HistogramSlider from 'vue-histogram-slider';
38 | import 'vue-histogram-slider/dist/histogram-slider.css';
39 |
40 | Vue.component(HistogramSlider.name, HistogramSlider);
41 | ```
42 |
43 | ```xml
44 |
49 | ```
50 |
51 | ## 📋 Props
52 |
53 | Property |Type|Default|Description
54 | ---|:---:|:---:|---
55 | min|number|1|Set slider minimum value
56 | max|number|100|Set slider maximum value
57 | data|array| - |Data for histogram
58 | block|boolean|false|Locks slider and makes it inactive
59 | grid|boolean|true|Enables grid of values.
60 | gridNum|number|4|Number of grid units.
61 | step|number|1|Set sliders step. Always > 0. Could be fractional.
62 | hideMinMax|boolean|true|Hides min and max labels
63 | hideFromTo|boolean|false|Hides from and to labels
64 | toFixed|boolean|false|Fix position of right handle.
65 | fromFixed|boolean|false|Fix position of left (or single) handle.
66 | forceEdges|boolean|false|Slider will be always inside it's container.
67 | dragInterval|boolean|false|Allow user to drag whole range. Only in double type
68 | keyboard|boolean|true|Activates keyboard controls. Move left: ←, ↓, A, S. Move right: →, ↑, W, D.
69 | type|string|double|Choose slider type, could be single - for one handle, or double for two handles
70 | width|number|600|width of dialog
71 | barHeight|number|100|Set max histogram bar height
72 | barWidth|number|6|Set histogram bar width
73 | barGap|number|5|Set histogram bar gap
74 | barRadius|number|4|Set histogram bar radius
75 | prettify|function|null|Set up your own prettify function. Can be anything. For example, you can set up unix time as slider values and than transform them to cool looking dates.
76 | lineHeight|number|6|Set slider line height
77 | transitionDuration|number|100|Set duration to histogram bars
78 | primaryColor|string|#0091ff|Primary color
79 | labelColor|string|#0091ff|Label color
80 | holderColor|string|#dee4ec|Holder color
81 | handleColor|string|#ffffff|Slider handle color
82 | gridTextColor|string|silver|Primary color
83 | fontFamily|string|'Arial, sans-serif'|Set text font family
84 | fontSize|number|12|Set text font size
85 | handleSize|number|26|Slider handle size
86 | histSliderGap|number|6|Set gap between slider and histogram
87 | updateColorOnChange|boolean|true|Update histogram bar color on change **(recommended false for performance)**
88 |
89 | ## 🔧 Event
90 | Name|Description
91 | ---|---
92 | start |Triggers when slider start.
93 | change|Triggers when each values change.
94 | update|Triggers when slider is modified by external methods update or reset.
95 | finish|Triggers when user releases handle.
96 |
97 |
--------------------------------------------------------------------------------
/babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | presets: ['@vue/app']
3 | }
4 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "vue-histogram-slider",
3 | "description": "Range slider with histogram for vue.js",
4 | "version": "0.3.8",
5 | "main": "dist/histogram-slider.umd.min.js",
6 | "license": "MIT",
7 | "repository": {
8 | "type": "git",
9 | "url": "https://github.com/oguzhaninan/vue-histogram-slider.git"
10 | },
11 | "keywords": [
12 | "vue",
13 | "vuejs",
14 | "slider",
15 | "range-slider",
16 | "histogram",
17 | "histogram-slider"
18 | ],
19 | "scripts": {
20 | "serve": "vue-cli-service serve",
21 | "prepare": "yarn build",
22 | "build": "vue-cli-service build --name histogram-slider --entry ./src/lib/HistogramSlider.vue --target lib",
23 | "prepublishOnly": "yarn lint && yarn build",
24 | "lint": "vue-cli-service lint"
25 | },
26 | "dependencies": {
27 | "d3-array": "^2.3.2",
28 | "d3-brush": "^1.1.3",
29 | "d3-scale": "^3.1.0",
30 | "d3-selection": "^1.4.0",
31 | "d3-transition": "^1.2.0",
32 | "jquery": "3.5",
33 | "vue": "^2.6.10"
34 | },
35 | "devDependencies": {
36 | "@vue/cli-plugin-babel": "^3.11.0",
37 | "@vue/cli-plugin-eslint": "^3.11.0",
38 | "@vue/cli-service": "^3.11.0",
39 | "@vue/eslint-config-prettier": "^5.0.0",
40 | "babel-eslint": "^10.0.1",
41 | "eslint": "^5.16.0",
42 | "eslint-plugin-prettier": "^3.1.0",
43 | "eslint-plugin-vue": "^5.0.0",
44 | "lint-staged": "^8.1.5",
45 | "prettier": "^1.18.2",
46 | "vue-template-compiler": "^2.6.10"
47 | },
48 | "gitHooks": {
49 | "pre-commit": "lint-staged"
50 | },
51 | "lint-staged": {
52 | "*.{js,vue}": [
53 | "vue-cli-service lint",
54 | "git add"
55 | ]
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/postcss.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | plugins: {
3 | autoprefixer: {}
4 | }
5 | }
6 |
--------------------------------------------------------------------------------
/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | vue-histogram-slider
8 |
9 |
10 |
11 | We're sorry but vue-histogram-slider doesn't work properly without JavaScript enabled. Please enable it to continue.
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/resources/data.json:
--------------------------------------------------------------------------------
1 | ["2004-11-23T22:00:00.000Z", "2005-02-28T22:00:00.000Z", "2005-03-09T22:00:00.000Z", "2005-03-21T22:00:00.000Z", "2005-05-06T21:00:00.000Z", "2005-06-01T21:00:00.000Z", "2005-06-13T21:00:00.000Z", "2005-06-30T21:00:00.000Z", "2005-07-03T21:00:00.000Z", "2005-07-14T21:00:00.000Z", "2005-07-30T21:00:00.000Z", "2005-08-30T21:00:00.000Z", "2005-08-31T21:00:00.000Z", "2005-09-30T21:00:00.000Z", "2005-11-13T22:00:00.000Z", "2005-11-30T22:00:00.000Z", "2005-12-08T22:00:00.000Z", "2005-12-14T22:00:00.000Z", "2005-12-18T22:00:00.000Z", "2005-12-28T22:00:00.000Z", "2006-02-06T22:00:00.000Z", "2006-02-13T22:00:00.000Z", "2006-02-14T22:00:00.000Z", "2006-02-14T22:00:00.000Z", "2006-03-14T22:00:00.000Z", "2006-03-16T22:00:00.000Z", "2006-03-31T21:00:00.000Z", "2006-04-04T21:00:00.000Z", "2006-04-05T21:00:00.000Z", "2006-04-11T21:00:00.000Z", "2006-04-23T21:00:00.000Z", "2006-04-30T21:00:00.000Z", "2006-05-09T21:00:00.000Z", "2006-05-11T21:00:00.000Z", "2006-05-11T21:00:00.000Z", "2006-05-25T21:00:00.000Z", "2006-05-29T21:00:00.000Z", "2006-06-01T21:00:00.000Z", "2006-06-06T21:00:00.000Z", "2006-06-07T21:00:00.000Z", "2006-06-08T21:00:00.000Z", "2006-06-13T21:00:00.000Z", "2006-06-15T21:00:00.000Z", "2006-06-20T21:00:00.000Z", "2006-06-25T21:00:00.000Z", "2006-06-27T21:00:00.000Z", "2006-07-04T21:00:00.000Z", "2006-07-04T21:00:00.000Z", "2006-07-06T21:00:00.000Z", "2006-07-31T21:00:00.000Z", "2006-08-02T21:00:00.000Z", "2006-08-20T21:00:00.000Z", "2006-08-22T21:00:00.000Z", "2006-09-13T21:00:00.000Z", "2006-09-27T21:00:00.000Z", "2006-09-30T21:00:00.000Z", "2006-09-30T21:00:00.000Z", "2006-10-05T21:00:00.000Z", "2006-10-17T21:00:00.000Z", "2006-10-19T21:00:00.000Z", "2006-10-24T21:00:00.000Z", "2006-11-06T22:00:00.000Z", "2006-11-09T22:00:00.000Z", "2006-11-10T22:00:00.000Z", "2006-11-19T22:00:00.000Z", "2006-11-21T22:00:00.000Z", "2006-11-30T22:00:00.000Z", "2006-12-11T22:00:00.000Z", "2006-12-17T22:00:00.000Z", "2006-12-18T22:00:00.000Z", "2006-12-18T22:00:00.000Z", "2006-12-19T22:00:00.000Z", "2006-12-20T22:00:00.000Z", "2006-12-23T22:00:00.000Z", "2006-12-25T22:00:00.000Z", "2006-12-26T22:00:00.000Z", "2006-12-27T22:00:00.000Z", "2006-12-28T22:00:00.000Z", "2007-01-22T22:00:00.000Z", "2007-01-29T22:00:00.000Z", "2007-01-30T22:00:00.000Z", "2007-01-31T22:00:00.000Z", "2007-02-24T22:00:00.000Z", "2007-02-24T22:00:00.000Z", "2007-03-04T22:00:00.000Z", "2007-03-10T22:00:00.000Z", "2007-03-11T22:00:00.000Z", "2007-03-12T22:00:00.000Z", "2007-03-13T22:00:00.000Z", "2007-03-15T22:00:00.000Z", "2007-03-25T21:00:00.000Z", "2007-04-01T21:00:00.000Z", "2007-04-02T21:00:00.000Z", "2007-04-07T21:00:00.000Z", "2007-04-08T21:00:00.000Z", "2007-04-12T21:00:00.000Z", "2007-04-22T21:00:00.000Z", "2007-04-23T21:00:00.000Z", "2007-04-23T21:00:00.000Z", "2007-04-25T21:00:00.000Z", "2007-04-29T21:00:00.000Z", "2007-05-04T21:00:00.000Z", "2007-05-14T21:00:00.000Z", "2007-05-15T21:00:00.000Z", "2007-05-17T21:00:00.000Z", "2007-05-23T21:00:00.000Z", "2007-05-24T21:00:00.000Z", "2007-06-12T21:00:00.000Z", "2007-06-15T21:00:00.000Z", "2007-06-24T21:00:00.000Z", "2007-06-26T21:00:00.000Z", "2007-07-05T21:00:00.000Z", "2007-07-18T21:00:00.000Z", "2007-07-22T21:00:00.000Z", "2007-08-01T21:00:00.000Z", "2007-08-03T21:00:00.000Z", "2007-08-12T21:00:00.000Z", "2007-08-31T21:00:00.000Z", "2007-08-31T21:00:00.000Z", "2007-09-05T21:00:00.000Z", "2007-09-11T21:00:00.000Z", "2007-09-13T21:00:00.000Z", "2007-09-16T21:00:00.000Z", "2007-09-24T21:00:00.000Z", "2007-09-27T21:00:00.000Z", "2007-10-07T21:00:00.000Z", "2007-10-10T21:00:00.000Z", "2007-10-18T21:00:00.000Z", "2007-10-21T21:00:00.000Z", "2007-10-23T21:00:00.000Z", "2007-10-29T22:00:00.000Z", "2007-10-31T22:00:00.000Z", "2007-10-31T22:00:00.000Z", "2007-11-01T22:00:00.000Z", "2007-11-04T22:00:00.000Z", "2007-11-05T22:00:00.000Z", "2007-11-08T22:00:00.000Z", "2007-11-10T22:00:00.000Z", "2007-11-11T22:00:00.000Z", "2007-11-13T22:00:00.000Z", "2007-11-19T22:00:00.000Z", "2007-11-21T22:00:00.000Z", "2007-11-24T22:00:00.000Z", "2007-11-25T22:00:00.000Z", "2007-12-04T22:00:00.000Z", "2007-12-10T22:00:00.000Z", "2007-12-10T22:00:00.000Z", "2007-12-27T22:00:00.000Z", "2007-12-31T22:00:00.000Z", "2008-02-05T22:00:00.000Z", "2008-02-27T22:00:00.000Z", "2008-02-29T22:00:00.000Z", "2008-02-29T22:00:00.000Z", "2008-02-29T22:00:00.000Z", "2008-03-04T22:00:00.000Z", "2008-03-05T22:00:00.000Z", "2008-03-08T22:00:00.000Z", "2008-03-10T22:00:00.000Z", "2008-03-17T22:00:00.000Z", "2008-03-31T21:00:00.000Z", "2008-03-31T21:00:00.000Z", "2008-04-24T21:00:00.000Z", "2008-04-27T21:00:00.000Z", "2008-04-27T21:00:00.000Z", "2008-04-27T21:00:00.000Z", "2008-04-28T21:00:00.000Z", "2008-04-28T21:00:00.000Z", "2008-04-28T21:00:00.000Z", "2008-04-28T21:00:00.000Z", "2008-04-30T21:00:00.000Z", "2008-04-30T21:00:00.000Z", "2008-05-03T21:00:00.000Z", "2008-05-05T21:00:00.000Z", "2008-06-02T21:00:00.000Z", "2008-06-13T21:00:00.000Z", "2008-06-14T21:00:00.000Z", "2008-06-16T21:00:00.000Z", "2008-06-22T21:00:00.000Z", "2008-06-30T21:00:00.000Z", "2008-07-02T21:00:00.000Z", "2008-07-17T21:00:00.000Z", "2008-08-19T21:00:00.000Z", "2008-08-27T21:00:00.000Z", "2008-08-31T21:00:00.000Z", "2008-08-31T21:00:00.000Z", "2008-09-17T21:00:00.000Z", "2008-09-18T21:00:00.000Z", "2008-09-21T21:00:00.000Z", "2008-09-30T21:00:00.000Z", "2008-10-07T21:00:00.000Z", "2008-10-07T21:00:00.000Z", "2008-10-29T22:00:00.000Z", "2008-11-02T22:00:00.000Z", "2008-11-11T22:00:00.000Z", "2008-11-12T22:00:00.000Z", "2008-11-18T22:00:00.000Z", "2008-11-25T22:00:00.000Z", "2008-11-27T22:00:00.000Z", "2008-12-04T22:00:00.000Z", "2008-12-17T22:00:00.000Z", "2008-12-31T22:00:00.000Z", "2008-12-31T22:00:00.000Z", "2009-01-19T22:00:00.000Z", "2009-01-31T22:00:00.000Z", "2009-02-12T22:00:00.000Z", "2009-02-16T22:00:00.000Z", "2009-02-21T22:00:00.000Z", "2009-02-22T22:00:00.000Z", "2009-02-24T22:00:00.000Z", "2009-02-25T22:00:00.000Z", "2009-02-27T22:00:00.000Z", "2009-03-19T22:00:00.000Z", "2009-03-31T21:00:00.000Z", "2009-03-31T21:00:00.000Z", "2009-04-03T21:00:00.000Z", "2009-04-08T21:00:00.000Z", "2009-04-09T21:00:00.000Z", "2009-04-12T21:00:00.000Z", "2009-04-15T21:00:00.000Z", "2009-04-30T21:00:00.000Z", "2009-05-04T21:00:00.000Z", "2009-05-18T21:00:00.000Z", "2009-05-26T21:00:00.000Z", "2009-05-29T21:00:00.000Z", "2009-06-04T21:00:00.000Z", "2009-06-14T21:00:00.000Z", "2009-07-02T21:00:00.000Z", "2009-07-19T21:00:00.000Z", "2009-07-22T21:00:00.000Z", "2009-07-29T21:00:00.000Z", "2009-08-06T21:00:00.000Z", "2009-08-09T21:00:00.000Z", "2009-08-16T21:00:00.000Z", "2009-08-16T21:00:00.000Z", "2009-08-26T21:00:00.000Z", "2009-08-27T21:00:00.000Z", "2009-08-31T21:00:00.000Z", "2009-09-07T21:00:00.000Z", "2009-09-14T21:00:00.000Z", "2009-10-02T21:00:00.000Z", "2009-10-18T21:00:00.000Z", "2009-10-20T21:00:00.000Z", "2009-10-29T22:00:00.000Z", "2009-10-30T22:00:00.000Z", "2009-11-01T22:00:00.000Z", "2009-11-04T22:00:00.000Z", "2009-11-05T22:00:00.000Z", "2009-11-05T22:00:00.000Z", "2009-11-05T22:00:00.000Z", "2009-11-09T22:00:00.000Z", "2009-11-22T22:00:00.000Z", "2009-11-29T22:00:00.000Z", "2009-11-30T22:00:00.000Z", "2009-12-16T22:00:00.000Z", "2010-02-07T22:00:00.000Z", "2010-02-09T22:00:00.000Z", "2010-02-15T22:00:00.000Z", "2010-02-28T22:00:00.000Z", "2010-03-13T22:00:00.000Z", "2010-03-22T22:00:00.000Z", "2010-03-22T22:00:00.000Z", "2010-03-22T22:00:00.000Z", "2010-03-28T21:00:00.000Z", "2010-03-31T21:00:00.000Z", "2010-04-08T21:00:00.000Z", "2010-04-13T21:00:00.000Z", "2010-04-20T21:00:00.000Z", "2010-04-25T21:00:00.000Z", "2010-04-28T21:00:00.000Z", "2010-04-29T21:00:00.000Z", "2010-05-04T21:00:00.000Z", "2010-05-04T21:00:00.000Z", "2010-05-04T21:00:00.000Z", "2010-05-11T21:00:00.000Z", "2010-05-18T21:00:00.000Z", "2010-05-18T21:00:00.000Z", "2010-05-18T21:00:00.000Z", "2010-05-26T21:00:00.000Z", "2010-06-07T21:00:00.000Z", "2010-06-18T21:00:00.000Z", "2010-06-19T21:00:00.000Z", "2010-06-21T21:00:00.000Z", "2010-06-30T21:00:00.000Z", "2010-08-23T21:00:00.000Z", "2010-08-31T21:00:00.000Z", "2010-08-31T21:00:00.000Z", "2010-08-31T21:00:00.000Z", "2010-09-30T21:00:00.000Z", "2010-09-30T21:00:00.000Z", "2010-09-30T21:00:00.000Z", "2010-10-18T21:00:00.000Z", "2010-10-18T21:00:00.000Z", "2010-10-21T21:00:00.000Z", "2010-10-22T21:00:00.000Z", "2010-10-26T21:00:00.000Z", "2010-11-05T22:00:00.000Z", "2010-11-07T22:00:00.000Z", "2010-11-10T22:00:00.000Z", "2010-11-18T22:00:00.000Z", "2010-11-25T22:00:00.000Z", "2010-12-09T22:00:00.000Z", "2010-12-09T22:00:00.000Z", "2010-12-09T22:00:00.000Z", "2010-12-26T22:00:00.000Z", "2010-12-31T22:00:00.000Z", "2011-01-17T22:00:00.000Z", "2011-01-27T22:00:00.000Z", "2011-02-21T22:00:00.000Z", "2011-03-10T22:00:00.000Z", "2011-03-22T22:00:00.000Z", "2011-03-22T22:00:00.000Z", "2011-03-23T22:00:00.000Z", "2011-03-28T21:00:00.000Z", "2011-04-05T21:00:00.000Z", "2011-04-06T21:00:00.000Z", "2011-04-06T21:00:00.000Z", "2011-04-08T21:00:00.000Z", "2011-04-25T21:00:00.000Z", "2011-05-10T21:00:00.000Z", "2011-05-15T21:00:00.000Z", "2011-05-18T21:00:00.000Z", "2011-05-19T21:00:00.000Z", "2011-05-24T21:00:00.000Z", "2011-07-13T21:00:00.000Z", "2011-07-26T21:00:00.000Z", "2011-08-31T21:00:00.000Z", "2011-09-02T21:00:00.000Z", "2011-09-18T21:00:00.000Z", "2011-09-27T21:00:00.000Z", "2011-09-30T21:00:00.000Z", "2011-10-31T22:00:00.000Z", "2011-11-03T22:00:00.000Z", "2011-11-06T22:00:00.000Z", "2011-11-08T22:00:00.000Z", "2011-11-15T22:00:00.000Z", "2011-11-23T22:00:00.000Z", "2011-11-25T22:00:00.000Z", "2011-11-27T22:00:00.000Z", "2011-12-27T22:00:00.000Z", "2012-02-16T22:00:00.000Z", "2012-02-19T22:00:00.000Z", "2012-03-19T22:00:00.000Z", "2012-03-27T21:00:00.000Z", "2012-04-15T21:00:00.000Z", "2012-04-15T21:00:00.000Z", "2012-04-16T21:00:00.000Z", "2012-04-18T21:00:00.000Z", "2012-04-24T21:00:00.000Z", "2012-05-03T21:00:00.000Z", "2012-05-13T21:00:00.000Z", "2012-06-15T21:00:00.000Z", "2012-06-17T21:00:00.000Z", "2012-07-17T21:00:00.000Z", "2012-07-18T21:00:00.000Z", "2012-07-30T21:00:00.000Z", "2012-08-09T21:00:00.000Z", "2012-08-31T21:00:00.000Z", "2012-09-05T21:00:00.000Z", "2012-09-05T21:00:00.000Z", "2012-09-15T21:00:00.000Z", "2012-09-19T21:00:00.000Z", "2012-09-20T21:00:00.000Z", "2012-10-09T21:00:00.000Z", "2012-10-10T21:00:00.000Z", "2012-10-16T21:00:00.000Z", "2012-10-19T21:00:00.000Z", "2012-10-20T21:00:00.000Z", "2012-10-30T22:00:00.000Z", "2012-11-01T22:00:00.000Z", "2012-11-08T22:00:00.000Z", "2012-11-14T22:00:00.000Z", "2012-12-02T22:00:00.000Z", "2013-01-14T22:00:00.000Z", "2013-01-23T22:00:00.000Z", "2013-02-06T22:00:00.000Z", "2013-02-28T22:00:00.000Z", "2013-03-18T22:00:00.000Z", "2013-03-23T22:00:00.000Z", "2013-04-02T21:00:00.000Z", "2013-04-09T21:00:00.000Z", "2013-04-10T21:00:00.000Z", "2013-04-11T21:00:00.000Z", "2013-04-16T21:00:00.000Z", "2013-04-17T21:00:00.000Z", "2013-04-18T21:00:00.000Z", "2013-04-24T21:00:00.000Z", "2013-04-25T21:00:00.000Z", "2013-04-27T21:00:00.000Z", "2013-04-30T21:00:00.000Z", "2013-04-30T21:00:00.000Z", "2013-05-06T21:00:00.000Z", "2013-05-12T21:00:00.000Z", "2013-05-19T21:00:00.000Z", "2013-05-21T21:00:00.000Z", "2013-06-04T21:00:00.000Z", "2013-06-06T21:00:00.000Z", "2013-07-02T21:00:00.000Z", "2013-08-22T21:00:00.000Z", "2013-08-29T21:00:00.000Z", "2013-09-05T21:00:00.000Z", "2013-09-21T21:00:00.000Z", "2013-09-22T21:00:00.000Z", "2013-09-26T21:00:00.000Z", "2013-10-08T21:00:00.000Z", "2013-10-16T21:00:00.000Z", "2013-10-19T21:00:00.000Z", "2013-10-22T21:00:00.000Z", "2013-11-04T22:00:00.000Z", "2013-11-13T22:00:00.000Z", "2013-11-25T22:00:00.000Z", "2013-11-28T22:00:00.000Z", "2013-11-28T22:00:00.000Z", "2013-12-05T22:00:00.000Z", "2014-02-03T22:00:00.000Z", "2014-02-19T22:00:00.000Z", "2014-04-14T21:00:00.000Z", "2014-06-05T21:00:00.000Z", "2014-06-10T21:00:00.000Z", "2014-06-11T21:00:00.000Z", "2014-07-02T21:00:00.000Z", "2014-07-03T21:00:00.000Z", "2014-07-06T21:00:00.000Z", "2014-07-16T21:00:00.000Z", "2014-07-16T21:00:00.000Z", "2014-08-04T21:00:00.000Z", "2014-08-26T21:00:00.000Z", "2014-09-01T21:00:00.000Z", "2014-09-01T21:00:00.000Z", "2014-09-18T21:00:00.000Z", "2014-09-20T21:00:00.000Z", "2014-09-23T21:00:00.000Z", "2014-10-23T21:00:00.000Z", "2014-10-27T22:00:00.000Z", "2014-10-30T22:00:00.000Z", "2014-11-04T22:00:00.000Z", "2014-12-06T22:00:00.000Z", "2014-12-18T22:00:00.000Z", "2015-02-05T22:00:00.000Z", "2015-02-28T22:00:00.000Z", "2015-04-09T21:00:00.000Z", "2015-05-17T21:00:00.000Z", "2015-05-21T21:00:00.000Z", "2015-05-31T21:00:00.000Z", "2015-06-28T21:00:00.000Z", "2015-08-19T21:00:00.000Z", "2015-09-01T21:00:00.000Z", "2015-09-09T21:00:00.000Z", "2015-09-18T21:00:00.000Z", "2015-09-20T21:00:00.000Z", "2015-09-30T21:00:00.000Z", "2015-11-10T22:00:00.000Z", "2015-11-25T22:00:00.000Z", "2016-06-23T21:00:00.000Z", "2016-08-31T21:00:00.000Z", "2016-10-05T21:00:00.000Z", "2016-10-21T21:00:00.000Z", "2016-12-12T21:00:00.000Z", "2016-12-25T21:00:00.000Z", "2017-02-15T21:00:00.000Z", "2017-03-23T21:00:00.000Z"]
--------------------------------------------------------------------------------
/resources/header.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oguzhaninan/vue-histogram-slider/fe8f143095a548ffb956b340a1fe528bab8b4dc2/resources/header.png
--------------------------------------------------------------------------------
/resources/histogram-slider-demo.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oguzhaninan/vue-histogram-slider/fe8f143095a548ffb956b340a1fe528bab8b4dc2/resources/histogram-slider-demo.gif
--------------------------------------------------------------------------------
/src/App.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
18 |
19 |
34 |
35 |
36 |
37 |
70 |
--------------------------------------------------------------------------------
/src/lib/HistogramSlider.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
235 |
236 |
510 |
--------------------------------------------------------------------------------
/src/lib/props.js:
--------------------------------------------------------------------------------
1 | export default {
2 | data: {
3 | type: Array,
4 | required: true
5 | },
6 | min: {
7 | type: Number
8 | },
9 | max: {
10 | type: Number
11 | },
12 | clip: {
13 | type: Boolean,
14 | default: true
15 | },
16 | block: {
17 | type: Boolean,
18 | default: false
19 | },
20 | grid: {
21 | type: Boolean,
22 | default: true
23 | },
24 | gridNum: {
25 | type: Number,
26 | default: 4
27 | },
28 | step: {
29 | type: Number,
30 | default: 1
31 | },
32 | hideMinMax: {
33 | type: Boolean,
34 | default: true
35 | },
36 | hideFromTo: {
37 | type: Boolean,
38 | default: false
39 | },
40 | toFixed: {
41 | type: Boolean,
42 | default: false
43 | },
44 | fromFixed: {
45 | type: Boolean,
46 | default: false
47 | },
48 | forceEdges: {
49 | type: Boolean,
50 | default: false
51 | },
52 | dragInterval: {
53 | type: Boolean,
54 | default: false
55 | },
56 | keyboard: {
57 | type: Boolean,
58 | default: true
59 | },
60 | type: {
61 | type: String,
62 | default: 'double',
63 | validator: function(value) {
64 | return ['double', 'single'].indexOf(value) !== -1
65 | }
66 | },
67 | width: {
68 | type: Number,
69 | default: 650
70 | },
71 | barHeight: {
72 | type: Number,
73 | default: 100
74 | },
75 | barWidth: {
76 | type: Number,
77 | default: 6
78 | },
79 | barGap: {
80 | type: Number,
81 | default: 5
82 | },
83 | barRadius: {
84 | type: Number,
85 | default: 4
86 | },
87 | prettify: Function,
88 | labelColor: {
89 | type: String,
90 | default: '#0091ff'
91 | },
92 | primaryColor: {
93 | type: String,
94 | default: '#0091ff'
95 | },
96 | holderColor: {
97 | type: String,
98 | default: '#dee4ec'
99 | },
100 | handleColor: {
101 | type: String,
102 | default: '#ffffff'
103 | },
104 | gridTextColor: {
105 | type: String,
106 | default: 'silver'
107 | },
108 | lineHeight: {
109 | type: Number,
110 | default: 6
111 | },
112 | transitionDuration: {
113 | type: Number,
114 | default: 80
115 | },
116 | fontFamily: {
117 | type: String,
118 | default: 'Arial, sans-serif'
119 | },
120 | fontSize: {
121 | type: Number,
122 | default: 12
123 | },
124 | histSliderGap: {
125 | type: Number,
126 | default: 6
127 | },
128 | colors: {
129 | type: Array
130 | },
131 | updateColorOnChange: {
132 | type: Boolean,
133 | default: true
134 | },
135 | handleSize: {
136 | type: Number,
137 | default: 26
138 | }
139 | }
140 |
--------------------------------------------------------------------------------
/src/lib/range-slider.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable */
2 | // Ion.RangeSlider
3 | // version 2.3.1 Build: 382
4 | // © Denis Ineshin, 2019
5 | // https://github.com/IonDen
6 | //
7 | // Project page: http://ionden.com/a/plugins/ion.rangeSlider/en.html
8 | // GitHub page: https://github.com/IonDen/ion.rangeSlider
9 | //
10 | // Released under MIT licence:
11 | // http://ionden.com/a/plugins/licence-en.html
12 | // =====================================================================================================================
13 |
14 | var jQuery = require('jquery')
15 |
16 | ;(function(factory) {
17 | if ((typeof jQuery === 'undefined' || !jQuery) && typeof define === 'function' && define.amd) {
18 | define(['jquery'], function(jQuery) {
19 | return factory(jQuery, document, window, navigator)
20 | })
21 | } else if ((typeof jQuery === 'undefined' || !jQuery) && typeof exports === 'object') {
22 | factory(require('jquery'), document, window, navigator)
23 | } else {
24 | factory(jQuery, document, window, navigator)
25 | }
26 | })(function($, document, window, navigator, undefined) {
27 | 'use strict'
28 |
29 | // =================================================================================================================
30 | // Service
31 |
32 | var plugin_count = 0
33 |
34 | // IE8 fix
35 | var is_old_ie = (function() {
36 | var n = navigator.userAgent,
37 | r = /msie\s\d+/i,
38 | v
39 | if (n.search(r) > 0) {
40 | v = r.exec(n).toString()
41 | v = v.split(' ')[1]
42 | if (v < 9) {
43 | $('html').addClass('lt-ie9')
44 | return true
45 | }
46 | }
47 | return false
48 | })()
49 | if (!Function.prototype.bind) {
50 | Function.prototype.bind = function bind(that) {
51 | var target = this
52 | var slice = [].slice
53 |
54 | if (typeof target != 'function') {
55 | throw new TypeError()
56 | }
57 |
58 | var args = slice.call(arguments, 1),
59 | bound = function() {
60 | if (this instanceof bound) {
61 | var F = function() {}
62 | F.prototype = target.prototype
63 | var self = new F()
64 |
65 | var result = target.apply(self, args.concat(slice.call(arguments)))
66 | if (Object(result) === result) {
67 | return result
68 | }
69 | return self
70 | } else {
71 | return target.apply(that, args.concat(slice.call(arguments)))
72 | }
73 | }
74 |
75 | return bound
76 | }
77 | }
78 | if (!Array.prototype.indexOf) {
79 | Array.prototype.indexOf = function(searchElement, fromIndex) {
80 | var k
81 | if (this == null) {
82 | throw new TypeError('"this" is null or not defined')
83 | }
84 | var O = Object(this)
85 | var len = O.length >>> 0
86 | if (len === 0) {
87 | return -1
88 | }
89 | var n = +fromIndex || 0
90 | if (Math.abs(n) === Infinity) {
91 | n = 0
92 | }
93 | if (n >= len) {
94 | return -1
95 | }
96 | k = Math.max(n >= 0 ? n : len - Math.abs(n), 0)
97 | while (k < len) {
98 | if (k in O && O[k] === searchElement) {
99 | return k
100 | }
101 | k++
102 | }
103 | return -1
104 | }
105 | }
106 |
107 | // =================================================================================================================
108 | // Template
109 |
110 | var base_html =
111 | '' +
112 | ' ' +
113 | '0 1 ' +
114 | '0 0 0 ' +
115 | ' ' +
116 | ' '
117 |
118 | var single_html =
119 | ' ' +
120 | ' ' +
121 | ' '
122 |
123 | var double_html =
124 | ' ' +
125 | ' ' +
126 | ' ' +
127 | ' ' +
128 | ' '
129 |
130 | var disable_html = ' '
131 |
132 | // =================================================================================================================
133 | // Core
134 |
135 | /**
136 | * Main plugin constructor
137 | *
138 | * @param input {Object} link to base input element
139 | * @param options {Object} slider config
140 | * @param plugin_count {Number}
141 | * @constructor
142 | */
143 | var IonRangeSlider = function(input, options, plugin_count) {
144 | this.VERSION = '2.3.1'
145 | this.input = input
146 | this.plugin_count = plugin_count
147 | this.current_plugin = 0
148 | this.calc_count = 0
149 | this.update_tm = 0
150 | this.old_from = 0
151 | this.old_to = 0
152 | this.old_min_interval = null
153 | this.raf_id = null
154 | this.dragging = false
155 | this.force_redraw = false
156 | this.no_diapason = false
157 | this.has_tab_index = true
158 | this.is_key = false
159 | this.is_update = false
160 | this.is_start = true
161 | this.is_finish = false
162 | this.is_active = false
163 | this.is_resize = false
164 | this.is_click = false
165 |
166 | options = options || {}
167 |
168 | // cache for links to all DOM elements
169 | this.$cache = {
170 | win: $(window),
171 | body: $(document.body),
172 | input: $(input),
173 | cont: null,
174 | rs: null,
175 | min: null,
176 | max: null,
177 | from: null,
178 | to: null,
179 | single: null,
180 | bar: null,
181 | line: null,
182 | s_single: null,
183 | s_from: null,
184 | s_to: null,
185 | shad_single: null,
186 | shad_from: null,
187 | shad_to: null,
188 | edge: null,
189 | grid: null,
190 | grid_labels: []
191 | }
192 |
193 | // storage for measure variables
194 | this.coords = {
195 | // left
196 | x_gap: 0,
197 | x_pointer: 0,
198 |
199 | // width
200 | w_rs: 0,
201 | w_rs_old: 0,
202 | w_handle: 0,
203 |
204 | // percents
205 | p_gap: 0,
206 | p_gap_left: 0,
207 | p_gap_right: 0,
208 | p_step: 0,
209 | p_pointer: 0,
210 | p_handle: 0,
211 | p_single_fake: 0,
212 | p_single_real: 0,
213 | p_from_fake: 0,
214 | p_from_real: 0,
215 | p_to_fake: 0,
216 | p_to_real: 0,
217 | p_bar_x: 0,
218 | p_bar_w: 0,
219 |
220 | // grid
221 | grid_gap: 0,
222 | big_num: 0,
223 | big: [],
224 | big_w: [],
225 | big_p: [],
226 | big_x: []
227 | }
228 |
229 | // storage for labels measure variables
230 | this.labels = {
231 | // width
232 | w_min: 0,
233 | w_max: 0,
234 | w_from: 0,
235 | w_to: 0,
236 | w_single: 0,
237 |
238 | // percents
239 | p_min: 0,
240 | p_max: 0,
241 | p_from_fake: 0,
242 | p_from_left: 0,
243 | p_to_fake: 0,
244 | p_to_left: 0,
245 | p_single_fake: 0,
246 | p_single_left: 0
247 | }
248 |
249 | /**
250 | * get and validate config
251 | */
252 | var $inp = this.$cache.input,
253 | val = $inp.prop('value'),
254 | config,
255 | config_from_data,
256 | prop
257 |
258 | // default config
259 | config = {
260 | skin: 'flat',
261 | type: 'single',
262 |
263 | min: 10,
264 | max: 100,
265 | from: null,
266 | to: null,
267 | step: 1,
268 |
269 | min_interval: 0,
270 | max_interval: 0,
271 | drag_interval: false,
272 |
273 | values: [],
274 | p_values: [],
275 |
276 | from_fixed: false,
277 | from_min: null,
278 | from_max: null,
279 | from_shadow: false,
280 |
281 | to_fixed: false,
282 | to_min: null,
283 | to_max: null,
284 | to_shadow: false,
285 |
286 | prettify_enabled: true,
287 | prettify_separator: ' ',
288 | prettify: null,
289 |
290 | force_edges: false,
291 |
292 | keyboard: true,
293 |
294 | grid: false,
295 | grid_margin: true,
296 | grid_num: 4,
297 | grid_snap: false,
298 |
299 | hide_min_max: false,
300 | hide_from_to: false,
301 |
302 | prefix: '',
303 | postfix: '',
304 | max_postfix: '',
305 | decorate_both: true,
306 | values_separator: ' — ',
307 |
308 | input_values_separator: ';',
309 |
310 | disable: false,
311 | block: false,
312 |
313 | extra_classes: '',
314 |
315 | scope: null,
316 | onStart: null,
317 | onChange: null,
318 | onFinish: null,
319 | onUpdate: null
320 | }
321 |
322 | // check if base element is input
323 | if ($inp[0].nodeName !== 'INPUT') {
324 | console && console.warn && console.warn('Base element should be !', $inp[0])
325 | }
326 |
327 | // config from data-attributes extends js config
328 | config_from_data = {
329 | skin: $inp.data('skin'),
330 | type: $inp.data('type'),
331 |
332 | min: $inp.data('min'),
333 | max: $inp.data('max'),
334 | from: $inp.data('from'),
335 | to: $inp.data('to'),
336 | step: $inp.data('step'),
337 |
338 | min_interval: $inp.data('minInterval'),
339 | max_interval: $inp.data('maxInterval'),
340 | drag_interval: $inp.data('dragInterval'),
341 |
342 | values: $inp.data('values'),
343 |
344 | from_fixed: $inp.data('fromFixed'),
345 | from_min: $inp.data('fromMin'),
346 | from_max: $inp.data('fromMax'),
347 | from_shadow: $inp.data('fromShadow'),
348 |
349 | to_fixed: $inp.data('toFixed'),
350 | to_min: $inp.data('toMin'),
351 | to_max: $inp.data('toMax'),
352 | to_shadow: $inp.data('toShadow'),
353 |
354 | prettify_enabled: $inp.data('prettifyEnabled'),
355 | prettify_separator: $inp.data('prettifySeparator'),
356 |
357 | force_edges: $inp.data('forceEdges'),
358 |
359 | keyboard: $inp.data('keyboard'),
360 |
361 | grid: $inp.data('grid'),
362 | grid_margin: $inp.data('gridMargin'),
363 | grid_num: $inp.data('gridNum'),
364 | grid_snap: $inp.data('gridSnap'),
365 |
366 | hide_min_max: $inp.data('hideMinMax'),
367 | hide_from_to: $inp.data('hideFromTo'),
368 |
369 | prefix: $inp.data('prefix'),
370 | postfix: $inp.data('postfix'),
371 | max_postfix: $inp.data('maxPostfix'),
372 | decorate_both: $inp.data('decorateBoth'),
373 | values_separator: $inp.data('valuesSeparator'),
374 |
375 | input_values_separator: $inp.data('inputValuesSeparator'),
376 |
377 | disable: $inp.data('disable'),
378 | block: $inp.data('block'),
379 |
380 | extra_classes: $inp.data('extraClasses')
381 | }
382 | config_from_data.values = config_from_data.values && config_from_data.values.split(',')
383 |
384 | for (prop in config_from_data) {
385 | if (config_from_data.hasOwnProperty(prop)) {
386 | if (config_from_data[prop] === undefined || config_from_data[prop] === '') {
387 | delete config_from_data[prop]
388 | }
389 | }
390 | }
391 |
392 | // input value extends default config
393 | if (val !== undefined && val !== '') {
394 | val = val.split(
395 | config_from_data.input_values_separator || options.input_values_separator || ';'
396 | )
397 |
398 | if (val[0] && val[0] == +val[0]) {
399 | val[0] = +val[0]
400 | }
401 | if (val[1] && val[1] == +val[1]) {
402 | val[1] = +val[1]
403 | }
404 |
405 | if (options && options.values && options.values.length) {
406 | config.from = val[0] && options.values.indexOf(val[0])
407 | config.to = val[1] && options.values.indexOf(val[1])
408 | } else {
409 | config.from = val[0] && +val[0]
410 | config.to = val[1] && +val[1]
411 | }
412 | }
413 |
414 | // js config extends default config
415 | $.extend(config, options)
416 |
417 | // data config extends config
418 | $.extend(config, config_from_data)
419 | this.options = config
420 |
421 | // validate config, to be sure that all data types are correct
422 | this.update_check = {}
423 | this.validate()
424 |
425 | // default result object, returned to callbacks
426 | this.result = {
427 | input: this.$cache.input,
428 | slider: null,
429 |
430 | min: this.options.min,
431 | max: this.options.max,
432 |
433 | from: this.options.from,
434 | from_percent: 0,
435 | from_value: null,
436 |
437 | to: this.options.to,
438 | to_percent: 0,
439 | to_value: null
440 | }
441 |
442 | this.init()
443 | }
444 |
445 | IonRangeSlider.prototype = {
446 | /**
447 | * Starts or updates the plugin instance
448 | *
449 | * @param [is_update] {boolean}
450 | */
451 | init: function(is_update) {
452 | this.no_diapason = false
453 | this.coords.p_step = this.convertToPercent(this.options.step, true)
454 |
455 | this.target = 'base'
456 |
457 | this.toggleInput()
458 | this.append()
459 | this.setMinMax()
460 |
461 | if (is_update) {
462 | this.force_redraw = true
463 | this.calc(true)
464 |
465 | // callbacks called
466 | this.callOnUpdate()
467 | } else {
468 | this.force_redraw = true
469 | this.calc(true)
470 |
471 | // callbacks called
472 | this.callOnStart()
473 | }
474 |
475 | this.updateScene()
476 | },
477 |
478 | /**
479 | * Appends slider template to a DOM
480 | */
481 | append: function() {
482 | var container_html =
483 | ''
490 | this.$cache.input.before(container_html)
491 | this.$cache.input.prop('readonly', true)
492 | this.$cache.cont = this.$cache.input.prev()
493 | this.result.slider = this.$cache.cont
494 |
495 | this.$cache.cont.html(base_html)
496 | this.$cache.rs = this.$cache.cont.find('.irs')
497 | this.$cache.min = this.$cache.cont.find('.irs-min')
498 | this.$cache.max = this.$cache.cont.find('.irs-max')
499 | this.$cache.from = this.$cache.cont.find('.irs-from')
500 | this.$cache.to = this.$cache.cont.find('.irs-to')
501 | this.$cache.single = this.$cache.cont.find('.irs-single')
502 | this.$cache.line = this.$cache.cont.find('.irs-line')
503 | this.$cache.grid = this.$cache.cont.find('.irs-grid')
504 |
505 | if (this.options.type === 'single') {
506 | this.$cache.cont.append(single_html)
507 | this.$cache.bar = this.$cache.cont.find('.irs-bar')
508 | this.$cache.edge = this.$cache.cont.find('.irs-bar-edge')
509 | this.$cache.s_single = this.$cache.cont.find('.single')
510 | this.$cache.from[0].style.visibility = 'hidden'
511 | this.$cache.to[0].style.visibility = 'hidden'
512 | this.$cache.shad_single = this.$cache.cont.find('.shadow-single')
513 | } else {
514 | this.$cache.cont.append(double_html)
515 | this.$cache.bar = this.$cache.cont.find('.irs-bar')
516 | this.$cache.s_from = this.$cache.cont.find('.from')
517 | this.$cache.s_to = this.$cache.cont.find('.to')
518 | this.$cache.shad_from = this.$cache.cont.find('.shadow-from')
519 | this.$cache.shad_to = this.$cache.cont.find('.shadow-to')
520 |
521 | this.setTopHandler()
522 | }
523 |
524 | if (this.options.hide_from_to) {
525 | this.$cache.from[0].style.display = 'none'
526 | this.$cache.to[0].style.display = 'none'
527 | this.$cache.single[0].style.display = 'none'
528 | }
529 |
530 | this.appendGrid()
531 |
532 | if (this.options.disable) {
533 | this.appendDisableMask()
534 | this.$cache.input[0].disabled = true
535 | } else {
536 | this.$cache.input[0].disabled = false
537 | this.removeDisableMask()
538 | this.bindEvents()
539 | }
540 |
541 | // block only if not disabled
542 | if (!this.options.disable) {
543 | if (this.options.block) {
544 | this.appendDisableMask()
545 | } else {
546 | this.removeDisableMask()
547 | }
548 | }
549 |
550 | if (this.options.drag_interval) {
551 | this.$cache.bar[0].style.cursor = 'ew-resize'
552 | }
553 | },
554 |
555 | /**
556 | * Determine which handler has a priority
557 | * works only for double slider type
558 | */
559 | setTopHandler: function() {
560 | var min = this.options.min,
561 | max = this.options.max,
562 | from = this.options.from,
563 | to = this.options.to
564 |
565 | if (from > min && to === max) {
566 | this.$cache.s_from.addClass('type_last')
567 | } else if (to < max) {
568 | this.$cache.s_to.addClass('type_last')
569 | }
570 | },
571 |
572 | /**
573 | * Determine which handles was clicked last
574 | * and which handler should have hover effect
575 | *
576 | * @param target {String}
577 | */
578 | changeLevel: function(target) {
579 | switch (target) {
580 | case 'single':
581 | this.coords.p_gap = this.toFixed(this.coords.p_pointer - this.coords.p_single_fake)
582 | this.$cache.s_single.addClass('state_hover')
583 | break
584 | case 'from':
585 | this.coords.p_gap = this.toFixed(this.coords.p_pointer - this.coords.p_from_fake)
586 | this.$cache.s_from.addClass('state_hover')
587 | this.$cache.s_from.addClass('type_last')
588 | this.$cache.s_to.removeClass('type_last')
589 | break
590 | case 'to':
591 | this.coords.p_gap = this.toFixed(this.coords.p_pointer - this.coords.p_to_fake)
592 | this.$cache.s_to.addClass('state_hover')
593 | this.$cache.s_to.addClass('type_last')
594 | this.$cache.s_from.removeClass('type_last')
595 | break
596 | case 'both':
597 | this.coords.p_gap_left = this.toFixed(this.coords.p_pointer - this.coords.p_from_fake)
598 | this.coords.p_gap_right = this.toFixed(this.coords.p_to_fake - this.coords.p_pointer)
599 | this.$cache.s_to.removeClass('type_last')
600 | this.$cache.s_from.removeClass('type_last')
601 | break
602 | }
603 | },
604 |
605 | /**
606 | * Then slider is disabled
607 | * appends extra layer with opacity
608 | */
609 | appendDisableMask: function() {
610 | this.$cache.cont.append(disable_html)
611 | this.$cache.cont.addClass('irs-disabled')
612 | },
613 |
614 | /**
615 | * Then slider is not disabled
616 | * remove disable mask
617 | */
618 | removeDisableMask: function() {
619 | this.$cache.cont.remove('.irs-disable-mask')
620 | this.$cache.cont.removeClass('irs-disabled')
621 | },
622 |
623 | /**
624 | * Remove slider instance
625 | * and unbind all events
626 | */
627 | remove: function() {
628 | this.$cache.cont.remove()
629 | this.$cache.cont = null
630 |
631 | this.$cache.line.off('keydown.irs_' + this.plugin_count)
632 |
633 | this.$cache.body.off('touchmove.irs_' + this.plugin_count)
634 | this.$cache.body.off('mousemove.irs_' + this.plugin_count)
635 |
636 | this.$cache.win.off('touchend.irs_' + this.plugin_count)
637 | this.$cache.win.off('mouseup.irs_' + this.plugin_count)
638 |
639 | if (is_old_ie) {
640 | this.$cache.body.off('mouseup.irs_' + this.plugin_count)
641 | this.$cache.body.off('mouseleave.irs_' + this.plugin_count)
642 | }
643 |
644 | this.$cache.grid_labels = []
645 | this.coords.big = []
646 | this.coords.big_w = []
647 | this.coords.big_p = []
648 | this.coords.big_x = []
649 |
650 | cancelAnimationFrame(this.raf_id)
651 | },
652 |
653 | /**
654 | * bind all slider events
655 | */
656 | bindEvents: function() {
657 | if (this.no_diapason) {
658 | return
659 | }
660 |
661 | this.$cache.body.on('touchmove.irs_' + this.plugin_count, this.pointerMove.bind(this))
662 | this.$cache.body.on('mousemove.irs_' + this.plugin_count, this.pointerMove.bind(this))
663 |
664 | this.$cache.win.on('touchend.irs_' + this.plugin_count, this.pointerUp.bind(this))
665 | this.$cache.win.on('mouseup.irs_' + this.plugin_count, this.pointerUp.bind(this))
666 |
667 | this.$cache.line.on(
668 | 'touchstart.irs_' + this.plugin_count,
669 | this.pointerClick.bind(this, 'click')
670 | )
671 | this.$cache.line.on(
672 | 'mousedown.irs_' + this.plugin_count,
673 | this.pointerClick.bind(this, 'click')
674 | )
675 |
676 | this.$cache.line.on('focus.irs_' + this.plugin_count, this.pointerFocus.bind(this))
677 |
678 | if (this.options.drag_interval && this.options.type === 'double') {
679 | this.$cache.bar.on(
680 | 'touchstart.irs_' + this.plugin_count,
681 | this.pointerDown.bind(this, 'both')
682 | )
683 | this.$cache.bar.on(
684 | 'mousedown.irs_' + this.plugin_count,
685 | this.pointerDown.bind(this, 'both')
686 | )
687 | } else {
688 | this.$cache.bar.on(
689 | 'touchstart.irs_' + this.plugin_count,
690 | this.pointerClick.bind(this, 'click')
691 | )
692 | this.$cache.bar.on(
693 | 'mousedown.irs_' + this.plugin_count,
694 | this.pointerClick.bind(this, 'click')
695 | )
696 | }
697 |
698 | if (this.options.type === 'single') {
699 | this.$cache.single.on(
700 | 'touchstart.irs_' + this.plugin_count,
701 | this.pointerDown.bind(this, 'single')
702 | )
703 | this.$cache.s_single.on(
704 | 'touchstart.irs_' + this.plugin_count,
705 | this.pointerDown.bind(this, 'single')
706 | )
707 | this.$cache.shad_single.on(
708 | 'touchstart.irs_' + this.plugin_count,
709 | this.pointerClick.bind(this, 'click')
710 | )
711 |
712 | this.$cache.single.on(
713 | 'mousedown.irs_' + this.plugin_count,
714 | this.pointerDown.bind(this, 'single')
715 | )
716 | this.$cache.s_single.on(
717 | 'mousedown.irs_' + this.plugin_count,
718 | this.pointerDown.bind(this, 'single')
719 | )
720 | this.$cache.edge.on(
721 | 'mousedown.irs_' + this.plugin_count,
722 | this.pointerClick.bind(this, 'click')
723 | )
724 | this.$cache.shad_single.on(
725 | 'mousedown.irs_' + this.plugin_count,
726 | this.pointerClick.bind(this, 'click')
727 | )
728 | } else {
729 | this.$cache.single.on(
730 | 'touchstart.irs_' + this.plugin_count,
731 | this.pointerDown.bind(this, null)
732 | )
733 | this.$cache.single.on(
734 | 'mousedown.irs_' + this.plugin_count,
735 | this.pointerDown.bind(this, null)
736 | )
737 |
738 | this.$cache.from.on(
739 | 'touchstart.irs_' + this.plugin_count,
740 | this.pointerDown.bind(this, 'from')
741 | )
742 | this.$cache.s_from.on(
743 | 'touchstart.irs_' + this.plugin_count,
744 | this.pointerDown.bind(this, 'from')
745 | )
746 | this.$cache.to.on('touchstart.irs_' + this.plugin_count, this.pointerDown.bind(this, 'to'))
747 | this.$cache.s_to.on(
748 | 'touchstart.irs_' + this.plugin_count,
749 | this.pointerDown.bind(this, 'to')
750 | )
751 | this.$cache.shad_from.on(
752 | 'touchstart.irs_' + this.plugin_count,
753 | this.pointerClick.bind(this, 'click')
754 | )
755 | this.$cache.shad_to.on(
756 | 'touchstart.irs_' + this.plugin_count,
757 | this.pointerClick.bind(this, 'click')
758 | )
759 |
760 | this.$cache.from.on(
761 | 'mousedown.irs_' + this.plugin_count,
762 | this.pointerDown.bind(this, 'from')
763 | )
764 | this.$cache.s_from.on(
765 | 'mousedown.irs_' + this.plugin_count,
766 | this.pointerDown.bind(this, 'from')
767 | )
768 | this.$cache.to.on('mousedown.irs_' + this.plugin_count, this.pointerDown.bind(this, 'to'))
769 | this.$cache.s_to.on('mousedown.irs_' + this.plugin_count, this.pointerDown.bind(this, 'to'))
770 | this.$cache.shad_from.on(
771 | 'mousedown.irs_' + this.plugin_count,
772 | this.pointerClick.bind(this, 'click')
773 | )
774 | this.$cache.shad_to.on(
775 | 'mousedown.irs_' + this.plugin_count,
776 | this.pointerClick.bind(this, 'click')
777 | )
778 | }
779 |
780 | if (this.options.keyboard) {
781 | this.$cache.line.on('keydown.irs_' + this.plugin_count, this.key.bind(this, 'keyboard'))
782 | }
783 |
784 | if (is_old_ie) {
785 | this.$cache.body.on('mouseup.irs_' + this.plugin_count, this.pointerUp.bind(this))
786 | this.$cache.body.on('mouseleave.irs_' + this.plugin_count, this.pointerUp.bind(this))
787 | }
788 | },
789 |
790 | /**
791 | * Focus with tabIndex
792 | *
793 | * @param e {Object} event object
794 | */
795 | pointerFocus: function(e) {
796 | if (!this.target) {
797 | var x
798 | var $handle
799 |
800 | if (this.options.type === 'single') {
801 | $handle = this.$cache.single
802 | } else {
803 | $handle = this.$cache.from
804 | }
805 |
806 | x = $handle.offset().left
807 | x += $handle.width() / 2 - 1
808 |
809 | this.pointerClick('single', { preventDefault: function() {}, pageX: x })
810 | }
811 | },
812 |
813 | /**
814 | * Mousemove or touchmove
815 | * only for handlers
816 | *
817 | * @param e {Object} event object
818 | */
819 | pointerMove: function(e) {
820 | if (!this.dragging) {
821 | return
822 | }
823 |
824 | var x = e.pageX || (e.originalEvent.touches && e.originalEvent.touches[0].pageX)
825 | this.coords.x_pointer = x - this.coords.x_gap
826 |
827 | this.calc()
828 | },
829 |
830 | /**
831 | * Mouseup or touchend
832 | * only for handlers
833 | *
834 | * @param e {Object} event object
835 | */
836 | pointerUp: function(e) {
837 | if (this.current_plugin !== this.plugin_count) {
838 | return
839 | }
840 |
841 | if (this.is_active) {
842 | this.is_active = false
843 | } else {
844 | return
845 | }
846 |
847 | this.$cache.cont.find('.state_hover').removeClass('state_hover')
848 |
849 | this.force_redraw = true
850 |
851 | if (is_old_ie) {
852 | $('*').prop('unselectable', false)
853 | }
854 |
855 | this.updateScene()
856 | this.restoreOriginalMinInterval()
857 |
858 | // callbacks call
859 | if ($.contains(this.$cache.cont[0], e.target) || this.dragging) {
860 | this.callOnFinish()
861 | }
862 |
863 | this.dragging = false
864 | },
865 |
866 | /**
867 | * Mousedown or touchstart
868 | * only for handlers
869 | *
870 | * @param target {String|null}
871 | * @param e {Object} event object
872 | */
873 | pointerDown: function(target, e) {
874 | e.preventDefault()
875 | var x = e.pageX || (e.originalEvent.touches && e.originalEvent.touches[0].pageX)
876 | if (e.button === 2) {
877 | return
878 | }
879 |
880 | if (target === 'both') {
881 | this.setTempMinInterval()
882 | }
883 |
884 | if (!target) {
885 | target = this.target || 'from'
886 | }
887 |
888 | this.current_plugin = this.plugin_count
889 | this.target = target
890 |
891 | this.is_active = true
892 | this.dragging = true
893 |
894 | this.coords.x_gap = this.$cache.rs.offset().left
895 | this.coords.x_pointer = x - this.coords.x_gap
896 |
897 | this.calcPointerPercent()
898 | this.changeLevel(target)
899 |
900 | if (is_old_ie) {
901 | $('*').prop('unselectable', true)
902 | }
903 |
904 | this.$cache.line.trigger('focus')
905 |
906 | this.updateScene()
907 | },
908 |
909 | /**
910 | * Mousedown or touchstart
911 | * for other slider elements, like diapason line
912 | *
913 | * @param target {String}
914 | * @param e {Object} event object
915 | */
916 | pointerClick: function(target, e) {
917 | e.preventDefault()
918 | var x = e.pageX || (e.originalEvent.touches && e.originalEvent.touches[0].pageX)
919 | if (e.button === 2) {
920 | return
921 | }
922 |
923 | this.current_plugin = this.plugin_count
924 | this.target = target
925 |
926 | this.is_click = true
927 | this.coords.x_gap = this.$cache.rs.offset().left
928 | this.coords.x_pointer = +(x - this.coords.x_gap).toFixed()
929 |
930 | this.force_redraw = true
931 | this.calc()
932 |
933 | this.$cache.line.trigger('focus')
934 | },
935 |
936 | /**
937 | * Keyborard controls for focused slider
938 | *
939 | * @param target {String}
940 | * @param e {Object} event object
941 | * @returns {boolean|undefined}
942 | */
943 | key: function(target, e) {
944 | if (
945 | this.current_plugin !== this.plugin_count ||
946 | e.altKey ||
947 | e.ctrlKey ||
948 | e.shiftKey ||
949 | e.metaKey
950 | ) {
951 | return
952 | }
953 |
954 | switch (e.which) {
955 | case 83: // W
956 | case 65: // A
957 | case 40: // DOWN
958 | case 37: // LEFT
959 | e.preventDefault()
960 | this.moveByKey(false)
961 | break
962 |
963 | case 87: // S
964 | case 68: // D
965 | case 38: // UP
966 | case 39: // RIGHT
967 | e.preventDefault()
968 | this.moveByKey(true)
969 | break
970 | }
971 |
972 | return true
973 | },
974 |
975 | /**
976 | * Move by key
977 | *
978 | * @param right {boolean} direction to move
979 | */
980 | moveByKey: function(right) {
981 | var p = this.coords.p_pointer
982 | var p_step = (this.options.max - this.options.min) / 100
983 | p_step = this.options.step / p_step
984 |
985 | if (right) {
986 | p += p_step
987 | } else {
988 | p -= p_step
989 | }
990 |
991 | this.coords.x_pointer = this.toFixed((this.coords.w_rs / 100) * p)
992 | this.is_key = true
993 | this.calc()
994 | },
995 |
996 | /**
997 | * Set visibility and content
998 | * of Min and Max labels
999 | */
1000 | setMinMax: function() {
1001 | if (!this.options) {
1002 | return
1003 | }
1004 |
1005 | if (this.options.hide_min_max) {
1006 | this.$cache.min[0].style.display = 'none'
1007 | this.$cache.max[0].style.display = 'none'
1008 | return
1009 | }
1010 |
1011 | if (this.options.values.length) {
1012 | this.$cache.min.html(this.decorate(this.options.p_values[this.options.min]))
1013 | this.$cache.max.html(this.decorate(this.options.p_values[this.options.max]))
1014 | } else {
1015 | var min_pretty = this._prettify(this.options.min)
1016 | var max_pretty = this._prettify(this.options.max)
1017 |
1018 | this.result.min_pretty = min_pretty
1019 | this.result.max_pretty = max_pretty
1020 |
1021 | this.$cache.min.html(this.decorate(min_pretty, this.options.min))
1022 | this.$cache.max.html(this.decorate(max_pretty, this.options.max))
1023 | }
1024 |
1025 | this.labels.w_min = this.$cache.min.outerWidth(false)
1026 | this.labels.w_max = this.$cache.max.outerWidth(false)
1027 | },
1028 |
1029 | /**
1030 | * Then dragging interval, prevent interval collapsing
1031 | * using min_interval option
1032 | */
1033 | setTempMinInterval: function() {
1034 | var interval = this.result.to - this.result.from
1035 |
1036 | if (this.old_min_interval === null) {
1037 | this.old_min_interval = this.options.min_interval
1038 | }
1039 |
1040 | this.options.min_interval = interval
1041 | },
1042 |
1043 | /**
1044 | * Restore min_interval option to original
1045 | */
1046 | restoreOriginalMinInterval: function() {
1047 | if (this.old_min_interval !== null) {
1048 | this.options.min_interval = this.old_min_interval
1049 | this.old_min_interval = null
1050 | }
1051 | },
1052 |
1053 | // =============================================================================================================
1054 | // Calculations
1055 |
1056 | /**
1057 | * All calculations and measures start here
1058 | *
1059 | * @param update {boolean=}
1060 | */
1061 | calc: function(update) {
1062 | if (!this.options) {
1063 | return
1064 | }
1065 |
1066 | this.calc_count++
1067 |
1068 | if (this.calc_count === 10 || update) {
1069 | this.calc_count = 0
1070 | this.coords.w_rs = this.$cache.rs.outerWidth(false)
1071 |
1072 | this.calcHandlePercent()
1073 | }
1074 |
1075 | if (!this.coords.w_rs) {
1076 | return
1077 | }
1078 |
1079 | this.calcPointerPercent()
1080 | var handle_x = this.getHandleX()
1081 |
1082 | if (this.target === 'both') {
1083 | this.coords.p_gap = 0
1084 | handle_x = this.getHandleX()
1085 | }
1086 |
1087 | if (this.target === 'click') {
1088 | this.coords.p_gap = this.coords.p_handle / 2
1089 | handle_x = this.getHandleX()
1090 |
1091 | if (this.options.drag_interval) {
1092 | this.target = 'both_one'
1093 | } else {
1094 | this.target = this.chooseHandle(handle_x)
1095 | }
1096 | }
1097 |
1098 | switch (this.target) {
1099 | case 'base':
1100 | var w = (this.options.max - this.options.min) / 100,
1101 | f = (this.result.from - this.options.min) / w,
1102 | t = (this.result.to - this.options.min) / w
1103 |
1104 | this.coords.p_single_real = this.toFixed(f)
1105 | this.coords.p_from_real = this.toFixed(f)
1106 | this.coords.p_to_real = this.toFixed(t)
1107 |
1108 | this.coords.p_single_real = this.checkDiapason(
1109 | this.coords.p_single_real,
1110 | this.options.from_min,
1111 | this.options.from_max
1112 | )
1113 | this.coords.p_from_real = this.checkDiapason(
1114 | this.coords.p_from_real,
1115 | this.options.from_min,
1116 | this.options.from_max
1117 | )
1118 | this.coords.p_to_real = this.checkDiapason(
1119 | this.coords.p_to_real,
1120 | this.options.to_min,
1121 | this.options.to_max
1122 | )
1123 |
1124 | this.coords.p_single_fake = this.convertToFakePercent(this.coords.p_single_real)
1125 | this.coords.p_from_fake = this.convertToFakePercent(this.coords.p_from_real)
1126 | this.coords.p_to_fake = this.convertToFakePercent(this.coords.p_to_real)
1127 |
1128 | this.target = null
1129 |
1130 | break
1131 |
1132 | case 'single':
1133 | if (this.options.from_fixed) {
1134 | break
1135 | }
1136 |
1137 | this.coords.p_single_real = this.convertToRealPercent(handle_x)
1138 | this.coords.p_single_real = this.calcWithStep(this.coords.p_single_real)
1139 | this.coords.p_single_real = this.checkDiapason(
1140 | this.coords.p_single_real,
1141 | this.options.from_min,
1142 | this.options.from_max
1143 | )
1144 |
1145 | this.coords.p_single_fake = this.convertToFakePercent(this.coords.p_single_real)
1146 |
1147 | break
1148 |
1149 | case 'from':
1150 | if (this.options.from_fixed) {
1151 | break
1152 | }
1153 |
1154 | this.coords.p_from_real = this.convertToRealPercent(handle_x)
1155 | this.coords.p_from_real = this.calcWithStep(this.coords.p_from_real)
1156 | if (this.coords.p_from_real > this.coords.p_to_real) {
1157 | this.coords.p_from_real = this.coords.p_to_real
1158 | }
1159 | this.coords.p_from_real = this.checkDiapason(
1160 | this.coords.p_from_real,
1161 | this.options.from_min,
1162 | this.options.from_max
1163 | )
1164 | this.coords.p_from_real = this.checkMinInterval(
1165 | this.coords.p_from_real,
1166 | this.coords.p_to_real,
1167 | 'from'
1168 | )
1169 | this.coords.p_from_real = this.checkMaxInterval(
1170 | this.coords.p_from_real,
1171 | this.coords.p_to_real,
1172 | 'from'
1173 | )
1174 |
1175 | this.coords.p_from_fake = this.convertToFakePercent(this.coords.p_from_real)
1176 |
1177 | break
1178 |
1179 | case 'to':
1180 | if (this.options.to_fixed) {
1181 | break
1182 | }
1183 |
1184 | this.coords.p_to_real = this.convertToRealPercent(handle_x)
1185 | this.coords.p_to_real = this.calcWithStep(this.coords.p_to_real)
1186 | if (this.coords.p_to_real < this.coords.p_from_real) {
1187 | this.coords.p_to_real = this.coords.p_from_real
1188 | }
1189 | this.coords.p_to_real = this.checkDiapason(
1190 | this.coords.p_to_real,
1191 | this.options.to_min,
1192 | this.options.to_max
1193 | )
1194 | this.coords.p_to_real = this.checkMinInterval(
1195 | this.coords.p_to_real,
1196 | this.coords.p_from_real,
1197 | 'to'
1198 | )
1199 | this.coords.p_to_real = this.checkMaxInterval(
1200 | this.coords.p_to_real,
1201 | this.coords.p_from_real,
1202 | 'to'
1203 | )
1204 |
1205 | this.coords.p_to_fake = this.convertToFakePercent(this.coords.p_to_real)
1206 |
1207 | break
1208 |
1209 | case 'both':
1210 | if (this.options.from_fixed || this.options.to_fixed) {
1211 | break
1212 | }
1213 |
1214 | handle_x = this.toFixed(handle_x + this.coords.p_handle * 0.001)
1215 |
1216 | this.coords.p_from_real = this.convertToRealPercent(handle_x) - this.coords.p_gap_left
1217 | this.coords.p_from_real = this.calcWithStep(this.coords.p_from_real)
1218 | this.coords.p_from_real = this.checkDiapason(
1219 | this.coords.p_from_real,
1220 | this.options.from_min,
1221 | this.options.from_max
1222 | )
1223 | this.coords.p_from_real = this.checkMinInterval(
1224 | this.coords.p_from_real,
1225 | this.coords.p_to_real,
1226 | 'from'
1227 | )
1228 | this.coords.p_from_fake = this.convertToFakePercent(this.coords.p_from_real)
1229 |
1230 | this.coords.p_to_real = this.convertToRealPercent(handle_x) + this.coords.p_gap_right
1231 | this.coords.p_to_real = this.calcWithStep(this.coords.p_to_real)
1232 | this.coords.p_to_real = this.checkDiapason(
1233 | this.coords.p_to_real,
1234 | this.options.to_min,
1235 | this.options.to_max
1236 | )
1237 | this.coords.p_to_real = this.checkMinInterval(
1238 | this.coords.p_to_real,
1239 | this.coords.p_from_real,
1240 | 'to'
1241 | )
1242 | this.coords.p_to_fake = this.convertToFakePercent(this.coords.p_to_real)
1243 |
1244 | break
1245 |
1246 | case 'both_one':
1247 | if (this.options.from_fixed || this.options.to_fixed) {
1248 | break
1249 | }
1250 |
1251 | var real_x = this.convertToRealPercent(handle_x),
1252 | from = this.result.from_percent,
1253 | to = this.result.to_percent,
1254 | full = to - from,
1255 | half = full / 2,
1256 | new_from = real_x - half,
1257 | new_to = real_x + half
1258 |
1259 | if (new_from < 0) {
1260 | new_from = 0
1261 | new_to = new_from + full
1262 | }
1263 |
1264 | if (new_to > 100) {
1265 | new_to = 100
1266 | new_from = new_to - full
1267 | }
1268 |
1269 | this.coords.p_from_real = this.calcWithStep(new_from)
1270 | this.coords.p_from_real = this.checkDiapason(
1271 | this.coords.p_from_real,
1272 | this.options.from_min,
1273 | this.options.from_max
1274 | )
1275 | this.coords.p_from_fake = this.convertToFakePercent(this.coords.p_from_real)
1276 |
1277 | this.coords.p_to_real = this.calcWithStep(new_to)
1278 | this.coords.p_to_real = this.checkDiapason(
1279 | this.coords.p_to_real,
1280 | this.options.to_min,
1281 | this.options.to_max
1282 | )
1283 | this.coords.p_to_fake = this.convertToFakePercent(this.coords.p_to_real)
1284 |
1285 | break
1286 | }
1287 |
1288 | if (this.options.type === 'single') {
1289 | this.coords.p_bar_x = this.coords.p_handle / 2
1290 | this.coords.p_bar_w = this.coords.p_single_fake
1291 |
1292 | this.result.from_percent = this.coords.p_single_real
1293 | this.result.from = this.convertToValue(this.coords.p_single_real)
1294 | this.result.from_pretty = this._prettify(this.result.from)
1295 |
1296 | if (this.options.values.length) {
1297 | this.result.from_value = this.options.values[this.result.from]
1298 | }
1299 | } else {
1300 | this.coords.p_bar_x = this.toFixed(this.coords.p_from_fake + this.coords.p_handle / 2)
1301 | this.coords.p_bar_w = this.toFixed(this.coords.p_to_fake - this.coords.p_from_fake)
1302 |
1303 | this.result.from_percent = this.coords.p_from_real
1304 | this.result.from = this.convertToValue(this.coords.p_from_real)
1305 | this.result.from_pretty = this._prettify(this.result.from)
1306 | this.result.to_percent = this.coords.p_to_real
1307 | this.result.to = this.convertToValue(this.coords.p_to_real)
1308 | this.result.to_pretty = this._prettify(this.result.to)
1309 |
1310 | if (this.options.values.length) {
1311 | this.result.from_value = this.options.values[this.result.from]
1312 | this.result.to_value = this.options.values[this.result.to]
1313 | }
1314 | }
1315 |
1316 | this.calcMinMax()
1317 | this.calcLabels()
1318 | },
1319 |
1320 | /**
1321 | * calculates pointer X in percent
1322 | */
1323 | calcPointerPercent: function() {
1324 | if (!this.coords.w_rs) {
1325 | this.coords.p_pointer = 0
1326 | return
1327 | }
1328 |
1329 | if (this.coords.x_pointer < 0 || isNaN(this.coords.x_pointer)) {
1330 | this.coords.x_pointer = 0
1331 | } else if (this.coords.x_pointer > this.coords.w_rs) {
1332 | this.coords.x_pointer = this.coords.w_rs
1333 | }
1334 |
1335 | this.coords.p_pointer = this.toFixed((this.coords.x_pointer / this.coords.w_rs) * 100)
1336 | },
1337 |
1338 | convertToRealPercent: function(fake) {
1339 | var full = 100 - this.coords.p_handle
1340 | return (fake / full) * 100
1341 | },
1342 |
1343 | convertToFakePercent: function(real) {
1344 | var full = 100 - this.coords.p_handle
1345 | return (real / 100) * full
1346 | },
1347 |
1348 | getHandleX: function() {
1349 | var max = 100 - this.coords.p_handle,
1350 | x = this.toFixed(this.coords.p_pointer - this.coords.p_gap)
1351 |
1352 | if (x < 0) {
1353 | x = 0
1354 | } else if (x > max) {
1355 | x = max
1356 | }
1357 |
1358 | return x
1359 | },
1360 |
1361 | calcHandlePercent: function() {
1362 | if (this.options.type === 'single') {
1363 | this.coords.w_handle = this.$cache.s_single.outerWidth(false)
1364 | } else {
1365 | this.coords.w_handle = this.$cache.s_from.outerWidth(false)
1366 | }
1367 |
1368 | this.coords.p_handle = this.toFixed((this.coords.w_handle / this.coords.w_rs) * 100)
1369 | },
1370 |
1371 | /**
1372 | * Find closest handle to pointer click
1373 | *
1374 | * @param real_x {Number}
1375 | * @returns {String}
1376 | */
1377 | chooseHandle: function(real_x) {
1378 | if (this.options.type === 'single') {
1379 | return 'single'
1380 | } else {
1381 | var m_point =
1382 | this.coords.p_from_real + (this.coords.p_to_real - this.coords.p_from_real) / 2
1383 | if (real_x >= m_point) {
1384 | return this.options.to_fixed ? 'from' : 'to'
1385 | } else {
1386 | return this.options.from_fixed ? 'to' : 'from'
1387 | }
1388 | }
1389 | },
1390 |
1391 | /**
1392 | * Measure Min and Max labels width in percent
1393 | */
1394 | calcMinMax: function() {
1395 | if (!this.coords.w_rs) {
1396 | return
1397 | }
1398 |
1399 | this.labels.p_min = (this.labels.w_min / this.coords.w_rs) * 100
1400 | this.labels.p_max = (this.labels.w_max / this.coords.w_rs) * 100
1401 | },
1402 |
1403 | /**
1404 | * Measure labels width and X in percent
1405 | */
1406 | calcLabels: function() {
1407 | if (!this.coords.w_rs || this.options.hide_from_to) {
1408 | return
1409 | }
1410 |
1411 | if (this.options.type === 'single') {
1412 | this.labels.w_single = this.$cache.single.outerWidth(false)
1413 | this.labels.p_single_fake = (this.labels.w_single / this.coords.w_rs) * 100
1414 | this.labels.p_single_left =
1415 | this.coords.p_single_fake + this.coords.p_handle / 2 - this.labels.p_single_fake / 2
1416 | this.labels.p_single_left = this.checkEdges(
1417 | this.labels.p_single_left,
1418 | this.labels.p_single_fake
1419 | )
1420 | } else {
1421 | this.labels.w_from = this.$cache.from.outerWidth(false)
1422 | this.labels.p_from_fake = (this.labels.w_from / this.coords.w_rs) * 100
1423 | this.labels.p_from_left =
1424 | this.coords.p_from_fake + this.coords.p_handle / 2 - this.labels.p_from_fake / 2
1425 | this.labels.p_from_left = this.toFixed(this.labels.p_from_left)
1426 | this.labels.p_from_left = this.checkEdges(this.labels.p_from_left, this.labels.p_from_fake)
1427 |
1428 | this.labels.w_to = this.$cache.to.outerWidth(false)
1429 | this.labels.p_to_fake = (this.labels.w_to / this.coords.w_rs) * 100
1430 | this.labels.p_to_left =
1431 | this.coords.p_to_fake + this.coords.p_handle / 2 - this.labels.p_to_fake / 2
1432 | this.labels.p_to_left = this.toFixed(this.labels.p_to_left)
1433 | this.labels.p_to_left = this.checkEdges(this.labels.p_to_left, this.labels.p_to_fake)
1434 |
1435 | this.labels.w_single = this.$cache.single.outerWidth(false)
1436 | this.labels.p_single_fake = (this.labels.w_single / this.coords.w_rs) * 100
1437 | this.labels.p_single_left =
1438 | (this.labels.p_from_left + this.labels.p_to_left + this.labels.p_to_fake) / 2 -
1439 | this.labels.p_single_fake / 2
1440 | this.labels.p_single_left = this.toFixed(this.labels.p_single_left)
1441 | this.labels.p_single_left = this.checkEdges(
1442 | this.labels.p_single_left,
1443 | this.labels.p_single_fake
1444 | )
1445 | }
1446 | },
1447 |
1448 | // =============================================================================================================
1449 | // Drawings
1450 |
1451 | /**
1452 | * Main function called in request animation frame
1453 | * to update everything
1454 | */
1455 | updateScene: function() {
1456 | if (this.raf_id) {
1457 | cancelAnimationFrame(this.raf_id)
1458 | this.raf_id = null
1459 | }
1460 |
1461 | clearTimeout(this.update_tm)
1462 | this.update_tm = null
1463 |
1464 | if (!this.options) {
1465 | return
1466 | }
1467 |
1468 | this.drawHandles()
1469 |
1470 | if (this.is_active) {
1471 | this.raf_id = requestAnimationFrame(this.updateScene.bind(this))
1472 | } else {
1473 | this.update_tm = setTimeout(this.updateScene.bind(this), 300)
1474 | }
1475 | },
1476 |
1477 | /**
1478 | * Draw handles
1479 | */
1480 | drawHandles: function() {
1481 | this.coords.w_rs = this.$cache.rs.outerWidth(false)
1482 |
1483 | if (!this.coords.w_rs) {
1484 | return
1485 | }
1486 |
1487 | if (this.coords.w_rs !== this.coords.w_rs_old) {
1488 | this.target = 'base'
1489 | this.is_resize = true
1490 | }
1491 |
1492 | if (this.coords.w_rs !== this.coords.w_rs_old || this.force_redraw) {
1493 | this.setMinMax()
1494 | this.calc(true)
1495 | this.drawLabels()
1496 | if (this.options.grid) {
1497 | this.calcGridMargin()
1498 | this.calcGridLabels()
1499 | }
1500 | this.force_redraw = true
1501 | this.coords.w_rs_old = this.coords.w_rs
1502 | this.drawShadow()
1503 | }
1504 |
1505 | if (!this.coords.w_rs) {
1506 | return
1507 | }
1508 |
1509 | if (!this.dragging && !this.force_redraw && !this.is_key) {
1510 | return
1511 | }
1512 |
1513 | if (
1514 | this.old_from !== this.result.from ||
1515 | this.old_to !== this.result.to ||
1516 | this.force_redraw ||
1517 | this.is_key
1518 | ) {
1519 | this.drawLabels()
1520 |
1521 | this.$cache.bar[0].style.left = this.coords.p_bar_x + '%'
1522 | this.$cache.bar[0].style.width = this.coords.p_bar_w + '%'
1523 |
1524 | if (this.options.type === 'single') {
1525 | this.$cache.bar[0].style.left = 0
1526 | this.$cache.bar[0].style.width = this.coords.p_bar_w + this.coords.p_bar_x + '%'
1527 |
1528 | this.$cache.s_single[0].style.left = this.coords.p_single_fake + '%'
1529 |
1530 | this.$cache.single[0].style.left = this.labels.p_single_left + '%'
1531 | } else {
1532 | this.$cache.s_from[0].style.left = this.coords.p_from_fake + '%'
1533 | this.$cache.s_to[0].style.left = this.coords.p_to_fake + '%'
1534 |
1535 | if (this.old_from !== this.result.from || this.force_redraw) {
1536 | this.$cache.from[0].style.left = this.labels.p_from_left + '%'
1537 | }
1538 | if (this.old_to !== this.result.to || this.force_redraw) {
1539 | this.$cache.to[0].style.left = this.labels.p_to_left + '%'
1540 | }
1541 |
1542 | this.$cache.single[0].style.left = this.labels.p_single_left + '%'
1543 | }
1544 |
1545 | this.writeToInput()
1546 |
1547 | if (
1548 | (this.old_from !== this.result.from || this.old_to !== this.result.to) &&
1549 | !this.is_start
1550 | ) {
1551 | this.$cache.input.trigger('change')
1552 | this.$cache.input.trigger('input')
1553 | }
1554 |
1555 | this.old_from = this.result.from
1556 | this.old_to = this.result.to
1557 |
1558 | // callbacks call
1559 | if (!this.is_resize && !this.is_update && !this.is_start && !this.is_finish) {
1560 | this.callOnChange()
1561 | }
1562 | if (this.is_key || this.is_click) {
1563 | this.is_key = false
1564 | this.is_click = false
1565 | this.callOnFinish()
1566 | }
1567 |
1568 | this.is_update = false
1569 | this.is_resize = false
1570 | this.is_finish = false
1571 | }
1572 |
1573 | this.is_start = false
1574 | this.is_key = false
1575 | this.is_click = false
1576 | this.force_redraw = false
1577 | },
1578 |
1579 | /**
1580 | * Draw labels
1581 | * measure labels collisions
1582 | * collapse close labels
1583 | */
1584 | drawLabels: function() {
1585 | if (!this.options) {
1586 | return
1587 | }
1588 |
1589 | var values_num = this.options.values.length
1590 | var p_values = this.options.p_values
1591 | var text_single
1592 | var text_from
1593 | var text_to
1594 | var from_pretty
1595 | var to_pretty
1596 |
1597 | if (this.options.hide_from_to) {
1598 | return
1599 | }
1600 |
1601 | if (this.options.type === 'single') {
1602 | if (values_num) {
1603 | text_single = this.decorate(p_values[this.result.from])
1604 | this.$cache.single.html(text_single)
1605 | } else {
1606 | from_pretty = this._prettify(this.result.from)
1607 |
1608 | text_single = this.decorate(from_pretty, this.result.from)
1609 | this.$cache.single.html(text_single)
1610 | }
1611 |
1612 | this.calcLabels()
1613 |
1614 | if (this.labels.p_single_left < this.labels.p_min + 1) {
1615 | this.$cache.min[0].style.visibility = 'hidden'
1616 | } else {
1617 | this.$cache.min[0].style.visibility = 'visible'
1618 | }
1619 |
1620 | if (this.labels.p_single_left + this.labels.p_single_fake > 100 - this.labels.p_max - 1) {
1621 | this.$cache.max[0].style.visibility = 'hidden'
1622 | } else {
1623 | this.$cache.max[0].style.visibility = 'visible'
1624 | }
1625 | } else {
1626 | if (values_num) {
1627 | if (this.options.decorate_both) {
1628 | text_single = this.decorate(p_values[this.result.from])
1629 | text_single += this.options.values_separator
1630 | text_single += this.decorate(p_values[this.result.to])
1631 | } else {
1632 | text_single = this.decorate(
1633 | p_values[this.result.from] + this.options.values_separator + p_values[this.result.to]
1634 | )
1635 | }
1636 | text_from = this.decorate(p_values[this.result.from])
1637 | text_to = this.decorate(p_values[this.result.to])
1638 |
1639 | this.$cache.single.html(text_single)
1640 | this.$cache.from.html(text_from)
1641 | this.$cache.to.html(text_to)
1642 | } else {
1643 | from_pretty = this._prettify(this.result.from)
1644 | to_pretty = this._prettify(this.result.to)
1645 |
1646 | if (this.options.decorate_both) {
1647 | text_single = this.decorate(from_pretty, this.result.from)
1648 | text_single += this.options.values_separator
1649 | text_single += this.decorate(to_pretty, this.result.to)
1650 | } else {
1651 | text_single = this.decorate(
1652 | from_pretty + this.options.values_separator + to_pretty,
1653 | this.result.to
1654 | )
1655 | }
1656 | text_from = this.decorate(from_pretty, this.result.from)
1657 | text_to = this.decorate(to_pretty, this.result.to)
1658 |
1659 | this.$cache.single.html(text_single)
1660 | this.$cache.from.html(text_from)
1661 | this.$cache.to.html(text_to)
1662 | }
1663 |
1664 | this.calcLabels()
1665 |
1666 | var min = Math.min(this.labels.p_single_left, this.labels.p_from_left),
1667 | single_left = this.labels.p_single_left + this.labels.p_single_fake,
1668 | to_left = this.labels.p_to_left + this.labels.p_to_fake,
1669 | max = Math.max(single_left, to_left)
1670 |
1671 | if (this.labels.p_from_left + this.labels.p_from_fake >= this.labels.p_to_left) {
1672 | this.$cache.from[0].style.visibility = 'hidden'
1673 | this.$cache.to[0].style.visibility = 'hidden'
1674 | this.$cache.single[0].style.visibility = 'visible'
1675 |
1676 | if (this.result.from === this.result.to) {
1677 | if (this.target === 'from') {
1678 | this.$cache.from[0].style.visibility = 'visible'
1679 | } else if (this.target === 'to') {
1680 | this.$cache.to[0].style.visibility = 'visible'
1681 | } else if (!this.target) {
1682 | this.$cache.from[0].style.visibility = 'visible'
1683 | }
1684 | this.$cache.single[0].style.visibility = 'hidden'
1685 | max = to_left
1686 | } else {
1687 | this.$cache.from[0].style.visibility = 'hidden'
1688 | this.$cache.to[0].style.visibility = 'hidden'
1689 | this.$cache.single[0].style.visibility = 'visible'
1690 | max = Math.max(single_left, to_left)
1691 | }
1692 | } else {
1693 | this.$cache.from[0].style.visibility = 'visible'
1694 | this.$cache.to[0].style.visibility = 'visible'
1695 | this.$cache.single[0].style.visibility = 'hidden'
1696 | }
1697 |
1698 | if (min < this.labels.p_min + 1) {
1699 | this.$cache.min[0].style.visibility = 'hidden'
1700 | } else {
1701 | this.$cache.min[0].style.visibility = 'visible'
1702 | }
1703 |
1704 | if (max > 100 - this.labels.p_max - 1) {
1705 | this.$cache.max[0].style.visibility = 'hidden'
1706 | } else {
1707 | this.$cache.max[0].style.visibility = 'visible'
1708 | }
1709 | }
1710 | },
1711 |
1712 | /**
1713 | * Draw shadow intervals
1714 | */
1715 | drawShadow: function() {
1716 | var o = this.options,
1717 | c = this.$cache,
1718 | is_from_min = typeof o.from_min === 'number' && !isNaN(o.from_min),
1719 | is_from_max = typeof o.from_max === 'number' && !isNaN(o.from_max),
1720 | is_to_min = typeof o.to_min === 'number' && !isNaN(o.to_min),
1721 | is_to_max = typeof o.to_max === 'number' && !isNaN(o.to_max),
1722 | from_min,
1723 | from_max,
1724 | to_min,
1725 | to_max
1726 |
1727 | if (o.type === 'single') {
1728 | if (o.from_shadow && (is_from_min || is_from_max)) {
1729 | from_min = this.convertToPercent(is_from_min ? o.from_min : o.min)
1730 | from_max = this.convertToPercent(is_from_max ? o.from_max : o.max) - from_min
1731 | from_min = this.toFixed(from_min - (this.coords.p_handle / 100) * from_min)
1732 | from_max = this.toFixed(from_max - (this.coords.p_handle / 100) * from_max)
1733 | from_min = from_min + this.coords.p_handle / 2
1734 |
1735 | c.shad_single[0].style.display = 'block'
1736 | c.shad_single[0].style.left = from_min + '%'
1737 | c.shad_single[0].style.width = from_max + '%'
1738 | } else {
1739 | c.shad_single[0].style.display = 'none'
1740 | }
1741 | } else {
1742 | if (o.from_shadow && (is_from_min || is_from_max)) {
1743 | from_min = this.convertToPercent(is_from_min ? o.from_min : o.min)
1744 | from_max = this.convertToPercent(is_from_max ? o.from_max : o.max) - from_min
1745 | from_min = this.toFixed(from_min - (this.coords.p_handle / 100) * from_min)
1746 | from_max = this.toFixed(from_max - (this.coords.p_handle / 100) * from_max)
1747 | from_min = from_min + this.coords.p_handle / 2
1748 |
1749 | c.shad_from[0].style.display = 'block'
1750 | c.shad_from[0].style.left = from_min + '%'
1751 | c.shad_from[0].style.width = from_max + '%'
1752 | } else {
1753 | c.shad_from[0].style.display = 'none'
1754 | }
1755 |
1756 | if (o.to_shadow && (is_to_min || is_to_max)) {
1757 | to_min = this.convertToPercent(is_to_min ? o.to_min : o.min)
1758 | to_max = this.convertToPercent(is_to_max ? o.to_max : o.max) - to_min
1759 | to_min = this.toFixed(to_min - (this.coords.p_handle / 100) * to_min)
1760 | to_max = this.toFixed(to_max - (this.coords.p_handle / 100) * to_max)
1761 | to_min = to_min + this.coords.p_handle / 2
1762 |
1763 | c.shad_to[0].style.display = 'block'
1764 | c.shad_to[0].style.left = to_min + '%'
1765 | c.shad_to[0].style.width = to_max + '%'
1766 | } else {
1767 | c.shad_to[0].style.display = 'none'
1768 | }
1769 | }
1770 | },
1771 |
1772 | /**
1773 | * Write values to input element
1774 | */
1775 | writeToInput: function() {
1776 | if (this.options.type === 'single') {
1777 | if (this.options.values.length) {
1778 | this.$cache.input.prop('value', this.result.from_value)
1779 | } else {
1780 | this.$cache.input.prop('value', this.result.from)
1781 | }
1782 | this.$cache.input.data('from', this.result.from)
1783 | } else {
1784 | if (this.options.values.length) {
1785 | this.$cache.input.prop(
1786 | 'value',
1787 | this.result.from_value + this.options.input_values_separator + this.result.to_value
1788 | )
1789 | } else {
1790 | this.$cache.input.prop(
1791 | 'value',
1792 | this.result.from + this.options.input_values_separator + this.result.to
1793 | )
1794 | }
1795 | this.$cache.input.data('from', this.result.from)
1796 | this.$cache.input.data('to', this.result.to)
1797 | }
1798 | },
1799 |
1800 | // =============================================================================================================
1801 | // Callbacks
1802 |
1803 | callOnStart: function() {
1804 | this.writeToInput()
1805 |
1806 | if (this.options.onStart && typeof this.options.onStart === 'function') {
1807 | if (this.options.scope) {
1808 | this.options.onStart.call(this.options.scope, this.result)
1809 | } else {
1810 | this.options.onStart(this.result)
1811 | }
1812 | }
1813 | },
1814 | callOnChange: function() {
1815 | this.writeToInput()
1816 |
1817 | if (this.options.onChange && typeof this.options.onChange === 'function') {
1818 | if (this.options.scope) {
1819 | this.options.onChange.call(this.options.scope, this.result)
1820 | } else {
1821 | this.options.onChange(this.result)
1822 | }
1823 | }
1824 | },
1825 | callOnFinish: function() {
1826 | this.writeToInput()
1827 |
1828 | if (this.options.onFinish && typeof this.options.onFinish === 'function') {
1829 | if (this.options.scope) {
1830 | this.options.onFinish.call(this.options.scope, this.result)
1831 | } else {
1832 | this.options.onFinish(this.result)
1833 | }
1834 | }
1835 | },
1836 | callOnUpdate: function() {
1837 | this.writeToInput()
1838 |
1839 | if (this.options.onUpdate && typeof this.options.onUpdate === 'function') {
1840 | if (this.options.scope) {
1841 | this.options.onUpdate.call(this.options.scope, this.result)
1842 | } else {
1843 | this.options.onUpdate(this.result)
1844 | }
1845 | }
1846 | },
1847 |
1848 | // =============================================================================================================
1849 | // Service methods
1850 |
1851 | toggleInput: function() {
1852 | this.$cache.input.toggleClass('irs-hidden-input')
1853 |
1854 | if (this.has_tab_index) {
1855 | this.$cache.input.prop('tabindex', -1)
1856 | } else {
1857 | this.$cache.input.removeProp('tabindex')
1858 | }
1859 |
1860 | this.has_tab_index = !this.has_tab_index
1861 | },
1862 |
1863 | /**
1864 | * Convert real value to percent
1865 | *
1866 | * @param value {Number} X in real
1867 | * @param no_min {boolean=} don't use min value
1868 | * @returns {Number} X in percent
1869 | */
1870 | convertToPercent: function(value, no_min) {
1871 | var diapason = this.options.max - this.options.min,
1872 | one_percent = diapason / 100,
1873 | val,
1874 | percent
1875 |
1876 | if (!diapason) {
1877 | this.no_diapason = true
1878 | return 0
1879 | }
1880 |
1881 | if (no_min) {
1882 | val = value
1883 | } else {
1884 | val = value - this.options.min
1885 | }
1886 |
1887 | percent = val / one_percent
1888 |
1889 | return this.toFixed(percent)
1890 | },
1891 |
1892 | /**
1893 | * Convert percent to real values
1894 | *
1895 | * @param percent {Number} X in percent
1896 | * @returns {Number} X in real
1897 | */
1898 | convertToValue: function(percent) {
1899 | var min = this.options.min,
1900 | max = this.options.max,
1901 | min_decimals = min.toString().split('.')[1],
1902 | max_decimals = max.toString().split('.')[1],
1903 | min_length,
1904 | max_length,
1905 | avg_decimals = 0,
1906 | abs = 0
1907 |
1908 | if (percent === 0) {
1909 | return this.options.min
1910 | }
1911 | if (percent === 100) {
1912 | return this.options.max
1913 | }
1914 |
1915 | if (min_decimals) {
1916 | min_length = min_decimals.length
1917 | avg_decimals = min_length
1918 | }
1919 | if (max_decimals) {
1920 | max_length = max_decimals.length
1921 | avg_decimals = max_length
1922 | }
1923 | if (min_length && max_length) {
1924 | avg_decimals = min_length >= max_length ? min_length : max_length
1925 | }
1926 |
1927 | if (min < 0) {
1928 | abs = Math.abs(min)
1929 | min = +(min + abs).toFixed(avg_decimals)
1930 | max = +(max + abs).toFixed(avg_decimals)
1931 | }
1932 |
1933 | var number = ((max - min) / 100) * percent + min,
1934 | string = this.options.step.toString().split('.')[1],
1935 | result
1936 |
1937 | if (string) {
1938 | number = +number.toFixed(string.length)
1939 | } else {
1940 | number = number / this.options.step
1941 | number = number * this.options.step
1942 |
1943 | number = +number.toFixed(0)
1944 | }
1945 |
1946 | if (abs) {
1947 | number -= abs
1948 | }
1949 |
1950 | if (string) {
1951 | result = +number.toFixed(string.length)
1952 | } else {
1953 | result = this.toFixed(number)
1954 | }
1955 |
1956 | if (result < this.options.min) {
1957 | result = this.options.min
1958 | } else if (result > this.options.max) {
1959 | result = this.options.max
1960 | }
1961 |
1962 | return result
1963 | },
1964 |
1965 | /**
1966 | * Round percent value with step
1967 | *
1968 | * @param percent {Number}
1969 | * @returns percent {Number} rounded
1970 | */
1971 | calcWithStep: function(percent) {
1972 | var rounded = Math.round(percent / this.coords.p_step) * this.coords.p_step
1973 |
1974 | if (rounded > 100) {
1975 | rounded = 100
1976 | }
1977 | if (percent === 100) {
1978 | rounded = 100
1979 | }
1980 |
1981 | return this.toFixed(rounded)
1982 | },
1983 |
1984 | checkMinInterval: function(p_current, p_next, type) {
1985 | var o = this.options,
1986 | current,
1987 | next
1988 |
1989 | if (!o.min_interval) {
1990 | return p_current
1991 | }
1992 |
1993 | current = this.convertToValue(p_current)
1994 | next = this.convertToValue(p_next)
1995 |
1996 | if (type === 'from') {
1997 | if (next - current < o.min_interval) {
1998 | current = next - o.min_interval
1999 | }
2000 | } else {
2001 | if (current - next < o.min_interval) {
2002 | current = next + o.min_interval
2003 | }
2004 | }
2005 |
2006 | return this.convertToPercent(current)
2007 | },
2008 |
2009 | checkMaxInterval: function(p_current, p_next, type) {
2010 | var o = this.options,
2011 | current,
2012 | next
2013 |
2014 | if (!o.max_interval) {
2015 | return p_current
2016 | }
2017 |
2018 | current = this.convertToValue(p_current)
2019 | next = this.convertToValue(p_next)
2020 |
2021 | if (type === 'from') {
2022 | if (next - current > o.max_interval) {
2023 | current = next - o.max_interval
2024 | }
2025 | } else {
2026 | if (current - next > o.max_interval) {
2027 | current = next + o.max_interval
2028 | }
2029 | }
2030 |
2031 | return this.convertToPercent(current)
2032 | },
2033 |
2034 | checkDiapason: function(p_num, min, max) {
2035 | var num = this.convertToValue(p_num),
2036 | o = this.options
2037 |
2038 | if (typeof min !== 'number') {
2039 | min = o.min
2040 | }
2041 |
2042 | if (typeof max !== 'number') {
2043 | max = o.max
2044 | }
2045 |
2046 | if (num < min) {
2047 | num = min
2048 | }
2049 |
2050 | if (num > max) {
2051 | num = max
2052 | }
2053 |
2054 | return this.convertToPercent(num)
2055 | },
2056 |
2057 | toFixed: function(num) {
2058 | num = num.toFixed(20)
2059 | return +num
2060 | },
2061 |
2062 | _prettify: function(num) {
2063 | if (!this.options.prettify_enabled) {
2064 | return num
2065 | }
2066 |
2067 | if (this.options.prettify && typeof this.options.prettify === 'function') {
2068 | return this.options.prettify(num)
2069 | } else {
2070 | return this.prettify(num)
2071 | }
2072 | },
2073 |
2074 | prettify: function(num) {
2075 | var n = num.toString()
2076 | return n.replace(/(\d{1,3}(?=(?:\d\d\d)+(?!\d)))/g, '$1' + this.options.prettify_separator)
2077 | },
2078 |
2079 | checkEdges: function(left, width) {
2080 | if (!this.options.force_edges) {
2081 | return this.toFixed(left)
2082 | }
2083 |
2084 | if (left < 0) {
2085 | left = 0
2086 | } else if (left > 100 - width) {
2087 | left = 100 - width
2088 | }
2089 |
2090 | return this.toFixed(left)
2091 | },
2092 |
2093 | validate: function() {
2094 | var o = this.options,
2095 | r = this.result,
2096 | v = o.values,
2097 | vl = v.length,
2098 | value,
2099 | i
2100 |
2101 | if (typeof o.min === 'string') o.min = +o.min
2102 | if (typeof o.max === 'string') o.max = +o.max
2103 | if (typeof o.from === 'string') o.from = +o.from
2104 | if (typeof o.to === 'string') o.to = +o.to
2105 | if (typeof o.step === 'string') o.step = +o.step
2106 |
2107 | if (typeof o.from_min === 'string') o.from_min = +o.from_min
2108 | if (typeof o.from_max === 'string') o.from_max = +o.from_max
2109 | if (typeof o.to_min === 'string') o.to_min = +o.to_min
2110 | if (typeof o.to_max === 'string') o.to_max = +o.to_max
2111 |
2112 | if (typeof o.grid_num === 'string') o.grid_num = +o.grid_num
2113 |
2114 | if (o.max < o.min) {
2115 | o.max = o.min
2116 | }
2117 |
2118 | if (vl) {
2119 | o.p_values = []
2120 | o.min = 0
2121 | o.max = vl - 1
2122 | o.step = 1
2123 | o.grid_num = o.max
2124 | o.grid_snap = true
2125 |
2126 | for (i = 0; i < vl; i++) {
2127 | value = +v[i]
2128 |
2129 | if (!isNaN(value)) {
2130 | v[i] = value
2131 | value = this._prettify(value)
2132 | } else {
2133 | value = v[i]
2134 | }
2135 |
2136 | o.p_values.push(value)
2137 | }
2138 | }
2139 |
2140 | if (typeof o.from !== 'number' || isNaN(o.from)) {
2141 | o.from = o.min
2142 | }
2143 |
2144 | if (typeof o.to !== 'number' || isNaN(o.to)) {
2145 | o.to = o.max
2146 | }
2147 |
2148 | if (o.type === 'single') {
2149 | if (o.from < o.min) o.from = o.min
2150 | if (o.from > o.max) o.from = o.max
2151 | } else {
2152 | if (o.from < o.min) o.from = o.min
2153 | if (o.from > o.max) o.from = o.max
2154 |
2155 | if (o.to < o.min) o.to = o.min
2156 | if (o.to > o.max) o.to = o.max
2157 |
2158 | if (this.update_check.from) {
2159 | if (this.update_check.from !== o.from) {
2160 | if (o.from > o.to) o.from = o.to
2161 | }
2162 | if (this.update_check.to !== o.to) {
2163 | if (o.to < o.from) o.to = o.from
2164 | }
2165 | }
2166 |
2167 | if (o.from > o.to) o.from = o.to
2168 | if (o.to < o.from) o.to = o.from
2169 | }
2170 |
2171 | if (typeof o.step !== 'number' || isNaN(o.step) || !o.step || o.step < 0) {
2172 | o.step = 1
2173 | }
2174 |
2175 | if (typeof o.from_min === 'number' && o.from < o.from_min) {
2176 | o.from = o.from_min
2177 | }
2178 |
2179 | if (typeof o.from_max === 'number' && o.from > o.from_max) {
2180 | o.from = o.from_max
2181 | }
2182 |
2183 | if (typeof o.to_min === 'number' && o.to < o.to_min) {
2184 | o.to = o.to_min
2185 | }
2186 |
2187 | if (typeof o.to_max === 'number' && o.from > o.to_max) {
2188 | o.to = o.to_max
2189 | }
2190 |
2191 | if (r) {
2192 | if (r.min !== o.min) {
2193 | r.min = o.min
2194 | }
2195 |
2196 | if (r.max !== o.max) {
2197 | r.max = o.max
2198 | }
2199 |
2200 | if (r.from < r.min || r.from > r.max) {
2201 | r.from = o.from
2202 | }
2203 |
2204 | if (r.to < r.min || r.to > r.max) {
2205 | r.to = o.to
2206 | }
2207 | }
2208 |
2209 | if (
2210 | typeof o.min_interval !== 'number' ||
2211 | isNaN(o.min_interval) ||
2212 | !o.min_interval ||
2213 | o.min_interval < 0
2214 | ) {
2215 | o.min_interval = 0
2216 | }
2217 |
2218 | if (
2219 | typeof o.max_interval !== 'number' ||
2220 | isNaN(o.max_interval) ||
2221 | !o.max_interval ||
2222 | o.max_interval < 0
2223 | ) {
2224 | o.max_interval = 0
2225 | }
2226 |
2227 | if (o.min_interval && o.min_interval > o.max - o.min) {
2228 | o.min_interval = o.max - o.min
2229 | }
2230 |
2231 | if (o.max_interval && o.max_interval > o.max - o.min) {
2232 | o.max_interval = o.max - o.min
2233 | }
2234 | },
2235 |
2236 | decorate: function(num, original) {
2237 | var decorated = '',
2238 | o = this.options
2239 |
2240 | if (o.prefix) {
2241 | decorated += o.prefix
2242 | }
2243 |
2244 | decorated += num
2245 |
2246 | if (o.max_postfix) {
2247 | if (o.values.length && num === o.p_values[o.max]) {
2248 | decorated += o.max_postfix
2249 | if (o.postfix) {
2250 | decorated += ' '
2251 | }
2252 | } else if (original === o.max) {
2253 | decorated += o.max_postfix
2254 | if (o.postfix) {
2255 | decorated += ' '
2256 | }
2257 | }
2258 | }
2259 |
2260 | if (o.postfix) {
2261 | decorated += o.postfix
2262 | }
2263 |
2264 | return decorated
2265 | },
2266 |
2267 | updateFrom: function() {
2268 | this.result.from = this.options.from
2269 | this.result.from_percent = this.convertToPercent(this.result.from)
2270 | this.result.from_pretty = this._prettify(this.result.from)
2271 | if (this.options.values) {
2272 | this.result.from_value = this.options.values[this.result.from]
2273 | }
2274 | },
2275 |
2276 | updateTo: function() {
2277 | this.result.to = this.options.to
2278 | this.result.to_percent = this.convertToPercent(this.result.to)
2279 | this.result.to_pretty = this._prettify(this.result.to)
2280 | if (this.options.values) {
2281 | this.result.to_value = this.options.values[this.result.to]
2282 | }
2283 | },
2284 |
2285 | updateResult: function() {
2286 | this.result.min = this.options.min
2287 | this.result.max = this.options.max
2288 | this.updateFrom()
2289 | this.updateTo()
2290 | },
2291 |
2292 | // =============================================================================================================
2293 | // Grid
2294 |
2295 | appendGrid: function() {
2296 | if (!this.options.grid) {
2297 | return
2298 | }
2299 |
2300 | var o = this.options,
2301 | i,
2302 | z,
2303 | total = o.max - o.min,
2304 | big_num = o.grid_num,
2305 | big_p = 0,
2306 | big_w = 0,
2307 | small_max = 4,
2308 | local_small_max,
2309 | small_p,
2310 | small_w = 0,
2311 | result,
2312 | html = ''
2313 |
2314 | this.calcGridMargin()
2315 |
2316 | if (o.grid_snap) {
2317 | big_num = total / o.step
2318 | }
2319 |
2320 | if (big_num > 50) big_num = 50
2321 | big_p = this.toFixed(100 / big_num)
2322 |
2323 | if (big_num > 4) {
2324 | small_max = 3
2325 | }
2326 | if (big_num > 7) {
2327 | small_max = 2
2328 | }
2329 | if (big_num > 14) {
2330 | small_max = 1
2331 | }
2332 | if (big_num > 28) {
2333 | small_max = 0
2334 | }
2335 |
2336 | for (i = 0; i < big_num + 1; i++) {
2337 | local_small_max = small_max
2338 |
2339 | big_w = this.toFixed(big_p * i)
2340 |
2341 | if (big_w > 100) {
2342 | big_w = 100
2343 | }
2344 | this.coords.big[i] = big_w
2345 |
2346 | small_p = (big_w - big_p * (i - 1)) / (local_small_max + 1)
2347 |
2348 | for (z = 1; z <= local_small_max; z++) {
2349 | if (big_w === 0) {
2350 | break
2351 | }
2352 |
2353 | small_w = this.toFixed(big_w - small_p * z)
2354 |
2355 | html += ' '
2356 | }
2357 |
2358 | html += ' '
2359 |
2360 | result = this.convertToValue(big_w)
2361 | if (o.values.length) {
2362 | result = o.p_values[result]
2363 | } else {
2364 | result = this._prettify(result)
2365 | }
2366 |
2367 | html +=
2368 | '' +
2373 | result +
2374 | ' '
2375 | }
2376 | this.coords.big_num = Math.ceil(big_num + 1)
2377 |
2378 | this.$cache.cont.addClass('irs-with-grid')
2379 | this.$cache.grid.html(html)
2380 | this.cacheGridLabels()
2381 | },
2382 |
2383 | cacheGridLabels: function() {
2384 | var $label,
2385 | i,
2386 | num = this.coords.big_num
2387 |
2388 | for (i = 0; i < num; i++) {
2389 | $label = this.$cache.grid.find('.js-grid-text-' + i)
2390 | this.$cache.grid_labels.push($label)
2391 | }
2392 |
2393 | this.calcGridLabels()
2394 | },
2395 |
2396 | calcGridLabels: function() {
2397 | var i,
2398 | label,
2399 | start = [],
2400 | finish = [],
2401 | num = this.coords.big_num
2402 |
2403 | for (i = 0; i < num; i++) {
2404 | this.coords.big_w[i] = this.$cache.grid_labels[i].outerWidth(false)
2405 | this.coords.big_p[i] = this.toFixed((this.coords.big_w[i] / this.coords.w_rs) * 100)
2406 | this.coords.big_x[i] = this.toFixed(this.coords.big_p[i] / 2)
2407 |
2408 | start[i] = this.toFixed(this.coords.big[i] - this.coords.big_x[i])
2409 | finish[i] = this.toFixed(start[i] + this.coords.big_p[i])
2410 | }
2411 |
2412 | if (this.options.force_edges) {
2413 | if (start[0] < -this.coords.grid_gap) {
2414 | start[0] = -this.coords.grid_gap
2415 | finish[0] = this.toFixed(start[0] + this.coords.big_p[0])
2416 |
2417 | this.coords.big_x[0] = this.coords.grid_gap
2418 | }
2419 |
2420 | if (finish[num - 1] > 100 + this.coords.grid_gap) {
2421 | finish[num - 1] = 100 + this.coords.grid_gap
2422 | start[num - 1] = this.toFixed(finish[num - 1] - this.coords.big_p[num - 1])
2423 |
2424 | this.coords.big_x[num - 1] = this.toFixed(
2425 | this.coords.big_p[num - 1] - this.coords.grid_gap
2426 | )
2427 | }
2428 | }
2429 |
2430 | this.calcGridCollision(2, start, finish)
2431 | this.calcGridCollision(4, start, finish)
2432 |
2433 | for (i = 0; i < num; i++) {
2434 | label = this.$cache.grid_labels[i][0]
2435 |
2436 | if (this.coords.big_x[i] !== Number.POSITIVE_INFINITY) {
2437 | label.style.marginLeft = -this.coords.big_x[i] + '%'
2438 | }
2439 | }
2440 | },
2441 |
2442 | // Collisions Calc Beta
2443 | // TODO: Refactor then have plenty of time
2444 | calcGridCollision: function(step, start, finish) {
2445 | var i,
2446 | next_i,
2447 | label,
2448 | num = this.coords.big_num
2449 |
2450 | for (i = 0; i < num; i += step) {
2451 | next_i = i + step / 2
2452 | if (next_i >= num) {
2453 | break
2454 | }
2455 |
2456 | label = this.$cache.grid_labels[next_i][0]
2457 |
2458 | if (finish[i] <= start[next_i]) {
2459 | label.style.visibility = 'visible'
2460 | } else {
2461 | label.style.visibility = 'hidden'
2462 | }
2463 | }
2464 | },
2465 |
2466 | calcGridMargin: function() {
2467 | if (!this.options.grid_margin) {
2468 | return
2469 | }
2470 |
2471 | this.coords.w_rs = this.$cache.rs.outerWidth(false)
2472 | if (!this.coords.w_rs) {
2473 | return
2474 | }
2475 |
2476 | if (this.options.type === 'single') {
2477 | this.coords.w_handle = this.$cache.s_single.outerWidth(false)
2478 | } else {
2479 | this.coords.w_handle = this.$cache.s_from.outerWidth(false)
2480 | }
2481 | this.coords.p_handle = this.toFixed((this.coords.w_handle / this.coords.w_rs) * 100)
2482 | this.coords.grid_gap = this.toFixed(this.coords.p_handle / 2 - 0.1)
2483 |
2484 | this.$cache.grid[0].style.width = this.toFixed(100 - this.coords.p_handle) + '%'
2485 | this.$cache.grid[0].style.left = this.coords.grid_gap + '%'
2486 | },
2487 |
2488 | // =============================================================================================================
2489 | // Public methods
2490 |
2491 | update: function(options) {
2492 | if (!this.input) {
2493 | return
2494 | }
2495 |
2496 | this.is_update = true
2497 |
2498 | this.options.from = this.result.from
2499 | this.options.to = this.result.to
2500 | this.update_check.from = this.result.from
2501 | this.update_check.to = this.result.to
2502 |
2503 | this.options = $.extend(this.options, options)
2504 | this.validate()
2505 | this.updateResult(options)
2506 |
2507 | this.toggleInput()
2508 | this.remove()
2509 | this.init(true)
2510 | },
2511 |
2512 | reset: function() {
2513 | if (!this.input) {
2514 | return
2515 | }
2516 |
2517 | this.updateResult()
2518 | this.update()
2519 | },
2520 |
2521 | destroy: function() {
2522 | if (!this.input) {
2523 | return
2524 | }
2525 |
2526 | this.toggleInput()
2527 | this.$cache.input.prop('readonly', false)
2528 | $.data(this.input, 'ionRangeSlider', null)
2529 |
2530 | this.remove()
2531 | this.input = null
2532 | this.options = null
2533 | }
2534 | }
2535 |
2536 | $.fn.ionRangeSlider = function(options) {
2537 | return this.each(function() {
2538 | if (!$.data(this, 'ionRangeSlider')) {
2539 | $.data(this, 'ionRangeSlider', new IonRangeSlider(this, options, plugin_count++))
2540 | }
2541 | })
2542 | }
2543 |
2544 | // =================================================================================================================
2545 | // http://paulirish.com/2011/requestanimationframe-for-smart-animating/
2546 | // http://my.opera.com/emoller/blog/2011/12/20/requestanimationframe-for-smart-er-animating
2547 |
2548 | // requestAnimationFrame polyfill by Erik Möller. fixes from Paul Irish and Tino Zijdel
2549 |
2550 | // MIT license
2551 |
2552 | ;(function() {
2553 | var lastTime = 0
2554 | var vendors = ['ms', 'moz', 'webkit', 'o']
2555 | for (var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {
2556 | window.requestAnimationFrame = window[vendors[x] + 'RequestAnimationFrame']
2557 | window.cancelAnimationFrame =
2558 | window[vendors[x] + 'CancelAnimationFrame'] ||
2559 | window[vendors[x] + 'CancelRequestAnimationFrame']
2560 | }
2561 |
2562 | if (!window.requestAnimationFrame)
2563 | window.requestAnimationFrame = function(callback, element) {
2564 | var currTime = new Date().getTime()
2565 | var timeToCall = Math.max(0, 16 - (currTime - lastTime))
2566 | var id = window.setTimeout(function() {
2567 | callback(currTime + timeToCall)
2568 | }, timeToCall)
2569 | lastTime = currTime + timeToCall
2570 | return id
2571 | }
2572 |
2573 | if (!window.cancelAnimationFrame)
2574 | window.cancelAnimationFrame = function(id) {
2575 | clearTimeout(id)
2576 | }
2577 | })()
2578 | })
2579 |
--------------------------------------------------------------------------------
/src/main.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import App from './App.vue'
3 |
4 | Vue.config.productionTip = false
5 |
6 | new Vue({
7 | render: h => h(App)
8 | }).$mount('#app')
9 |
--------------------------------------------------------------------------------
/vue.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | devServer: {
3 | port: 8000
4 | }
5 | }
6 |
--------------------------------------------------------------------------------