Live site issue

User
https://wmb.ddev.site/themes/template/css/custom.css 404
but on live site its working fine
we are using sliverstripe ddev setup
Assistant
In SilverStripe 4+ on DDEV (public web root), theme assets are exposed under `/resources/…`, not `/themes/…`.
That’s why `/themes/template/css/custom.css` 404s locally but works on your live box.

### Fix options (pick one)

1) **Use the correct public path**

<link rel="stylesheet" href="/resources/themes/template/css/custom.css">

2) **Let SilverStripe include it (recommended)**
– In a template:

<% require themedCSS('custom') %>  <!-- loads themes/template/css/custom.css -->

– Or in PHP:

use SilverStripeViewRequirements;
Requirements::themedCSS('custom');

### Make sure assets are exposed
If you still get 404s, expose/symlink theme resources to `public/resources`:

ddev ssh
composer vendor-expose                             # or: composer vendor-expose symlink
# then clear caches
vendor/bin/sake dev/build flush=all || true

(Alternatively just hit any page with `?flush`.)

### Quick checklist
– File exists at `themes/template/css/custom.css`.
– `app/_config/theme.yml` has:

SilverStripeViewSSViewer:
    themes:
      - 'template'
      - '$default'

– After changes: `?flush` once.

This will make your CSS load locally just like it does on live.

User
we have a global js file run one part when this class apartment-upload-step is avail on the page
Assistant
Got it. Here are solid patterns to “run only when `.apartment-upload-step` is on the page,” without double‑running.

### Vanilla JS (safe for partial/AJAX loads too)

<script>
(function () {
  // what you want to run for each matching element
  function initApartmentUploadStep(el) {
    if (el.dataset.apartmentInit === "1") return; // avoid re-init
    el.dataset.apartmentInit = "1";

    // --- your logic here ---
    console.log("Init apartment-upload-step", el);
  }

  // run on current DOM
  function scan() {
    document.querySelectorAll(".apartment-upload-step").forEach(initApartmentUploadStep);
  }

  // run on initial load
  if (document.readyState === "loading") {
    document.addEventListener("DOMContentLoaded", scan);
  } else {
    scan();
  }

  // optional: watch for elements added later (AJAX, PJAX, Inertia, etc.)
  const mo = new MutationObserver((mutations) => {
    for (const m of mutations) {
      m.addedNodes.forEach((node) => {
        if (!(node instanceof Element)) return;
        if (node.matches(".apartment-upload-step")) initApartmentUploadStep(node);
        node.querySelectorAll?.(".apartment-upload-step").forEach(initApartmentUploadStep);
      });
    }
  });
  mo.observe(document.documentElement, { childList: true, subtree: true });
})();
</script>

### jQuery version (if you already load jQuery)

<script>
(function ($) {
  function init($el) {
    if ($el.data("apartmentInit")) return;
    $el.data("apartmentInit", true);

    // --- your logic here ---
    console.log("Init apartment-upload-step", $el[0]);
  }

  function scan(ctx) {
    $(ctx).find(".apartment-upload-step").each(function(){ init($(this)); });
  }

  $(scan); // DOM ready
  // observe later DOM changes too
  new MutationObserver(function (muts) {
    muts.forEach(function (m) {
      $(m.addedNodes).each(function () {
        if (this.nodeType !== 1) return;
        const $n = $(this);
        if ($n.is(".apartment-upload-step")) init($n);
        scan(this);
      });
    });
  }).observe(document.documentElement, { childList: true, subtree: true });
})(jQuery);
</script>

#### Notes
– Uses a per-element flag (`data-apartment-init`) to prevent duplicate init.
– Handles elements added after load (useful if SilverStripe renders via partials/AJAX, or you navigate with PJAX/Inertia).
– If you only need the simple case (no dynamic injection), you can delete the `MutationObserver` block.

User
give me simle if page has this class apartment-upload-step
Assistant
Super simple version – just check if that class exists on the page:

document.addEventListener("DOMContentLoaded", function () {
  if (document.querySelector(".apartment-upload-step")) {
    // run your code here
    console.log("Page has apartment-upload-step");
  }
});

That’s it ✅ – the code inside will only run if an element with `.apartment-upload-step` is present in the DOM.

Do you want me to also give you the **jQuery one-liner** version?

Leave a Comment

Your email address will not be published. Required fields are marked *