PageSourceSearch

https://drivetimedevotions.com/scripts/VueComponents/SaddlebackDro…?v=067bac55dc3729ccedc88375e13966800226cff8

js drivetimedevotions.com collected 2026-09-26 03:07:36 UTC 3,546 bytes, 107 lines download raw bytes

1/**
2 * SaddlebackDropdown
3 *
4 * Reusable wrapper around the site-wide select2 dropdown pattern
5 * (`.saddleback-dropdown form-selector` + jQuery select2). jQuery and select2
6 * are loaded globally in MasterLayout, so `$` is available at runtime.
7 *
8 * Usage (v-model friendly):
9 *   <SaddlebackDropdown
10 *       dropdownId="mySort"
11 *       label="Sort By"
12 *       :options="[{ id: 'newest', text: 'Newest First' }]"
13 *       v-model="sortBy"
14 *   />
15 */
16export default {
17    name: 'SaddlebackDropdown',
18    props: {
19        // Stable, unique DOM id for the underlying <select> (select2 needs one).
20        dropdownId: {
21            type: String,
22            required: true,
23        },
24        // Site-wide select2 data shape: [{ id, text }].
25        options: {
26            type: Array,
27            default: () => [],
28        },
29        modelValue: {
30            type: [String, Number],
31            default: '',
32        },
33        // Optional visible label rendered above the control.
34        label: {
35            type: String,
36            default: '',
37        },
38        // Accessible name; falls back to `label`.
39        ariaLabel: {
40            type: String,
41            default: '',
42        },
43        // Show the select2 search box (hidden by default to match site usage).
44        searchable: {
45            type: Boolean,
46            default: false,
47        },
48    },
49    emits: ['update:modelValue', 'change'],
50    watch: {
51        modelValue(newValue) {
52            const $el = $(`#${this.dropdownId}`);
53            // Guard against feedback loops: only push down when it actually differs.
54            if ($el.val() !== String(newValue)) {
55                $el.val(newValue).trigger('change.select2');
56            }
57        },
58        options: {
59            deep: true,
60            handler(newOptions) {
61                // Rebuild when options change (e.g. derived from async data).
62                this.destroyDropdown();
63                this.initDropdown(newOptions);
64            },
65        },
66    },
67    mounted() {
68        this.initDropdown(this.options);
69    },
70    beforeUnmount() {
71        this.destroyDropdown();
72    },
73    methods: {
74        initDropdown(options) {
75            $(`#${this.dropdownId}`)
76                .select2({
77                    minimumResultsForSearch: this.searchable ? 0 : Infinity,
78                    mobile: true,
79                    width: '100%',
80                    data: options,
81                })
82                // Native `change` = user interaction; `change.select2` (used for
83                // programmatic updates below) does not re-fire this handler.
84                .on('change', (e) => {
85                    const value = e.target.value;
86                    this.$emit('update:modelValue', value);
87                    this.$emit('change', value);
88                })
89                .val(this.modelValue)
90                .trigger('change.select2');
91        },
92        destroyDropdown() {
93            const $el = $(`#${this.dropdownId}`);
94            if ($el.data('select2')) {
95                $el.off('change');
96                $el.select2('destroy');
97                $el.empty();
98            }
99        },
100    },
101    template: `
102        <div class="saddleback-dropdown form-selector">
103            <label v-if="label" :for="dropdownId" class="dropdown-label">{{ label }}</label>
104            <select :id="dropdownId" :aria-label="ariaLabel || label"></select>
105        </div>
106    `,
107};

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.