PluginProbe ʕ •ᴥ•ʔ
JetFormBuilder — Dynamic Blocks Form Builder / 3.1.6
JetFormBuilder — Dynamic Blocks Form Builder v3.1.6
3.6.3.1 3.6.3 3.6.2.2 3.6.2.1 3.6.2 3.6.1.1 3.6.1 3.6.0.1 trunk 1.0.0 1.0.1 1.0.2 1.0.3 1.1.0 1.1.1 1.1.2 1.1.3 1.1.4 1.1.5 1.1.6 1.1.7 1.2.0 1.2.1 1.2.2 1.2.3 1.2.4 1.2.5 1.2.6 1.2.7 1.3.0 1.3.1 1.3.2 1.3.3 1.4.0 1.4.1 1.4.2 1.4.3 1.5.0 1.5.1 1.5.2 1.5.3 1.5.4 1.5.5 2.0.0 2.0.1 2.0.2 2.0.3 2.0.4 2.0.5 2.0.6 2.1.0 2.1.1 2.1.10 2.1.11 2.1.2 2.1.3 2.1.4 2.1.5 2.1.6 2.1.7 2.1.8 2.1.9 3.0.0 3.0.0.1 3.0.0.2 3.0.0.3 3.0.1 3.0.1.1 3.0.2 3.0.3 3.0.4 3.0.5 3.0.6 3.0.7 3.0.8 3.0.9 3.1.0 3.1.0.1 3.1.1 3.1.2 3.1.3 3.1.4 3.1.5 3.1.6 3.1.7 3.1.8 3.1.9 3.2.0 3.2.1 3.2.2 3.2.3 3.3.0 3.3.1 3.3.2 3.3.3 3.3.3.1 3.3.4 3.3.4.1 3.3.4.2 3.4.0 3.4.1 3.4.2 3.4.3 3.4.4 3.4.5 3.4.5.1 3.4.5.2 3.4.6 3.4.7 3.4.7.1 3.5.0 3.5.1 3.5.1.1 3.5.1.2 3.5.2 3.5.2.1 3.5.3 3.5.4 3.5.5 3.5.6 3.5.6.1 3.5.6.2 3.5.6.3 3.6.0
jetformbuilder / assets / src / admin-package / components / CxVuiFSelect.vue
jetformbuilder / assets / src / admin-package / components Last commit date
ColumnWrapper.vue 2 years ago CxVuiCollapseMini.vue 2 years ago CxVuiDate.vue 2 years ago CxVuiFSelect.vue 2 years ago CxVuiPopup.vue 2 years ago CxVuiSelect.vue 2 years ago CxVuiTabs.vue 2 years ago CxVuiTabsPanel.vue 2 years ago Delimiter.vue 2 years ago DetailsTable.vue 2 years ago DetailsTableRow.vue 2 years ago DetailsTableRowValue.vue 2 years ago ExternalLink.vue 2 years ago ListComponents.vue 2 years ago PrintButton.vue 2 years ago RowWrapper.vue 2 years ago Tooltip.vue 2 years ago
CxVuiFSelect.vue
345 lines
1 <template>
2 <div class="cx-vui-f-select">
3 <div :class="{
4 'cx-vui-f-select__selected': true,
5 'cx-vui-f-select__selected-not-empty': this.value.length > 0
6 }">
7 <div
8 v-for="option in value"
9 class="cx-vui-f-select__selected-option"
10 @click="handleResultClick( option )"
11 >
12 <template v-if="$slots[ 'option-' + option ]">
13 <slot :name="'option-' + option"></slot>
14 </template>
15 <template v-else>
16 <span v-if="!isNonRemovable( option )" class="cx-vui-f-select__selected-option-icon">
17 <svg width="10" height="10" viewBox="0 0 10 10" fill="none" xmlns="http://www.w3.org/2000/svg">><path
18 d="M10 1.00671L6.00671 5L10 8.99329L8.99329 10L5 6.00671L1.00671 10L0 8.99329L3.99329 5L0 1.00671L1.00671 0L5 3.99329L8.99329 0L10 1.00671Z"/></svg>
19 </span>
20 {{ getOptionLabel( option ) }}
21 </template>
22 </div>
23 </div>
24 <div
25 v-click-outside.capture="onClickOutside"
26 v-click-outside:mousedown.capture="onClickOutside"
27 v-click-outside:touchstart.capture="onClickOutside"
28
29 @keydown.up.prevent="handleOptionsNav"
30 @keydown.down.prevent="handleOptionsNav"
31 @keydown.tab="handleOptionsNav"
32 @keydown.enter="handleEnter"
33
34 class="cx-vui-f-select__control"
35 >
36 <input
37 :id="elementId"
38 :placeholder="placeholder"
39 :autocomplete="autocomplete"
40 type="text"
41 :value="query"
42 @input="handleInput"
43 @focus="handleFocus"
44 :class="{
45 'cx-vui-f-select__input': true,
46 'cx-vui-input--in-focus': inFocus,
47 'cx-vui-input': true,
48 ['cx-vui-input--' + stateType() ]: stateType(),
49 'size-fullwidth': true,
50 'has-error': error,
51 }"
52 >
53 <div class="cx-vui-f-select__results" v-if="inFocus">
54 <div
55 v-if="! filteredOptions.length"
56 v-html="notFoundMeassge"
57 class="cx-vui-f-select__results-message"
58 ></div>
59 <div v-else>
60 <div
61 v-for="( option, optionIndex ) in filteredOptions"
62 :class="{
63 'cx-vui-f-select__result': true,
64 'in-focus': optionIndex === optionInFocus,
65 'is-selected': isSelectedOption( option )
66 }"
67 @click="handleResultClick( option.value )"
68 >{{ getOptionLabel( option ) }}
69 </div>
70 </div>
71 </div>
72 </div>
73 <select
74 :placeholder="placeholder"
75 :disabled="disabled"
76 :readonly="readonly"
77 :multiple="multiple"
78 :value="currentValues"
79 class="cx-vui-f-select__select-tag"
80 >
81 <option
82 v-for="option in currentValues"
83 :value="option"
84 selected
85 ></option>
86 </select>
87 </div>
88 </template>
89
90 <script>
91 import { directive as clickOutside } from 'v-click-outside-x';
92
93 export default {
94 name: 'CxVuiFSelect',
95 directives: { clickOutside },
96 props: {
97 value: {
98 type: [ String, Number, Array ],
99 default: '',
100 },
101 placeholder: {
102 type: String,
103 default: '',
104 },
105 optionsList: {
106 type: Array,
107 default: function () {
108 return [];
109 },
110 },
111 disabled: {
112 type: Boolean,
113 default: false,
114 },
115 readonly: {
116 type: Boolean,
117 default: false,
118 },
119 error: {
120 type: Boolean,
121 default: false,
122 },
123 multiple: {
124 type: Boolean,
125 default: false,
126 },
127 autocomplete: {
128 validator( value ) {
129 return [ 'on', 'off' ].includes( value );
130 },
131 default: 'off',
132 },
133 conditions: {
134 type: Array,
135 default: function () {
136 return [];
137 },
138 },
139 remote: {
140 type: Boolean,
141 default: false,
142 },
143 remoteCallback: {
144 type: Function,
145 },
146 remoteTrigger: {
147 type: Number,
148 default: 3,
149 },
150 remoteTriggerMessage: {
151 type: String,
152 default: 'Please enter %d char(s) to start search',
153 },
154 notFoundMeassge: {
155 type: String,
156 default: 'There is no items find matching this query',
157 },
158 loadingMessage: {
159 type: String,
160 default: 'Loading...',
161 },
162 preventWrap: {
163 type: Boolean,
164 default: false,
165 },
166 // Wrapper related props (should be passed into wrapper component)
167 wrapperCss: {
168 type: Array,
169 default: function () {
170 return [];
171 },
172 },
173 // basically used from injected
174 elementId: {
175 type: String,
176 },
177 // basically used from injected
178 stateType: {
179 type: Function,
180 },
181 },
182 data() {
183 return {
184 query: '',
185 inFocus: false,
186 optionInFocus: false,
187 loading: false,
188 loaded: false,
189 };
190 },
191 created() {
192 if ( !this.currentValues ) {
193 this.currentValues = [];
194 }
195 },
196 computed: {
197 filteredOptions() {
198 if ( !this.query ) {
199 return this.optionsList;
200 }
201 else {
202 return this.optionsList.filter( option => {
203 return option.label.includes( this.query ) || option.value.includes( this.query );
204 } );
205 }
206 },
207 },
208 methods: {
209 handleFocus( event ) {
210 this.inFocus = true;
211 this.$emit( 'on-focus', event );
212 },
213 handleOptionsNav( event ) {
214
215 // next
216 if ( 'ArrowUp' === event.key || 'Tab' === event.key ) {
217 this.navigateOptions( -1 );
218 }
219 // prev
220 if ( 'ArrowDown' === event.key ) {
221 this.navigateOptions( 1 );
222 }
223
224 },
225 navigateOptions( direction ) {
226
227 if ( false === this.optionInFocus ) {
228 this.optionInFocus = -1;
229 }
230
231 let index = this.optionInFocus + direction;
232 let maxLength = this.filteredOptions.length - 1;
233
234 if ( maxLength < 0 ) {
235 maxLength = 0;
236 }
237
238 if ( index < 0 ) {
239 index = 0;
240 }
241 else if ( index > maxLength ) {
242 index = maxLength;
243 }
244
245 this.optionInFocus = index;
246
247 },
248 onClickOutside( event ) {
249
250 if ( this.inFocus ) {
251 this.inFocus = false;
252 this.$emit( 'on-blur', event );
253 }
254
255 },
256 handleInput( event ) {
257 this.$emit( 'input', event.target.value );
258 this.query = event.target.value;
259
260 if ( !this.inFocus ) {
261 this.inFocus = true;
262 }
263
264 },
265 handleEnter() {
266
267 if ( false === this.optionInFocus || !this.optionsList[ this.optionInFocus ] ) {
268 return;
269 }
270
271 let value = this.filteredOptions[ this.optionInFocus ].value;
272
273 this.handleResultClick( value );
274
275 },
276 handleResultClick( value ) {
277 if ( this.isNonRemovable( value ) ) {
278 return;
279 }
280
281 if ( this.value.includes( value ) ) {
282 this.removeValue( value );
283 }
284 else if ( this.multiple ) {
285 this.storeValues( [
286 ...new Set( this.value ),
287 value,
288 ] );
289 }
290 else {
291 this.storeValues( value );
292 }
293
294 this.inFocus = false;
295 this.optionInFocus = false;
296 this.query = '';
297
298 },
299 removeValue( value ) {
300 if ( !this.multiple ) {
301 this.storeValues( '' );
302 }
303 const filtered = this.value.filter( current => current !== value );
304
305 this.storeValues( filtered );
306 },
307 storeValues( value ) {
308 this.$emit( 'change', this.sanitizeValue( value ) );
309 },
310 getOptionLabel( option ) {
311 const optionValue = 'string' === typeof option ? option : option.value;
312 const find = this.optionsList.find( ( { value } ) => value === optionValue );
313
314 return find?.label ?? '';
315 },
316 sanitizeValue( value ) {
317 if ( this.multiple ) {
318 return Array.isArray( value ) ? value : [ value ].filter( Boolean );
319 }
320
321 return Array.isArray( value ) ? value[ 0 ] : value;
322 },
323 isSelectedOption( option ) {
324 const optionValue = 'string' === typeof option ? option : option.value;
325
326 return this.value.includes( optionValue );
327 },
328 isNonRemovable( option ) {
329 const optionValue = 'string' === typeof option ? option : option.value;
330 const find = this.optionsList.find( ( { value } ) => value === optionValue );
331
332 return find?.nonRemovable ?? false;
333 },
334 },
335 inject: [ 'elementId', 'stateType' ],
336 };
337 </script>
338
339 <style scoped lang="scss">
340 .cx-vui-input {
341 &--warning-danger {
342 border: 1px solid #d63638;
343 }
344 }
345 </style>