Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Anchor fragment prevents CMSPreview dynamic reload #195

Open
blueo opened this issue Feb 28, 2018 · 5 comments
Open

Anchor fragment prevents CMSPreview dynamic reload #195

blueo opened this issue Feb 28, 2018 · 5 comments

Comments

@blueo
Copy link
Contributor

blueo commented Feb 28, 2018

We've been attempting to implement a feature where when the some changes happen within a block (ie, reordering objects on a gridfield) then the CMS preview refreshes to reflect the changes.

I've run into a problem because the Block's preview link includes a fragment/anchor. This means that when re-initialising the CMS preview (eg jQuery('.cms-preview').entwine('ss.preview')._initialiseFromContent()) the link is set on the preview iframe but because it is the same url, and it includes a hash, it ignores the change. You can confirm this by removing the anchor addition in the Link function of BaseElement and calling the reload script above and notice that a reload occurs.

We're working around it by removing the anchor from the preview link but I assume this is intended to move the preview to the anchor - if so, I'm not exactly sure how to go about properly solving this. Perhaps adding a timestamp to the preview link in localstorage after a reload occurs?

@robbieaverill
Copy link
Contributor

I assume this is intended to move the preview to the anchor

Yep that's right - issue was #121

@robbieaverill
Copy link
Contributor

@blueo do you know off hand if this is still an issue?

@blueo
Copy link
Contributor Author

blueo commented Nov 18, 2018

@robbieaverill unfortunately this is a bit tricky for me to test atm as we've worked our UI around it. But I assume that if you've still got anchor tags on the preview iframe, then any JS that updates the iframe src, and only changes the anchor tag (eg a change to preview scroll to another block on the same page) will have the same problem - the preview will not reload.

@mooror
Copy link

mooror commented Feb 25, 2024

I cannot confirm that this is still is an issue with Elemental, but when I implemented my own CMSPreviewable DataObject with an element/anchor hash on the end the preview pane no longer refreshes when the DataObject is saved:

I used the following for my PreviewLink method:

public function PreviewLink($action = null)
    {
        // @codingStandardsIgnoreEnd
        $link = null;
        if (!$this->isInDB()) {
            return $link;
        }

        // Add extra GET variable
        $cmsModeVar = $this->config()->get('cms_preview_mode_url_var');
        $action = $action . "?$cmsModeVar=1";

        // Scroll the preview straight to where the object sits on the page.
        $page = $this->getPage();
        if ($page && $page->exists()) {
            $link = $page->Link($action) . '#' . $this->HtmlID; // This breaks the live preview
            // $link = $page->Link($action); This one works fine
        }

        $this->extend('updatePreviewLink', $link, $action);
        return $link;
    }

The only way I could get around it was to use a random string in my GET parameter so that the URL was different every save
So from this:

$action = $action . "?$cmsModeVar=1";

To this:

$action = $action . "?$cmsModeVar=".mt_rand();

But this seems to break page caching and so the preview pane refresh is noticeably longer then if you keep the URL the same and remove the html fragment part

@mooror
Copy link

mooror commented Feb 25, 2024

I figured out a work around using some javascript and an extra GET parameter:

So from my above code I added a second GET parameter:

$action = $action . "?$cmsModeVar=1"; // Before
$action = $action . "?$cmsModeVar=1&scroll-to=" . $this->HtmlID; // After

And removed the HTML ID hash

$link = $page->Link($action) . '#' . $this->HtmlID; // Before
$link = $page->Link($action); // After

Then I add the following javascript to the page when the preview mode GET parameter is detected:

  const urlVars = new URLSearchParams(window.location.search);
  const scrollTo = urlVars.get('scroll-to');
  window.location = (""+window.location).replace(/#[A-Za-z0-9_]*$/,'')+"#"+scrollTo;

This allows us to have no hash tags in preview URL (so the refresh works) and we still get the scroll to element effect 🎊

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants