mirror of
https://github.com/TryGhost/Ghost.git
synced 2025-03-11 02:12:21 -05:00
Added throttling and animation when updating signup form preview
fixes https://github.com/TryGhost/Team/issues/3378
This commit is contained in:
parent
c2c6e54578
commit
22f4d55f75
4 changed files with 91 additions and 56 deletions
|
@ -24,16 +24,18 @@
|
|||
/>
|
||||
</div>
|
||||
|
||||
<div class="gh-stack-item row">
|
||||
<label class="modal-fullsettings-title">
|
||||
Background color
|
||||
</label>
|
||||
<Modals::Newsletters::Components::ColorPicker
|
||||
@color={{this.backgroundColor}}
|
||||
@presetColors={{this.backgroundPresetColors}}
|
||||
@onColorChange={{this.setBackgroundColor}}
|
||||
/>
|
||||
</div>
|
||||
{{#unless (eq this.style 'minimal')}}
|
||||
<div class="gh-stack-item row">
|
||||
<label class="modal-fullsettings-title">
|
||||
Background color
|
||||
</label>
|
||||
<Modals::Newsletters::Components::ColorPicker
|
||||
@color={{this.backgroundColor}}
|
||||
@presetColors={{this.backgroundPresetColors}}
|
||||
@onColorChange={{this.setBackgroundColor}}
|
||||
/>
|
||||
</div>
|
||||
{{/unless}}
|
||||
|
||||
<div class="gh-stack-item">
|
||||
<label class="modal-fullsettings-title">
|
||||
|
|
|
@ -1,11 +1,19 @@
|
|||
<div>
|
||||
<div {{did-update this.onChangeHtml @html}}>
|
||||
<iframe
|
||||
srcDoc="<!DOCTYPE html>"
|
||||
class="gh-signup-form-iframe"
|
||||
class={{if (eq this.visibleIframeIndex 0) "gh-signup-form-iframe" "gh-signup-form-iframe gh-iframe-hidden"}}
|
||||
frameborder="0"
|
||||
allowtransparency="true"
|
||||
title="Signup Form Preview"
|
||||
{{on "load" this.onLoad}}
|
||||
{{did-update this.updateContent @html}}
|
||||
title="Signup Form Preview 1"
|
||||
{{on "load" (fn this.onLoad 0) }}
|
||||
></iframe>
|
||||
|
||||
<iframe
|
||||
srcDoc="<!DOCTYPE html>"
|
||||
class={{if (eq this.visibleIframeIndex 1) "gh-signup-form-iframe" "gh-signup-form-iframe gh-iframe-hidden"}}
|
||||
frameborder="0"
|
||||
allowtransparency="true"
|
||||
title="Signup Form Preview 2"
|
||||
{{on "load" (fn this.onLoad 1)}}
|
||||
></iframe>
|
||||
</div>
|
||||
|
|
|
@ -1,59 +1,74 @@
|
|||
import Component from '@glimmer/component';
|
||||
import {action} from '@ember/object';
|
||||
import {throttle} from '@ember/runloop';
|
||||
import {tracked} from '@glimmer/tracking';
|
||||
|
||||
export default class Preview extends Component {
|
||||
iframe;
|
||||
iframeRoot;
|
||||
isContentLoaded = false;
|
||||
// We have two iframes
|
||||
// When the HTML changes, the invisible iframe will get changed, once that one is fully loaded, it will become visible and the other iframe will be hidden
|
||||
|
||||
/**
|
||||
* When updating the frame, to avoid layout jumps, we'll reuse the last known height
|
||||
*/
|
||||
@tracked
|
||||
cachedHeight = 0;
|
||||
iframes = [
|
||||
{element: null, html: '', loading: true},
|
||||
{element: null, html: '', loading: true}
|
||||
];
|
||||
|
||||
@action
|
||||
onLoad(event) {
|
||||
this.iframe = event.currentTarget;
|
||||
if (!this.isContentLoaded) {
|
||||
this.updateContent();
|
||||
}
|
||||
this.onResize();
|
||||
(new ResizeObserver(() => this.onResize(this.iframeRoot)))?.observe?.(this.iframeRoot);
|
||||
@tracked
|
||||
visibleIframeIndex = 0;
|
||||
|
||||
get visibleHtml() {
|
||||
return this.iframes[this.visibleIframeIndex].html;
|
||||
}
|
||||
|
||||
@action
|
||||
updateContent() {
|
||||
if (!this.iframe) {
|
||||
onLoad(index, event) {
|
||||
const iframe = this.iframes[index];
|
||||
if (!iframe) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!iframe.element) {
|
||||
iframe.element = event.currentTarget;
|
||||
|
||||
if (index === this.visibleIframeIndex) {
|
||||
this.updateContent(index);
|
||||
}
|
||||
} else {
|
||||
// Finished loading this iframe
|
||||
iframe.loading = false;
|
||||
this.visibleIframeIndex = index;
|
||||
}
|
||||
}
|
||||
|
||||
@action onChangeHtml() {
|
||||
// Get next iframe
|
||||
throttle(this, this.throttledUpdate, 300, false);
|
||||
}
|
||||
|
||||
throttledUpdate() {
|
||||
// Update the invisible iframe content
|
||||
const index = this.visibleIframeIndex === 0 ? 1 : 0;
|
||||
this.updateContent(index);
|
||||
}
|
||||
|
||||
@action
|
||||
updateContent(index) {
|
||||
const iframe = this.iframes[index];
|
||||
if (!iframe || !iframe.element) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (index === this.visibleIframeIndex && !iframe.loading) {
|
||||
return;
|
||||
}
|
||||
|
||||
iframe.loading = true;
|
||||
const html = `<html><head><style>body, html {padding: 0; margin: 0;}</style></head><body>${this.args.html}</body></html>`;
|
||||
iframe.html = this.args.html;
|
||||
|
||||
// Set the iframe's new HTML
|
||||
this.iframe.contentWindow.document.open();
|
||||
this.iframe.contentWindow.document.write(html);
|
||||
this.iframe.contentWindow.document.close();
|
||||
|
||||
this.iframeRoot = this.iframe.contentDocument.body;
|
||||
|
||||
// fix for Safari causing the iframe load to inifite loop
|
||||
// Set the flag indicating the content has been loaded
|
||||
this.isContentLoaded = true;
|
||||
}
|
||||
|
||||
@action
|
||||
onResize() {
|
||||
if (!this.iframeRoot) {
|
||||
return;
|
||||
}
|
||||
|
||||
const height = this.iframeRoot.scrollHeight || this.cachedHeight;
|
||||
|
||||
//this.iframe.style.height = `${height}px`;
|
||||
|
||||
if (height > 30) {
|
||||
this.cachedHeight = height;
|
||||
}
|
||||
iframe.element.contentWindow.document.open();
|
||||
iframe.element.contentWindow.document.write(html);
|
||||
iframe.element.contentWindow.document.close();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3081,6 +3081,16 @@ p.theme-validation-details {
|
|||
.gh-signup-form-iframe {
|
||||
width: 100%;
|
||||
border: 0;
|
||||
opacity: 1;
|
||||
z-index: 0;
|
||||
transition: none;
|
||||
}
|
||||
|
||||
.gh-signup-form-iframe.gh-iframe-hidden {
|
||||
opacity: 0;
|
||||
z-index: 1;
|
||||
transition: 0.3s opacity;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.fullwidth-modal {
|
||||
|
|
Loading…
Add table
Reference in a new issue