Skip to content

Commit

Permalink
openOnFocus fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
patrickkunka committed Mar 31, 2019
1 parent 216384c commit 525f775
Show file tree
Hide file tree
Showing 17 changed files with 112 additions and 9 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
Changelog
=========

## 4.1.1
- Fixes issue introduced in 4.1.0 where UI no longer closed on select by default
- Fixes issue introduced in 4.1.0 where clicking an option while `behavior.openOnFocus` set would close the UI without selecting any option.

## 4.1.0
- Fixes a styling issue in Beanstalk and Ivy themes where native select element was discoverable on click to the left of the head element.
- Fixes the `behavior.closeOnSelect` configuration option which not previously implemented internally.
Expand Down
2 changes: 1 addition & 1 deletion bundle/easydropdown.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion bundle/easydropdown.js.map

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion demos/easydropdown.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion demos/easydropdown.js.map

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "easydropdown",
"version": "4.1.0",
"version": "4.1.1",
"description": "A lightweight library for building beautiful styleable select elements",
"author": "KunkaLabs Limited",
"private": false,
Expand Down
2 changes: 1 addition & 1 deletion src/Config/Behavior.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import IBehavior from './Interfaces/IBehavior';
class Behavior implements IBehavior {
public showPlaceholderWhenOpen: boolean = false;
public openOnFocus: boolean = false;
public closeOnSelect: boolean = false;
public closeOnSelect: boolean = true;
public useNativeUiOnMobile: boolean = true;
public loop: boolean = false;
public clampMaxVisibleItems: boolean = true;
Expand Down
33 changes: 33 additions & 0 deletions src/Events/Handlers/handleBodyMousedown.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import {assert} from 'chai';
import {spy} from 'sinon';

import createMockEvent from '../Mock/createMockEvent';
import createMockHandlerParams from '../Mock/createMockHandlerParams';

import handleBodyMousedown from './handleBodyMousedown';

describe('handleBodyMousedown()', () => {
it('calls `stopPropagation` on the provided event', () => {
const params = createMockHandlerParams();
const mockEvent = createMockEvent();

handleBodyMousedown(mockEvent, params);

assert.isTrue(mockEvent.stopPropagation.called);
});

it('calls `actions.startClickSelecting()` if the event target is an option', () => {
const params = createMockHandlerParams();
const startClickSelectingSpy = spy(params.actions, 'startClickSelecting');
const option = document.createElement('div');
const mockEvent = createMockEvent(option);

option.setAttribute('data-ref', 'option');

params.dom.option.push(option);

handleBodyMousedown(mockEvent, params);

assert.isTrue(startClickSelectingSpy.called);
});
});
15 changes: 15 additions & 0 deletions src/Events/Handlers/handleBodyMousedown.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import closestParent from '../../Shared/Util/closestParent';
import * as Selectors from '../Constants/Selectors';
import IHandlerParams from '../Interfaces/IHandlerParams';

function handleBodyMousedown(e: Event, {actions}: IHandlerParams): void {
e.stopPropagation();

const option = closestParent(e.target as HTMLElement, Selectors.OPTION, true);

if (!option) return;

actions.startClickSelecting();
}

export default handleBodyMousedown;
21 changes: 20 additions & 1 deletion src/Events/Handlers/handleSelectBlur.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,18 +29,37 @@ describe('handleSelectBlur()', () => {
assert.isFalse(blurSpy.called);
});

it('calls `actions.close()` if `config.openOnFocus` is set', () => {
it('calls `actions.close()` if `config.openOnFocus` is set and `state.isClickSelecting` not set', () => {
const params = createMockHandlerParams({
behavior: {
openOnFocus: true
}
});

params.state.isClickSelecting = false;

const mockEvent = createMockEvent();
const closeSpy = spy(params.actions, 'close');

handleSelectBlur(mockEvent, params);

assert.isTrue(closeSpy.called);
});

it('does not call `actions.close()` if `config.openOnFocus` is set and `state.isClickSelecting` is set', () => {
const params = createMockHandlerParams({
behavior: {
openOnFocus: true
}
});

params.state.isClickSelecting = true;

const mockEvent = createMockEvent();
const closeSpy = spy(params.actions, 'close');

handleSelectBlur(mockEvent, params);

assert.isFalse(closeSpy.called);
});
});
2 changes: 1 addition & 1 deletion src/Events/Handlers/handleSelectBlur.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ function handleSelectBlur(e: Event, {actions, state, config}: IHandlerParams): v

actions.blur();

if (config.behavior.openOnFocus) actions.close();
if (config.behavior.openOnFocus && !state.isClickSelecting) actions.close();
}

export default handleSelectBlur;
6 changes: 6 additions & 0 deletions src/Events/getEventsList.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import Dom from '../Renderer/Dom';

import handleBodyClick from './Handlers/handleBodyClick';
import handleBodyMousedown from './Handlers/handleBodyMousedown';
import handleBodyMouseover from './Handlers/handleBodyMouseover';
import handleHeadClick from './Handlers/handleHeadClick';
import handleItemsListScroll from './Handlers/handleItemsListScroll';
Expand All @@ -19,6 +20,11 @@ const getEventsList = (dom: Dom): IEventBinding[] => [
type: 'click',
handler: handleHeadClick
},
{
target: dom.body,
type: 'mousedown',
handler: handleBodyMousedown
},
{
target: dom.body,
type: 'click',
Expand Down
1 change: 1 addition & 0 deletions src/State/Interfaces/IActions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ interface IActions {
close(): void;
makeScrollable(): void;
makeUnscrollable(): void;
startClickSelecting(): void;
selectOption(index: number, close?: boolean): void;
focusOption(index: number, shouldScrollToView?: boolean): void;
search(): void;
Expand Down
1 change: 1 addition & 0 deletions src/State/State.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ class State {
public isFocused: boolean = false;
public isUseNativeMode: boolean = false;
public isScrollable: boolean = false;
public isClickSelecting: boolean = false;
public isSearching: boolean = false;
public isKeying: boolean = false;

Expand Down
18 changes: 18 additions & 0 deletions src/State/resolveActions.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -183,13 +183,31 @@ describe('resolveActions', function(): void {
});
});

describe('.startClickSelecting()', () => {
it('sets `state.isClickSelecting` to `true`', () => {
self.actions.startClickSelecting();

assert.isTrue(self.state.isClickSelecting);
});
});

describe('.selectOption()', () => {
it('sets `state.selectedIndex` to the provided index', () => {
self.actions.selectOption(2);

assert.equal(self.state.selectedIndex, 2);
});

it('sets `state.isClickSelecting` to `false`', () => {
self.actions.startClickSelecting();

assert.isTrue(self.state.isClickSelecting);

self.actions.selectOption(2);

assert.isFalse(self.state.isClickSelecting);
});

it(
'it does not set `state.selectedIndex` to the provided ' +
'index, if the option is disabled',
Expand Down
6 changes: 6 additions & 0 deletions src/State/resolveActions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,9 +75,15 @@ const resolveActions = (state: State): IActions => ({
state.focusedIndex = -1;
},

startClickSelecting(): void {
state.isClickSelecting = true;
},

selectOption(this: IActions, index: number, close = true): void {
const optionAtIndex = state.getOptionFromIndex(index);

state.isClickSelecting = false;

if (index > -1 && (!optionAtIndex || optionAtIndex.isDisabled)) return;

state.selectedIndex = index;
Expand Down

0 comments on commit 525f775

Please sign in to comment.