PageSourceSearch

https://www.nurtec.com/lib/blocks/image-container/image-container.js

js nurtec.com collected 2026-09-26 05:14:35 UTC 6,523 bytes, 152 lines download raw bytes

1import { FranklinBlock, throttle, blockColorThemeStructure, awaitChildBlocksReady, addThemingToBlock } from '../../scripts/lib-franklin.js';
2
3export default class ImageContainer extends FranklinBlock {
4  variants = [
5    {
6      name: 'bottom',
7      test: this.block.classList.contains('bottom'),
8    },
9    {
10      name: 'top',
11      test: true,
12    },
13  ];
14
15  /**
16   * Get the color theme configuration for the image container
17   * This is used by both beforeBlockRenderColorThemingChildren and afterBlockRenderColorTheming
18   * @returns {Object} The collection block configuration object
19   */
20  getCollectionBlockConfiguration() {
21    const parentCollectionSection = this.block?.parentElement;
22    const parentThemeAttr = Array.from(parentCollectionSection?.attributes || []).find((attr) => attr.name.includes('data-collection-color-theme'));
23
24    const themeOneWhiteClasses = ['color-theme-1-white'];
25    const hasThemeOneWhite = themeOneWhiteClasses.includes(parentThemeAttr?.value);
26    const themeOneCoreTintedClasses = ['color-theme-1-core-tinted'];
27    const hasThemeOneCoreTinted = themeOneCoreTintedClasses.includes(parentThemeAttr?.value);
28    const themeOneCoreSeedClasses = ['color-theme-1-core-seed'];
29    const hasThemeOneCoreSeed = themeOneCoreSeedClasses.includes(parentThemeAttr?.value);
30
31    return {
32      'color-theme-1-white': {
33        isMatch: hasThemeOneWhite,
34        colorThemeCollection: 'data-color-theme-one',
35        colorModeValue: 'white',
36        collectionWrappers: [{ target: ':scope > .core-image-container', classToAdd: 'surface' }],
37      },
38      'color-theme-1-core-tinted': {
39        isMatch: hasThemeOneCoreTinted,
40        colorThemeCollection: 'data-color-theme-one',
41        colorModeValue: 'core-tinted',
42        collectionWrappers: [{ target: ':scope > .core-image-container', classToAdd: 'surface' }],
43      },
44      'color-theme-1-core-seed': {
45        isMatch: hasThemeOneCoreSeed,
46        colorThemeCollection: 'data-color-theme-one',
47        colorModeValue: 'core-seed',
48        collectionWrappers: [{ target: ':scope > .core-image-container', classToAdd: 'surface' }],
49      },
50    };
51  }
52
53  beforeBlockRender() {
54    // Build initial inputData with image blocks
55    this.inputData = {
56      imageBlocks: this.config.imageBlocks.map((blockHTML) => {
57        const template = document.createElement('template');
58        template.innerHTML = blockHTML;
59        const imageBlock = template.content.querySelector('.core-image');
60        imageBlock?.classList.add('image-container-item');
61        imageBlock?.classList.remove('top', 'bottom');
62        imageBlock?.classList.add(this.variant === 'bottom' ? 'bottom' : 'top');
63        if (this.block.classList.contains('has-divider')) {
64          imageBlock?.classList.add('has-divider');
65        }
66        return template.innerHTML;
67      }),
68      textBlock: this.config.textBlock,
69    };
70
71    // Try to get the theme from parent section if not already set on the block
72    // This handles the case where the collection container hasn't set it yet
73    if (!this.block.dataset.collectionColorTheme) {
74      const parentSection = this.block.closest('.section');
75      const parentThemeAttr = Array.from(parentSection?.attributes || []).find((attr) => attr.name.includes('data-collection-color-theme'));
76      if (parentThemeAttr) {
77        this.block.dataset.collectionColorTheme = parentThemeAttr.value;
78      }
79    }
80
81    this.inputData = this.beforeBlockRenderColorThemingChildren(this.inputData, this.block.dataset.collectionColorTheme);
82  }
83
84  beforeBlockRenderColorThemingChildren(inputData, isActive = false) {
85    if (isActive) {
86      const { imageBlocks, textBlock } = inputData;
87      const themedImageBlocks = imageBlocks.map((blockHTML) => addThemingToBlock(blockHTML, 'core-image', this.block.dataset.collectionColorTheme));
88      const themedTextBlock = textBlock ? addThemingToBlock(textBlock, 'core-text', this.block.dataset.collectionColorTheme) : null;
89      return { ...inputData, imageBlocks: themedImageBlocks, textBlock: themedTextBlock };
90    }
91    return inputData;
92  }
93
94  /**
95   * Function to construct and target the proper DOM elements based on variant for color theming
96   */
97  async afterBlockRenderColorTheming() {
98    const parentCollectionSection = this.block?.parentElement;
99    const parentThemeAttr = Array.from(parentCollectionSection?.attributes || []).find((attr) => attr.name.includes('data-collection-color-theme'));
100    if (!parentThemeAttr) return;
101
102    const collectionBlockConfiguration = this.getCollectionBlockConfiguration();
103    blockColorThemeStructure(this.block, collectionBlockConfiguration, true);
104  }
105
106  afterBlockRender() {
107    // global standard rules for block padding
108    this.block.classList.add('block-padding-standard');
109
110    awaitChildBlocksReady(this.block).then(() => {
111      this.calculateContentHeight();
112      this.calculateImageHeight();
113    });
114
115    // Recalculate height on window resize
116    window.addEventListener(
117      'resize',
118      throttle(() => {
119        this.calculateContentHeight();
120        this.calculateImageHeight();
121      }, 100)
122    );
123
124    // Apply color theming after render
125    // Double-check if theme attribute exists, fallback to parent section if needed
126    if (!this.block?.dataset?.collectionColorTheme) {
127      const parentSection = this.block.closest('.section');
128      const parentThemeAttr = Array.from(parentSection?.attributes || []).find((attr) => attr.name.includes('data-collection-color-theme'));
129
130      if (parentThemeAttr) this.block.dataset.collectionColorTheme = parentThemeAttr.value;
131
132      this.afterBlockRenderColorTheming();
133      this.block.setAttribute('data-color-theming-activated', 'true');
134    }
135
136    if (this.block.classList.contains('editorial')) {
137      this.block.classList.add('block-padding-desktop-x-190');
138    }
139  }
140
141  calculateImageHeight() {
142    this.block.style.removeProperty('--image-container-image-height');
143    const maxImageHeight = Math.max(...Array.from(this.block.querySelectorAll('.core-image-image-container')).map((img) => img.offsetHeight));
144    this.block.style.setProperty('--image-container-image-height', `${maxImageHeight}px`);
145  }
146
147  calculateContentHeight() {
148    this.block.style.removeProperty('--image-container-content-height');
149    const maxContentHeight = Math.max(...Array.from(this.block.querySelectorAll('.core-image-content')).map((img) => img.offsetHeight));
150    this.block.style.setProperty('--image-container-content-height', `${maxContentHeight}px`);
151  }
152}

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.