the following example:
create a ScrollToTop button in vanilla - old school style
"use strict";
document.addEventListener( 'DOMContentLoaded', function () {
const scrollButton = document
.createElementNS( 'http://www.w3.org/2000/svg', 'svg' );
scrollButton.setAttributeNS( 'http://www.w3.org/2000/xmlns/',
'xmlns:xlink', 'http://www.w3.org/1999/xlink' );
scrollButton.setAttribute( 'viewBox', "0 0 100 100" );
scrollButton.style.width ='50px'
scrollButton.style.position = 'fixed'
scrollButton.style.right = '10px'
scrollButton.style.bottom = '10px'
scrollButton.style.zIndex = '1000'
scrollButton.style.opacity = '0.5'
scrollButton.style.cursor = 'pointer'
scrollButton.style.transition = 'all ease 400ms'
scrollButton.style.display = 'none'
const myCircle = document
.createElementNS( 'http://www.w3.org/2000/svg', 'circle' );
myCircle.setAttribute( 'cx', '50' );
myCircle.setAttribute( 'cy', '50' );
myCircle.setAttribute( 'r', '50' );
myCircle.setAttribute( 'fill', 'red' );
scrollButton.appendChild( myCircle );
const myArrow = document
.createElementNS( 'http://www.w3.org/2000/svg', 'path' );
myArrow.setAttribute( 'd', 'M50 80 L50 20 M50 20 L80 50 M50 20 L20 50' );
myArrow.setAttribute( 'stroke', 'white' );
myArrow.setAttribute( 'stroke-width', '15' );
myArrow.setAttribute( 'stroke-linecap', 'round' );
scrollButton.appendChild( myArrow );
scrollButton.addEventListener( 'mouseover',
() => scrollButton.style.opacity = '1'
);
scrollButton.addEventListener( 'mouseout',
() => scrollButton.style.opacity = '.3'
);
scrollButton.addEventListener( 'click', () => document
.querySelector( 'body' )
.scrollIntoView( { behavior: 'smooth' } )
);
document.body.appendChild( scrollButton );
window.onscroll = () =>
scrollButton.style.display =
( document.querySelector( 'html' ).scrollTop /
( document.querySelector( 'html' ).scrollHeight -
document.querySelector( 'html' ).clientHeight ) ) > 0.25
? '' : 'none';
})
now the same solution using a selector engine.
In this example I used my own engine, it doesn't matter for the comparison.
<script type="text/javascript" src="https://w-web.de/myquery/myquery-min.js"></script>
or
<script type="text/javascript" src="https://w-web.de/myquery/myquery.js"></script>
"use strict";
$().ready( () => {
let scrollButton =
$().sCreate( '0 0 100 100' )
.styles()
.width( '50px' ).position( 'fixed' )
.right( '10px' ).bottom( '10px' )
.zIndex( '1000' ).opacity( '0.3' )
.cursor( 'pointer' ).transition( 'all ease 400ms' )
.display( 'none' ).parent()
.sAppend(
$().sCircle( 50, 50, 50 ).fill( 'red' ) )
.sAppend(
$().sPath( 'M50 80 L50 20 M50 20 L80 50 M50 20 L20 50' )
.shortStroke( 'white' , '15', 'round' ) )
.on( 'mouseover', function (){ this.style.opacity = '1' } )
.on( 'mouseout', function (){ this.style.opacity = '.3' } )
.click( () => $( 'body' ).n.scrollIntoView( { behavior: 'smooth' } ) )
.appendEnd( $( 'body' ) )
$(window).on('scroll', () =>
scrollButton.n.style.display =
( $('html').n.scrollTop /
( $('html').n.scrollHeight -
$('html').n.clientHeight ) ) > 0.25
? '' : 'none'
)
})
Advantages of a SelectorEngine
- shorter code
- Chaining
Disadvantages
- greater learning effort
I think that if you have to deal with a lot of changing employees in a team, the vanilla JS solution certainly makes more sense.
If you are a lone fighter, you should use a Selector Engine.
what is your opinion?
Discussion (3)
If the code becomes complex, is generally a sign that the code should be updated, not that we need to add a new dependency like jQuery. This particular problem has several solutions that are way simpler, here's one for example:
The styles are moved to CSS, making it way easier to customize and less complex on the JS side. No need for an "onload", you just defer it. No need for event listeners for style related changes, just use CSS. No need to create a bunch of static elements, when we can just use a template (ideally even a SVG file).
Here's the JS of that CodePen:
Even if you still think the jQuery solution is more readable somehow, you still need to consider those 30.3kB (Minified and Gzipped) that you're adding to your app.
Cheers!
There are many ways to Rome, of course I know that this can also be solved in other ways.
As you may have overlooked, the code was designed as a plugin. That's why the ready, scope!!
It's not about a CodeGolf competition.
In my opinion, your code is unnecessarily complicated, why use template?
Why the strange way via the hidden attribute, which is ultimately misused as a class?
Why assign the circle attribute in the CSS?
All of this means that the code shown does not work on IOS devices, for example!!
sample code, if you don't design it as a plugin:
css
Javascript:
I agree. My point was mainly that jQuery is not the best way to Rome, but you can use it if you want. I'm not saying mine is the best either, but gets the same job done without the need of jQuery.
I get is a plugin, but if you defer it, it has the same effect (both for jQuery and vanilla):
That will run the script when the DOM is ready. And you can just load your styles with that:
I wasn't golfing. Trust me this is far from being golf.
Because the
template
element is used to ... well ... create templates. And if you just want to have an SVG with some elements on it that will never change or have events on their own, then a template is just fine. You could also just use adiv
in memory, but I thinktemplate
is a better element for that because it is designed with this kind of usages in mind.Is not a "strange way", is actually a standard global attribute. Ideally you should use it every time you want to "hide" something, is also better for a11y.
TBH, I almost removed the circle altogether and replaced it with a
button
with CSS to make it look like a circle (which is also better for a11y than a floating SVG). But I was already doing a lot of changes just to showcase that you don't need jQuery for this, so it felt like an overkill already. So I just moved the styles to whey they belong (CSS).Safari is way behind the curve in a lot of stuff, but yeah, I didn't even check Safari for the same reasons above. If you really want me to create an example that works on iOS and still demonstrates that you don't need jQuery, I'd be happy to do it, but maybe the point is already made without that.
Why didn't you had that code as an example for JS? Is way better than the one on the article and still works as a "plugin" (you just put that code on a deferred script tag and done). It still needs some work (missing
hidden
attribute, unnecessaryxmlns:xlink
attribute, still not inside abutton
, usage ofid
, and so on), but it better showcases how vanilla nowadays is so good you generally don't even need jQuery.