Skip to content

Commit

Permalink
GH-321: Resize Callout image to parent height
Browse files Browse the repository at this point in the history
CAVEAT: The addition to 0001 migration was manual  and is untested.
  • Loading branch information
wesleyboar committed Aug 24, 2021
1 parent acefadf commit 9767d45
Show file tree
Hide file tree
Showing 5 changed files with 116 additions and 2 deletions.
6 changes: 5 additions & 1 deletion taccsite_cms/contrib/taccsite_callout/cms_plugins.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,12 @@ def get_render_template(self, context, instance, placeholder):
'description': TEXT_FOR_NESTED_PLUGIN_CONTENT_SWAP.format(
element='an image',
plugin_name='Image'
) + '\
<br />\
When the image resize field is checked, the image may disappear after saving this plugin. Reload the page to reload the image.',
'fields': (
'resize_figure_to_fit',
),
'fields': (),
}),
(_('Advanced settings'), {
'classes': ('collapse',),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ class Migration(migrations.Migration):
('cmsplugin_ptr', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, related_name='taccsite_callout_taccsitecallout', serialize=False, to='cms.CMSPlugin')),
('title', models.CharField(blank=True, help_text='A heading for the callout.', max_length=100, verbose_name='Title')),
('description', models.CharField(blank=True, help_text='A paragraph for the callout.', max_length=200, verbose_name='Description')),
('resize_figure_to_fit', models.BooleanField(default=True, help_text='Make image shorter or taller to match the height of text beside it.', verbose_name='Resize any image to fit')),
('attributes', djangocms_attributes_field.fields.AttributesField(default=dict)),
('anchor', models.CharField(blank=True, help_text='Appends the value only after the internal or external link. Do <em>not</em> include a preceding "#" symbol.', max_length=255, verbose_name='Anchor')),
('external_link', models.CharField(blank=True, help_text='Provide a link to an external source.', max_length=2040, validators=[djangocms_link.validators.IntranetURLValidator(intranet_host_re=None)], verbose_name='External link')),
Expand Down
7 changes: 7 additions & 0 deletions taccsite_cms/contrib/taccsite_callout/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,13 @@ class TaccsiteCallout(AbstractLink):
max_length=200,
)

resize_figure_to_fit = models.BooleanField(
verbose_name=_('Resize any image to fit'),
help_text=_('Make image shorter or taller to match the height of text beside it.'),
blank=False,
default=True
)

attributes = fields.AttributesField()

def get_short_description(self):
Expand Down
6 changes: 5 additions & 1 deletion taccsite_cms/contrib/taccsite_callout/templates/callout.html
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,11 @@ <h2 class="c-callout__title">{{ instance.title }}</h2>
<p class="c-callout__desc">{{ instance.description }}</p>

{% if image_plugin %}
<figure class="c-callout__figure">
<figure class="c-callout__figure"
{% if instance.resize_figure_to_fit %}
data-transform="size-content-to-fit" hidden
{% endif %}
>
{% for plugin_instance in instance.child_plugin_instances %}
{% render_plugin plugin_instance %}
{% endfor %}
Expand Down
98 changes: 98 additions & 0 deletions taccsite_cms/static/site_cms/js/modules/elementTransformer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
/**
* Resize content to fit parent height
*
* - Manipulates attributes within existing markup.
* - Size is NOT dynamically updated after initial load.
* @module elementTransformer
*/

/** Resize first child element to match parent height (track state in markup) */
export class SizeContentToFit {



// FAQ: Offers clarity of intent and consistency with state attr.
// NOTE: Could faciliate programmatic transforms (like as a plugin option)
/** A suggested selector to match the container */
static containerSelector = '[data-transform="size-content-to-fit"]';



/**
* Initialize and resize
* @param {HTMLElement} container - The direct parent of the content to resize
*/
constructor (container) {
/** The `HTMLElement` containing the content to resize */
this.container = container;
/** The `HTMLElement` to resize */
this.content = container.querySelector(':scope > *');

// GH-320: Test whether `this.content` was in the DOM at runtime
// FAQ: Use `cloneNode` to NOT watch element reference that is updated later
// console.log({
// container: this.container.cloneNode(true),
// content: this.content.cloneNode(true)
// });

this.resizeContent();
}



/** Mark transformation as in the given state */
setState(state) {
this.container.dataset.transformState = state;
}

/** Mark transformation as NOT in the given state */
removeState(state) {
// NOTE: Multiple states are not supported, so there is no use for `state`
this.container.dataset.transformState = null;
}

/** Whether transformation is in given state */
isState(state) {
return (this.container.dataset.transformState == state);
}

/** Whether to resize the content */
shouldResizeContent() {
if (this.container.getAttribute('hidden') !== null) {
this.content.style.offsetHeight = '0';
this.container.removeAttribute('hidden');
}
}


/** Resize the content */
resizeContent() {
/* To prevent natural height of content from increasing container height */
/* FAQ: Module will set wrong height if content is taller than is desired */
if (this.container.getAttribute('hidden') !== null) {
this.content.style.height = '0';
this.container.removeAttribute('hidden');
}

/* To inform observers that this module is active */
this.setState('resizing-content');

/* To make container (and its content) the same height as a root element */
/* FAQ: Given tall content, figure height equals content height */
/* FAQ: Given hidden content, figure height equals desired content height */
this.container.style.height = '100%';
this.content.style.height = this.container.offsetHeight + 'px';
this.container.style.height = null;

/* To clean up mess (only if it appears to be the mess of this module) */
if (this.isState('resizing-content')) {
this.removeState('resizing-content');
if ( ! this.container.getAttribute('style')) {
this.container.removeAttribute('style');
}
}

/* To inform observers that this module is done */
this.setState('complete');
}
}

0 comments on commit 9767d45

Please sign in to comment.