• Activity
  • Votes
  • Comments
  • New
  • All activity
  • Showing only topics in ~comp with the tag "web". Back to normal view / Search all groups
    1. Making infinite scrollable lists for web without a constantly expanding DOM

      A common theme in web development, and the crux of the so-called "Web 2.0" is scrolling through dynamic lists of content. Tildes is such an example: you can scroll through about 50 topics on the...

      A common theme in web development, and the crux of the so-called "Web 2.0" is scrolling through dynamic lists of content. Tildes is such an example: you can scroll through about 50 topics on the front page before you reach a "next" button if you want to keep looking.

      There's a certain beauty in the simplicity of the next/previous page. When done right it's fast, it's easy, and fits neatly into a server-side rendered model. However, it does cause that small bit of friction where you need to hit the next button to go forward -- taking you out of the "flow", so-to-speak. It's slick, but it could be slicker. Perhaps more importantly, it's an interesting problem to solve.

      A step up from the next/previous button is to load the next page of content when you reach the end of the list, inserting it below. If the load is pretty fast, this will hardly interrupt your flow at all! The ever-so-popular reddit enhancement suite does precisely that for reddit: instead of a next button, when you reach the bottom, the next page of items simply plops into place. If the loading isn't fast enough, perhaps instead of loading when they reach the last item, you might choose to load when they hit the fifth from last item, etc.

      To try to keep this post more concrete, and more helpful, here's how this type of pagination would work in practice, in typescript and using the Intersection Observer API but otherwise framework agnostic:

      /**
       * Allows the user to scroll forever through the given list by calling the given loadMore()
       * function whenever the bottom element (by default) becomes visible. This assumes that
       * loadMore is the only thing that modifies the list, and that the list is done being modified
       * once the promise returned from loadMore resolves
       *
       * @param list The element which contains the individual items
       * @param loadMore A function which can be called to insert more items into the list. Can return
       *   a rejected promise to indicate that there are no more items to load
       * @param triggerLoadAt The index of the child in the list which triggers the load. Negative numbers
       *   are interpreted as offsets from the end of the list. 
       */
      function handlePagination(list: Element, loadMore: () => Promise<void>, triggerLoadAt: number = -1) {
          manageIntersection();
          return;
      
          function handleIntersection(ele: Element, handler: () => void): () => void {
              let active = true;
              const observer = new IntersectionObserver((entries) => {
                  if (active && entries[0].isIntersecting) {
                      handler()
                  }
              }, { root: null, threshold: 0.5 });
              observer.observe(ele);
              return () => {
                  if (active) {
                      active = false;
                      observer.disconnect();
                  }
              }
          }
      
          function manageIntersection() {
              const index = triggerLoadAt < 0 ? list.children.length + triggerLoadAt : triggerLoadAt;
              if (index < 0 || index >= list.children.length) {
                  throw new Error(`index=${index} is not valid for a list of ${list.children.length} items`);
              }
      
              const child = list.children[index];
              const removeIntersectionHandler = handleIntersection(child, () => {
                  removeIntersectionHandler();
                  loadMore().then(() => {
                      manageIntersection();
                  }).catch((e) => {});
              });
          }
      }
      

      If you're sane, this probably suffices for you. However, there is still one problem: as you scroll,
      the number of elements on the DOM get longer and longer. This means they necessarily take up
      some amount of memory, and browsers probably have to do some amount of work to keep
      track of them. Thus, in theory, if you were to scroll long enough, the page would get slower and
      slower! How long "long enough" is would depend mostly on how complicated each item is: if each one
      is a unique 20k element svg, it'll get slow pretty quickly.

      The trick to avoid this, and to get a constant overhead, is that when adding new items below, remove the same number of items above! Of course, if the user scrolls back up they'll be expecting those items to be there, but no worries, the handlePagination from before works just as well for loading items before the first item.

      However, this simple change is where a key problem arises: inserting elements below doesn't cause any layout shift, but inserting an item above ought to--right?

      The answer is: it depends on the browser! Back in 2017 chrome realized that it's often convenient to be able to insert items into the dom above the viewport, and implemented scroll anchoring, which basically ensures that if you insert an item 50px tall above the viewport, then scroll 50px down so that there's no visual layout shift. Firefox followed suite in 2019, and edge got support in 2020. But alas, safari both on mac and ios does not support scroll anchoring (though they expressed interest in it since 2017)

      Now, there's two responses to this:

      • Surely Safari support is coming soon, they've posted on that bug as recently as April! Just use simpler pagination for now
      • Pshhhh, just implement scroll anchoring ourself!

      Of course, I've gone and done #2, and it almost perfectly works. Here's the idea:

      • Right before loadMore, find the first item in the list which is inside the viewport. This is the item whose position we don't want to move. Use getBoundingClientRect to find it's top position.
      • Perform the DOM manipulation as desired
      • Use getBoundingClientRect again to find the new top of that item.
      • Insert (or remove) the appropriate amount of blank space at the top of the list to offset the change in client rect (note that if there's scroll anchoring support in the browser this should always be zero, which means this effectively works as progressive enhancement)

      Now, the function to do this is a tad too long for this post. I implemented it in React, however, and combined it with some stronger preloading object (we don't need all the items we've fetched from the API on the DOM, so we can use before, onTheDom, after lists to avoid getting a bunch of api requests just from scrolling down and up within the same small number of items).

      What's interesting is that it still works perfectly on chrome even with scroll-anchoring disabled (via overflow-anchor: none), but on Safari there is still, sometimes, 1 frame where it renders the wrong scroll position before immediately adjusting. Because I implemented it in react, however, my current hypothesis is I have a mistake somewhere which causes the javascript to yield to the renderer before all the manipulations are done, and it only shows up on Safari because of the generally higher framerates there

      If it's interesting to people, I could extract the infinite list component outside of this project: I certainly like it, and in my case I do expect people to want to quickly scroll through hundreds to thousands of items, so the lighter DOM feels worth it (though perhaps it wouldn't if I had known, when starting, how painful getting it to work on Safari would be!).

      What do you think of this type of "true" infinite scrolling for web? Good thing, neutral thing, bad thing? Would you use it, if the component were available? Would you remove it, if you saw someone doing this? Are there other questions about how this was accomplished? Is this an appropriate post for Tildes?

      11 votes
    2. How can I push/inspire myself to learn JavaScript and Node?

      I'm a full stack dev and my current use of JavaScript language is limited to making the best (read trivial) use of jquery for DOM manipulation in my web apps which primarily use PHP or Python...

      I'm a full stack dev and my current use of JavaScript language is limited to making the best (read trivial) use of jquery for DOM manipulation in my web apps which primarily use PHP or Python (Flask/Django) as backend.

      Now, have you watched that popular thriller movie called Inception which is based on a radical sci-fi concept that an idea or thought can be implanted into someone remotely?

      Just like that, I often find myself facing this strange idea that JavaScript is supposed to be just a toy running inside the web browser. No idea where exactly this idea came from! Each time I try to learn JS or think of getting deeper with things like npm, react, etc., this idea just pops up and kinda stops me from doing anything!

      Is there any way to get rid of this idea somehow?

      9 votes
    3. What advice would you give to someone who has coded in jquery for years and now wants to gracefully switch to modern js?

      Title says it all. Bootstrap+jquery has been my default route and path of least resistance when it comes to web development. Perhaps because I'm coding since a long time and belong to the old...

      Title says it all. Bootstrap+jquery has been my default route and path of least resistance when it comes to web development. Perhaps because I'm coding since a long time and belong to the old school when modern libraries like react weren't yet invented yet?

      I had tried to meddle with Angular.js 1.0 back in those days but was soon disillusioned! It was cool and cutting edge but highly opinionated. It tried to do so many things under the hood that I soon quit the effort and the word "Angular" was stigmatized in my mind ever since! I don't know how different today's typescript based Angular is but that stigma or phobia prevents me from even looking at that direction!

      React is another cool technology which everyone is talking about and I'm sure it has some merits. But I'm not sure exactly what React brings to my development workflow which jquery doesn't already do. Can you tell me some specific advantages or pros of react over jquery which can motivate me to learn the former and let go of the latter? What should I do?

      7 votes
    4. Browser Session vs JWT tokens for authentication system for an app?

      I'm working on an app idea, it's going to be "API first" in design which means there is a clear separation between the backend and frontend. Former will be accessible through a REST API and the...

      I'm working on an app idea, it's going to be "API first" in design which means there is a clear separation between the backend and frontend. Former will be accessible through a REST API and the latter can be simple HTML without me having to delve too much on it. The idea is that the end users or clients will write their own front-end interacting with this REST API in future.

      Firstly, I want to know where to start. Writing a REST API seems quite easy and simple for me as a backend engineer but I've never implemented a "pure API" app in practice. Do you just validate the headers, do the crunching and return back a JSON response? What all must you take care of here?

      Finally, authentication and session handling is something very important here, isn't it? If I make use of session feature in the REST API (like PHP sessions or Django sessions, for eg), authentication will be pretty easier. I don't have to worry about encryption as SSL/TLS would be already doing that for me through the browser. But then what is the downside of this method? Why do so many people use JWT tokens then?

      Coming to JWT tokens, is that the only way of encrypting/validating REST APIs, or are there others? My biggest concern here is scaling and performance. I'm willing to implement the most efficient path here, the one that gives the most performance using least resources.

      3 votes
    5. What is the present state of NPM Packaging System?

      As I recall, about 2-3 years ago I had experimented with what is called the npm install xyz through some tutorials, etc. The objective was to improve my tooling or toolchain at least with things...

      As I recall, about 2-3 years ago I had experimented with what is called the npm install xyz through some tutorials, etc. The objective was to improve my tooling or toolchain at least with things like css/js minification, etc. along with Bootstrap customization. The idea was to then move on to other newer learnings like react, etc.

      But I was soon disgruntled by the whole process! Neither bootstrap turned out to be an easy horse to tame, and NPM was like this astronomical universe of packages that keep on downloading into your folders! I soon lost taste of the whole thing and kept using my tried and tested stack of PHP scripts and using stock Bootstrap through CDNs.

      But today, I want to give it another shot. Has NPM improved than earlier days? What is the best way to go about building a toolchain using it? Are there any useful guides that make the whole process easier to digest?

      6 votes
    6. AdminLTE vs Pure Bootstrap for a new web project?

      I'm primarily a freelance backend dev and for the first time venturing on full-stack development of a non-trivial web app on my own, hence I needed some guidance. I've got all the backend stuff in...

      I'm primarily a freelance backend dev and for the first time venturing on full-stack development of a non-trivial web app on my own, hence I needed some guidance.

      I've got all the backend stuff in php/mysql covered, I just want to know what's the best way to create a dashboard (with left sidebar) considering various aspects like long-term code maintenance and support, robustness, etc. Looks don't matter that much as it's a CRUD app but obviously, better is more appreciated.

      Based on my research until now, AdminLTE seems to be the most popular way of doing it among most devs although a few others like material and coreui also seem to have some street cred.

      But another approach I'm considering apart from AdminLTE is to just use pure bootstrap and fiddle up my own sidebar using something like this. That way, I won't be tied to just one Bootstrap version which is used by AdminLTE (v4.6) and troubleshooting will be much easier through google search and StackOverflow. What do you guys think is the right approach?

      5 votes
    7. Help me decide what technology should I use for this project

      I’m a solo freelance programmer and want to write an app for internal project management, somewhere I can add projects, milestones, tasks, etc. and track them as I work on them, occasionally...

      I’m a solo freelance programmer and want to write an app for internal project management, somewhere I can add projects, milestones, tasks, etc. and track them as I work on them, occasionally remind me of things like take a break, lunch time, etc. and over time I can track on which category I worked how many hours, etc.

      I’m actually confused between whether to build this as a Web or Windows Desktop app. I’m considering latter because it can run efficiently on my laptop in the system tray using least memory and resources, web-based on the other hand will force me keep running an apache server too which will be an overhead (unless I host it on Google Cloud or someplace which might be an option?)

      The only reason for considering web-based is that eventually I’m planning to make this tool open source and with web-based, many others can find this useful too (including OSX/Linux users). At that point, I may consider expanding its schema to include multi-user connectivity, client login, etc. but that’s going too far at this point!

      The idea is that this tool should be useful not just for me but other freelancers, students, etc. who might be in my shoes. From that perspective, what do you think is the right technology to use? Web based or Windows based?

      (I’ve extensively worked on C#/WinForms projects before and I’m thinking Visual Studio Express for desktop development. If web-based, it’ll be php/mysql based)

      5 votes
    8. Looking for recommendations for self-hostable static blog software

      I used to use a random FOSS Python program to manage my blog. The software honestly wasn't the best (partially my own fault for not setting it up super well) and I stopped using it, lost my blog's...

      I used to use a random FOSS Python program to manage my blog. The software honestly wasn't the best (partially my own fault for not setting it up super well) and I stopped using it, lost my blog's source code, and haven't updated the blog in a long time because of that. So I'm looking for a static site generator that is simple, well maintained, and no-frills.

      14 votes
    9. Spiders

      Is anyone here familiar with crawling the web? I’m interested in broad crawling, rather than focusing on particular sites. I’d appreciate pretty much any information about how this is usually...

      Is anyone here familiar with crawling the web? I’m interested in broad crawling, rather than focusing on particular sites. I’d appreciate pretty much any information about how this is usually done, and things to watch out for if attempting it.

      10 votes
    10. What features do you want to see in a userscript manager?

      I'm currently developing a minimal userscript manager who's main goal is to be fully auditable by any user in only ten minutes or so - my prototype uses less than 300 lines of javascript, and I'm...

      I'm currently developing a minimal userscript manager who's main goal is to be fully auditable by any user in only ten minutes or so - my prototype uses less than 300 lines of javascript, and I'm trying to keep it that way.

      To get the codebase this small, however, I have to be very picky with what features I implement - most notably, the code editor has to be very barebones. Are there any features that I'd be shooting myself in the foot by not including?

      For example:

      • syntax highlighting
      • cloud sync
      • regex url matching
      • fullscreen editor (currently, it's just a browser popup - the intention is that you write code elsewhere and paste it in)

      Any feedback is greatly appreciated!

      7 votes
    11. Recommend a self-host, open source URL Shortener

      At my day job at a non-for-profit, I direct the digital services and platforms (among other things). One thing that I've seen in my org. is the widespread use of the Bitly URL shortener (free...

      At my day job at a non-for-profit, I direct the digital services and platforms (among other things). One thing that I've seen in my org. is the widespread use of the Bitly URL shortener (free plan/tier) for the sharing of our many online and offline campaigns. The myriad departments in the org. for the most part operate quite autonomously, though I can influence the use of digital platforms (at least the majority of the time). I'd like to get away from using Bitly. Would anyone kindly recommend alternatives to Bitly? Self-host and open source options would be preferred, but not required if the price is right (read: low enough for a non-profit).

      I've used YOURLs many years ago, and it worked great; did everything that I needed and was straight-forward to install and use. (The only cost was a cheap $5/month Digital Ocean droplet, that I happened to run other things on too.) However, I have also heard of - but never used - the following other options:

      So...Are any of the above worth considering (or avoiding)? Are there any other, perhaps better alternatives not listed here? I'd appreciate any suggestions and recommendations! Thanks in advanced!

      4 votes