Custom list picker

Size
5,009 Kb
Views
10,120

How do I make an custom list picker?

What is a custom list picker? How do you make a custom list picker? This script and codes were developed by Anthony Pothin on 17 January 2023, Tuesday.

Custom list picker Previews

Custom list picker - Script Codes HTML Codes

<!DOCTYPE html>
<html >
<head> <meta charset="UTF-8"> <title>custom list picker</title> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/normalize/5.0.0/normalize.min.css">
</head>
<body> <!-- dependancies -->
<!-- gesture list -->
<link rel="import" href="https://codepen.io/Thorien/pen/VLWzWR.html" />
<!-- easing -->
<link rel="import" href="https://codepen.io/Thorien/pen/f0e61caa5742e9d488421d33a5bf7dd2.html" />
<!-- custom scroll -->
<link rel="import" href="https://codepen.io/Thorien/pen/xGgMwV.html" />
<template id="c-list-picker"> <style scoped="scoped"> :host{ position: relative; flex-shrink: 0; flex-basis: 0; display: flex; flex-direction: column; justify-content: stretch; } c-scroll { flex: 1 1 0; cursor: pointer; text-align: center; -moz-user-select: -moz-none; -webkit-user-select: none; -khtml-user-select: none; -o-user-select: none; user-select: none; } #selection{ position: absolute; width: 100%; background-color: rgba(250, 0, 0, 0.5); } /* surcharge */ c-list-picker { position: relative; flex-shrink: 0; flex-basis: 0; display: flex; flex-direction: column; justify-content: stretch; } </style> <div id="selection"></div> <c-scroll hidescrollbar> <div class="padding" id="paddingtop"></div> <div class="padding" id="paddingbottom"></div> </c-scroll>
</template>
<script> var HTMLCustomListPickerElement = (function() { var parentDoc = (document._currentScript || document.currentScript).ownerDocument; // fonctions privées var onScrollEnd = function(event) { console.warn('onScrollEnd', event); var customListPicker = event.currentTarget.parentNode.host; var scroll = event.currentTarget; // récupérer hauteur d'un élément var itemHeight = customListPicker.shadowRoot.querySelector('c-scroll div:not(.wrapper):not(.padding)').clientHeight; // récupérer hauteur totale var visibleHeight = customListPicker.shadowRoot.querySelector('c-scroll').clientHeight; // calculer padding var verticalPadding = (visibleHeight - itemHeight) / 2; // récupérer scrollTop var scrollTop = customListPicker.shadowRoot.querySelector('c-scroll').scrollTop; offsetTopTarget = scrollTop + verticalPadding + (itemHeight / 2); console.error('scrollTop', scrollTop, 'verticalPadding', verticalPadding, '(itemHeight / 2)', (itemHeight / 2), 'offsetTopTarget', offsetTopTarget); // parcourir les div var divList = customListPicker.shadowRoot.querySelectorAll('c-scroll div:not(.wrapper):not(.padding)'); var selectedDiv; for (var i=0, iMax=divList.length; i<iMax; i++) { if ((offsetTopTarget - divList.item(i).offsetTop) / 2 <= itemHeight / 2) { selectedDiv = divList.item(i); customListPicker.select(selectedDiv.value); break; } } if (!selectedDiv && customListPicker.value) { customListPicker.select(customListPicker.value); } }; var onResize = function(event) { clearTimeout(this.resizeTimeoutID); var customListPicker = this; this.resizeTimeoutID = setTimeout(function() { delete customListPicker.resizeTimeoutID; customListPicker.resize(); }, 100); } // objet custom return document.registerElement('c-list-picker', { prototype: Object.create(HTMLElement.prototype, { // constructeur createdCallback: { value: function() { // création shadow root this.createShadowRoot(); // ajout contenu depuis le template var cloneTemplate = document.importNode(parentDoc.querySelector('template#c-list-picker').content, true); this.shadowRoot.appendChild(cloneTemplate); // propriétés custom avec stockage caché var _value = null; Object.defineProperty(this, 'value', { configurable: false, enumerable: false, get: function() { //console.info('HTMLCustomListPickerElement.value.get()'); return _value; }, set: function(value) { //console.info('HTMLCustomListPickerElement.value.set()'); var oldValue = _value; _value = (value === null || value === '' ? null : value); Object.getNotifier(this).notify({ type: 'update', name: 'value', oldValue: oldValue }); } }); // ajout event interaction // propriétés custom avec stockage caché // ajout event propriété Object.observe(this, function(changes) { //console.info('HTMLCustomListPickerElement.onchange()'); changes.forEach(function(change) { // change === {name (nom propriété), object (l'objet observé), type (add, update, delete), oldValue} //console.info('Object.observe', change.object, change.name, 'qui valait', change.oldValue, 'vaut désormais', change.object[change.name]); // stuff switch (change.name) { default: break; } }); }); // initialisation this.init(); } }, // propriétés custom name: { get: function() { //console.info('HTMLCustomListPickerElement.name.get()'); return this.getAttribute('name'); }, set: function(value) { //console.info('HTMLCustomListPickerElement.name.set()'); var oldValue = this.getAttribute('name'); this.setAttribute('name', value); Object.getNotifier(this).notify({ type: 'update', name: 'name', oldValue: oldValue }); } }, min: { get: function() { //console.info('HTMLCustomListPickerElement.min.get()'); return (this.hasAttribute('min') && !isNaN(this.getAttribute('min')) ? parseFloat(this.getAttribute('min')) : null); }, set: function(value) { //console.info('HTMLCustomListPickerElement.min.set()'); var oldValue = this.getAttribute('min'); this.setAttribute('min', value); Object.getNotifier(this).notify({ type: 'update', name: 'min', oldValue: oldValue }); } }, max: { get: function() { //console.info('HTMLCustomListPickerElement.max.get()'); return (this.hasAttribute('max') && !isNaN(this.getAttribute('max')) ? parseFloat(this.getAttribute('max')) : null); }, set: function(value) { //console.info('HTMLCustomListPickerElement.max.set()'); var oldValue = this.getAttribute('max'); this.setAttribute('max', value); Object.getNotifier(this).notify({ type: 'update', name: 'max', oldValue: oldValue }); } }, step: { get: function() { //console.info('HTMLCustomListPickerElement.step.get()'); return (this.hasAttribute('step') && !isNaN(this.getAttribute('step')) ? parseFloat(this.getAttribute('step')) : null); }, set: function(value) { //console.info('HTMLCustomListPickerElement.step.set()'); var oldValue = this.getAttribute('step'); this.setAttribute('step', value); Object.getNotifier(this).notify({ type: 'update', name: 'step', oldValue: oldValue }); } }, reverse: { get: function() { //console.info('HTMLCustomListPickerElement.reverse.get()'); return this.hasAttribute('reverse'); }, set: function(value) { //console.info('HTMLCustomListPickerElement.reverse.set()'); var oldValue = this.hasAttribute('reverse'); if (value) { this.setAttribute('reverse', 'reverse'); } else { this.removeAttribute('reverse'); } Object.getNotifier(this).notify({ type: 'update', name: 'reverse', oldValue: oldValue }); } }, // méthodes custom clear: { value: function() { var scroll = this.shadowRoot.querySelector('c-scroll'); var div = scroll.querySelector('div:not(.wrapper):not(.padding)'); while (div) { scroll.removeChild(div); div = scroll.querySelector('div:not(.wrapper):not(.padding)'); } } }, init: { value: function() { //console.info('HTMLCustomListPickerElement.init()'); if (this.min === null || this.max === null) { return; } var scroll = this.shadowRoot.querySelector('c-scroll'); // supprimer précédents éléments this.clear(); // créer nouveaux éléments var step = (this.step && this.step !== 0 ? this.step : 1); var reverse = this.reverse; for (var i=this.min, iMax=this.max; i<=iMax; i += step) { div = document.createElement('div'); div.textContent = i; div.value = i; div.id = 'lp'+i; if (!reverse) { //scroll.appendChild(div); scroll.insertBefore(div, scroll.querySelector('#paddingbottom')); } else { //scroll.insertBefore(div, scroll.firstElementChild); scroll.insertBefore(div, scroll.querySelector('#paddingtop').nextElementSibling); } } this.resize(); } }, select: { value: function(value) { //console.error('HTMLCustomListPickerElement.select()', value); // trouver la div if (value === null) { return; } var target = this.shadowRoot.querySelector('#lp'+value); if (!target) { //console.error('unfound value',value) target = this.shadowRoot.querySelector('#lp'+ this.max); if(!target) { //console.error('HTMLCustomListPickerElement.select() => unfound value',value, 'or',(value - 1)); this.value = null; return; } } // repositionner le scroll top var scroll = this.shadowRoot.querySelector('c-scroll'); // récupérer hauteur d'un élément var itemHeight = this.shadowRoot.querySelector('c-scroll div:not(.wrapper):not(.padding)').clientHeight; // récupérer hauteur totale var visibleHeight = this.shadowRoot.querySelector('c-scroll').clientHeight; // calculer padding var verticalPadding = (visibleHeight - itemHeight) / 2; var delta = target.offsetTop - (scroll.scrollTop + verticalPadding); var targetScrollTop = scroll.scrollTop + delta; if (targetScrollTop !== scroll.scrollTop) { var previousScrollTop = scroll.scrollTop; var intervalID, timeoutID, pastTime = 0, currentTime = 0, interval = 10, duration = 100; var onInterval = function() { currentTime += interval; var ratio = easing.easeOutBounce(currentTime / duration); scroll.scrollTop = previousScrollTop + (delta * ratio); } var onTimeout = function() { clearInterval(intervalID); clearTimeout(timeoutID); scroll.scrollTop = previousScrollTop + delta; } intervalID = setInterval(onInterval, interval); timeoutID = setTimeout(onTimeout, duration); } // affecter nouvelle valeur this.value = target.value; } }, resize: { value: function(value) { // passer padding à 0 /*this.shadowRoot.querySelector('c-scroll').style.paddingTop = null; this.shadowRoot.querySelector('c-scroll').style.paddingBottom = null;*/ this.shadowRoot.querySelector('#paddingtop').style.height = null; this.shadowRoot.querySelector('#paddingbottom').style.height = null; var itemHeight = this.shadowRoot.querySelector('c-scroll div:not(.wrapper):not(.padding)').clientHeight; // récupérer hauteur totale var visibleHeight = this.shadowRoot.querySelector('c-scroll').clientHeight; // calculer padding var verticalPadding = (visibleHeight - itemHeight) / 2; // affecter padding /*this.shadowRoot.querySelector('c-scroll').style.paddingTop = verticalPadding + 'px'; this.shadowRoot.querySelector('c-scroll').style.paddingBottom = verticalPadding + 'px';*/ this.shadowRoot.querySelector('#paddingtop').style.height = verticalPadding + 'px'; this.shadowRoot.querySelector('#paddingbottom').style.height = verticalPadding + 'px'; // repositionner la boite de sélection var selectionBox = this.shadowRoot.querySelector('#selection'); selectionBox.style.height = itemHeight + 'px'; selectionBox.style.top = verticalPadding + 'px'; this.select(this.value); } }, // méthode exécuté à chaque insertion de l'élément custom attachedCallback: { value: function() { //console.info('HTMLCustomListPickerElement.attachedCallback()'); // methode bindée this.onResize = onResize.bind(this); // ajout des events this.shadowRoot.querySelector('c-scroll').addEventListener('c-scrollEnd', onScrollEnd, true); window.addEventListener('resize', this.onResize, true); } }, // méthode exécuté à chaque détachement de l'élément custom detachedCallback: { value: function() { //console.info('HTMLCustomListPickerElement.detachedCallback()'); // retrait des events this.shadowRoot.querySelector('c-scroll').removeEventListener('c-scrollEnd', onScrollEnd, true); window.removeEventListener('resize', this.onResize, true); // methode bindée delete this.onResize; } }, // méthode exécuté quand un attribut est modifié attributeChangedCallback: { value: function(attrName, oldValue, newValue) { //console.info('HTMLCustomListPickerElement.attributeChangedCallback()'); //console.info('attributeChangedCallback', this, attrName, 'qui valait', oldValue, 'vaut désormais', newValue); switch (attrName) { case 'min': case 'max': case 'step': this.init(); break; } } } }) }); })();
</script> <script src="js/index.js"></script>
</body>
</html>

Custom list picker - Script Codes JS Codes

var onScrollEnd = function(event) { console.warn('onScrollEnd', event); var customListPicker = event.currentTarget.parentNode.host; var scroll = event.currentTarget; // trouver la balise // récupérer hauteur d'un élément var itemHeight = customListPicker.shadowRoot.querySelector('c-scroll div:not(.wrapper)').clientHeight; // récupérer hauteur totale var visibleHeight = customListPicker.shadowRoot.querySelector('c-scroll').clientHeight; // calculer padding var verticalPadding = (visibleHeight - itemHeight) / 2; // récupérer scrollTop var scrollTop = customListPicker.shadowRoot.querySelector('c-scroll').scrollTop; offsetTopTarget = scrollTop + verticalPadding + (itemHeight / 2); // parcourir les div var divList = customListPicker.shadowRoot.querySelectorAll('c-scroll div:not(.wrapper)'); var selectedDiv; for (var i=0, iMax=divList.length; i<iMax; i++) { if ((offsetTopTarget - divList.item(i).offsetTop) / 2 <= itemHeight / 2) { } } // la repositionner // enregistrer la nouvelle valeur }
Custom list picker - Script Codes
Custom list picker - Script Codes
Home Page Home
Developer Anthony Pothin
Username Thorien
Uploaded January 17, 2023
Rating 3
Size 5,009 Kb
Views 10,120
Do you need developer help for Custom list picker?

Find the perfect freelance services for your business! Fiverr's mission is to change how the world works together. Fiverr connects businesses with freelancers offering digital services in 500+ categories. Find Developer!

Anthony Pothin (Thorien) Script Codes
Create amazing love letters with AI!

Jasper is the AI Content Generator that helps you and your team break through creative blocks to create amazing, original content 10X faster. Discover all the ways the Jasper AI Content Platform can help streamline your creative workflows. Start For Free!