[HN Gopher] Mastering DOM manipulation with vanilla JavaScript
___________________________________________________________________
Mastering DOM manipulation with vanilla JavaScript
Author : srirangr
Score : 346 points
Date : 2023-11-06 13:41 UTC (7 hours ago)
(HTM) web link (phuoc.ng)
(TXT) w3m dump (phuoc.ng)
| snide wrote:
| Excellent list and examples. Browsing through a dozen or so of
| these I'm amazed at the care and detail in the examples. They are
| not only functional, but provide very solid UI work as well.
|
| As I've shifted away from platforms like React to smaller,
| minimalist implementations, I often have trouble finding ways for
| how to do complex patterns in standard JS. It's funny when you
| look at the code and think... huh, that's actually a lot easier
| than importing a huge library with way too many props :)
|
| Thanks to the author for putting this together.
| bob1029 wrote:
| > It's funny when you look at the code and think... huh, that's
| actually a lot easier than importing a huge library with way
| too many props
|
| I had this realization after the 3rd or 4th RiotJS major
| version update. It started getting harder to do it the
| opinionated way. I realized that _every_ minimalistic JS
| framework would eventually suffer this fate as totally innocent
| feature requests gradually accumulate into a monstrous pile of
| hooks, events and other side-effect bandaids.
|
| I don't even use jQuery anymore. I will use things like ES
| modules to help organize code, but you _don 't_ need to run a
| goddamn npm command to use any of that technology. All of this
| is a _global browser standard_ , not something you have to
| vendor in.
|
| I look at MDN as the Bible these days. If you take a leap of
| faith, it _will_ carry you almost 100% of the way. The
| frameworks will cripple you after a certain point. I can 't say
| this would have been true ~5 years ago. Things have shifted
| rapidly with browser APIs converging on a powerful set of
| primitives (modules, flexbox, grid, etc) that are now very
| consistent across platforms.
| reactordev wrote:
| I like the fact that you said "I can't say this would have
| been true ~5 years ago".
|
| React et al. exist because there weren't global standards
| around these things and composability suffered. Now that we
| are all playing the same chorus, these frameworks provide
| little more than component libraries to reuse. This can be
| done with ES modules. JSX is why most React folks stick with
| React, not knowing they can use Preact or just NakedJSX if
| they wish.
|
| I just wanted to verbally concur that vanilla JS is more than
| capable of doing everything you need. Custom tags. Shadow
| dom. Composed UI. etc. if you are ok with returning
| HTMLElement vs a JSX closure.
| snide wrote:
| And this is absolutely true in CSS now as well. I find a
| lot of people are needing to rediscover the standards now
| that they've upped their featuresets.
| irrational wrote:
| I though React, et al were originally created as a better
| way to manage DOM updates (shadow DOM). Has that need gone
| away?
| evan_ wrote:
| React et al use a virtual DOM, not shadow DOM (unless you
| specifically render it to shadow DOM).
|
| They are a better* way to manipulate DOM in that you no
| longer _need_ to manipulate the DOM, you just build a
| function that returns what the DOM should look like and
| it figures out what transforms need to happen.
|
| *They're pitched as a better way, and I think it's
| better, but people can reasonably disagree
| nicoburns wrote:
| Not at all. Without React (or a similar framework) you
| are still left with the options of:
|
| - Manually keep track of UI state (which is complex, and
| often leads to hard to maintain spaghetti code)
|
| - Recreate an entire DOM tree every time you re-render
| (which is slow to the extent that it will often lead to
| performance problems in practice). Apparently this is not
| as slow as it used to (so you could probably get away
| with this sometimes - and you could before), but it's
| still generally a better idea to use a framework as you
| get better performance for very low cost.
|
| There are plenty of non-React frameworks that will you
| these benefits too. And many of them are much smaller. I
| think the reason to use React specifically is more
| "business reasons" such assurances that the framework
| will continue to be maintained, library ecosystem,
| developer pool, etc. Other frameworks are often
| technically superior, the difference just isn't that
| great.
| nine_k wrote:
| One of the points of React vs e.g. jQuery was the ability
| to do efficient updates in large DOM.trees.
|
| Did something arrive to plain JS APIs to allow this in a
| simple enough way?
| r-spaghetti wrote:
| It depends on the type of relations between the updates
| you want to make, for example adding/removing a class can
| group DOM elements. Updating all elements with this class
| is easy.
| kevindamm wrote:
| Templates and shadow DOM help a lot with creating and
| cloning of large subtrees, but time to first render and
| caution around page re-layout still require attention to
| do well at scale.
| wruza wrote:
| _the ability to do efficient updates in large DOM.trees_
|
| It was the ability to do efficient updates based on large
| VDOM diffs. The speed of updates is the same between a
| React VDOM-diff update plan and a direct update of the
| same size based on e.g. observers.
| nine_k wrote:
| Yes, that's the point: computing what needs to change
| using observers quickly becomes hard. React allows you to
| run all updates against an unchanged view; observers can
| interact with each other's updates.
|
| While React proper may be too large, I find the approach
| indispensable for more complex interfaces. One can pick
| Preact instead.
|
| But it's indeed overkill for adding small bits of
| interactivity to large, mostly static documents.
| nicoburns wrote:
| > JSX is why most React folks stick with React, not knowing
| they can use Preact or just NakedJSX if they wish.
|
| The large ecosystem of component libraries and the backing
| of a large corporate company is why people continue to use
| React. That, and that the extra 100kb that comes with React
| is generally dwarfed by the actual application in any large
| app.
| explaininjs wrote:
| I'm using preact for a few projects and the integration
| with React stuff is _generally_ seamless, but there are
| enough rough edges encountered that looking back I wouldn
| 't mind taking the difference of a few dozen kB to avoid
| them all. The _vast_ majority of my load time is taken by
| TTFB, even from the Cloudflare Pages local cache, so
| worrying about kilobytes seems misguided.
| sesm wrote:
| React exists because Facebook needed to sync DOM elements
| in different parts of webpage with a single source of
| state. There is still no global standard that solves this
| problem.
| gedy wrote:
| Yeah I think some people glorify "simple", low level
| solutions, which work fine for sprinkles of
| interactivity. But if I'm building a non trivial UI
| application - give me a framework please!
| marcosdumay wrote:
| You mean state handlers? Those are one of the main
| reasons people adopted OOP at the 80's.
|
| The observer pattern got pretty much standardized by the
| GoP book, but people overwhelmingly prefer to run some
| non-standard specialized thing, as it's usually much
| simpler. It's a pretty much solved problem since way
| before a lot of current developers were even born.
|
| All of (ok, a lot of) the React's complexity comes from
| it being a generic library that must support every kind
| of usage. Any standard would have to be as complex.
| reactordev wrote:
| BS there's custom elements and classes and the ability to
| target them with a selector. This is standard now. Web
| components.
| nicoburns wrote:
| Web components don't really do the same thing. If you use
| web components then you still need to manage the DOM
| manually.
| MrJohz wrote:
| Web components solve encapsulation of structure, style,
| and behaviour within a single component, but they don't
| solve the larger state problems, because web components
| don't come with any sort of state management beyond what
| you can do with normal Javascript.
|
| React does provide components, but there's not so much
| different in React components than any other component
| system. The main reason to use React is the state
| management it provides on top of those components, making
| sure that state is in sync across the whole application.
|
| In my experience, the hard part of larger applications is
| that handling of application state. Rendering data can be
| done in umpteen different ways, and they're all pretty
| much good enough, but handling application state in such
| a way that every component remains in sync with all other
| components is hard.
| wayfinder wrote:
| No, React exists because there was a need for a template
| engine that's easy to use.
|
| There is still no global standard for templates.
|
| Just like mustache, Twig, Java Server Pages, Jinja, ERB...
| every language has this problem. You have a bunch of
| components written in HTML and you need to mix and match
| them together in a bigger unit. React+JSX let you do that
| easier than appending DOM components. Before React, you'd
| use different libraries that did what React did.
|
| The ONLY major language I can think of that has templating
| baked in is PHP.
| Joeri wrote:
| HTML has built-in templates now, and custom elements (web
| components) provide composability. If the built-in
| templating is not quite powerful enough (it has no logic
| or variables) there's developit/htm which is basically
| JSX but parsing in the browser.
|
| React is still easier, but it comes at a maintainability
| tax because you have to keep upgrading to new react
| versions and port to new react wrapper framework versions
| if you want to keep a codebase in active development.
| Vanilla web development has no such problem because web
| standards remain backwards compatible.
|
| For a small project where I don't care about SEO /
| server-side rendering I absolutely prefer vanilla web dev
| over React now.
| wayfinder wrote:
| Yes, it does! But while I have not used them yet, the
| approach used by them (via SGML tags) is not new and many
| libraries / XLST have done it before in the past 20+
| years and I find the approach usable at best. It's too
| verbose for my taste and it never really caught on, and I
| find it hard to think that it would catch on this time.
| nicoburns wrote:
| > React is still easier, but it comes at a
| maintainability tax because you have to keep upgrading to
| new react versions and port to new react wrapper
| framework versions if you want to keep a codebase in
| active development.
|
| There has been one breaking version of React (the recent
| React 18) in it's 8 years of history. Upgrading React
| versions is a non-issue.
|
| Wrapper frameworks like next.js can come with a much
| higher maintenance cost, but you don't need to use those
| to use React (and I think most people don't).
| johnmaguire wrote:
| > The ONLY major language I can think of that has
| templating baked in is PHP.
|
| Depends on what you mean exactly. For example, Go ships
| with templates. They don't mix HTML markup and Go code
| directly though.
| efdee wrote:
| No, jQuery existed for that reason. React has other
| reasons, one of them being that manual DOM tracking and
| manipulation is brittle and annoying and the way React
| works turns that around completely.
|
| I'm not sure what Preact or NakedJSX offers me that would
| make it a better choice than React.
| reactordev wrote:
| We don't do manual dom tracking anymore. We have custom
| tags, shadow dom, es modules, etc making React obsolete.
| hombre_fatal wrote:
| Nothing in TFA competes with a web client framework, though,
| since the framework is solving the general questions of how to
| manage state and then update the UI when state changes.
|
| For example, pretty much all of the TFA examples are code you'd
| have to write even if you were using React.
| jeffgreco wrote:
| This looks like some helpful refreshers as I try and mess with
| building a browser extension.
| mg wrote:
| These days, I get by with just two dependencies. One is dqs.js:
|
| https://github.com/no-gravity/dqs.js
|
| Which turns document.querySelector('.some .thing') into
| dqs('.some .thing').
|
| The other one is Handlebars:
|
| https://github.com/handlebars-lang/handlebars.js/
|
| Which I use for all my frontend templating needs.
| dylan604 wrote:
| are we really concerned about the shortness of the code for the
| worse tradeoff of being less readable?
|
| how much is truly saved by this? these seem like the things of
| a solo dev vs building something for other people to follow
| mg wrote:
| What's wrong with solo devs?
|
| You are talking to me on a site done by one.
|
| This is the frontend code:
|
| https://news.ycombinator.com/hn.js
| evbogue wrote:
| hn would benefit from the ael library
| throw555chip wrote:
| That's wild, never really looked into it, reminds me how a
| C programmer thinks. I'm mostly backend but get involved
| with frontend every now and then. Tried to avoid Angular
| and React but now trying to teach myself Angular. AngularJS
| was nice. Angular sucks, very complicated for doing the
| same things I can do with vanilla HTML/CSS/JS, but that's
| what companies seem to be hiring for.
| dylan604 wrote:
| I've been a solo dev as well. But unless you're going to
| live forever, the code should be maintainable by someone
| else. You can be a solo dev that's impossible to ever work
| with, or you can maintain good practices so that other
| people can play along as well.
| deathanatos wrote:
| ... is that a good example?
|
| ... upvote/downvotes are does by fetching an "image", i.e.,
| it does a GET request _with side-effects_! ... also seems
| like a trivial CSRF vuln, too...
| von_lohengramm wrote:
| There's a reason why web developers have the reputation they
| do.
| evbogue wrote:
| Combine this with https://github.com/dominictarr/hscrpt and
| you'll be building websites in no time!
| bambax wrote:
| Instead of importing dsq you can do this
| const $ = document.querySelector.bind(document); const
| $$ = document.querySelectorAll.bind(document);
| mg wrote:
| That's what I did before I put those lines (and some more)
| into dqs.js
| throw555chip wrote:
| That's a neat shortcut, I prefer vanilla JS too.
| gmiller123456 wrote:
| That's pretty much what that include file does, but with
| "dqs" rather than "$". I'm not a fan of using the $ as it
| might confuse others that you're using JQuery.
| bambax wrote:
| Wouldn't that be a feature? ;-)
| chrismorgan wrote:
| $ is what I would expect and prefer, because it's what I've
| been using in my browser dev tools for over fifteen years
| (ah, Firebug; fond reminiscences). If your document doesn't
| use the names, you'll get implementations roughly
| equivalent to these: function $(selector,
| element = document) { return
| element.querySelector(selector); }
| function $$(selector, element = document) {
| return Array.from(element.querySelectorAll(selector));
| }
|
| Reference on more magic available in the console (there's a
| lot of good stuff):
|
| * https://firefox-source-docs.mozilla.org/devtools-
| user/web_co... (I think ":help" is my new favourite: opens
| that URL, which is not particularly discoverable)
|
| * https://developer.chrome.com/docs/devtools/console/utilit
| ies...
| xeckr wrote:
| Or
|
| const $ = (query) => document.querySelector(query);
|
| const $$ = (query) => document.querySelectorAll(query);
|
| (How do I write monospace on HN?)
| bambax wrote:
| > _How do I write monospace on HN?_
|
| Line that start with four spaces like
| this
| xeckr wrote:
| Looks like 2 spaces are sufficient. But I sympathize with
| 4-space indentation.
| bambax wrote:
| Indeed! I've always thought it was 4, because...
| Markdown, probably?
| chrismorgan wrote:
| > _(How do I write monospace on HN?)_
|
| Two-space indentation.
| xeckr wrote:
| Thank you
| crtasm wrote:
| Is there a way to make this also work as a function? e.g.
| myTable.$$('tr').foreach()
| mg wrote:
| import {qsA} from './dqs.js'; rows =
| qsA(myTable, 'tr');
| crtasm wrote:
| Thanks but the point is being able to chain it:
|
| myTable.qsA('tr')
|
| TypeError: myTable.qsA is not a function
| mg wrote:
| Well, since html elements already have a querySelectorAll
| function, you could just assign it to a new method "qsA":
| HTMLElement.prototype.qsA =
| HTMLElement.prototype.querySelectorAll;
|
| Now myTable.qsA('tr') will work. You can try it right
| here on the HN page in the browser console:
| HTMLElement.prototype.qsA =
| HTMLElement.prototype.querySelectorAll;
| document.querySelector('#hnmain').qsA('tr');
|
| Why do you prefer chaining?
| crtasm wrote:
| Perfect, thankyou!
|
| I suppose habit plus I find it easier to grok in that
| order, targetelement->childelements->foreach.
| xeckr wrote:
| You'll have to do this in addition to one of the
| previously discussed solutions if you want something like
| document.qsA since document isn't an HTMLElement.
| r-spaghetti wrote:
| Can you use Handlebars in Cloudflare workers? EJS was not
| accepted and string literals are string literals.
| mg wrote:
| handlebars.js runs in the browser:
|
| https://plnkr.co/edit/LXb5TOMoyAxdbTxB
| nicoburns wrote:
| These days? This is what we were using 10 years ago before
| React came about! It works fine, but performance can be a
| problem in large apps as handlebars just naively recreates
| entire DOM trees rather than diffing.
| danielvaughn wrote:
| So I'm working on this side project. I don't have a name for it
| yet but I've been describing it as "vim for web designers". The
| idea is that you can build a website (or components) in the
| browser, similar to Webflow, but it's entirely driven by a
| command language.
|
| When I began the project, I told myself I wasn't going to use a
| framework. After all, I've been doing this since 2009, I was
| working with JS for a long time before I ever touched a
| framework. And besides, the native DOM APIs have long been good
| enough. Right?
|
| My god, it was an absolute slog. Marshalling data into and out of
| the DOM is so tedious and error prone that I began writing my own
| mini framework to save my own sanity. And then I remembered why I
| began using frameworks to begin with - because ultimately you're
| going to be using a framework of some kind regardless, it's just
| whether you want your own custom one or a community-built
| industry standard.
|
| I do still think native DOM is great, if you're working with
| small amounts of interactivity. Most sites that use React
| probably don't need it. But if your product has even a little bit
| of nuance or complexity, I'd go with a framework and avoid the
| hassle.
|
| In the end I migrated to Svelte, and I'm much happier as a
| result.
| bryancoxwell wrote:
| How's that saying go? Choose a framework or you'll invent one?
| danielvaughn wrote:
| Yep, and it's exactly right. It had been so many years since
| I'd worked directly at the DOM layer that I'd forgotten why I
| stopped.
|
| That being said, it was equally difficult picking a framework
| that had the least likelihood to handicap me down the road.
| And I am still using plenty native methods, especially for
| the CSSOM. That has yet to be sufficiently abstracted into
| any kind of framework.
| synergy20 wrote:
| sveltekit is all about SSR these days, svelte itself does not
| have a default client side router, I was trying svelte for csr
| spa and gave up
| danielvaughn wrote:
| I'm using Astro for SSR and only using Svelte for the client-
| side state. It's working out well so far.
| meiraleal wrote:
| With the view transition API[1], directory/index.html is/will
| be the client-side router.
|
| 1. https://chipcullen.com/adding-view-transitions-api/
| dmix wrote:
| Hyper minimalist projects always end up re-implementing half of
| jquery or lodash. Much easier to just find a good library that
| does treeshaking like ramda and use it sparingly.
| Klonoar wrote:
| I will gladly reimplement half of those projects if it means
| I can avoid the JS build systems that break when I come back
| and try to build in a year.
|
| And to be fair I'm sure the build systems have gotten better
| - they just all left a bad taste in my mouth. I spent more
| than enough time working with them, writing plug-ins, etc.
| danielvaughn wrote:
| This was one of the reasons I really tried to go native.
| Once you introduce a build system, it has to be maintained.
|
| I eventually did choose Svelte, but I'm dockerizing it so I
| can still use the thing a year from now, unlike virtually
| all of my other projects.
| the__alchemist wrote:
| You are building application - I could estimate from your
| description alone that you're better off wrapping the DOM
| interactions.
|
| For websites that need interaction, DOM manipulation is IMO a
| better move due to it using a more fundamental/universal skill,
| light or no build process, faster execution, and explicitness.
|
| This is a _categorization_ , with lots of room for grey areas!
| I bring it up because your use case falls squarely in the
| category that benefits from a framework.
| danielvaughn wrote:
| Yeah, agreed. I was hoping I could lean into a quasi-HATEOAS
| approach, where the state of the editor is reflected in the
| state of the html output. My thinking was that if it's only
| in the html, then in theory it would handle very large
| numbers of nodes better, since you don't have to
| correspondingly increase the size of JS object in memory.
|
| I'm still attracted to that idea, but it's not worth it in
| the short term.
| marban wrote:
| All good except for _Create a custom scrollbar_
| beardyw wrote:
| I am a great fan of vanilla JavaScript so for me it is a great
| resource. Sadly many js developers nowadays don't really
| understand what the Dom can do for them. A great resource!
| bobmaxup wrote:
| If I were making a cookbook on HTML/JS I would probably leave out
| this:
|
| https://phuoc.ng/collection/html-dom/sanitize-html-strings/#...
| panzi wrote:
| `value.startsWith('javascript:')` and there you have a
| vulnerability. There can be arbitrary white-space before the
| URL, so you'd need to do
| `value.trim().startsWith('javascript:')` instead. However, I
| much prefer white listing instead, i.e. only allowing `http:`,
| `https:` and maybe `mailto:`, `ftp:`, `sftp:` and such. Maybe
| allow relative URLs starting with `/`. Maybe. Though that would
| mean to correctly handle all attributes that actually can be
| URLs. Again, I'd just white list a few tags plus a few of their
| attributes.
| zeroCalories wrote:
| Why? This is a common need. Is there an issue with the
| implementation or another reason why you would want to use a
| library?
| chrismorgan wrote:
| I'm not sure quite why you're against removing script tags, but
| honestly that entire article is poor, riddled with disastrously
| bad advice:
|
| * "Using regular expressions": it suggests that this approach
| is acceptable within its limits. It's not _at all_. As a simple
| example, the expression shown is trivially bypassed by
| "<script>...</script >". This is why, unlike the post claims
| claims, using regular expressions for cleaning HTML is _not_ a
| common approach.
|
| * ("Eliminating the script tags": I want to grumble about using
| `[...scriptElements].forEach((s) => s.remove())` instead of
| `for (const s of scriptElements) { s.remove(); }` or even
| `Array.prototype.forEach.call(scriptElements, (s) =>
| s.remove())`. Creating an array from that HTMLCollection is
| just unnecessary and a bad habit.)
|
| * "Removing event handlers": `value.startsWith('javascript:')
| || value.startsWith('data:text/html')` is inadequate. Tricks
| like capitalising and adding whitespace (which the browser will
| subsequently normalise) in order to bypass such poor checks
| have been common for _decades_.
|
| * "Retrieving the sanitized HTML": you are now vulnerable to
| mXSS attacks, which undo all your effort.
|
| * "Elements and attributes to remove from the DOM tree": this
| proposes a blacklist approach and mentions _a few examples_ of
| things that should be removed. Each example misses adjacent but
| equally-important things that should be removed. You _will not_
| get acceptable filtering if you start from this approach.
|
| * "Simplifying HTML sanitization with external libraries": this
| is pitched merely as easier, faster and cheaper, rather than as
| the _only_ way to have any confidence in the result.
|
| * "Conclusion": as I hope I've shown, "The DOMParser API is one
| tool you can use to get the job done right." is not an
| acceptable position.
|
| Really, the article could be significantly improved by
| presenting it as what a common developer might think, and then
| scribbling all over the problematic things with these
| explanations of why they're so bad, and ending with the
| conclusion "so: just use the DOMPurify library; consider
| nothing else acceptable". (There have at times been a couple of
| other libraries of acceptable quality, but as far as I'm
| concerned, DOMPurify has long been the one that everyone should
| use. I note also that this article is talking about _client-
| side_ filtration. I'm not familiar with the state of the art in
| server-side HTML sanitisation, where you probably don't have an
| actual DOM; this is also a reasonable place to wish to do
| filtering, but the remaining active mXSS vectors might pose a
| challenge. I'd want to research carefully before doing
| anything.)
|
| I look forward to the Sanitizer API
| <https://wicg.github.io/sanitizer-api/> being completed and
| deployed, so that DOMPurify can become just a fallback library
| for older browsers.
| bobmaxup wrote:
| > I'm not sure quite why you're against removing script tags
|
| My bad, I left a fragment in the URL.
| cmrdporcupine wrote:
| Nice. Bookmarked. Another good one in a similar vein is
| https://youmightnotneedjquery.com/
|
| I don't do web stuff often, but when I do I am _completely_
| demoralized by the state of framework-itis there. It 's gotten
| completely out of control. A fresh React project is hundreds of
| dependencies. The weight of that complexity is astounding to me.
|
| Meanwhile the core cross-platform browser tech shipped by default
| has never been more capable and the amount of code to do common
| things ... isn't very much.
|
| Front-end devs: are you ok?
| danielvaughn wrote:
| Agreed it's out of control. But in the past year I've
| transitioned to a platform team so I'm working with devops-ish
| tooling for the first time. Holy shit...the amount of
| complexity there gives front-end a run for its money. You've
| got Kubernetes, Helm, Terraform, CircleCI, yadda yadda. The
| amount of layered terminology in just those technologies alone
| is absurd.
| throw555chip wrote:
| As a mostly backend dev, maybe I'm biased but all the tech
| you listed there isn't layers of stuff. Each of those do
| something different. For all but FAANG, kube is overkill.
| Helm is just templating. The rest existed before DevOps was a
| term.
| cmrdporcupine wrote:
| Was replying saying mostly this. I stay away from most of
| that kind of stuff and work in embedded-type space mostly,
| but when I have ventured in there, it all kind of makes a
| certain amount of sense as modules that layer _relatively_
| independent of each other. Because, well, most things
| interoperate via Rest or gRPC or whatever, without a lot of
| coupling.
|
| The problem with the JS/TS/Node ecosystem is the _cultural_
| tendency there to build and proselytize _frameworks_.
| Heavily coupling seems to be seen as a positive rather than
| negative.
| mattlondon wrote:
| I am no fan at all of react or npm, but some frameworks do
| provide some helpful things that pure DOM APIs do not, so they
| still have a place I think.
|
| So e.g. application state management and routing are two huge
| things you'll still need to implement yourself if you just use
| pure DOM APIs
|
| Depending on the complexity of your app then that might not be
| such a big deal, but these extras are rapidly worth their
| weight in gold as soon as you go beyond a basic app. Unless you
| are using anything that needs NPM in which case you are fucked.
| mablopoule wrote:
| Another excellent resource in the same vein is the marvelous
| https://javascript.info/
|
| As a front-end dev who actually like the fundamental platform
| and the capacities it offers, I'm both happy to see so much
| nice things coming our way (nested CSS, container queries, and
| a generally nicer JS experience since ES6) and at the same time
| horrified by the amount of people using components for trivial
| things like buttons or bold text.
|
| And I do like framework, but so much framework and library's
| marketing depend on making people believe that CSS and vanilla
| DOM manipulation is insanely hard (it's not once you know the
| fundamentals), and that pulling a random package on NPM is not
| just quick and easy, but also _the professional thing to do_.
| troupo wrote:
| > Meanwhile the core cross-platform browser tech shipped by
| default has never been more capable and the amount of code to
| do common things ... isn't very much.
|
| Have you tried to use this "capable cross-platform tech" to do
| anything non-trivial? And React isn't the only thing out there.
| panzi wrote:
| `value.startsWith('javascript:')` and there you have a
| vulnerability. There can be arbitrary white-space before the URL,
| so you'd need to do `value.trim().startsWith('javascript:')`
| instead. However, I much prefer white listing instead, i.e. only
| allowing `http:`, `https:` and maybe `mailto:`, `ftp:`, `sftp:`
| and such. Maybe allow relative URLs starting with `/`. Maybe.
| Though that would mean to correctly handle all attributes that
| actually can be URLs. Again, I'd just white list a few tags plus
| a few of their attributes.
| simonw wrote:
| You mean from this article "Sanitize HTML strings"?
| https://phuoc.ng/collection/html-dom/sanitize-html-strings/
|
| Yeah, that article really shouldn't imply that sanitization is
| "that easy". It does at least mention
| https://github.com/cure53/DOMPurify at the end but it should
| LOUDLY argue against attempting to write this particular thing
| yourself and promote that exclusively in my opinion.
|
| Filed an issue about this here:
| https://github.com/phuocng/html-dom/issues/281
| runarberg wrote:
| There is also a future way of doing this with vanilla
| JavaScript using the Sanitize API. It is enabled under flags
| in most browsers currently.
|
| https://developer.mozilla.org/en-
| US/docs/Web/API/HTML_Saniti...
| jfhr wrote:
| Unless you need to support ancient browsers [1], I'd go the
| easy way and leave the URL parsing to the browser, e.g.
| `['http:', 'https:', 'mailto:', 'tel:'].includes(new URL(value,
| location.origin).protocol)`
|
| [1] https://caniuse.com/url
| keepamovin wrote:
| JavaScript elegance is always welcome!
| fatnoah wrote:
| What's old is new again. My first front-end role was building web
| applications wayyyyy back in 1999. Everything was done with
| "Vanilla" JS, including fancy stuff like drag and drop in a
| treeview, click to edit, building what effectively was a single
| page app, etc. etc. The hardest part was negotiating the
| differences between Netscape and Internet Explorer.
| kossTKR wrote:
| Great resource! I've defaulted to just use vanilla js and petite-
| vue, it's 15 kilobytes and gives a good base.
|
| The problem is the build requirements you run into quickly if you
| want to use plugins these days with vanilla js.
|
| Elegance was being able to load actual modules from a CDN. Why
| did we need these anti-web build steps on top of JS?
|
| I feel like there was a sweet spot of complexity around Vue 1 or
| say 2014.
|
| The Vue 2-->3 jump illustrates the welcome but total breakdown of
| frameworks in my opinion. It constantly gets in your way and
| moving data on a page with a hierarchy you need some bizarrely
| complex data flow, so many folders, files, tools, brittle
| typescript linting, "auto" this and that, constant building and
| so many rules it's not fun to engineer anymore.
|
| Anyway, i think we are very close to a sweet spot if we just use
| something like Petite-vue / Alpine on top of JS maybe with a tiny
| router and get creative with JS around that, or just early
| versions say Vue if we need anything more complex.
| athanagor2 wrote:
| The toolchain complexity problem was already present with Vue 2
| (and anyway it was usable as a dependency pulled into a classic
| web page). It definitely could be better, and it seems to be on
| the way of being improved.
|
| I feel like a lot of criticism toward Vue 3 is based on
| feelings and vibes. What exactly are your complaints toward v3?
| flanbiscuit wrote:
| Seems like a helpful list of things to know, I haven't gone
| through it all but looks good so far.
|
| Clicked on the first one and I noticed something.
|
| They write this: const setFavicon = () => {
| const favicon = document.querySelector('link[rel="icon"]');
| favicon.href = (window.matchMedia('(prefers-color-scheme:
| dark)').matches) ? 'dark-mode-
| favicon.png' : 'light-mode-favicon.png';
| }; setFavicon();
|
| And then this:
|
| > We can use this function to update the user's color scheme
| preference whenever they make a change. window
| .matchMedia('(prefers-color-scheme: dark)')
| .addEventListener('change', setFavicon);
|
| They are running "window.matchMedia('(prefers-color-scheme:
| dark)')" twice unnecessarily. If you're going to run `setFavicon`
| as the callback to the event listener, you can get the result
| from the `event` parameter passed to the callback like this:
| const setFavicon = (event) => { const favicon =
| document.querySelector('link[rel="icon"]');
| favicon.href = event.matches ? 'dark-mode-favicon.png' : 'light-
| mode-favicon.png';
|
| This would be my preferred way of doing it because it supports
| users who are visiting with JS disabled. <link
| href="light-mode-favicon.png" rel="icon" media="(prefers-color-
| scheme: light)"> <link href="dark-mode-favicon.png"
| rel="icon" media="(prefers-color-scheme: dark)">
|
| https://phuoc.ng/collection/html-dom/change-the-favicon-dyna...
| explaininjs wrote:
| Also, doing it in HTML prevents the flash of alternate-themed
| content. Doing the same with the `theme-color` meta is also a
| seldom-used but great feature for detail-minded PWA developers.
| alin23 wrote:
| yeaaaaaaah no. Never going this path again for any interactive
| page.
|
| This summer I built an irrigation system for my father's field,
| with the idea that the scheduling would be done in relative time
| (water this zone for 2h) instead of absolute (start watering this
| zone at 9AM and end at 11AM).
|
| I kept it as simple as possible: - 16 cheap
| relays for the 24V AC electric valves - 1 beefy relay for
| the pump - 1 Pi Pico W for controlling the relays
|
| Here's a picture of the "low-tech" build:
| https://files.alinpanaitiu.com/lowtech-irigation.jpeg
|
| The Pico W would have a _code.py_ with all the relay and schedule
| logic, and an _index.html_ which would be a simple list of
| sliders to set how much time each valve should be open. The Pico
| W would function as a "hotspot" which the phone would connect
| to, and the "app" would be available at 192.168.4.1.
|
| _It can be added to homescreen and it looks just like a native
| app as far as my father is concerned. It doesn 't feel like one
| though, he can tell._
|
| The web page looks like this: https://shots.panaitiu.com/lHMGplFn
|
| That's all there is to it, really. That _simple_ single page with
| a few sliders and buttons took weeks to build and test thoroughly
| with only vanilla JS. I was obviously constrained by the flash
| memory, but there are KB-sized helper frameworks nowadays which I
| wasn 't aware of.
|
| It's also really hard to refactor. I initially stored the
| schedules at minute-resolution, but then had to store it in
| second-resolution to add a _repeat schedule_ feature. Oh boy, so
| much code to parse and change, so many slider.value calculations
| to redo... yep, never doing this again
| explaininjs wrote:
| The magic of react is that it handles the entire View part of
| MVVC and also provides a nice DSL for writing the View
| Controller. With a lot of architectural planning you can
| develop as clean of code without it (cleaner, perhaps), but I
| agree it's better to just embrace it.
| TheRealPomax wrote:
| If you want to use the browser as a user interface for an
| application, use a user interface library. Knowing what you're
| building is just as important as picking the right tools after
| you figured that part out: not all web pages (in fact, _man_
| web pages) are not, and don 't need to be, user interfaces for
| applications.
| topspin wrote:
| Is the code shared anywhere? I'm thinking that it could benefit
| from some input from others that have done a lot of vanilla
| JavaScript work. That application should be pretty concise and
| DRY using <template>.
| throw555chip wrote:
| AI models will no doubt gobble it up and spit out back out in a
| unique looking laundered format minus the comments.
| est wrote:
| Is there a CSS version of this? Like Zen-garden but modern
| jampekka wrote:
| I appreciate the benefit of not having dependencies but not a fan
| of this rabid vanilla fixation.
|
| Of course you can do anything with Vanilla that you can do with
| e.g. jquery. Otherwise jquery obviously couldn't do it.
|
| The problem is that the vanilla DOM API sucks.
| document.getElementById sucks vs $, document.querySelector sucks
| vs $. setTimeout and setInterval suck. addEventHandler really
| sucks.
| tolmasky wrote:
| These are great. It's unfortunate that if there's any minor bugs
| there's no way to really keep in sync though, for example the
| security issue mentioned in another comment in these comments. It
| would be cool if these examples could be wrapped up into some
| sort of convenient "package" or something like that, such that
| you could easily know if there are any updates and grab them, as
| well as just make it easier to grab these functions whenever you
| need them instead of copy-pasting them...
| wangii wrote:
| so, after 10 years of reactjs, we've forgot how to do this in
| javascript?
| agumonkey wrote:
| Very nice list, it's nice to "down to earth" after too much react
| ui libs :). Thanks.
| blablabla123 wrote:
| What really blew my mind was when I found out that many of the
| DOM functions return live HTMLCollections that are automatically
| updated. I wonder how often that feature is being actively used
| in production code (before the framework craze or developing with
| no framework being somewhat more popular again)
| selimnairb wrote:
| In Capitalist America, DOM manipulates you!
| sumoboy wrote:
| Same developer who has offers a form validator, very solid and
| was worth the $ for past projects. Nice list of JS snippets.
| bakkoting wrote:
| A number of these are using older, awkward APIs, when there's
| nicer native versions now.
|
| For example, "replace an element" is
| ele.parentNode.replaceChild(newEle, ele);
|
| but unless you're targeting Chrome < 54, FF < 49, or Safari < 10,
| you can just do ele.replaceWith(newEle)
|
| `replaceWith` also lets you replace a node with _multiple_ nodes,
| or with text.
|
| Similarly, "loop over a nodelist" wants you to use array spread
| and then forEach, instead of just for (let ele
| of nodelist) ...
| akira2501 wrote:
| Good to keep in mind that nodelist is a live object. So
| manipulating that list while looping over it can yield
| surprising results.
| DerekBickerton wrote:
| For syntactic DOM manipulation sugar I use Cash[0]
|
| [0] https://kenwheeler.github.io/cash/
| throwaway858 wrote:
| The technique for "Make a textarea auto-expand" is obsoleted by a
| new CSS property("form-sizing"):
|
| https://chriscoyier.net/2023/09/29/css-solves-auto-expanding...
|
| Even without using this new CSS property, the technique that is
| used (adjusting the "height" of the element) is not ideal and can
| be glitchy.
|
| A better approach is to use a mirror hidden element:
|
| https://css-tricks.com/the-cleanest-trick-for-autogrowing-te...
| earthboundkid wrote:
| https://phuoc.ng/collection/html-dom/resize-an-iframe-to-fit...
|
| There should be a way to do this with CSS and maybe some magic
| headers. It's super annoying that it has be done via JS.
| purplecats wrote:
| what is the value in manually processing knowledge bases like
| this (besides perhaps in an artisan fashion) if your knowledge
| interface such as chatgpt already knows it and surfaces it at
| will?
| kavaruka wrote:
| ChatGPT is useful only if you understand the code that it
| produces
| spacechild1 wrote:
| You can ask the same question about any knowledge base. Why
| here? This is completely off topic.
| russellbeattie wrote:
| My new favorite bit of vanilla JavaScript has been around since
| Chrome 1.0 and IE: Element.insertAdjacentHTML. To say it's useful
| is an understatement, especially with multi-line Strings using `.
| I can't believe it's been around so long and I only realized it a
| year or so ago.
|
| _The insertAdjacentHTML(position, text) method of the Element
| interface parses the specified text as HTML or XML and inserts
| the resulting nodes into the DOM tree at a specified position._
|
| A contrived example of something that's a pain to do with raw
| DOM: let anchors = ['#a', '#b', '#c'];
| let el = document.querySelector('ul'); for (let a of
| anchors) { el.insertAdjacentHTML(
| 'beforeend', `<li><a
| href="${a}">${a.substr(1)}</a></li>` ); }
|
| Previously I would have to create the li element, then the a
| element, add it as a child, set the href attribute, then the text
| value of the a element, then insert it into the ul element. Or,
| I'd batch it all up as a big string and insert it using
| innerHTML. Modifying an existing list was even more painful and
| verbose.
|
| 1. https://developer.mozilla.org/en-
| US/docs/Web/API/Element/ins...
___________________________________________________________________
(page generated 2023-11-06 21:01 UTC)