0
# UI Enhancements
1
2
Additional UI features including tooltips, scale markers (pips), styling customization, and advanced interaction capabilities.
3
4
## Capabilities
5
6
### Pips (Scale Markers)
7
8
Scale markers that provide visual reference points along the slider track.
9
10
#### pips()
11
12
Adds or updates scale markers on the slider.
13
14
```javascript { .api }
15
/**
16
* Add or update scale markers (pips) on the slider
17
* @param config - Pips configuration object
18
* @returns HTML element containing the pips
19
*/
20
slider.noUiSlider.pips(config: PipsConfig): HTMLElement;
21
22
interface PipsConfig {
23
mode: 'range' | 'steps' | 'positions' | 'count' | 'values';
24
values?: number[];
25
stepped?: boolean;
26
density?: number;
27
filter?: (value: number, type: number) => number;
28
format?: Formatter;
29
}
30
```
31
32
#### removePips()
33
34
Removes all scale markers from the slider.
35
36
```javascript { .api }
37
/**
38
* Remove all scale markers from the slider
39
*/
40
slider.noUiSlider.removePips(): void;
41
```
42
43
**Usage Examples:**
44
45
```javascript
46
// Basic pips using range mode
47
slider.noUiSlider.pips({
48
mode: 'range',
49
density: 3
50
});
51
52
// Count mode - specific number of markers
53
slider.noUiSlider.pips({
54
mode: 'count',
55
values: 5, // 5 evenly spaced markers
56
density: 2
57
});
58
59
// Positions mode - markers at specific percentages
60
slider.noUiSlider.pips({
61
mode: 'positions',
62
values: [0, 25, 50, 75, 100],
63
density: 4
64
});
65
66
// Values mode - markers at specific values
67
slider.noUiSlider.pips({
68
mode: 'values',
69
values: [10, 25, 50, 75, 90],
70
density: 3
71
});
72
73
// Steps mode - markers at step intervals
74
slider.noUiSlider.pips({
75
mode: 'steps',
76
density: 2,
77
stepped: true
78
});
79
80
// Remove pips
81
slider.noUiSlider.removePips();
82
```
83
84
### Pips Configuration Options
85
86
#### mode
87
Determines how pip positions are calculated.
88
89
- `'range'`: Distribute pips evenly across the range
90
- `'steps'`: Place pips at step intervals
91
- `'positions'`: Place pips at specific percentage positions
92
- `'count'`: Place a specific number of evenly distributed pips
93
- `'values'`: Place pips at specific values
94
95
#### values
96
Array of values or positions (usage depends on mode).
97
98
```javascript
99
// For 'positions' mode: percentage positions
100
values: [0, 25, 50, 75, 100]
101
102
// For 'values' mode: actual slider values
103
values: [100, 500, 1000, 2000]
104
105
// For 'count' mode: number of pips
106
values: 6 // or as single number
107
```
108
109
#### density
110
Controls spacing and visibility of pips.
111
112
```javascript
113
// Higher density = more pips shown
114
density: 1 // Show every pip
115
density: 2 // Show every other pip
116
density: 4 // Show every fourth pip
117
```
118
119
#### stepped
120
Whether to align pips to step values (for 'range' and 'steps' modes).
121
122
```javascript
123
stepped: true // Align to steps
124
stepped: false // Use exact positions
125
```
126
127
#### filter
128
Function to customize which pips are displayed.
129
130
```javascript { .api }
131
filter?: (value: number, type: number) => number;
132
133
// Type values:
134
// -1: No pip
135
// 0: Normal pip
136
// 1: Large pip
137
// 2: Sub pip
138
```
139
140
```javascript
141
// Custom filter example
142
slider.noUiSlider.pips({
143
mode: 'range',
144
density: 2,
145
filter: function(value, type) {
146
// Hide pips for odd values
147
if (value % 2 === 1) {
148
return -1; // No pip
149
}
150
151
// Large pips for multiples of 10
152
if (value % 10 === 0) {
153
return 1; // Large pip
154
}
155
156
return 0; // Normal pip
157
}
158
});
159
```
160
161
#### format
162
Custom formatting for pip labels.
163
164
```javascript
165
slider.noUiSlider.pips({
166
mode: 'count',
167
values: 5,
168
format: {
169
to: function(value) {
170
return '$' + Math.round(value);
171
}
172
}
173
});
174
```
175
176
### Tooltips
177
178
Dynamic value display attached to slider handles.
179
180
#### Tooltip Configuration
181
182
Set during slider creation or via updateOptions.
183
184
```javascript { .api }
185
tooltips?: boolean | Formatter | (boolean | Formatter)[];
186
```
187
188
#### removeTooltips()
189
190
Removes all tooltips from the slider.
191
192
```javascript { .api }
193
/**
194
* Remove all tooltips from the slider
195
*/
196
slider.noUiSlider.removeTooltips(): void;
197
```
198
199
#### getTooltips()
200
201
Returns array of tooltip elements.
202
203
```javascript { .api }
204
/**
205
* Get array of tooltip DOM elements
206
* @returns Array of tooltip elements (null for handles without tooltips)
207
*/
208
slider.noUiSlider.getTooltips(): HTMLElement[];
209
```
210
211
**Usage Examples:**
212
213
```javascript
214
// Enable default tooltips
215
noUiSlider.create(element, {
216
start: [20, 80],
217
range: { min: 0, max: 100 },
218
tooltips: true
219
});
220
221
// Custom tooltip formatting
222
noUiSlider.create(element, {
223
start: [1000, 3000],
224
range: { min: 0, max: 5000 },
225
tooltips: {
226
to: function(value) {
227
return '$' + Math.round(value).toLocaleString();
228
}
229
}
230
});
231
232
// Per-handle tooltip configuration
233
noUiSlider.create(element, {
234
start: [20, 50, 80],
235
range: { min: 0, max: 100 },
236
tooltips: [
237
true, // Default tooltip for first handle
238
false, // No tooltip for second handle
239
{ to: value => value.toFixed(1) + '%' } // Custom for third handle
240
]
241
});
242
243
// Access and modify tooltips
244
const tooltips = slider.noUiSlider.getTooltips();
245
tooltips[0].style.backgroundColor = 'red';
246
247
// Remove tooltips
248
slider.noUiSlider.removeTooltips();
249
```
250
251
### Handle Management
252
253
Access to slider handle elements for advanced customization.
254
255
#### getOrigins()
256
257
Returns array of handle origin elements.
258
259
```javascript { .api }
260
/**
261
* Get array of handle origin DOM elements
262
* @returns Array of handle origin elements
263
*/
264
slider.noUiSlider.getOrigins(): HTMLElement[];
265
```
266
267
**Usage Examples:**
268
269
```javascript
270
// Get handle elements
271
const handles = slider.noUiSlider.getOrigins();
272
273
// Customize handle appearance
274
handles[0].style.backgroundColor = 'red';
275
handles[1].style.backgroundColor = 'blue';
276
277
// Add custom event listeners to handles
278
handles.forEach((handle, index) => {
279
handle.addEventListener('mouseenter', function() {
280
console.log('Hovering over handle', index);
281
});
282
});
283
284
// Add custom content to handles
285
handles[0].innerHTML = '<span class="handle-label">Min</span>';
286
handles[1].innerHTML = '<span class="handle-label">Max</span>';
287
```
288
289
## Advanced Styling
290
291
### CSS Classes
292
293
Access to default CSS classes for styling customization.
294
295
```javascript { .api }
296
noUiSlider.cssClasses: CSSClasses;
297
```
298
299
**Usage Examples:**
300
301
```javascript
302
// Access default CSS classes
303
console.log(noUiSlider.cssClasses.handle); // "handle"
304
console.log(noUiSlider.cssClasses.connect); // "connect"
305
306
// Use for custom styling
307
const handleClass = 'noUi-' + noUiSlider.cssClasses.handle;
308
document.querySelectorAll('.' + handleClass).forEach(handle => {
309
handle.style.borderRadius = '50%';
310
});
311
```
312
313
### Custom CSS Classes
314
315
Override default CSS classes during creation.
316
317
```javascript
318
noUiSlider.create(element, {
319
start: [20, 80],
320
range: { min: 0, max: 100 },
321
cssPrefix: 'custom-',
322
cssClasses: {
323
target: 'slider',
324
base: 'slider-base',
325
handle: 'slider-handle',
326
connect: 'slider-connect'
327
}
328
});
329
```
330
331
### Target Element Access
332
333
#### target Property
334
335
Reference to the original DOM element.
336
337
```javascript { .api }
338
/**
339
* Reference to the slider's target DOM element
340
*/
341
slider.noUiSlider.target: HTMLElement;
342
```
343
344
**Usage Examples:**
345
346
```javascript
347
// Access target element
348
const targetElement = slider.noUiSlider.target;
349
350
// Add custom classes
351
targetElement.classList.add('premium-slider');
352
353
// Custom styling
354
targetElement.style.boxShadow = '0 4px 8px rgba(0,0,0,0.1)';
355
356
// Data attributes
357
targetElement.setAttribute('data-slider-id', 'price-range');
358
```
359
360
## Practical UI Enhancement Patterns
361
362
### Custom Pip Labels
363
364
```javascript
365
// Currency pips with custom labels
366
slider.noUiSlider.pips({
367
mode: 'values',
368
values: [0, 1000, 2500, 5000, 10000],
369
format: {
370
to: function(value) {
371
if (value >= 1000) {
372
return '$' + (value / 1000) + 'k';
373
}
374
return '$' + value;
375
}
376
},
377
filter: function(value, type) {
378
// Large pips for major values
379
if ([0, 5000, 10000].includes(value)) {
380
return 1; // Large pip
381
}
382
return 0; // Normal pip
383
}
384
});
385
```
386
387
### Interactive Tooltips
388
389
```javascript
390
// Create slider with tooltips
391
noUiSlider.create(element, {
392
start: [20, 80],
393
range: { min: 0, max: 100 },
394
tooltips: true,
395
connect: true
396
});
397
398
// Enhance tooltips with click handlers
399
const tooltips = slider.noUiSlider.getTooltips();
400
tooltips.forEach((tooltip, index) => {
401
if (tooltip) {
402
tooltip.addEventListener('click', function() {
403
const newValue = prompt('Enter new value:');
404
if (newValue !== null) {
405
slider.noUiSlider.setHandle(index, parseFloat(newValue));
406
}
407
});
408
409
tooltip.style.cursor = 'pointer';
410
tooltip.title = 'Click to edit value';
411
}
412
});
413
```
414
415
### Dynamic Pip Updates
416
417
```javascript
418
// Update pips based on zoom level
419
function updatePipsForZoom(zoomLevel) {
420
const pipConfigs = {
421
1: { mode: 'count', values: 5, density: 2 },
422
2: { mode: 'count', values: 10, density: 3 },
423
3: { mode: 'range', density: 1 }
424
};
425
426
slider.noUiSlider.removePips();
427
slider.noUiSlider.pips(pipConfigs[zoomLevel]);
428
}
429
430
// Zoom controls
431
document.getElementById('zoom-in').addEventListener('click', () => {
432
currentZoom = Math.min(3, currentZoom + 1);
433
updatePipsForZoom(currentZoom);
434
});
435
```
436
437
### Handle Labeling
438
439
```javascript
440
// Add persistent labels to handles
441
const handles = slider.noUiSlider.getOrigins();
442
const labels = ['Minimum', 'Maximum'];
443
444
handles.forEach((handle, index) => {
445
const label = document.createElement('div');
446
label.className = 'handle-label';
447
label.textContent = labels[index];
448
label.style.position = 'absolute';
449
label.style.top = '-30px';
450
label.style.left = '50%';
451
label.style.transform = 'translateX(-50%)';
452
label.style.fontSize = '12px';
453
label.style.fontWeight = 'bold';
454
455
handle.appendChild(label);
456
});
457
```
458
459
### Progress Indication
460
461
```javascript
462
// Visual progress indicator
463
function updateProgress() {
464
const values = slider.noUiSlider.get();
465
const progress = parseFloat(values[0]); // Use first handle
466
const maxValue = slider.noUiSlider.options.range.max;
467
const percentage = (progress / maxValue) * 100;
468
469
// Update progress bar
470
document.getElementById('progress-bar').style.width = percentage + '%';
471
472
// Update progress text
473
document.getElementById('progress-text').textContent =
474
Math.round(percentage) + '% Complete';
475
}
476
477
slider.noUiSlider.on('update', updateProgress);
478
```
479
480
### Conditional Styling
481
482
```javascript
483
// Style based on values
484
function updateSliderStyling(values) {
485
const range = parseFloat(values[1]) - parseFloat(values[0]);
486
const target = slider.noUiSlider.target;
487
488
// Remove previous state classes
489
target.classList.remove('narrow-range', 'wide-range', 'full-range');
490
491
// Add appropriate class based on range
492
if (range < 20) {
493
target.classList.add('narrow-range');
494
} else if (range > 80) {
495
target.classList.add('wide-range');
496
} else if (range === 100) {
497
target.classList.add('full-range');
498
}
499
}
500
501
slider.noUiSlider.on('update', function(values) {
502
updateSliderStyling(values);
503
});
504
```
505
506
## Accessibility Enhancements
507
508
```javascript
509
// Enhance accessibility
510
const handles = slider.noUiSlider.getOrigins();
511
handles.forEach((handle, index) => {
512
const handleElement = handle.querySelector('.noUi-handle');
513
514
// Custom aria labels
515
handleElement.setAttribute('aria-label', `Handle ${index + 1}`);
516
517
// Descriptive titles
518
handleElement.setAttribute('title', `Drag to adjust value ${index + 1}`);
519
});
520
521
// Update aria-valuetext with formatted values
522
slider.noUiSlider.on('update', function(values, handle) {
523
const handleElement = handles[handle].querySelector('.noUi-handle');
524
handleElement.setAttribute('aria-valuetext',
525
`Current value: ${values[handle]}`);
526
});
527
```