Three related /lignes fixes: 1. Column widths: shrink Date/Facture/Libellé/Signalement (the four editable text columns) to free up room for the amount columns (Montant HT/TTC, the 8 compte columns, Écart), which were cramped. Date/Facture stay nowrap (already short: jj/mm/aa, Fxxxxxxx); Libellé/ Signalement keep wrapping. 2. Signalement editing: replaced the comma-separated inline text input with a small modal -- one tag per line, each with its own remove button, plus an add field at the bottom. Clearer than parsing/ retyping a whole comma list to drop one tag. Backend endpoint is unchanged (still takes a comma-joined value); only the front-end interaction model changed. 3. Scroll storm: a continuous scroll gesture fires many native 'scroll' events, and checkEdges() ran on every one of them -- each qualifying event queued its own loadOlder()/loadNewer() call (queuing, not dropping, was the previous session's fix for a *different* bug), and every queued call did a real fetch + scroll compensation regardless of whether an earlier one already moved the window away from the edge. That pileup is what looked like the same request firing over and over and dragged the scroll position around unpredictably. Fixed by guarding checkEdges() with the existing loadingOlder/ loadingNewer flags so it stops queuing once one's already in flight. (A first attempt at this suppressed the compensation write's own resulting scroll event via a flag cleared on requestAnimationFrame -- reproduced, live, the exact "stuck forever" failure already fixed once this session for the old rAF-based scroll throttle, because rAF doesn't reliably fire in this environment. Removed: turns out no suppression is needed at all, since that event finds loadingOlder already true and the checkEdges() guard blocks it on its own.) Also added a re-entrancy guard to pollForChanges(), which had no protection against a slow response overlapping with the next setInterval tick. Verified with scripted scroll stress tests (dense bursts of 40-100 events, and repeated attempts to scroll back from the very top): exactly one fetch per genuine edge crossing, no duplicate requests, scroll position stays correctly anchored, never snaps back down. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Modules extend your site functionality beyond Drupal core. WHAT TO PLACE IN THIS DIRECTORY? -------------------------------- Placing downloaded and custom modules in this directory separates downloaded and custom modules from Drupal core's modules. This allows Drupal core to be updated without overwriting these files. DOWNLOAD ADDITIONAL MODULES --------------------------- Contributed modules from the Drupal community may be downloaded at https://www.drupal.org/project/project_module. ORGANIZING MODULES IN THIS DIRECTORY ------------------------------------ You may create subdirectories in this directory, to organize your added modules, without breaking the site. Some common subdirectories include "contrib" for contributed modules, and "custom" for custom modules. Note that if you move a module to a subdirectory after it has been enabled, you may need to clear the Drupal cache so it can be found. There are number of directories that are ignored when looking for modules. These are 'src', 'lib', 'vendor', 'assets', 'css', 'files', 'images', 'js', 'misc', 'templates', 'includes', 'fixtures' and 'Drupal'. MULTISITE CONFIGURATION ----------------------- In multisite configurations, modules found in this directory are available to all sites. You may also put modules in the sites/all/modules directory, and the versions in sites/all/modules will take precedence over versions of the same module that are here. Alternatively, the sites/your_site_name/modules directory pattern may be used to restrict modules to a specific site instance. MORE INFORMATION ---------------- Refer to the “Developing for Drupal” section of the README.md in the Drupal root directory for further information on extending Drupal with custom modules.