├── app
├── .gitkeep
└── components
│ └── range-slider.js
├── addon
├── .gitkeep
├── templates
│ └── components
│ │ └── range-slider.hbs
└── components
│ └── range-slider.js
├── vendor
├── .gitkeep
├── shims
│ └── nouislider.js
├── prism.css
└── prism.js
├── tests
├── helpers
│ └── .gitkeep
├── integration
│ ├── .gitkeep
│ └── components
│ │ └── range-slider-test.js
├── dummy
│ ├── app
│ │ ├── helpers
│ │ │ └── .gitkeep
│ │ ├── models
│ │ │ └── .gitkeep
│ │ ├── routes
│ │ │ ├── .gitkeep
│ │ │ ├── index.js
│ │ │ ├── events.js
│ │ │ └── options.js
│ │ ├── components
│ │ │ ├── .gitkeep
│ │ │ └── source-code.js
│ │ ├── controllers
│ │ │ ├── .gitkeep
│ │ │ ├── events.js
│ │ │ └── options.js
│ │ ├── templates
│ │ │ ├── components
│ │ │ │ ├── .gitkeep
│ │ │ │ ├── source-code.hbs
│ │ │ │ └── navigation.hbs
│ │ │ ├── application.hbs
│ │ │ ├── index.hbs
│ │ │ ├── download.hbs
│ │ │ ├── component.hbs
│ │ │ ├── events.hbs
│ │ │ └── options.hbs
│ │ ├── resolver.js
│ │ ├── styles
│ │ │ ├── app.scss
│ │ │ └── _base.scss
│ │ ├── router.js
│ │ ├── app.js
│ │ └── index.html
│ ├── config
│ │ ├── optional-features.json
│ │ ├── targets.js
│ │ └── environment.js
│ └── public
│ │ └── robots.txt
├── test-helper.js
├── .jshintrc
└── index.html
├── .watchmanconfig
├── .prettierrc.js
├── config
├── environment.js
└── ember-try.js
├── .template-lintrc.js
├── .ember-cli
├── .eslintignore
├── .editorconfig
├── .gitignore
├── .npmignore
├── rebuild-demo.sh
├── testem.js
├── ember-cli-build.js
├── CONTRIBUTING.md
├── LICENSE.md
├── .eslintrc.js
├── index.js
├── .travis.yml
├── package.json
├── README.md
└── CHANGELOG.md
/app/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/addon/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/vendor/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/tests/helpers/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/tests/integration/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/tests/dummy/app/helpers/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/tests/dummy/app/models/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/tests/dummy/app/routes/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/tests/dummy/app/components/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/tests/dummy/app/controllers/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/tests/dummy/app/templates/components/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/addon/templates/components/range-slider.hbs:
--------------------------------------------------------------------------------
1 | {{yield}}
2 |
--------------------------------------------------------------------------------
/tests/dummy/app/templates/application.hbs:
--------------------------------------------------------------------------------
1 | {{outlet}}
2 |
--------------------------------------------------------------------------------
/.watchmanconfig:
--------------------------------------------------------------------------------
1 | {
2 | "ignore_dirs": ["tmp", "dist"]
3 | }
4 |
--------------------------------------------------------------------------------
/tests/dummy/config/optional-features.json:
--------------------------------------------------------------------------------
1 | {
2 | "jquery-integration": false
3 | }
4 |
--------------------------------------------------------------------------------
/tests/dummy/public/robots.txt:
--------------------------------------------------------------------------------
1 | # http://www.robotstxt.org
2 | User-agent: *
3 | Disallow:
4 |
--------------------------------------------------------------------------------
/.prettierrc.js:
--------------------------------------------------------------------------------
1 | /* eslint-env node */
2 | module.exports = {
3 | singleQuote: true
4 | };
5 |
--------------------------------------------------------------------------------
/tests/dummy/app/templates/components/source-code.hbs:
--------------------------------------------------------------------------------
1 | {{yield}}
2 |
--------------------------------------------------------------------------------
/app/components/range-slider.js:
--------------------------------------------------------------------------------
1 | export { default } from 'ember-cli-nouislider/components/range-slider';
2 |
--------------------------------------------------------------------------------
/tests/dummy/app/resolver.js:
--------------------------------------------------------------------------------
1 | import Resolver from 'ember-resolver';
2 |
3 | export default Resolver;
4 |
--------------------------------------------------------------------------------
/config/environment.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | module.exports = function(/* environment, appConfig */) {
4 | return { };
5 | };
6 |
--------------------------------------------------------------------------------
/.template-lintrc.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | module.exports = {
4 | extends: 'recommended',
5 |
6 | rules: {
7 | 'no-inline-styles': false
8 | }
9 | };
10 |
--------------------------------------------------------------------------------
/vendor/shims/nouislider.js:
--------------------------------------------------------------------------------
1 | (function() {
2 | function vendorModule() {
3 | 'use strict';
4 |
5 | return { 'default': self['noUiSlider'] };
6 | }
7 |
8 | define('noUiSlider', [], vendorModule);
9 | })();
10 |
--------------------------------------------------------------------------------
/tests/dummy/app/styles/app.scss:
--------------------------------------------------------------------------------
1 | // Import the base styles
2 | @import "base";
3 |
4 | // Now we can tweak them where needed
5 | .hi {
6 | h2 {
7 | @media (min-width: 800px) {
8 | margin-top: 5px;
9 | }
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/tests/test-helper.js:
--------------------------------------------------------------------------------
1 | import Application from '../app';
2 | import config from '../config/environment';
3 | import { setApplication } from '@ember/test-helpers';
4 | import { start } from 'ember-qunit';
5 |
6 | setApplication(Application.create(config.APP));
7 |
8 | start();
9 |
--------------------------------------------------------------------------------
/.ember-cli:
--------------------------------------------------------------------------------
1 | {
2 | /**
3 | Ember CLI sends analytics information by default. The data is completely
4 | anonymous, but there are times when you might want to disable this behavior.
5 |
6 | Setting `disableAnalytics` to true will prevent any data from being sent.
7 | */
8 | "disableAnalytics": false
9 | }
10 |
--------------------------------------------------------------------------------
/.eslintignore:
--------------------------------------------------------------------------------
1 | # unconventional js
2 | /blueprints/*/files/
3 | /vendor/
4 |
5 | # compiled output
6 | /dist/
7 | /tmp/
8 |
9 | # dependencies
10 | /bower_components/
11 | /node_modules/
12 |
13 | # misc
14 | /coverage/
15 | !.*
16 |
17 | # ember-try
18 | /.node_modules.ember-try/
19 | /bower.json.ember-try
20 | /package.json.ember-try
21 |
--------------------------------------------------------------------------------
/tests/dummy/config/targets.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const browsers = [
4 | 'last 1 Chrome versions',
5 | 'last 1 Firefox versions',
6 | 'last 1 Safari versions'
7 | ];
8 |
9 | const isCI = !!process.env.CI;
10 | const isProduction = process.env.EMBER_ENV === 'production';
11 |
12 | if (isCI || isProduction) {
13 | browsers.push('ie 11');
14 | }
15 |
16 | module.exports = {
17 | browsers
18 | };
19 |
--------------------------------------------------------------------------------
/tests/dummy/app/router.js:
--------------------------------------------------------------------------------
1 | import EmberRouter from '@ember/routing/router';
2 | import config from './config/environment';
3 |
4 | const Router = EmberRouter.extend({
5 | location: config.locationType,
6 | rootURL: config.rootURL
7 | });
8 |
9 | Router.map(function() {
10 | this.route('download');
11 | this.route('component');
12 | this.route('options');
13 | this.route('events');
14 | });
15 |
16 | export default Router;
17 |
--------------------------------------------------------------------------------
/tests/dummy/app/routes/index.js:
--------------------------------------------------------------------------------
1 | import { debug } from '@ember/debug';
2 | import Route from '@ember/routing/route';
3 |
4 | export default Route.extend({
5 | model: function() {
6 | return {
7 | value: [20, 80]
8 | };
9 | },
10 |
11 | actions: {
12 | sliderChanged: function(value) {
13 | this.set("model.value", value);
14 | debug("Slider value changed to %@".fmt(value));
15 | }
16 | }
17 | });
18 |
--------------------------------------------------------------------------------
/tests/dummy/app/app.js:
--------------------------------------------------------------------------------
1 | import Application from '@ember/application';
2 | import Resolver from './resolver';
3 | import loadInitializers from 'ember-load-initializers';
4 | import config from './config/environment';
5 |
6 | const App = Application.extend({
7 | modulePrefix: config.modulePrefix,
8 | podModulePrefix: config.podModulePrefix,
9 | Resolver
10 | });
11 |
12 | loadInitializers(App, config.modulePrefix);
13 |
14 | export default App;
15 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | # EditorConfig helps developers define and maintain consistent
2 | # coding styles between different editors and IDEs
3 | # editorconfig.org
4 |
5 | root = true
6 |
7 |
8 | [*]
9 | end_of_line = lf
10 | charset = utf-8
11 | trim_trailing_whitespace = true
12 | insert_final_newline = true
13 | indent_style = space
14 | indent_size = 2
15 |
16 | [*.hbs]
17 | insert_final_newline = false
18 |
19 | [*.{diff,md}]
20 | trim_trailing_whitespace = false
21 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/ignore-files/ for more about ignoring files.
2 |
3 | # compiled output
4 | /dist/
5 | /tmp/
6 |
7 | # dependencies
8 | /bower_components/
9 | /node_modules/
10 |
11 | # misc
12 | /.env*
13 | /.pnp*
14 | /.sass-cache
15 | /connect.lock
16 | /coverage/
17 | /libpeerconnection.log
18 | /npm-debug.log*
19 | /testem.log
20 | /yarn-error.log
21 |
22 | # ember-try
23 | /.node_modules.ember-try/
24 | /bower.json.ember-try
25 | /package.json.ember-try
26 |
--------------------------------------------------------------------------------
/tests/dummy/app/components/source-code.js:
--------------------------------------------------------------------------------
1 | import { computed } from '@ember/object';
2 | import Component from '@ember/component';
3 | /* global Prism */
4 |
5 | export default Component.extend({
6 | tagName: "pre",
7 | language: undefined,
8 | codeClass: computed(function() {
9 | let lang = this.get("language");
10 | return "language-" + lang;
11 | }),
12 |
13 | didInsertElement() {
14 | var code = this.element.children[0];
15 | Prism.highlightElement(code);
16 | }
17 | });
18 |
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | # compiled output
2 | /dist/
3 | /tmp/
4 |
5 | # dependencies
6 | /bower_components/
7 |
8 | # misc
9 | /.bowerrc
10 | /.editorconfig
11 | /.ember-cli
12 | /.env*
13 | /.eslintignore
14 | /.eslintrc.js
15 | /.gitignore
16 | /.template-lintrc.js
17 | /.travis.yml
18 | /.watchmanconfig
19 | /bower.json
20 | /config/ember-try.js
21 | /CONTRIBUTING.md
22 | /ember-cli-build.js
23 | /testem.js
24 | /tests/
25 | /yarn.lock
26 | .gitkeep
27 |
28 | # ember-try
29 | /.node_modules.ember-try/
30 | /bower.json.ember-try
31 | /package.json.ember-try
32 |
--------------------------------------------------------------------------------
/tests/integration/components/range-slider-test.js:
--------------------------------------------------------------------------------
1 | import { module, test } from 'qunit';
2 | import { setupRenderingTest } from 'ember-qunit';
3 | import { render } from '@ember/test-helpers';
4 | import { hbs } from 'ember-cli-htmlbars';
5 |
6 | module('Integration | Component | range-slider', function(hooks) {
7 | setupRenderingTest(hooks);
8 |
9 | test('it renders', async function(assert) {
10 | assert.expect(1);
11 |
12 | await render(hbs`{{range-slider start=20}}`);
13 |
14 | assert.dom('.noUi-base', this.element).exists();
15 | });
16 | });
17 |
--------------------------------------------------------------------------------
/tests/dummy/app/templates/components/navigation.hbs:
--------------------------------------------------------------------------------
1 |
2 | {{#link-to "index" class="bar-link project"}}ember-cli-nouislider{{/link-to}}
3 | {{#link-to "component" class="bar-link"}}Base Component{{/link-to}}
4 | {{#link-to "options" class="bar-link"}}Options{{/link-to}}
5 | {{#link-to "events" class="bar-link"}}Events{{/link-to}}
6 |
Powered by noUiSlider
7 | {{#link-to "download" class="bar-link download"}}Download{{/link-to}}
8 |
9 |
--------------------------------------------------------------------------------
/tests/dummy/app/templates/index.hbs:
--------------------------------------------------------------------------------
1 |
2 |
<range-slider>
3 |
noUiSlider Range Slider Component for Ember.js
4 |
5 |
6 | {{range-slider start=model.value min=0 max=100 connect=true}}
7 |
8 | {{!-- template-lint-disable --}}
9 | {{#source-code language="handlebars"}}
10 | \{{range-slider start=model.value
11 | min=0
12 | max=100
13 | connect=true
14 | on-change="sliderChanged"
15 | }}
16 | {{/source-code}}
17 |
18 | {{#link-to "download" class="hi-dl"}}Download ember-cli-nouislider{{/link-to}}
19 |
20 |
21 |
22 |
4 |
Create your component
5 |
6 |
7 |
8 | Ensure you've already {{#link-to "download"}}downloaded & installed{{/link-to}}
9 | the addon
10 |
11 |
12 |
13 |
14 |
§
15 |
Render
16 |
17 |
18 |
Render your range-slider where you need it
19 |
20 |
21 | {{!-- template-lint-disable --}}
22 | {{#source-code language="handlebars"}}
23 | \{{! some template }}
24 | \{{range-slider start=someValue on-change="changedAction"}}
25 | {{/source-code}}
26 |
27 |
28 |
29 |
§
30 |
Action
31 |
32 |
33 |
34 | Setup an action handler in your route to catch
35 | any changes to the slider values.
36 |
37 |
38 |
39 | {{!-- template-lint-disable --}}
40 | {{#source-code language="javascript"}}
41 | // app/routes/my-route.js
42 | import Ember from 'ember';
43 |
44 | export default Ember.Route.extend({
45 | // ...
46 | actions: {
47 | // ...
48 | changedAction: function(value) {
49 | Ember.debug( "New slider value: %@".fmt( value ) );
50 | }
51 | }
52 | });
53 | {{/source-code}}
54 |
55 |
56 |
57 |
Next
58 |
59 |
60 |
Review the {{#link-to "options"}}available options{{/link-to}}...
61 |
62 |
63 |
64 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "ember-cli-nouislider",
3 | "version": "1.2.1",
4 | "description": "Ember range-slider component powered by nouislider",
5 | "author": "Kenneth Kalmer",
6 | "directories": {
7 | "doc": "doc",
8 | "test": "tests"
9 | },
10 | "scripts": {
11 | "build": "ember build",
12 | "lint:hbs": "ember-template-lint .",
13 | "lint:js": "eslint .",
14 | "start": "ember serve",
15 | "test": "ember test",
16 | "test:all": "ember try:each"
17 | },
18 | "dependencies": {
19 | "broccoli-funnel": "^3.0.2",
20 | "broccoli-merge-trees": "^4.0.1",
21 | "ember-cli-babel": "^7.7.3",
22 | "ember-cli-htmlbars": "^4.2.3",
23 | "nouislider": "^14.1.1"
24 | },
25 | "devDependencies": {
26 | "@ember/optional-features": "^0.7.0",
27 | "broccoli-asset-rev": "^3.0.0",
28 | "ember-cli": "~3.12.0",
29 | "ember-cli-dependency-checker": "^3.1.0",
30 | "ember-cli-eslint": "^5.1.0",
31 | "ember-cli-inject-live-reload": "^1.8.2",
32 | "ember-cli-sass": "^10.0.0",
33 | "ember-cli-sri": "^2.1.1",
34 | "ember-cli-template-lint": "^1.0.0-beta.1",
35 | "ember-cli-uglify": "^3.0.0",
36 | "ember-disable-prototype-extensions": "^1.1.3",
37 | "ember-export-application-global": "^2.0.0",
38 | "ember-load-initializers": "^2.0.0",
39 | "ember-maybe-import-regenerator": "^0.1.6",
40 | "ember-qunit": "^4.4.1",
41 | "ember-resolver": "^5.0.1",
42 | "ember-source": "~3.12.0",
43 | "ember-source-channel-url": "^1.1.0",
44 | "ember-try": "^1.0.0",
45 | "eslint-plugin-ember": "^6.2.0",
46 | "eslint-plugin-node": "^9.0.1",
47 | "loader.js": "^4.7.0",
48 | "qunit-dom": "^0.8.4",
49 | "sass": "^1.26.1"
50 | },
51 | "keywords": [
52 | "ember-addon",
53 | "nouislider",
54 | "slider",
55 | "range slider",
56 | "jquery range slider",
57 | "ember-component"
58 | ],
59 | "repository": "https://github.com/kennethkalmer/ember-cli-nouislider",
60 | "license": "MIT",
61 | "engines": {
62 | "node": "10.* || >= 12"
63 | },
64 | "ember-addon": {
65 | "configPath": "tests/dummy/config",
66 | "demoURL": "http://kennethkalmer.github.com/ember-cli-nouislider"
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/config/ember-try.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const getChannelURL = require('ember-source-channel-url');
4 |
5 | module.exports = async function() {
6 | return {
7 | useYarn: true,
8 | scenarios: [
9 | {
10 | name: 'ember-lts-3.12',
11 | npm: {
12 | devDependencies: {
13 | 'ember-source': '~3.12.0'
14 | }
15 | }
16 | },
17 | {
18 | name: 'ember-lts-3.16',
19 | npm: {
20 | devDependencies: {
21 | 'ember-source': '~3.16.0'
22 | }
23 | }
24 | },
25 | {
26 | name: 'ember-release',
27 | npm: {
28 | devDependencies: {
29 | 'ember-source': await getChannelURL('release')
30 | }
31 | }
32 | },
33 | {
34 | name: 'ember-beta',
35 | npm: {
36 | devDependencies: {
37 | 'ember-source': await getChannelURL('beta')
38 | }
39 | }
40 | },
41 | {
42 | name: 'ember-canary',
43 | npm: {
44 | devDependencies: {
45 | 'ember-source': await getChannelURL('canary')
46 | }
47 | }
48 | },
49 | // The default `.travis.yml` runs this scenario via `npm test`,
50 | // not via `ember try`. It's still included here so that running
51 | // `ember try:each` manually or from a customized CI config will run it
52 | // along with all the other scenarios.
53 | {
54 | name: 'ember-default',
55 | npm: {
56 | devDependencies: {}
57 | }
58 | },
59 | {
60 | name: 'ember-default-with-jquery',
61 | env: {
62 | EMBER_OPTIONAL_FEATURES: JSON.stringify({
63 | 'jquery-integration': true
64 | })
65 | },
66 | npm: {
67 | devDependencies: {
68 | '@ember/jquery': '^0.5.1'
69 | }
70 | }
71 | },
72 | {
73 | name: 'ember-classic',
74 | env: {
75 | EMBER_OPTIONAL_FEATURES: JSON.stringify({
76 | 'application-template-wrapper': true,
77 | 'template-only-glimmer-components': false
78 | })
79 | },
80 | npm: {
81 | ember: {
82 | edition: 'classic'
83 | }
84 | }
85 | }
86 | ]
87 | };
88 | };
89 |
--------------------------------------------------------------------------------
/vendor/prism.css:
--------------------------------------------------------------------------------
1 | /* http://prismjs.com/download.html?themes=prism&languages=markup+css+clike+javascript+handlebars */
2 | /**
3 | * prism.js default theme for JavaScript, CSS and HTML
4 | * Based on dabblet (http://dabblet.com)
5 | * @author Lea Verou
6 | */
7 |
8 | code[class*="language-"],
9 | pre[class*="language-"] {
10 | color: black;
11 | text-shadow: 0 1px white;
12 | font-family: Consolas, Monaco, 'Andale Mono', monospace;
13 | direction: ltr;
14 | text-align: left;
15 | white-space: pre;
16 | word-spacing: normal;
17 | word-break: normal;
18 | line-height: 1.5;
19 |
20 | -moz-tab-size: 4;
21 | -o-tab-size: 4;
22 | tab-size: 4;
23 |
24 | -webkit-hyphens: none;
25 | -moz-hyphens: none;
26 | -ms-hyphens: none;
27 | hyphens: none;
28 | }
29 |
30 | pre[class*="language-"]::-moz-selection, pre[class*="language-"] ::-moz-selection,
31 | code[class*="language-"]::-moz-selection, code[class*="language-"] ::-moz-selection {
32 | text-shadow: none;
33 | background: #b3d4fc;
34 | }
35 |
36 | pre[class*="language-"]::selection, pre[class*="language-"] ::selection,
37 | code[class*="language-"]::selection, code[class*="language-"] ::selection {
38 | text-shadow: none;
39 | background: #b3d4fc;
40 | }
41 |
42 | @media print {
43 | code[class*="language-"],
44 | pre[class*="language-"] {
45 | text-shadow: none;
46 | }
47 | }
48 |
49 | /* Code blocks */
50 | pre[class*="language-"] {
51 | padding: 1em;
52 | margin: .5em 0;
53 | overflow: auto;
54 | }
55 |
56 | :not(pre) > code[class*="language-"],
57 | pre[class*="language-"] {
58 | background: #f5f2f0;
59 | }
60 |
61 | /* Inline code */
62 | :not(pre) > code[class*="language-"] {
63 | padding: .1em;
64 | border-radius: .3em;
65 | }
66 |
67 | .token.comment,
68 | .token.prolog,
69 | .token.doctype,
70 | .token.cdata {
71 | color: slategray;
72 | }
73 |
74 | .token.punctuation {
75 | color: #999;
76 | }
77 |
78 | .namespace {
79 | opacity: .7;
80 | }
81 |
82 | .token.property,
83 | .token.tag,
84 | .token.boolean,
85 | .token.number,
86 | .token.constant,
87 | .token.symbol,
88 | .token.deleted {
89 | color: #905;
90 | }
91 |
92 | .token.selector,
93 | .token.attr-name,
94 | .token.string,
95 | .token.char,
96 | .token.builtin,
97 | .token.inserted {
98 | color: #690;
99 | }
100 |
101 | .token.operator,
102 | .token.entity,
103 | .token.url,
104 | .language-css .token.string,
105 | .style .token.string {
106 | color: #a67f59;
107 | background: hsla(0, 0%, 100%, .5);
108 | }
109 |
110 | .token.atrule,
111 | .token.attr-value,
112 | .token.keyword {
113 | color: #07a;
114 | }
115 |
116 | .token.function {
117 | color: #DD4A68;
118 | }
119 |
120 | .token.regex,
121 | .token.important,
122 | .token.variable {
123 | color: #e90;
124 | }
125 |
126 | .token.important,
127 | .token.bold {
128 | font-weight: bold;
129 | }
130 | .token.italic {
131 | font-style: italic;
132 | }
133 |
134 | .token.entity {
135 | cursor: help;
136 | }
137 |
138 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # ember-cli-nouislider
2 |
3 | [](https://travis-ci.org/kennethkalmer/ember-cli-nouislider)
4 | [](http://badge.fury.io/js/ember-cli-nouislider)
5 | [](https://codeclimate.com/github/kennethkalmer/ember-cli-nouislider)
6 | [](http://emberobserver.com/addons/ember-cli-nouislider)
7 | [](https://www.codetriage.com/kennethkalmer/ember-cli-nouislider)
8 |
9 | This ember-cli addon provides you with a range-slider component, based on
10 | [noUiSlider](http://refreshless.com/nouislider). It includes everything you need,
11 | and adds no extra dependencies other than noUiSlider itself (which has no external dependencies).
12 |
13 | To get started simply install the addon:
14 |
15 | ```
16 | $ ember install ember-cli-nouislider
17 | ```
18 |
19 | This will install `nouislider` via Bower, and will include it into your application's
20 | mergetree, so you don't need to worry about anything there.
21 |
22 | ## Compatibility
23 |
24 | * Ember.js v3.12 or above
25 | * Ember CLI v2.13 or above
26 | * Node.js v10 or above
27 |
28 | ## Demo & documentation
29 |
30 | Have a look around then [demo and documentation](http://kennethkalmer.github.com/ember-cli-nouislider)
31 | to get a feel for how to use it.
32 |
33 | ## Component
34 |
35 | You have the opportunity to customize if needed.
36 |
37 | To do this, generate your own component and re-export
38 | the one provided:
39 |
40 | ```
41 | $ ember g component range-slider
42 | ```
43 |
44 | ```js
45 | // app/components/range-slider.js
46 | import RangeSlider from 'ember-cli-nouislider/components/range-slider';
47 |
48 | export default RangeSlider;
49 | ```
50 |
51 | Include the slider into your views like this:
52 |
53 | ```handlebars
54 | {{range-slider start=someValue on-change=(action "changedAction")}}
55 | ```
56 |
57 | And setup an action handler in your route:
58 |
59 | ```js
60 | // app/routes/my-route.js
61 | import Controller from '@ember/controller';
62 | import { debug } from '@ember/debug';
63 |
64 | export default Controller.extend({
65 | // ...
66 | actions: {
67 | // ...
68 | changedAction: function(value) {
69 | debug( `New slider value: ${value}`);
70 | }
71 | }
72 | });
73 | ```
74 |
75 | See the [documentation](https://kennethkalmer.github.com/ember-cli-nouislider/)
76 | for more actions.
77 |
78 | ## Configuration
79 |
80 | The component has a lot of configurable options, most of them mapping directly
81 | to the [original options](http://refreshless.com/nouislider/slider-options/).
82 | To see how the slider is initialized internally, please have a look at
83 | `app/components/range-slider.js` in this project, or browse through the
84 | [documentation](https://kennethkalmer.github.com/ember-cli-nouislider).
85 |
86 |
87 | ## License
88 |
89 | This project is licensed under the [MIT License](LICENSE.md).
90 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | ## master
2 |
3 | ## 1.2.1 2020-03-02
4 |
5 | * Merged several security related PR's (#77, #78, #79, #80, #81, #82, #83)
6 |
7 | ## 1.2.0 2020-03-02
8 |
9 | * Update nouislider version (#75 - @crowjonah)
10 | * Don't call slider.set during dragging (#63 - @stephankaag)
11 | * Added the padding option (#62 - @sonnyt)
12 | * Upgrade ember-cli-sass and add sass to devDependencies
13 | * Upgrade to ember-cli 3.12
14 |
15 | ## 1.1.0 2018-11-09
16 |
17 | * Support closure actions because sendAction is deprecated (#68 - @scottkidder)
18 |
19 | ## 1.0.0 2018-04-28 - My First Decade on GitHub
20 |
21 | * Remove deprecated `change` & `slide` properties
22 | * Use nouislider's ability to just remove all event listeners, instead of tediously keeping track
23 |
24 | ## 1.0.0-rc.2 2018-04-14
25 |
26 | * Add cssPrefix & cssClasses options (#57 - @stephankaag)
27 |
28 | ## 1.0.0-rc.1 2018-04-14
29 |
30 | * Upgrade to Ember 3.0 (#53 - @tchak & #59 - @tchak)
31 | * Bump to nouislider 11.0 (#53 - @tchak & #59 - @tchak)
32 | * Move broccoli-funnel & broccoli-merge-trees to dependencies (from devDependencies)
33 |
34 | ## 0.14.1 2017-10-08
35 |
36 | _Version bump only because I can't NPM properly_
37 |
38 | ## 0.14.0 2017-10-08
39 |
40 | * Expose multitouch option (#47)
41 | * Warn when component can't be initialized (#34)
42 | * Bump to nouislider 10.1.0
43 | * Bump to Ember 2.15.1
44 |
45 |
46 | ## 0.13.0 2017-03-12
47 |
48 | * Bump to nouislider 9.2.0 (#44)
49 |
50 | ## 0.12.0 2017-02-27
51 |
52 | * Fix deprecation warnings when rendering slider (#39 - @showy)
53 | * Fix incorrect behaviour with negative ranges (reporting #24 @Ramblurr, fixed #43 @eraleis)
54 | * Switch to using npm for nouislider (#44 - @bobisjan)
55 |
56 | ## 0.11.0 2016-12-16 - Happy Reconciliation Day
57 |
58 | * Bump to Ember 2.10.0
59 | * Updated docs example (#40 - @adambowles)
60 | * Update slider if component properties have changed (#38 - @renebigot)
61 |
62 | ## 0.10.0 2016-10-03
63 |
64 | * Bump to Ember 2.8.0 LTS
65 | * BETA support for tooltips (#35 - michalsnik)
66 | * Bump nouislider to 8.5.0
67 | * Support for the 'disabled' attribute (#25 - @alexspeller)
68 |
69 | ## 0.9.1 2016-07-11
70 |
71 | * Support for fastboot (#26 - @tschoartschi)
72 | * Documentation update (#29 - @sandstrom)
73 |
74 | ## 0.9.0 2016-04-14
75 |
76 | * Support for 'update', 'start' & 'end' events
77 | * Bump nouislider to 8.3.0
78 |
79 | ## 0.8.1 2016-03-26
80 |
81 | * Deprecate the old events ("change" & "slide") in favor of "on-change" & "on-slide"
82 | * Fix regression introduced by `set` action, now called `on-set`
83 |
84 | ## 0.8.0 2016-03-26
85 |
86 | * Bump nouislider to 8.0.2
87 | * Added nodejs 4 & 5 to Travis config, allow failures on Node 5
88 | * Upgrade ember-cli to 2.4.2
89 | * Added "set" action in order to use it in acceptance testing (#22 - @juliankmazo)
90 | * Include non-minified version of nouislider in development (#21 - @constantm)
91 |
92 | ## 0.7.0 2015-08-17
93 |
94 | * Add CodeClimate badge to README
95 | * Update ember-cli to 1.13.8, ember.js to 1.13.7
96 | * Bring back 'format' (#19 - @knownasilya)
97 | * Bring back 'snap' and 'pips' (#18 - @kbullaughey)
98 |
99 | ## 0.6.0 2015-07-09 - (Happy Birthday To Me)
100 |
101 | * Add demoURL to package.json
102 | * Use events instead of listeners (#14 - @knowasilya)
103 | * Add "formats" & "pips" suppor (#13 - @davidgoli)
104 |
105 | ## 0.5.0 2015-07-02
106 |
107 | * Upgrade to nouislider 8.0.1 (#10 - @blimmer)
108 | * Documentation improvements (#10 - @blimmer)
109 | * Toolchain upgrades and tlc (#10 - @blimmer)
110 |
111 | Thanks Ben Limmer for doing all this work!
112 |
113 | ## 0.4.2 2015-07-02
114 |
115 | * Pin nouislider dependency at 7.0.0 (#9 - @blimmer)
116 |
117 | ## 0.4.1 2015-06-19
118 |
119 | * Fixed an issue with actions not being called correctly (#6)
120 |
121 | ## 0.4.0 2015-05-09
122 |
123 | * Allow changing the name of the _change_ action
124 | * Allow specifying an action for when sliding (#3)
125 |
126 | ## 0.3.0 2015-04-17
127 |
128 | * Now works with prototype extensions disabled
129 | * Moved addon bits into addons/ directory so they don't conflict with application
130 | * Depend on ember-cli-htmlbars because we're shipping a template
131 |
132 | ## 0.2.0 2015-03-16
133 |
134 | * Now observe changes to `start` and pass the changes on to noUiSlider
135 | * Changed the default value of `start` to be `undefined`
136 | * Changed the default value of `step` to be `undefined`
137 | * Added missing `animate` attribute, default to `true`.
138 |
139 | ## 0.1.1 2015-03-09
140 |
141 | * Moved rimraf dependency to devDependencies
142 |
143 | ## 0.1.0 2015-03-09
144 |
145 | Initial release
146 |
--------------------------------------------------------------------------------
/addon/components/range-slider.js:
--------------------------------------------------------------------------------
1 | /* eslint ember/closure-actions: 0 */
2 |
3 | import { A } from '@ember/array';
4 | import Component from '@ember/component';
5 | import { run } from '@ember/runloop';
6 | import { isEmpty } from '@ember/utils';
7 | import { observer, computed } from '@ember/object';
8 | import Ember from 'ember';
9 | import noUiSlider from 'noUiSlider';
10 |
11 | const {
12 | Logger: { warn }
13 | } = Ember;
14 |
15 | export default Component.extend({
16 | attributeBindings: ['disabledOrUndefined:disabled'],
17 | slider: null,
18 | start: undefined,
19 | step: undefined,
20 | margin: undefined,
21 | padding: undefined,
22 | limit: undefined,
23 | pips: undefined,
24 | animate: true,
25 | snap: false,
26 | connect: false,
27 | disabled: false,
28 | orientation: 'horizontal',
29 | direction: 'ltr',
30 | behaviour: 'tap',
31 | tooltips: false,
32 | multitouch: false,
33 | keyboardSupport: true,
34 |
35 | min: 0,
36 | max: 100,
37 |
38 | range: computed('min', 'max', function() {
39 | return {
40 | min: this.get('min'),
41 | max: this.get('max')
42 | };
43 | }),
44 |
45 | formatTo(value) {
46 | return value;
47 | },
48 |
49 | formatFrom(value) {
50 | return +value;
51 | },
52 |
53 | format: computed('formatTo', 'formatFrom', function() {
54 | return {
55 | to: this.get('formatTo'),
56 | from: this.get('formatFrom')
57 | };
58 | }),
59 |
60 | didInsertElement() {
61 | this.setup();
62 | },
63 |
64 | setup() {
65 | let element = this.get('element');
66 | let { noUiSlider: slider } = element;
67 | let properties = this.getProperties(
68 | 'start', 'step', 'margin', 'padding',
69 | 'limit', 'range', 'connect',
70 | 'orientation', 'direction',
71 | 'behaviour', 'animate', 'snap',
72 | 'pips', 'format', 'tooltips',
73 | 'multitouch', 'cssPrefix',
74 | 'cssClasses', 'keyboardSupport'
75 | );
76 | let sliderEvents = A(['change', 'set', 'slide', 'update']);
77 |
78 | // We first check if the element has a slider already created
79 | if (slider && slider.destroy) {
80 | slider.destroy();
81 | }
82 |
83 | try {
84 | slider = noUiSlider.create(element, properties, true);
85 | } catch (err) {
86 | warn(`[ember-cli-nouislider]: ${err}`);
87 | }
88 |
89 | this.slider = slider;
90 |
91 | sliderEvents.forEach(event => {
92 | const eventActionName = `on-${event}`;
93 |
94 | if (!isEmpty(this.get(eventActionName))) {
95 | slider.on(event, () => {
96 | run(this, function() {
97 | const val = this.get('slider').get();
98 | const action = this.get(eventActionName);
99 |
100 | if (typeof(action) === 'string') {
101 | // Note that `sendAction` is deprecated and this will trigger a deprecation message.
102 | this.sendAction(eventActionName, val);
103 | } else if (typeof(action) === 'function') {
104 | action(val);
105 | }
106 | });
107 | });
108 | }
109 | });
110 |
111 | slider.on('start', () => {
112 | run(this, function() {
113 | this.onStart();
114 | if (!isEmpty(this.get(`on-start`))) {
115 | let val = this.get("slider").get();
116 | this.sendAction(`on-start`, val);
117 | }
118 | });
119 | });
120 |
121 | slider.on('end', () => {
122 | run(this, function() {
123 | this.onEnd();
124 | if (!isEmpty(this.get(`on-end`))) {
125 | let val = this.get("slider").get();
126 | this.sendAction(`on-end`, val);
127 | }
128 | });
129 | });
130 | },
131 |
132 | onStart() {
133 | this.sliding = true;
134 | },
135 |
136 | onEnd() {
137 | delete this.sliding;
138 | },
139 |
140 | didUpdateAttrs() {
141 | this.update();
142 | },
143 |
144 | update() {
145 | let { slider } = this;
146 | let properties = this.getProperties(
147 | 'margin', 'limit', 'step',
148 | 'range', 'animate', 'snap',
149 | 'start', 'padding', 'keyboardSupport'
150 | );
151 |
152 | if (slider) {
153 | slider.updateOptions(properties);
154 | }
155 | },
156 |
157 | willDestroyElement() {
158 | this.teardown();
159 | },
160 |
161 | teardown() {
162 | let { slider } = this;
163 |
164 | // Remove all event listeners
165 | slider.off();
166 |
167 | slider.destroy();
168 | },
169 |
170 | setValue: observer('start', function() {
171 | let { slider } = this;
172 |
173 | if (slider && !this.sliding) {
174 | let value = this.get('start');
175 | slider.set(value);
176 | }
177 | }),
178 |
179 | // disabled can't be just `false` - this leads to an attribute of disabled="false"
180 | disabledOrUndefined: computed('disabled', function() {
181 | if (this.get('disabled')) {
182 | return true;
183 | }
184 | return undefined;
185 | })
186 | });
187 |
--------------------------------------------------------------------------------
/tests/dummy/app/templates/events.hbs:
--------------------------------------------------------------------------------
1 |
4 |
Events
5 |
6 |
7 |
8 |
9 | The range-slider component can send two actions to your route when a
10 | user interacts with the slider. You can set on-change to an
11 | action that will be called when sliding has stopped, or you can
12 | set on-slide to an action for when a user is sliding the
13 | control.
14 |
15 |
16 |
17 | {{range-slider start=model.start range=model.range
18 | on-change=(action "change")
19 | on-slide=(action "slide")
20 | on-update=(action "update")
21 | on-set=(action "setValue")
22 | on-start=(action "started")
23 | on-end=(action "ended")}}
24 |
25 |
Update
26 |
Slide
27 |
Set
28 |
Change
29 |
Start
30 |
End
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 | on-update
41 | on-slide
42 | on-set
43 | on-change
44 |
45 |
46 |
47 |
48 | A handle is released after dragging
49 | Yes
50 | No
51 | Yes
52 | Yes
53 |
54 |
55 | A slider is moved by tapping it
56 | Yes
57 | Yes
58 | Yes
59 | Yes
60 |
61 |
62 | A handle moves while dragging
63 | Yes
64 | Yes
65 | No
66 | No
67 |
68 |
69 | The .set() method is called
70 | Yes
71 | No
72 | Yes
73 | No
74 |
75 |
76 |
77 |
78 |
79 | {{!-- template-lint-disable --}}
80 | {{#source-code language="handlebars"}}
81 | \{{range-slider start=model.start
82 | range=model.range
83 | on-slide=(action "slide")
84 | on-change=(action "changed")
85 | on-update=(action "update")
86 | on-set=(action "setValue")
87 | on-start=(action "started")
88 | on-end=(action "ended")}}
89 | {{/source-code}}
90 |
91 | {{#source-code language="javascript"}}
92 | // app/controller/events.js
93 | import Controller from '@ember/controller';
94 |
95 | export default Controller.extend({
96 | actions: {
97 | update(value) {
98 | // updating
99 | },
100 | changed(value) {
101 | // change event
102 | },
103 | slide(value) {
104 | // sliding
105 | },
106 | setValue(value) {
107 | // set event
108 | },
109 | started(value) {
110 | // sliding started
111 | },
112 | ended(value) {
113 | // sliding ended
114 | }
115 | }
116 | });
117 | {{/source-code}}
118 |
119 |
120 |
121 |
§ Change
122 |
123 |
124 |
125 | This action is great when you use the slider as 'just-another-input-type'.
126 |
127 |
128 | The name of the action can be changed
129 | by passing an action name to the change parameter
130 |
131 |
132 |
133 | {{!-- template-lint-disable --}}
134 | {{#source-code language="handlebars"}}
135 | \{{range-slider on-change=(action "myAction")}}
136 | {{/source-code}}
137 | {{#source-code language="javascript"}}
138 | // app/controller/events.js
139 | import Controller from '@ember/controller';
140 |
141 | export default Controller.extend({
142 | actions: {
143 | myAction(value) {
144 | // ...
145 | }
146 | }
147 | });
148 | {{/source-code}}
149 |
150 |
151 |
152 |
§ Slide
153 |
154 |
155 |
156 | This action is useful when you want to update a value or perform an
157 | action every time a handle is dragged. For example, you can use the
158 | 'slide' action to update graphs. For convenience, this function also
159 | fires on a change by 'tap'.
160 |
161 |
162 | By default no actions are sent, you need to explicitly specify an action
163 | name by setting the on-slide property.
164 |
165 |
166 |
167 | {{!-- template-lint-disable --}}
168 | {{#source-code language="handlebars"}}
169 | \{{range-slider on-slide="slidingAction"}}
170 | {{/source-code}}
171 | {{#source-code language="javascript"}}
172 | // app/controller/events.js
173 | import Controller from '@ember/controller';
174 |
175 | export default Controller.extend({
176 | actions: {
177 | slidingAction(value) {
178 | // ...
179 | }
180 | }
181 | });
182 | {{/source-code}}
183 |
184 |
185 |
186 |
--------------------------------------------------------------------------------
/vendor/prism.js:
--------------------------------------------------------------------------------
1 | /* http://prismjs.com/download.html?themes=prism&languages=markup+css+clike+javascript+handlebars */
2 | self="undefined"!=typeof window?window:"undefined"!=typeof WorkerGlobalScope&&self instanceof WorkerGlobalScope?self:{};var Prism=function(){var e=/\blang(?:uage)?-(?!\*)(\w+)\b/i,t=self.Prism={util:{encode:function(e){return e instanceof n?new n(e.type,t.util.encode(e.content),e.alias):"Array"===t.util.type(e)?e.map(t.util.encode):e.replace(/&/g,"&").replace(/e.length)break e;if(!(d instanceof a)){u.lastIndex=0;var m=u.exec(d);if(m){c&&(f=m[1].length);var y=m.index-1+f,m=m[0].slice(f),v=m.length,k=y+v,b=d.slice(0,y+1),w=d.slice(k+1),N=[p,1];b&&N.push(b);var O=new a(l,g?t.tokenize(m,g):m,h);N.push(O),w&&N.push(w),Array.prototype.splice.apply(r,N)}}}}}return r},hooks:{all:{},add:function(e,n){var a=t.hooks.all;a[e]=a[e]||[],a[e].push(n)},run:function(e,n){var a=t.hooks.all[e];if(a&&a.length)for(var r,i=0;r=a[i++];)r(n)}}},n=t.Token=function(e,t,n){this.type=e,this.content=t,this.alias=n};if(n.stringify=function(e,a,r){if("string"==typeof e)return e;if("Array"===t.util.type(e))return e.map(function(t){return n.stringify(t,a,e)}).join("");var i={type:e.type,content:n.stringify(e.content,a,r),tag:"span",classes:["token",e.type],attributes:{},language:a,parent:r};if("comment"==i.type&&(i.attributes.spellcheck="true"),e.alias){var l="Array"===t.util.type(e.alias)?e.alias:[e.alias];Array.prototype.push.apply(i.classes,l)}t.hooks.run("wrap",i);var s="";for(var o in i.attributes)s+=o+'="'+(i.attributes[o]||"")+'"';return"<"+i.tag+' class="'+i.classes.join(" ")+'" '+s+">"+i.content+""+i.tag+">"},!self.document)return self.addEventListener?(self.addEventListener("message",function(e){var n=JSON.parse(e.data),a=n.language,r=n.code;self.postMessage(JSON.stringify(t.util.encode(t.tokenize(r,t.languages[a])))),self.close()},!1),self.Prism):self.Prism;var a=document.getElementsByTagName("script");return a=a[a.length-1],a&&(t.filename=a.src,document.addEventListener&&!a.hasAttribute("data-manual")&&document.addEventListener("DOMContentLoaded",t.highlightAll)),self.Prism}();"undefined"!=typeof module&&module.exports&&(module.exports=Prism);;
3 | Prism.languages.markup={comment://,prolog:/<\?.+?\?>/,doctype://,cdata://i,tag:{pattern:/<\/?[\w:-]+\s*(?:\s+[\w:-]+(?:=(?:("|')(\\?[\w\W])*?\1|[^\s'">=]+))?\s*)*\/?>/i,inside:{tag:{pattern:/^<\/?[\w:-]+/i,inside:{punctuation:/^<\/?/,namespace:/^[\w-]+?:/}},"attr-value":{pattern:/=(?:('|")[\w\W]*?(\1)|[^\s>]+)/i,inside:{punctuation:/=|>|"/}},punctuation:/\/?>/,"attr-name":{pattern:/[\w:-]+/,inside:{namespace:/^[\w-]+?:/}}}},entity:/?[\da-z]{1,8};/i},Prism.hooks.add("wrap",function(t){"entity"===t.type&&(t.attributes.title=t.content.replace(/&/,"&"))});;
4 | Prism.languages.css={comment:/\/\*[\w\W]*?\*\//,atrule:{pattern:/@[\w-]+?.*?(;|(?=\s*\{))/i,inside:{punctuation:/[;:]/}},url:/url\((?:(["'])(\\\n|\\?.)*?\1|.*?)\)/i,selector:/[^\{\}\s][^\{\};]*(?=\s*\{)/,string:/("|')(\\\n|\\?.)*?\1/,property:/(\b|\B)[\w-]+(?=\s*:)/i,important:/\B!important\b/i,punctuation:/[\{\};:]/,"function":/[-a-z0-9]+(?=\()/i},Prism.languages.markup&&(Prism.languages.insertBefore("markup","tag",{style:{pattern:/