+131
-11
lines changedFilter options
+131
-11
lines changed Original file line number Diff line number Diff line change
@@ -77,7 +77,7 @@
77
77
"events": [
78
78
{
79
79
"event": "blur",
80
-
"description": "Emitted after the input looses focus",
80
+
"description": "Emitted after the input loses focus",
81
81
"args": [
82
82
{
83
83
"arg": "event",
Original file line number Diff line number Diff line change
@@ -2,7 +2,14 @@
2
2
// Based loosely on https://adamwathan.me/renderless-components-in-vuejs/
3
3
import { Vue } from '../../vue'
4
4
import { NAME_FORM_TAGS } from '../../constants/components'
5
-
import { EVENT_NAME_TAG_STATE, EVENT_OPTIONS_PASSIVE } from '../../constants/events'
5
+
import {
6
+
EVENT_NAME_BLUR,
7
+
EVENT_NAME_FOCUS,
8
+
EVENT_NAME_FOCUSIN,
9
+
EVENT_NAME_FOCUSOUT,
10
+
EVENT_NAME_TAG_STATE,
11
+
EVENT_OPTIONS_PASSIVE
12
+
} from '../../constants/events'
6
13
import { CODE_BACKSPACE, CODE_DELETE, CODE_ENTER } from '../../constants/key-codes'
7
14
import {
8
15
PROP_TYPE_ARRAY,
@@ -24,7 +31,7 @@ import { identity } from '../../utils/identity'
24
31
import { isEvent, isNumber, isString } from '../../utils/inspect'
25
32
import { looseEqual } from '../../utils/loose-equal'
26
33
import { makeModelMixin } from '../../utils/model'
27
-
import { pick, sortKeys } from '../../utils/object'
34
+
import { omit, pick, sortKeys } from '../../utils/object'
28
35
import { hasPropFunction, makeProp, makePropsConfigurable } from '../../utils/props'
29
36
import { escapeRegExp, toString, trim, trimLeft } from '../../utils/string'
30
37
import { formControlMixin, props as formControlProps } from '../../mixins/form-control'
@@ -154,7 +161,8 @@ export const BFormTags = /*#__PURE__*/ Vue.extend({
154
161
// Tags that were removed
155
162
removedTags: [],
156
163
// Populated when tags are parsed
157
-
tagsState: cleanTagsState()
164
+
tagsState: cleanTagsState(),
165
+
focusState: null
158
166
}
159
167
},
160
168
computed: {
@@ -180,9 +188,11 @@ export const BFormTags = /*#__PURE__*/ Vue.extend({
180
188
},
181
189
computedInputHandlers() {
182
190
return {
183
-
...this.bvListeners,
184
-
input: this.onInputInput,
191
+
...omit(this.bvListeners, [EVENT_NAME_FOCUSIN, EVENT_NAME_FOCUSOUT]),
192
+
blur: this.onInputBlur,
185
193
change: this.onInputChange,
194
+
focus: this.onInputFocus,
195
+
input: this.onInputInput,
186
196
keydown: this.onInputKeydown,
187
197
reset: this.reset
188
198
}
@@ -411,11 +421,39 @@ export const BFormTags = /*#__PURE__*/ Vue.extend({
411
421
})
412
422
}
413
423
},
414
-
onFocusin() {
424
+
onInputFocus(event) {
425
+
if (this.focusState !== 'out') {
426
+
this.focusState = 'in'
427
+
this.$nextTick(() => {
428
+
requestAF(() => {
429
+
if (this.hasFocus) {
430
+
this.$emit(EVENT_NAME_FOCUS, event)
431
+
this.focusState = null
432
+
}
433
+
})
434
+
})
435
+
}
436
+
},
437
+
onInputBlur(event) {
438
+
if (this.focusState !== 'in') {
439
+
this.focusState = 'out'
440
+
this.$nextTick(() => {
441
+
requestAF(() => {
442
+
if (!this.hasFocus) {
443
+
this.$emit(EVENT_NAME_BLUR, event)
444
+
this.focusState = null
445
+
}
446
+
})
447
+
})
448
+
}
449
+
},
450
+
onFocusin(event) {
415
451
this.hasFocus = true
452
+
this.$emit(EVENT_NAME_FOCUSIN, event)
416
453
},
417
-
onFocusout() {
454
+
onFocusout(event) {
418
455
this.hasFocus = false
456
+
this.$emit(EVENT_NAME_FOCUSOUT, event)
419
457
},
420
458
handleAutofocus() {
421
459
this.$nextTick(() => {
Original file line number Diff line number Diff line change
@@ -843,7 +843,7 @@ describe('form-tags', () => {
843
843
wrapper.destroy()
844
844
})
845
845
846
-
it('emits focus and blur events', async () => {
846
+
it('emits focus and blur events when wrapper gains/loses focus', async () => {
847
847
const onFocus = jest.fn()
848
848
const onBlur = jest.fn()
849
849
const wrapper = mount(BFormTags, {
@@ -864,6 +864,7 @@ describe('form-tags', () => {
864
864
865
865
$input.trigger('focus')
866
866
$input.trigger('focusin')
867
+
867
868
await waitNT(wrapper.vm)
868
869
await waitRAF()
869
870
@@ -879,4 +880,40 @@ describe('form-tags', () => {
879
880
880
881
wrapper.destroy()
881
882
})
883
+
884
+
it('emits focusin and focusout when internal focus changes', async () => {
885
+
const onFocusIn = jest.fn()
886
+
const onFocusOut = jest.fn()
887
+
const wrapper = mount(BFormTags, {
888
+
propsData: {
889
+
value: ['apple', 'orange']
890
+
},
891
+
listeners: {
892
+
focusin: onFocusIn,
893
+
focusout: onFocusOut
894
+
}
895
+
})
896
+
897
+
expect(onFocusIn).not.toHaveBeenCalled()
898
+
expect(onFocusOut).not.toHaveBeenCalled()
899
+
900
+
const $input = wrapper.find('input')
901
+
const $tag = wrapper.find('.b-form-tag')
902
+
903
+
$input.trigger('focusin')
904
+
905
+
await waitNT(wrapper.vm)
906
+
await waitRAF()
907
+
908
+
expect(onFocusIn).toHaveBeenCalledTimes(1)
909
+
expect(onFocusOut).not.toHaveBeenCalled()
910
+
911
+
$tag.trigger('focusin')
912
+
$input.trigger('focusout')
913
+
await waitNT(wrapper.vm)
914
+
await waitRAF()
915
+
916
+
expect(onFocusIn).toHaveBeenCalledTimes(2)
917
+
expect(onFocusOut).toHaveBeenCalledTimes(1)
918
+
})
882
919
})
Original file line number Diff line number Diff line change
@@ -130,6 +130,50 @@
130
130
}
131
131
],
132
132
"events": [
133
+
{
134
+
"event": "blur",
135
+
"description": "Emitted when component loses focus",
136
+
"args": [
137
+
{
138
+
"arg": "event",
139
+
"type": "FocusEvent",
140
+
"description": "Native blur event (before any formatting)"
141
+
}
142
+
]
143
+
},
144
+
{
145
+
"event": "focus",
146
+
"description": "Emitted when component gains focus",
147
+
"args": [
148
+
{
149
+
"arg": "event",
150
+
"type": "FocusEvent",
151
+
"description": "Native focus event (before any formatting)"
152
+
}
153
+
]
154
+
},
155
+
{
156
+
"event": "focusin",
157
+
"description": "Emitted when internal elements of component gain focus.",
158
+
"args": [
159
+
{
160
+
"arg": "event",
161
+
"type": "FocusEvent",
162
+
"description": "Native focusin event (before any formatting)"
163
+
}
164
+
]
165
+
},
166
+
{
167
+
"event": "focusout",
168
+
"description": "Emitted when internal elements of component lose focus.",
169
+
"args": [
170
+
{
171
+
"arg": "event",
172
+
"type": "FocusEvent",
173
+
"description": "Native focusout event (before any formatting)"
174
+
}
175
+
]
176
+
},
133
177
{
134
178
"event": "input",
135
179
"description": "Emitted when the tags changes. Updates the v-model",
Original file line number Diff line number Diff line change
@@ -73,7 +73,7 @@
73
73
"events": [
74
74
{
75
75
"event": "blur",
76
-
"description": "Emitted after the textarea looses focus",
76
+
"description": "Emitted after the textarea loses focus",
77
77
"args": [
78
78
{
79
79
"arg": "event",
Original file line number Diff line number Diff line change
@@ -705,7 +705,7 @@ export const BVTooltip = /*#__PURE__*/ Vue.extend({
705
705
eventOn(el, 'focusin', this.handleEvent, EVENT_OPTIONS_NO_CAPTURE)
706
706
eventOn(el, 'focusout', this.handleEvent, EVENT_OPTIONS_NO_CAPTURE)
707
707
} else if (trigger === 'blur') {
708
-
// Used to close $tip when element looses focus
708
+
// Used to close $tip when element loses focus
709
709
/* istanbul ignore next */
710
710
eventOn(el, 'focusout', this.handleEvent, EVENT_OPTIONS_NO_CAPTURE)
711
711
} else if (trigger === 'hover') {
Original file line number Diff line number Diff line change
@@ -16,6 +16,7 @@ export const EVENT_NAME_ENABLE = 'enable'
16
16
export const EVENT_NAME_ENABLED = 'enabled'
17
17
export const EVENT_NAME_FILTERED = 'filtered'
18
18
export const EVENT_NAME_FIRST = 'first'
19
+
export const EVENT_NAME_FOCUS = 'focus'
19
20
export const EVENT_NAME_FOCUSIN = 'focusin'
20
21
export const EVENT_NAME_FOCUSOUT = 'focusout'
21
22
export const EVENT_NAME_HEAD_CLICKED = 'head-clicked'
You can’t perform that action at this time.
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4