11521 sujets

JavaScript, DOM et API Web HTML5

Bonjour,

J'essai de convertir mes anciens codes jQuery en Vanilla JS par vagues successives, et je galère souvent (moi et JS...). Le problème du jour : Je veux convertir mon ancien code d'une flèche "retour en haut de page" (Arrow Scroll Top).

Voici mon ancien code jQuery (parfaitement fonctionnel) :
( function( $ ) {
	$( 'body > footer' ).append( '<a href="" class="scroll-top"><svg xmlns="http://www.w3.org/2000/svg"><path d="M20 32v-16l6 6 6-6-16-16-16 16 6 6 6-6v16z"/></svg></a>' ); // Création de l'élément 'a.scroll-top'
	var scrolltop = $( '.scroll-top' ); // Création de la variable uniquement après création de l'élément dans le DOM
	scrolltop.on( 'click', function() {
		$( 'html, body' ).animate( {scrollTop: 0}, 600 ); // Retour en haut progressif
		return false; // Empêche la génération de l'ancre sur le permalien
	} );
	$( window ).scroll( function() { // Apparition de la flèche 'retour en haut' au scroll de la page
		if ( $( this ).scrollTop() > 100 ) {
			scrolltop.fadeIn();
		} else {
			scrolltop.fadeOut();
		}
	} );
} )( jQuery );


Et voilà où j'en suis pour l'instant en vanilla JS :
function arrowScrollTop() {
	var el = document.getElementsByClassName( 'footer' )[0];
	el.insertAdjacentHTML( 'beforeend', '<a href="#" class="scroll-top"><svg xmlns="http://www.w3.org/2000/svg"><path d="M20 32v-16l6 6 6-6-16-16-16 16 6 6 6-6v16z"/></svg></a>' );
	var st = document.getElementsByClassName( 'scroll-top' )[0];
	st.style.transition = 'all 2s ease-in-out';
	st.style.display = 'none';
		window.onscroll = function() {
			var scrollTop = document.body.scrollTop;
			if ( scrollTop > 100 ) {
				st.style.display = 'block';
				st.style.opacity = 1;
			} else {
				setTimeout( function(){ // C'est ici - je pense - que le bâs blesse...
					st.style.display = 'none';
				}, 2000 );
				st.style.opacity = 0;
			}
		};
	st.onclick = function( e ){
		window.scrollTo( 0, 0 );
		e.preventDefault();
	};
}
arrowScrollTop();


Je voudrais (re)créer l'effet fadeIn/fadeOut de jQuery en Vanilla JS, donc : un effet de fondu, puis un retrait de l'élément html.

Afin de garantir l'effet de fondu je ne met un display:none sur la flèche qu'une fois l'effet de fondu terminé, grâce à une tempo setTimeout(). Mais il doit certainement y avoir une manière plus propre de procéder car cela peu produire des clignotements de la flèche (Si je me concentre uniquement sur l'effet de fondu tout est bien plus simple et je n'ai aucun problème).

Un pen : Arrow Scroll Top
Modifié par Olivier C (24 Dec 2016 - 19:55)
Eureka j'ai trouvé ! Il suffisait de faire ceci :
if(st.style.opacity === 0){
    st.style.display = 'none';
};

Edit : hélas, j'ai parlé trop vite, le code n'est pas fonctionnel en l'état...
Modifié par Olivier C (21 Dec 2016 - 09:26)
C'est bon, cette fois j'ai vraiment trouvé. En fait, ayant de bonne connaissance en CSS, j'ai tendance à faire appel au CSS via le javascript plutôt que de créer des solutions javascript pure. Du coup je faisais appel à une transition CSS dans mon code, plutôt qu'une variable js incrémentée pour l'opacité (du genre : "opacity += .1" avec un setTimeout). Du coup l'opacité passait directement de 1 à 0 en css, opacité écouté par le js sans prendre en compte la transition. Il fallait donc utiliser un transitionend (MDN) :
el.addEventListener( 'transitionend', function( event ) {
    el.style.display = 'none';
}, false);
Sans vouloir abuser, je dirai qu'avec css3+javascript2015 ce sera souvent la solution en 2017 sans jQuery, quoi qu'en eût pensé la fondation Mozilla du net (MozillaDeveloperNetwork) ou d'aucun sur Alsa ...

@Olivier C : j'adore te lire !
Modifié par pictural (24 Dec 2016 - 01:25)