├── .bowerrc
├── .editorconfig
├── .ember-cli
├── .eslintrc.js
├── .gitignore
├── .npmignore
├── .travis.yml
├── .watchmanconfig
├── CHANGELOG.md
├── LICENSE.md
├── README.md
├── addon
├── components
│ ├── rl-dropdown-container.js
│ ├── rl-dropdown-toggle.js
│ └── rl-dropdown.js
└── mixins
│ └── rl-dropdown-component.js
├── app
├── components
│ ├── rl-dropdown-container.js
│ ├── rl-dropdown-toggle.js
│ └── rl-dropdown.js
└── templates
│ └── components
│ └── rl-dropdown-container.hbs
├── bower.json
├── config
├── ember-try.js
└── environment.js
├── ember-cli-build.js
├── index.js
├── package.json
├── testem.js
└── tests
├── .eslintrc.js
├── dummy
├── app
│ ├── app.js
│ ├── components
│ │ ├── .gitkeep
│ │ └── user-controls.js
│ ├── controllers
│ │ └── .gitkeep
│ ├── helpers
│ │ └── .gitkeep
│ ├── index.html
│ ├── models
│ │ └── .gitkeep
│ ├── resolver.js
│ ├── router.js
│ ├── routes
│ │ └── .gitkeep
│ ├── styles
│ │ └── app.css
│ └── templates
│ │ ├── application.hbs
│ │ ├── components
│ │ ├── .gitkeep
│ │ └── user-controls.hbs
│ │ ├── dropdown-mixin-test.hbs
│ │ ├── dropdown-test.hbs
│ │ └── dropdown-with-checkbox-test.hbs
├── config
│ ├── environment.js
│ └── targets.js
└── public
│ ├── crossdomain.xml
│ └── robots.txt
├── helpers
├── destroy-app.js
├── module-for-acceptance.js
├── resolver.js
└── start-app.js
├── index.html
├── integration
├── dropdown-components-test.js
└── dropdown-mixin-test.js
└── test-helper.js
/.bowerrc:
--------------------------------------------------------------------------------
1 | {
2 | "directory": "bower_components",
3 | "analytics": false
4 | }
5 |
--------------------------------------------------------------------------------
/.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 |
--------------------------------------------------------------------------------
/.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 |
--------------------------------------------------------------------------------
/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | root: true,
3 | parserOptions: {
4 | ecmaVersion: 2017,
5 | sourceType: 'module'
6 | },
7 | plugins: [
8 | 'ember'
9 | ],
10 | extends: [
11 | 'eslint:recommended',
12 | 'plugin:ember/recommended'
13 | ],
14 | env: {
15 | browser: true
16 | },
17 | rules: {
18 | },
19 | overrides: [
20 | // node files
21 | {
22 | files: [
23 | 'index.js',
24 | 'testem.js',
25 | 'ember-cli-build.js',
26 | 'config/**/*.js',
27 | 'tests/dummy/config/**/*.js'
28 | ],
29 | excludedFiles: [
30 | 'app/**',
31 | 'addon/**',
32 | 'tests/dummy/app/**'
33 | ],
34 | parserOptions: {
35 | sourceType: 'script',
36 | ecmaVersion: 2015
37 | },
38 | env: {
39 | browser: false,
40 | node: true
41 | },
42 | plugins: ['node'],
43 | rules: Object.assign({}, require('eslint-plugin-node').configs.recommended.rules, {
44 | // add your custom rules and overrides for node files here
45 | })
46 | },
47 |
48 | // test files
49 | {
50 | files: ['tests/**/*.js'],
51 | excludedFiles: ['tests/dummy/**/*.js'],
52 | env: {
53 | embertest: true
54 | }
55 | }
56 | ]
57 | };
58 |
--------------------------------------------------------------------------------
/.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 | /node_modules
9 | /bower_components
10 |
11 | # misc
12 | /.sass-cache
13 | /connect.lock
14 | /coverage/*
15 | /libpeerconnection.log
16 | npm-debug.log*
17 | yarn-error.log
18 | testem.log
19 |
20 | # ember-try
21 | .node_modules.ember-try/
22 | bower.json.ember-try
23 | package.json.ember-try
24 |
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | /bower_components
2 | /config/ember-try.js
3 | /dist
4 | /tests
5 | /tmp
6 | **/.gitkeep
7 | .bowerrc
8 | .editorconfig
9 | .ember-cli
10 | .eslintrc.js
11 | .gitignore
12 | .watchmanconfig
13 | .travis.yml
14 | bower.json
15 | ember-cli-build.js
16 | testem.js
17 |
18 | # ember-try
19 | .node_modules.ember-try/
20 | bower.json.ember-try
21 | package.json.ember-try
22 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | ---
2 | language: node_js
3 | node_js:
4 | # we recommend testing addons with the same minimum supported node version as Ember CLI
5 | # so that your addon works for all apps
6 | - "4"
7 |
8 | sudo: false
9 | dist: trusty
10 |
11 | addons:
12 | chrome: stable
13 |
14 | cache:
15 | directories:
16 | - $HOME/.npm
17 |
18 | env:
19 | global:
20 | # See https://git.io/vdao3 for details.
21 | - JOBS=1
22 | matrix:
23 | # we recommend new addons test the current and previous LTS
24 | # as well as latest stable release (bonus points to beta/canary)
25 | - EMBER_TRY_SCENARIO=ember-lts-2.12
26 | - EMBER_TRY_SCENARIO=ember-lts-2.16
27 | - EMBER_TRY_SCENARIO=ember-release
28 | - EMBER_TRY_SCENARIO=ember-beta
29 | - EMBER_TRY_SCENARIO=ember-canary
30 | - EMBER_TRY_SCENARIO=ember-default
31 |
32 | matrix:
33 | fast_finish: true
34 | allow_failures:
35 | - env: EMBER_TRY_SCENARIO=ember-canary
36 |
37 | before_install:
38 | - npm config set spin false
39 | - npm install -g npm@4
40 | - npm --version
41 |
42 | script:
43 | - npm run lint:js
44 | # Usually, it's ok to finish the test scenario without reverting
45 | # to the addon's original dependency state, skipping "cleanup".
46 | - node_modules/.bin/ember try:one $EMBER_TRY_SCENARIO --skip-cleanup
47 |
--------------------------------------------------------------------------------
/.watchmanconfig:
--------------------------------------------------------------------------------
1 | {
2 | "ignore_dirs": ["tmp", "dist"]
3 | }
4 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Ember-rl-dropdown change log
2 |
3 | ## 0.10.0
4 |
5 | Adds `disabled` attribute to `rl-dropdown-toggle`. `disabled` may be set to `true` to disable the toggle button:
6 |
7 | ```hbs
8 | {{#rl-dropdown-container}}
9 | {{#rl-dropdown-toggle disabled=true}}
10 | Toggle
11 | {{/rl-dropdown-toggle}}
12 |
13 | {{#rl-dropdown}}
14 | ...
15 | {{/rl-dropdown}}
16 | {{/rl-dropdown-container}}
17 | ```
18 |
19 | ## 0.9.0
20 |
21 | Dropdown now closes when elements outside the dropdown receive focus. Fixes complicated bug in Firefox (see Pull Request
22 | #18, thanks @tomasznapieralski!).
23 |
24 | ## 0.8.0
25 |
26 | Thanks to @hakubo, it is now possible to bind actions to the `onOpen` and `onClose` attributes on the
27 | `rl-dropdown-container` component:
28 |
29 | ```hbs
30 | {{#rl-dropdown-container onOpen=(action "myOnOpenHandler") onClose=(action "myOnCloseHandler")}}
31 | ...
32 | {{/rl-dropdown-container}}
33 | ```
34 |
35 | The `onOpen` action will be called when the dropdown is opened; the `onClose` action will be called when the dropdown
36 | is closed.
37 |
38 | ## 0.7.0
39 |
40 | A block param was added to the `rl-dropdown-container` component indicating whether or not the dropdown is expanded,
41 | which can be used to e.g. customize the toggle button text based on whether the dropdown is expanded or closed:
42 |
43 | ```hbs
44 | {{#rl-dropdown-container as |dropdownExpanded|}}
45 | {{#rl-dropdown-toggle}}
46 | {{#if dropdownExpanded}}
47 | Close
48 | {{else}}
49 | Expand
50 | {{/if}}
51 | {{/rl-dropdown-toggle}}
52 |
53 | {{#rl-dropdown}}
54 | ...
55 | {{/rl-dropdown}}
56 | {{/rl-dropdown-container}}
57 | ```
58 |
59 | ## 0.6.0
60 |
61 | Fixes bug with the `propagateClicks` attribute so now clicks indeed propagate by default.
62 |
63 | The `rl-dropdown-container` component now gets a `dropdown-expanded` class when the dropdown is expanded.
64 |
65 | ## 0.5.0
66 |
67 | Previously click propagation on the `rl-dropdown-toggle` and `rl-dropdown` components was prevented by default. As of
68 | this version they are not prevented by default. The `propagateClicks` attribute must now be set to `false` on either or
69 | both of these components if you wish to prevent click event propagation on either or both.
70 |
71 | ## 0.4.0
72 |
73 | Dropdowns should now close on touch-start on mobile.
74 |
75 | ## 0.3.0
76 |
77 | Dropdowns should now close when pressing the Escape key. This can be disabled by setting `closeOnEscape` to `false`.
78 |
79 | The `clickoutEventNamespace` option has been renamed to `closingEventsNamespace`.
80 |
81 | ## 0.2.0
82 |
83 | Upgraded to ember-cli 0.2.x.
84 |
85 | ## 0.1.0
86 |
87 | Added `type='button'` to dropdown toggles with button tags, to prevent IE from treating it like a submit button when
88 | this is not intended.
89 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | # The MIT License (MIT)
2 |
3 | Copyright (c) 2014 R.S. Schermer
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 | # Ember-rl-dropdown
2 |
3 | THIS IS A LEGACY ADDON THAT'S NO LONGER ACTIVELY MAINTAINED. IF YOU'RE LOOKING FOR AN UP TO DATE ALTERNATIVE,
4 | I'D RECOMMEND http://ember-basic-dropdown.com/
5 |
6 | Simple dropdown component and mixin for Ember. While it is very straightforward to create toggle functionality in
7 | Ember with the if-helper, this dropdown will also close on click-out or when pressing the Escape key.
8 |
9 | [](https://travis-ci.org/RSSchermer/ember-rl-dropdown)
10 |
11 | ## Demo
12 |
13 | Demo available [here](http://rsschermer.github.io/ember-rl-dropdown/).
14 |
15 | ## Installation
16 |
17 | ```bash
18 | npm install --save-dev ember-rl-dropdown
19 | ```
20 |
21 | This addon does not provide any css for the dropdown, but it should work well with frameworks such as Twitter Bootstrap
22 | (see example below).
23 |
24 | ## Usage
25 |
26 | ```handlebars
27 |
28 |
29 | {{#rl-dropdown-container class="dropdown"}}
30 | {{#rl-dropdown-toggle class="btn btn-default"}}
31 | Toggle
32 | {{/rl-dropdown-toggle}}
33 |
34 | {{#rl-dropdown tagName="ul" class="dropdown-menu" closeOnChildClick="a:link"}}
35 |
Link 1
36 | Link 2
37 | Link 3
38 | {{/rl-dropdown}}
39 | {{/rl-dropdown-container}}
40 | ```
41 |
42 | The component tagnames and classes can be altered to work with your favorite framework or your own custom css.
43 |
44 | `closeOnChildClick` may be set to a jQuery selector for child elements that should cause the dropdown to close when
45 | clicked. The default behavior is for the dropdown to remain visible when the user interacts with its child elements.
46 | Set it to `true` if any child element should close the dropdown.
47 |
48 | `propagateClicks` may be set to `false` on the `rl-dropdown-toggle` component and/or the `rl-dropdown` component if
49 | click events should not propagate up through the DOM from either or both of these components.
50 |
51 | The `rl-dropdown-container` component also passes a boolean block param indicating whether or not the dropdown is
52 | expanded, which can be used to e.g. customize the toggle button text based on whether the dropdown is expanded or
53 | closed:
54 |
55 | ```hbs
56 | {{#rl-dropdown-container as |dropdownExpanded|}}
57 | {{#rl-dropdown-toggle}}
58 | {{#if dropdownExpanded}}
59 | Close
60 | {{else}}
61 | Expand
62 | {{/if}}
63 | {{/rl-dropdown-toggle}}
64 |
65 | {{#rl-dropdown}}
66 | ...
67 | {{/rl-dropdown}}
68 | {{/rl-dropdown-container}}
69 | ```
70 |
71 | It is also possible to bind actions to the `onOpen` and `onClose` attributes on the `rl-dropdown-container` component:
72 |
73 | ```hbs
74 | {{#rl-dropdown-container onOpen=(action "myOnOpenHandler") onClose=(action "myOnCloseHandler")}}
75 | ...
76 | {{/rl-dropdown-container}}
77 | ```
78 |
79 | The `onOpen` action will be called when the dropdown is opened; the `onClose` action will be called when the dropdown
80 | is closed.
81 |
82 | ## Mixin
83 |
84 | When integrating dropdown functionality in your own components, you may prefer to use the mixin instead of using the
85 | dropdown components. Be sure to add the `rl-dropdown-toggle` class to your dropdown toggle element, and to add the
86 | `rl-dropdown` class to your dropdown element. You can send `toggleDropdown`, `closeDropdown` and `openDropdown` events
87 | to toggle, close or open the dropdown.
88 |
89 |
90 | ```javascript
91 | // app/components/user-controls.js
92 | import Ember from 'ember';
93 | import DropdownComponentMixin from 'ember-rl-dropdown/mixins/rl-dropdown-component';
94 |
95 | export default Ember.Component.extend(DropdownComponentMixin, {
96 | // Some additional custom behaviour
97 | });
98 | ```
99 |
100 | ```handlebars
101 |
102 |
103 |
104 | User controls
105 |
106 | {{#if dropdownExpanded}}
107 |
108 |
109 | ...
110 |
Close
111 |
112 | {{/if}}
113 | ```
114 |
--------------------------------------------------------------------------------
/addon/components/rl-dropdown-container.js:
--------------------------------------------------------------------------------
1 | import Component from '@ember/component';
2 | import DropdownComponentMixin from 'ember-rl-dropdown/mixins/rl-dropdown-component';
3 |
4 | export default Component.extend(DropdownComponentMixin, {
5 | classNameBindings: ['dropdownExpanded']
6 | });
7 |
--------------------------------------------------------------------------------
/addon/components/rl-dropdown-toggle.js:
--------------------------------------------------------------------------------
1 | import Component from '@ember/component';
2 | import { computed } from '@ember/object';
3 | import RlDropdownContainer from './rl-dropdown-container';
4 |
5 | export default Component.extend({
6 | classNames: ['rl-dropdown-toggle'],
7 |
8 | tagName: 'button',
9 |
10 | attributeBindings: ['type', 'role', 'disabled'],
11 |
12 | type: computed('tagName', function () {
13 | return this.get('tagName') === 'button' ? 'button' : null;
14 | }),
15 |
16 | role: computed('tagName', function () {
17 | return this.get('tagName') === 'a' ? 'button' : null;
18 | }),
19 |
20 | dropdownContainer: computed(function () {
21 | return this.nearestOfType(RlDropdownContainer);
22 | }),
23 |
24 | action: 'toggleDropdown',
25 |
26 | propagateClicks: true,
27 |
28 | disabled: false,
29 |
30 | click(event) {
31 | if (!this.get('disabled')) {
32 | let propagateClicks = this.get('propagateClicks');
33 |
34 | this.get('dropdownContainer').send(this.get('action'));
35 |
36 | if (propagateClicks === false || propagateClicks === 'false') {
37 | event.stopPropagation();
38 | }
39 | }
40 | }
41 | });
42 |
--------------------------------------------------------------------------------
/addon/components/rl-dropdown.js:
--------------------------------------------------------------------------------
1 | import Component from '@ember/component';
2 | import { computed, observer } from '@ember/object';
3 | import { on } from '@ember/object/evented';
4 | import $ from 'jquery';
5 | import RlDropdownContainer from './rl-dropdown-container';
6 |
7 | export default Component.extend({
8 | classNames: ['rl-dropdown'],
9 |
10 | dropdownContainer: computed(function () {
11 | return this.nearestOfType(RlDropdownContainer);
12 | }),
13 |
14 | isExpanded: computed.alias('dropdownContainer.dropdownExpanded'),
15 |
16 | closeOnChildClick: false,
17 |
18 | propagateClicks: true,
19 |
20 | didInsertElement() {
21 | this._super(...arguments);
22 | this.element.addEventListener('click', (e) => {
23 | this._click(e);
24 | });
25 | },
26 |
27 | manageVisibility: on('didInsertElement', observer('isExpanded', function () {
28 | if (this.get('isExpanded')) {
29 | this.$().css('display', 'block');
30 | } else {
31 | this.$().css('display', 'none');
32 | }
33 | })),
34 |
35 | _click(event) {
36 | let closeOnChildClick = this.get('closeOnChildClick');
37 | let propagateClicks = this.get('propagateClicks');
38 | let $target = $(event.target);
39 | let $c = this.$();
40 |
41 | if ($target !== $c) {
42 | if ((closeOnChildClick === true || closeOnChildClick === "true") && $target.closest($c).length) {
43 | this.set('isExpanded', false);
44 | } else if (closeOnChildClick && $target.closest(closeOnChildClick, $c).length) {
45 | this.set('isExpanded', false);
46 | }
47 | }
48 |
49 | if (propagateClicks === false || propagateClicks === "false") {
50 | event.stopPropagation();
51 | }
52 | }
53 | });
54 |
--------------------------------------------------------------------------------
/addon/mixins/rl-dropdown-component.js:
--------------------------------------------------------------------------------
1 | import Mixin from '@ember/object/mixin';
2 | import { observer } from '@ember/object';
3 | import { on } from '@ember/object/evented';
4 | import { bind, later } from '@ember/runloop';
5 | import $ from 'jquery';
6 |
7 | export default Mixin.create({
8 | init: function () {
9 | this._super(...arguments);
10 |
11 | this.set('boundClickoutHandler', bind(this, this.clickoutHandler));
12 | this.set('boundEscapeHandler', bind(this, this.escapeHandler));
13 | },
14 |
15 | onOpen() {},
16 | onClose() {},
17 |
18 | dropdownExpanded: false,
19 |
20 | dropdownToggleSelector: '.rl-dropdown-toggle',
21 |
22 | dropdownSelector: '.rl-dropdown',
23 |
24 | closingEventNamespace: 'rl-dropdown',
25 |
26 | closeOnEscape: true,
27 |
28 | actions: {
29 | toggleDropdown: function () {
30 | this.toggleProperty('dropdownExpanded');
31 |
32 | if (this.get('dropdownExpanded')) {
33 | this.get('onOpen')();
34 | } else {
35 | this.get('onClose')();
36 | }
37 | },
38 |
39 | openDropdown: function () {
40 | this.set('dropdownExpanded', true);
41 | this.get('onOpen')();
42 | },
43 |
44 | closeDropdown: function () {
45 | this.set('dropdownExpanded', false);
46 | this.get('onClose')();
47 | }
48 | },
49 |
50 | manageClosingEvents: on('didInsertElement', observer('dropdownExpanded', function () {
51 | let namespace = this.get('closingEventNamespace');
52 | let clickEventName = 'click.'+ namespace;
53 | let focusEventName = 'focusin.'+ namespace;
54 | let touchEventName = 'touchstart.'+ namespace;
55 | let escapeEventName = 'keydown.'+ namespace;
56 | let component = this;
57 | let $document = $(document);
58 |
59 | if (this.get('dropdownExpanded')) {
60 |
61 | /* Add clickout handler with 1ms delay, to allow opening the dropdown
62 | * by clicking e.g. a checkbox and binding to dropdownExpanded, without
63 | * having the handler close the dropdown immediately. */
64 | later(() => {
65 | $document.bind(clickEventName, {component: component}, component.boundClickoutHandler);
66 | $document.bind(focusEventName, {component: component}, component.boundClickoutHandler);
67 | $document.bind(touchEventName, {component: component}, component.boundClickoutHandler);
68 | }, 1);
69 |
70 | if (this.get('closeOnEscape')) {
71 | $document.bind(escapeEventName, {component: component}, component.boundEscapeHandler);
72 | }
73 | } else {
74 | $document.unbind(clickEventName, component.boundClickoutHandler);
75 | $document.unbind(focusEventName, component.boundClickoutHandler);
76 | $document.unbind(touchEventName, component.boundClickoutHandler);
77 | $document.unbind(escapeEventName, component.boundEscapeHandler);
78 | }
79 | })),
80 |
81 | unbindClosingEvents: on('willDestroyElement', function () {
82 | let namespace = this.get('closingEventNamespace');
83 | let $document = $(document);
84 |
85 | $document.unbind('click.'+ namespace, this.boundClickoutHandler);
86 | $document.unbind('focusin.'+ namespace, this.boundClickoutHandler);
87 | $document.unbind('touchstart.'+ namespace, this.boundClickoutHandler);
88 | $document.unbind('keydown.'+ namespace, this.boundEscapeHandler);
89 | }),
90 |
91 | clickoutHandler(event) {
92 | let component = event.data.component;
93 | let $c = component.$();
94 | let $target = $(event.target);
95 |
96 | /* There is an issue when the click triggered a dom change in the
97 | * dropdown that unloaded the target element. The ancestry of the target
98 | * can no longer be determined. We can check if html is still an ancestor
99 | * to determine if this has happened. The safe option then seems to be to
100 | * not close the dropdown, as occasionaly not closing the dropdown when it
101 | * should have closed, seems to be less bad for usability than occasionaly
102 | * closing the dropdown when it should not have closed.
103 | */
104 | if(component.get('dropdownExpanded') && $target.closest('html').length &&
105 | !($target.closest($c.find(component.get('dropdownToggleSelector'))).length ||
106 | $target.closest($c.find(component.get('dropdownSelector'))).length)
107 | ) {
108 | component.send('closeDropdown');
109 | }
110 | },
111 |
112 | escapeHandler(event) {
113 | if (event.keyCode === 27) {
114 | event.data.component.send('closeDropdown');
115 | }
116 | }
117 | });
118 |
--------------------------------------------------------------------------------
/app/components/rl-dropdown-container.js:
--------------------------------------------------------------------------------
1 | import RlDropdownContainerComponent from 'ember-rl-dropdown/components/rl-dropdown-container';
2 |
3 | export default RlDropdownContainerComponent;
4 |
--------------------------------------------------------------------------------
/app/components/rl-dropdown-toggle.js:
--------------------------------------------------------------------------------
1 | import RlDropdownToggleComponent from 'ember-rl-dropdown/components/rl-dropdown-toggle';
2 |
3 | export default RlDropdownToggleComponent;
4 |
--------------------------------------------------------------------------------
/app/components/rl-dropdown.js:
--------------------------------------------------------------------------------
1 | import RlDropdownComponent from 'ember-rl-dropdown/components/rl-dropdown';
2 |
3 | export default RlDropdownComponent;
4 |
--------------------------------------------------------------------------------
/app/templates/components/rl-dropdown-container.hbs:
--------------------------------------------------------------------------------
1 | {{yield dropdownExpanded}}
2 |
--------------------------------------------------------------------------------
/bower.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "ember-rl-dropdown",
3 | "dependencies": {}
4 | }
5 |
--------------------------------------------------------------------------------
/config/ember-try.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | scenarios: [
3 | {
4 | name: 'ember-lts-2.12',
5 | npm: {
6 | devDependencies: {
7 | 'ember-source': '~2.12.0'
8 | }
9 | }
10 | },
11 | {
12 | name: 'ember-lts-2.16',
13 | npm: {
14 | devDependencies: {
15 | 'ember-source': '~2.16.0'
16 | }
17 | }
18 | },
19 | {
20 | name: 'ember-release',
21 | bower: {
22 | dependencies: {
23 | 'ember': 'components/ember#release'
24 | },
25 | resolutions: {
26 | 'ember': 'release'
27 | }
28 | },
29 | npm: {
30 | devDependencies: {
31 | 'ember-source': null
32 | }
33 | }
34 | },
35 | {
36 | name: 'ember-beta',
37 | bower: {
38 | dependencies: {
39 | 'ember': 'components/ember#beta'
40 | },
41 | resolutions: {
42 | 'ember': 'beta'
43 | }
44 | },
45 | npm: {
46 | devDependencies: {
47 | 'ember-source': null
48 | }
49 | }
50 | },
51 | {
52 | name: 'ember-canary',
53 | bower: {
54 | dependencies: {
55 | 'ember': 'components/ember#canary'
56 | },
57 | resolutions: {
58 | 'ember': 'canary'
59 | }
60 | },
61 | npm: {
62 | devDependencies: {
63 | 'ember-source': null
64 | }
65 | }
66 | },
67 | {
68 | name: 'ember-default',
69 | npm: {
70 | devDependencies: {}
71 | }
72 | }
73 | ]
74 | };
75 |
--------------------------------------------------------------------------------
/config/environment.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | module.exports = function(/* environment, appConfig */) {
4 | return { };
5 | };
6 |
--------------------------------------------------------------------------------
/ember-cli-build.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const EmberAddon = require('ember-cli/lib/broccoli/ember-addon');
4 |
5 | module.exports = function(defaults) {
6 | let app = new EmberAddon(defaults, {
7 | // Add options here
8 | });
9 |
10 | /*
11 | This build file specifies the options for the dummy test app of this
12 | addon, located in `/tests/dummy`
13 | This build file does *not* influence how the addon or the app using it
14 | behave. You most likely want to be modifying `./index.js` or app's build file
15 | */
16 |
17 | return app.toTree();
18 | };
19 |
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | module.exports = {
4 | name: 'ember-rl-dropdown'
5 | };
6 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "ember-rl-dropdown",
3 | "version": "0.10.2",
4 | "description": "Dropdown component and mixin for Ember.js",
5 | "keywords": [
6 | "ember-addon",
7 | "mixin",
8 | "component",
9 | "dropdown",
10 | "drop-down",
11 | "drop",
12 | "down"
13 | ],
14 | "license": "MIT",
15 | "author": "",
16 | "directories": {
17 | "doc": "doc",
18 | "test": "tests"
19 | },
20 | "repository": "https://github.com/rsschermer/ember-rl-dropdown",
21 | "scripts": {
22 | "build": "ember build",
23 | "lint:js": "eslint ./*.js addon addon-test-support app config lib server test-support tests",
24 | "start": "ember serve",
25 | "test": "ember try:each"
26 | },
27 | "dependencies": {
28 | "ember-cli-babel": "^6.6.0"
29 | },
30 | "devDependencies": {
31 | "broccoli-asset-rev": "^2.4.5",
32 | "ember-ajax": "^3.0.0",
33 | "ember-cli": "~2.18.2",
34 | "ember-cli-dependency-checker": "^2.0.0",
35 | "ember-cli-eslint": "^4.2.1",
36 | "ember-cli-htmlbars": "^2.0.1",
37 | "ember-cli-htmlbars-inline-precompile": "^1.0.0",
38 | "ember-cli-inject-live-reload": "^1.4.1",
39 | "ember-cli-qunit": "^4.1.1",
40 | "ember-cli-shims": "^1.2.0",
41 | "ember-cli-sri": "^2.1.0",
42 | "ember-cli-uglify": "^2.0.0",
43 | "ember-disable-prototype-extensions": "^1.1.2",
44 | "ember-export-application-global": "^2.0.0",
45 | "ember-load-initializers": "^1.0.0",
46 | "ember-resolver": "^4.0.0",
47 | "ember-source": "~2.18.0",
48 | "ember-welcome-page": "^3.0.0",
49 | "eslint-plugin-ember": "^5.0.0",
50 | "eslint-plugin-node": "^5.2.1",
51 | "loader.js": "^4.2.3"
52 | },
53 | "engines": {
54 | "node": "^4.5 || 6.* || >= 7.*"
55 | },
56 | "ember-addon": {
57 | "configPath": "tests/dummy/config",
58 | "demoURL": "http://rsschermer.github.io/ember-rl-dropdown/"
59 | },
60 | "bugs": {
61 | "url": "https://github.com/rsschermer/ember-rl-dropdown/issues"
62 | },
63 | "homepage": "https://github.com/rsschermer/ember-rl-dropdown"
64 | }
65 |
--------------------------------------------------------------------------------
/testem.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | test_page: 'tests/index.html?hidepassed',
3 | disable_watching: true,
4 | launch_in_ci: [
5 | 'Chrome'
6 | ],
7 | launch_in_dev: [
8 | 'Chrome'
9 | ],
10 | browser_args: {
11 | Chrome: {
12 | mode: 'ci',
13 | args: [
14 | // --no-sandbox is needed when running Chrome inside a container
15 | process.env.TRAVIS ? '--no-sandbox' : null,
16 |
17 | '--disable-gpu',
18 | '--headless',
19 | '--remote-debugging-port=0',
20 | '--window-size=1440,900'
21 | ].filter(Boolean)
22 | }
23 | }
24 | };
25 |
--------------------------------------------------------------------------------
/tests/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | env: {
3 | embertest: true
4 | }
5 | };
6 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/tests/dummy/app/components/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RSSchermer/ember-rl-dropdown/7fcce770042b93e0760c98e59536695bf4745756/tests/dummy/app/components/.gitkeep
--------------------------------------------------------------------------------
/tests/dummy/app/components/user-controls.js:
--------------------------------------------------------------------------------
1 | import Component from '@ember/component';
2 | import DropdownComponentMixin from 'ember-rl-dropdown/mixins/rl-dropdown-component';
3 |
4 | export default Component.extend(DropdownComponentMixin, {
5 | // Some additional custom behaviour
6 | });
7 |
--------------------------------------------------------------------------------
/tests/dummy/app/controllers/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RSSchermer/ember-rl-dropdown/7fcce770042b93e0760c98e59536695bf4745756/tests/dummy/app/controllers/.gitkeep
--------------------------------------------------------------------------------
/tests/dummy/app/helpers/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RSSchermer/ember-rl-dropdown/7fcce770042b93e0760c98e59536695bf4745756/tests/dummy/app/helpers/.gitkeep
--------------------------------------------------------------------------------
/tests/dummy/app/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Dummy
7 |
8 |
9 |
10 | {{content-for "head"}}
11 |
12 |
13 |
14 |
15 | {{content-for "head-footer"}}
16 |
17 |
18 | {{content-for "body"}}
19 |
20 |
21 |
22 |
23 | {{content-for "body-footer"}}
24 |
25 |
26 |
--------------------------------------------------------------------------------
/tests/dummy/app/models/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RSSchermer/ember-rl-dropdown/7fcce770042b93e0760c98e59536695bf4745756/tests/dummy/app/models/.gitkeep
--------------------------------------------------------------------------------
/tests/dummy/app/resolver.js:
--------------------------------------------------------------------------------
1 | import Resolver from 'ember-resolver';
2 |
3 | export default Resolver;
4 |
--------------------------------------------------------------------------------
/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('dropdown-test');
11 | this.route('dropdown-mixin-test');
12 | this.route('dropdown-with-checkbox-test');
13 | });
14 |
15 | export default Router;
16 |
--------------------------------------------------------------------------------
/tests/dummy/app/routes/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RSSchermer/ember-rl-dropdown/7fcce770042b93e0760c98e59536695bf4745756/tests/dummy/app/routes/.gitkeep
--------------------------------------------------------------------------------
/tests/dummy/app/styles/app.css:
--------------------------------------------------------------------------------
1 | html, body {
2 | margin: 20px;
3 | }
4 |
--------------------------------------------------------------------------------
/tests/dummy/app/templates/application.hbs:
--------------------------------------------------------------------------------
1 |
2 | Dropdown tests
3 |
4 | {{#link-to 'dropdown-test'}}Dropdown Test{{/link-to}} |
5 | {{#link-to 'dropdown-mixin-test'}}Dropdown Mixin Test{{/link-to}} |
6 | {{#link-to 'dropdown-with-checkbox-test'}}Dropdown with Checkbox Test{{/link-to}}
7 |
8 |
9 | {{outlet}}
10 |
--------------------------------------------------------------------------------
/tests/dummy/app/templates/components/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RSSchermer/ember-rl-dropdown/7fcce770042b93e0760c98e59536695bf4745756/tests/dummy/app/templates/components/.gitkeep
--------------------------------------------------------------------------------
/tests/dummy/app/templates/components/user-controls.hbs:
--------------------------------------------------------------------------------
1 |
2 | User controls
3 |
4 | {{#if dropdownExpanded}}
5 |
6 |
10 | {{/if}}
11 |
--------------------------------------------------------------------------------
/tests/dummy/app/templates/dropdown-mixin-test.hbs:
--------------------------------------------------------------------------------
1 |
2 | {{input type="checkbox" checked=dropdownExpanded id="dropdownCheckbox"}}
3 | dropdownExpanded
4 |
5 |
6 | {{user-controls dropdownExpanded=dropdownExpanded}}
7 |
--------------------------------------------------------------------------------
/tests/dummy/app/templates/dropdown-test.hbs:
--------------------------------------------------------------------------------
1 | {{#rl-dropdown-container as |isExpanded|}}
2 | {{#rl-dropdown-toggle}}
3 | {{#if isExpanded}}
4 | Close
5 | {{else}}
6 | Expand
7 | {{/if}}
8 | {{/rl-dropdown-toggle}}
9 |
10 | {{#rl-dropdown}}
11 | Link
12 | {{/rl-dropdown}}
13 | {{/rl-dropdown-container}}
14 |
15 |
16 |
--------------------------------------------------------------------------------
/tests/dummy/app/templates/dropdown-with-checkbox-test.hbs:
--------------------------------------------------------------------------------
1 | {{#rl-dropdown-container}}
2 | {{#rl-dropdown-toggle}}
3 | Toggle
4 | {{/rl-dropdown-toggle}}
5 |
6 | {{#rl-dropdown closeOnChildClick="a:link"}}
7 | {{input id="checkbox_in_dropdown" type="checkbox" checked=checkedCheckbox}}
8 | {{/rl-dropdown}}
9 |
10 | {{/rl-dropdown-container}}
11 |
12 |
13 | {{#if checkedCheckbox}}
14 | Checkbox is checked
15 | {{else}}
16 | Checkbox is not checked
17 | {{/if}}
18 |
19 |
--------------------------------------------------------------------------------
/tests/dummy/config/environment.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | module.exports = function(environment) {
4 | let ENV = {
5 | modulePrefix: 'dummy',
6 | environment,
7 | rootURL: '/',
8 | locationType: 'auto',
9 | EmberENV: {
10 | FEATURES: {
11 | // Here you can enable experimental features on an ember canary build
12 | // e.g. 'with-controller': true
13 | },
14 | EXTEND_PROTOTYPES: {
15 | // Prevent Ember Data from overriding Date.parse.
16 | Date: false
17 | }
18 | },
19 |
20 | APP: {
21 | // Here you can pass flags/options to your application instance
22 | // when it is created
23 | }
24 | };
25 |
26 | if (environment === 'development') {
27 | // ENV.APP.LOG_RESOLVER = true;
28 | // ENV.APP.LOG_ACTIVE_GENERATION = true;
29 | // ENV.APP.LOG_TRANSITIONS = true;
30 | // ENV.APP.LOG_TRANSITIONS_INTERNAL = true;
31 | // ENV.APP.LOG_VIEW_LOOKUPS = true;
32 | }
33 |
34 | if (environment === 'test') {
35 | // Testem prefers this...
36 | ENV.locationType = 'none';
37 |
38 | // keep test console output quieter
39 | ENV.APP.LOG_ACTIVE_GENERATION = false;
40 | ENV.APP.LOG_VIEW_LOOKUPS = false;
41 |
42 | ENV.APP.rootElement = '#ember-testing';
43 | ENV.APP.autoboot = false;
44 | }
45 |
46 | if (environment === 'production') {
47 | // here you can enable a production-specific feature
48 | }
49 |
50 | return ENV;
51 | };
52 |
--------------------------------------------------------------------------------
/tests/dummy/config/targets.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | browsers: [
3 | 'ie 9',
4 | 'last 1 Chrome versions',
5 | 'last 1 Firefox versions',
6 | 'last 1 Safari versions'
7 | ]
8 | };
9 |
--------------------------------------------------------------------------------
/tests/dummy/public/crossdomain.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
15 |
16 |
--------------------------------------------------------------------------------
/tests/dummy/public/robots.txt:
--------------------------------------------------------------------------------
1 | # http://www.robotstxt.org
2 | User-agent: *
3 | Disallow:
4 |
--------------------------------------------------------------------------------
/tests/helpers/destroy-app.js:
--------------------------------------------------------------------------------
1 | import { run } from '@ember/runloop';
2 |
3 | export default function destroyApp(application) {
4 | run(application, 'destroy');
5 | }
6 |
--------------------------------------------------------------------------------
/tests/helpers/module-for-acceptance.js:
--------------------------------------------------------------------------------
1 | import { module } from 'qunit';
2 | import { resolve } from 'rsvp';
3 | import startApp from '../helpers/start-app';
4 | import destroyApp from '../helpers/destroy-app';
5 |
6 | export default function(name, options = {}) {
7 | module(name, {
8 | beforeEach() {
9 | this.application = startApp();
10 |
11 | if (options.beforeEach) {
12 | return options.beforeEach.apply(this, arguments);
13 | }
14 | },
15 |
16 | afterEach() {
17 | let afterEach = options.afterEach && options.afterEach.apply(this, arguments);
18 | return resolve(afterEach).then(() => destroyApp(this.application));
19 | }
20 | });
21 | }
22 |
--------------------------------------------------------------------------------
/tests/helpers/resolver.js:
--------------------------------------------------------------------------------
1 | import Resolver from '../../resolver';
2 | import config from '../../config/environment';
3 |
4 | const resolver = Resolver.create();
5 |
6 | resolver.namespace = {
7 | modulePrefix: config.modulePrefix,
8 | podModulePrefix: config.podModulePrefix
9 | };
10 |
11 | export default resolver;
12 |
--------------------------------------------------------------------------------
/tests/helpers/start-app.js:
--------------------------------------------------------------------------------
1 | import Application from '../../app';
2 | import config from '../../config/environment';
3 | import { merge } from '@ember/polyfills';
4 | import { run } from '@ember/runloop';
5 |
6 | export default function startApp(attrs) {
7 | let attributes = merge({}, config.APP);
8 | attributes.autoboot = true;
9 | attributes = merge(attributes, attrs); // use defaults, but you can override;
10 |
11 | return run(() => {
12 | let application = Application.create(attributes);
13 | application.setupForTesting();
14 | application.injectTestHelpers();
15 | return application;
16 | });
17 | }
18 |
--------------------------------------------------------------------------------
/tests/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Dummy Tests
7 |
8 |
9 |
10 | {{content-for "head"}}
11 | {{content-for "test-head"}}
12 |
13 |
14 |
15 |
16 |
17 | {{content-for "head-footer"}}
18 | {{content-for "test-head-footer"}}
19 |
20 |
21 | {{content-for "body"}}
22 | {{content-for "test-body"}}
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 | {{content-for "body-footer"}}
31 | {{content-for "test-body-footer"}}
32 |
33 |
34 |
--------------------------------------------------------------------------------
/tests/integration/dropdown-components-test.js:
--------------------------------------------------------------------------------
1 | import hbs from 'htmlbars-inline-precompile';
2 | import { test, moduleForComponent } from 'ember-qunit';
3 | import Ember from 'ember';
4 |
5 | moduleForComponent('rl-dropdown-container', 'Dropdown components integration', {
6 | integration: true
7 | });
8 |
9 | test('The dropdown should not be displayed initially', function (assert) {
10 | this.render(hbs`
11 | {{#rl-dropdown-container}}
12 | {{#rl-dropdown-toggle}}Toggle{{/rl-dropdown-toggle}}
13 |
14 | {{#rl-dropdown}}
15 | ...
16 | {{/rl-dropdown}}
17 | {{/rl-dropdown-container}}
18 | `);
19 |
20 | assert.equal(this.$('.rl-dropdown').css('display'), 'none');
21 | });
22 |
23 | test('`isExpanded` correctly controls dropdown visibility', function (assert) {
24 | this.render(hbs`
25 | {{#rl-dropdown-container}}
26 | {{#rl-dropdown-toggle}}Toggle{{/rl-dropdown-toggle}}
27 |
28 | {{#rl-dropdown isExpanded=isExpanded}}
29 | ...
30 | {{/rl-dropdown}}
31 | {{/rl-dropdown-container}}
32 | `);
33 |
34 | let $dropdown = this.$('.rl-dropdown');
35 |
36 | this.set('isExpanded', false);
37 | assert.equal($dropdown.css('display'), 'none', 'The dropdown should not be displayed if `isExpanded` is false');
38 |
39 | this.set('isExpanded', true);
40 | assert.equal($dropdown.css('display'), 'block', 'The dropdown should be displayed if `isExpanded` is true');
41 | });
42 |
43 | test('The toggle button correctly controls dropdown visibility', function (assert) {
44 | this.render(hbs`
45 | {{#rl-dropdown-container}}
46 | {{#rl-dropdown-toggle}}Toggle{{/rl-dropdown-toggle}}
47 |
48 | {{#rl-dropdown}}
49 | ...
50 | {{/rl-dropdown}}
51 | {{/rl-dropdown-container}}
52 | `);
53 |
54 | let $dropdown = this.$('.rl-dropdown');
55 | let $toggleButton = this.$('.rl-dropdown-toggle');
56 |
57 | assert.equal($dropdown.css('display'), 'none', 'The dropdown is not displayed initially');
58 |
59 | $toggleButton.click();
60 | assert.equal($dropdown.css('display'), 'block', 'The dropdown is displayed after clicking the toggle button');
61 |
62 | $toggleButton.click();
63 | assert.equal($dropdown.css('display'), 'none', 'The dropdown is none displayed after clicking the toggle button twice');
64 | });
65 |
66 | test('The dropdown does not close when clicked on', function (assert) {
67 | this.render(hbs`
68 | {{#rl-dropdown-container}}
69 | {{#rl-dropdown-toggle}}Toggle{{/rl-dropdown-toggle}}
70 |
71 | {{#rl-dropdown isExpanded=true}}
72 | ...
73 | {{/rl-dropdown}}
74 | {{/rl-dropdown-container}}
75 | `);
76 |
77 | let $dropdown = this.$('.rl-dropdown');
78 |
79 | $dropdown.click();
80 |
81 | assert.equal($dropdown.css('display'), 'block');
82 | });
83 |
84 | test('The dropdown closes when clicking outside', function (assert) {
85 | this.render(hbs`
86 | {{#rl-dropdown-container}}
87 | {{#rl-dropdown-toggle}}Toggle{{/rl-dropdown-toggle}}
88 |
89 | {{#rl-dropdown isExpanded=true}}
90 | ...
91 | {{/rl-dropdown}}
92 | {{/rl-dropdown-container}}
93 |
94 | asdf
95 | `);
96 |
97 | let $dropdown = this.$('.rl-dropdown');
98 |
99 | assert.equal($dropdown.css('display'), 'block', 'The dropdown is displayed initially');
100 |
101 | // Click outside with a slight delay, because the event listener for outside clicks isn't added immediately
102 | let done = assert.async();
103 |
104 | Ember.run.later(() => {
105 | this.$().parent().find('#some-other-element').click();
106 |
107 | assert.equal($dropdown.css('display'), 'none', 'The dropdown is not displayed after clicking outside');
108 | done();
109 | }, 2);
110 | });
111 |
112 | test('`closeOnChildClick` correctly affects whether or not the dropdown closes when child elements are clicked', function (assert) {
113 | this.render(hbs`
114 | {{#rl-dropdown-container}}
115 | {{#rl-dropdown-toggle}}Toggle{{/rl-dropdown-toggle}}
116 |
117 | {{#rl-dropdown isExpanded=true closeOnChildClick=closeOnChildClick}}
118 | Link
119 | {{/rl-dropdown}}
120 | {{/rl-dropdown-container}}
121 | `);
122 |
123 | let $dropdown = this.$('.rl-dropdown');
124 |
125 | this.set('closeOnChildClick', false);
126 | $dropdown.find('a').click();
127 | assert.equal($dropdown.css('display'), 'block', 'The dropdown should not close when `closeOnChildClick` is false');
128 |
129 | this.set('closeOnChildClick', true);
130 | $dropdown.find('a').click();
131 | assert.equal($dropdown.css('display'), 'none', 'The dropdown should close when `closeOnChildClick` is true');
132 |
133 | this.set('closeOnChildClick', 'a:link');
134 | $dropdown.find('li').click();
135 | assert.equal($dropdown.css('display'), 'block', 'The dropdown should not close when `closeOnChildClick` selector is not matched');
136 |
137 | this.set('closeOnChildClick', 'a:link');
138 | $dropdown.find('a').click();
139 | assert.equal($dropdown.css('display'), 'none', 'The dropdown should close when `closeOnChildClick` selector is matched');
140 | });
141 |
142 | test('A checkbox inside the dropdown should properly check and uncheck', function (assert) {
143 | this.render(hbs`
144 | {{#rl-dropdown-container}}
145 | {{#rl-dropdown-toggle}}Toggle{{/rl-dropdown-toggle}}
146 |
147 | {{#rl-dropdown}}
148 | {{input id="checkbox-in-dropdown" type="checkbox" checked=checkedCheckbox}}
149 | {{/rl-dropdown}}
150 | {{/rl-dropdown-container}}
151 | `);
152 |
153 | this.set('checkedCheckbox', false);
154 |
155 | this.$('#checkbox-in-dropdown').click();
156 | assert.equal(this.get('checkedCheckbox'), true, 'The checkbox should get checked when clicked on');
157 |
158 | this.$('#checkbox-in-dropdown').click();
159 | assert.equal(this.get('checkedCheckbox'), false, 'The checkbox unchecks when it is clicked on a second time');
160 | });
161 |
162 | test('The container should pass a boolean block param that reflects whether the dropdown is expanded or not', function (assert) {
163 | this.render(hbs`
164 | {{#rl-dropdown-container as |dropdownExpanded|}}
165 | {{#rl-dropdown-toggle}}
166 | {{#if dropdownExpanded}}
167 | Close
168 | {{else}}
169 | Expand
170 | {{/if}}
171 | {{/rl-dropdown-toggle}}
172 |
173 | {{#rl-dropdown isExpanded=isExpanded}}
174 | ...
175 | {{/rl-dropdown}}
176 | {{/rl-dropdown-container}}
177 | `);
178 |
179 | let $dropdownToggle = this.$('.rl-dropdown-toggle');
180 |
181 | this.set('isExpanded', false);
182 | assert.equal($dropdownToggle.text().trim(), 'Expand', 'The dropdown toggle text should be "Expand" if `isExpanded` is false');
183 |
184 | this.set('isExpanded', true);
185 | assert.equal($dropdownToggle.text().trim(), 'Close', 'The dropdown toggle text should be "Close" if `isExpanded` is true');
186 | });
187 |
188 | test('The dropdown does not open when when clicking a toggle button for which disabled is true', function (assert) {
189 | this.render(hbs`
190 | {{#rl-dropdown-container}}
191 | {{#rl-dropdown-toggle disabled=true}}Toggle{{/rl-dropdown-toggle}}
192 |
193 | {{#rl-dropdown}}
194 | ...
195 | {{/rl-dropdown}}
196 | {{/rl-dropdown-container}}
197 | `);
198 |
199 | let $dropdown = this.$('.rl-dropdown');
200 | let $toggleButton = this.$('.rl-dropdown-toggle');
201 |
202 | assert.equal($dropdown.css('display'), 'none', 'The dropdown is not displayed initially');
203 |
204 | $toggleButton.click();
205 | assert.equal($dropdown.css('display'), 'none', 'The dropdown is not displayed after clicking the toggle button');
206 | });
207 |
--------------------------------------------------------------------------------
/tests/integration/dropdown-mixin-test.js:
--------------------------------------------------------------------------------
1 | import { module, test } from 'qunit';
2 | import startApp from '../helpers/start-app';
3 | import Ember from 'ember';
4 |
5 | let App;
6 |
7 | module('Dropdown mixin integration', {
8 | beforeEach() {
9 | App = startApp();
10 | },
11 |
12 | afterEach() {
13 | Ember.run(App, 'destroy');
14 | }
15 | });
16 |
17 | test('the dropdown should not be visible initialy', function (assert) {
18 | visit('/dropdown-mixin-test');
19 |
20 | andThen(() => {
21 | assert.equal(Ember.$('.user-controls-dropdown').length, 0);
22 | });
23 | });
24 |
25 | test('the dropdown should be visible after clicking the checkbox', function (assert) {
26 | visit('/dropdown-mixin-test');
27 |
28 | click('#dropdownCheckbox');
29 |
30 | andThen(() => {
31 | assert.equal(Ember.$('.user-controls-dropdown').length, 1);
32 | });
33 | });
34 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------