PageSourceSearch

https://www.janvanas.nl/static/themes/cloudsuite_responsive/js/vue-components/range-filter.js?q=1741152743

js janvanas.nl collected 2026-09-26 00:18:12 UTC 10,267 bytes, 275 lines download raw bytes

1// https://davidwalsh.name/javascript-debounce-function
2
3// Returns a function, that, as long as it continues to be invoked, will not
4// be triggered. The function will be called after it stops being called for
5// N milliseconds. If `immediate` is passed, trigger the function on the
6// leading edge, instead of the trailing.
7function debounce(func, wait, immediate) {
8	var timeout;
9	return function() {
10		var context = this, args = arguments;
11		var later = function() {
12			timeout = null;
13			if (!immediate) func.apply(context, args);
14		};
15		var callNow = immediate && !timeout;
16		clearTimeout(timeout);
17		timeout = setTimeout(later, wait);
18		if (callNow) func.apply(context, args);
19	};
20}
21
22Vue.component('slider', {
23    // depends on jquery ui slider
24    props: [
25        'range_min',
26        'range_max',
27        'selected_min',
28        'selected_max'
29    ],
30    mounted: function() {
31        let self = this;
32        $(this.$el).slider({
33            range: true,
34            min: Number(this.range_min),
35            max: Number(this.range_max),
36            values: [Number(this.selected_min), Number(this.selected_max) || Number(this.range_max)],
37            slide: function(event, ui) {
38                self.$emit('update-range', ui.values);
39            },
40            change: function() {
41                self.$emit('check-range');
42            }
43        })
44    },
45    watch: {
46        selected_min: function(val) {
47            $(this.$el).slider('values', 0, val);
48        },
49        selected_max: function(val) {
50            $(this.$el).slider('values', 1, val);
51        }
52    },
53    beforeDestroy: function() {
54        $(this.$el).slider('destroy');
55    },
56    template: '<div class="range-filter-slider"></div>'
57});
58
59Vue.component('range-filter', {
60    props: [
61        'range_min',
62        'range_max',
63        'selected_min',
64        'selected_max',
65        'x',
66        'y',
67        'width',
68        'height',
69        'filter_url',
70        'clear_url',
71        'check_url',
72        'uom',
73        'bg_color',
74        'fg_color',
75        'selection_color'
76    ],
77    mounted: function () {
78        this.init();
79    },
80    data: function () {
81        return {
82            selected_min_value: Number(this.selected_min) || Number(this.range_min),
83            selected_max_value: Number(this.selected_max) || Number(this.range_max),
84            items_found: false,
85            hasChanged: false,
86            untouched: !this.selected_min && !this.selected_max
87        }
88    },
89    watch: {
90        selected_min_value: function() {
91            this.hasChanged = true;
92            this.renderSelection();
93        },
94        selected_max_value: function() {
95            this.hasChanged = true;
96            this.renderSelection();
97        }
98    },
99    methods: {
100        init() {
101            this.initData();
102            this.setCanvasContext();
103            this.renderGraph();
104            this.renderSelection();
105        },
106        setCanvasContext() {
107            this.ctx = this.$refs['graph-canvas'].getContext('2d');
108            this.interactive_ctx = this.$refs['interactive-canvas'].getContext('2d');
109        },
110        fixMinValue(e) {
111            var val = e.target.value;
112            
113            if (val === null) {
114                return;
115            }
116            if (!this.selected_min_value) {
117                this.selected_min_value = Number(this.range_min);
118            }
119            if (Number(this.selected_min_value) > Number(this.selected_max_value)) {
120                this.selected_min_value = Number(this.selected_max_value);
121            }
122            if(Number(this.selected_min_value) < Number(this.range_min)) {
123                this.selected_min_value = Number(this.range_min);
124            }
125            this.renderSelection();
126        },
127        fixMaxValue(e) {
128            var val = e.target.value;
129            
130            if (val === null) {
131                return;
132            }
133            if (!this.selected_max_value) {
134                this.selected_max_value = Number(this.range_max);
135            }
136            if (Number(this.selected_max_value) <= Number(this.selected_min_value)) {
137                this.selected_max_value = Number(this.selected_min_value) + 1;
138            }
139            if(Number(this.selected_max_value) > Number(this.range_max)) {
140                this.selected_max_value = Number(this.range_max);
141            }
142            this.renderSelection();
143        },
144        initData() {
145            this.x_values = this.x.split(',');
146            this.y_values = this.y.split(',');
147
148            this.min_x = Math.min.apply(Math, this.x_values);
149            this.max_x = Math.max.apply(Math, this.x_values);
150            this.dest_min_x = 0;
151            this.dest_max_x = this.width;
152
153            this.min_y = Math.min.apply(Math, this.y_values);
154            this.max_y = Math.max.apply(Math, this.y_values);
155            this.dest_min_y = 0;
156            this.dest_max_y = this.height;
157        },
158        clearScreen() {
159            this.ctx.fillStyle = this.bg_color;
160            this.ctx.fillRect(0, 0, this.width, this.height);
161        },
162        clearInteractiveScreen() {
163            this.interactive_ctx.clearRect(0, 0, this.width, this.height);
164        },
165        remapValue(value, min, max, dest_min, dest_max) {
166            let old_range = max - min;
167            let new_range = dest_max - dest_min;
168            return (((value - min) * new_range) / old_range) + dest_min;
169        },
170        renderGraph() {
171            this.clearScreen();
172
173            for (let i = 0; i < this.x_values.length; i++) {
174                let x = this.remapValue(this.x_values[i], this.min_x, this.max_x, this.dest_min_x, this.dest_max_x);
175                let y = this.remapValue(this.y_values[i], this.min_y, this.max_y, this.dest_min_y, this.dest_max_y);
176
177                if (isNaN(y)) {
178                    y = 1;
179                }
180
181                // they would be invisible otherwise
182                if (y < 2) {
183                    y = 2;
184                }
185                this.ctx.fillStyle = this.fg_color;
186                this.ctx.fillRect(x, this.height - y, 2, y);
187            }
188        },
189        renderSelection() {
190            this.clearInteractiveScreen();
191            if (this.selected_min_value || this.selected_max_value) {
192                let x1 = this.remapValue(this.selected_min_value, this.min_x, this.max_x, this.dest_min_x, this.dest_max_x);
193                let x2 = this.remapValue(this.selected_max_value, this.min_x, this.max_x, this.dest_min_x, this.dest_max_x);
194
195                this.interactive_ctx.fillStyle = this.selection_color;
196                this.interactive_ctx.globalAlpha = 0.1;
197                this.interactive_ctx.fillRect(x1, 0, x2 - x1, this.height);
198                this.interactive_ctx.globalAlpha = 1.0;
199            }
200        },
201        filter(event) {
202            event.preventDefault();
203            if (this.selected_min_value || this.selected_max_value) {
204                window.location.href = this.updateUrl(this.filter_url);
205            }
206        },
207        clear(event) {
208            event.preventDefault();
209            if (this.untouched) {
210                this.selected_min_value = Number(this.range_min);
211                this.selected_max_value = Number(this.range_max);
212                this.clearInteractiveScreen();
213                this.hasChanged = false;
214            } else {
215                window.location.href = this.clear_url;
216            }
217        },
218        updateUrl(url) {
219            url = url.replace('min_argument', this.formatAsDecimal(this.selected_min_value || this.min_x));
220            url = url.replace('max_argument', this.formatAsDecimal(this.selected_max_value || this.max_x));
221            return url
222        },
223        formatAsDecimal(num) {
224            if (Number.isInteger(num)) {
225                return Number(num).toFixed(1);
226            }
227            return Number(num).toString();
228        },
229        updateRange(range) {
230            this.selected_min_value = Number(range[0]);
231            this.selected_max_value = Number(range[1]);
232        },
233        checkRange: debounce(function() {
234            let self = this;
235            let url = this.updateUrl(this.check_url);
236            $.get(url, function(res) {
237                self.items_found = res.total_found;
238            })
239        }, 250)
240    },
241    template: `
242        <div class="range-filter">
243            <div class="row range-filter-header">
244                <div class="col-xs-6">{{ range_min }} {{ this.uom }}</div>
245                <div class="col-xs-6 text-right">{{ range_max }} {{ this.uom }}</div>
246            </div>
247            <canvas ref="interactive-canvas"
248                    :width="width"
249                    :height="height"
250                    v-show="x"
251                    class="interactive-canvas hidden-xs">
252            </canvas>
253            <canvas ref="graph-canvas"
254                    :width="width"
255                    :height="height"
256                    v-show="x"
257                    class="graph-canvas hidden-xs">
258            </canvas>
259            <slider @update-range="updateRange"
260                    @check-range="checkRange"
261                    :range_min="range_min"
262                    :range_max="range_max"
263                    :selected_min="selected_min_value"
264                    :selected_max="selected_max_value"
265                    class="hidden-xs">
266            </slider>
267            <div class="list-group-item row controls">
268                <input class="col-xs-6 min-value" type="number" :min="range_min" v-on:blur="fixMinValue" :max="range_max" v-model.number="selected_min_value">
269                <input class="col-xs-6 max-value" type="number" :min="range_min" v-on:blur="fixMaxValue" :max="range_max" v-model.number="selected_max_value">
270            </div>
271            <button type="button" class="btn btn-primary btn-xs" v-on:click="filter" :disabled="!this.items_found">Filter</button><span class="badge info-badge" v-if="this.items_found !== false">{{ this.items_found }} items</span>
272            <button type="button" class="btn btn-default btn-xs pull-right" v-on:click="clear" v-if="!untouched || !(this.selected_min_value == this.range_min && this.selected_max_value == this.range_max)">Clear</button>
273        </div>
274    `
275});

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.