dpatte
April 12, 2025, 2:51pm
1
In order to support new paths for my images, I need to programmatically examine and modify some of my
<img src="old-path">
tags in my templates, before they are rendered by blaze.
It it possible to hook in somewhere when the template is first loaded to make such changes to a template?
Can’t you use spacebars
<img src=“{{checkAndUpdateLink “old-path”}}”>
1 Like
dpatte
April 12, 2025, 4:09pm
3
Yes, that works.
But in fact i have hundreds of individual pages that get imported into my main template, each with their own image tags, and several apps that use this process, so modifying them all to use helpers would be a huge job. Besides helpers don’t work on pages imported using {{{sub-page.html}}}
I’d like a single place to modify the paths on the fly.
You can create global helpers using “Handlebars.registerHelper”
dpatte
April 12, 2025, 8:01pm
5
I also tried that but even global helpers are not run on html read in through {{{sub-page.html}}}
I will probably end up having to branch Blaze and embed something to do my conversion
Hi @dpatte it might be not 100% your use case but an inspiration. My approach to lazy load images is first to construct the image attributes in onCreated
but do not use src
but a data-src
and then in onRendered actually load the image (here is use lozad
to handle the request etc. but this could be also implemented manually using fetch
and IntersectionObserver
):
<template name="image">
<img {{attributes}}>
</template>
import { Template } from 'meteor/templating'
import { Components } from '../Components'
import { Random } from 'meteor/random'
import lozad from 'lozad'
import './image.html'
const imageClass = 'lea-image'
Template.image.onCreated(function () {
const instance = this
instance.id = Random.id(4)
})
Template.image.helpers({
attributes () {
// xxx: for performance reasons this could also be put into onCreated
// and stored in a reactive var!
const instance = Template.instance()
const { data } = instance
const customClasses = data.class || ''
const shadowClass = data.shadow ? 'shadow' : ''
const classes = `${imageClass} ${shadowClass} ${customClasses}`
const obj = {}
const cors = data.cors || data.crossorigin
if (cors) {
obj.crossorigin = cors
}
Object.keys(data).forEach(key => {
if (key.includes('data-') || key.includes('aria-')) {
obj[key] = data[key]
}
})
const base = Components.contentPath()
const imageSrc = data.src.startsWith('http')
? data.src
: `${base}${data.src}`
return Object.assign(obj, {
'data-id': instance.id,
title: data.title,
alt: data.alt,
'aria-title': data.title,
width: data.width,
height: data.height,
class: classes,
'data-src': imageSrc
})
}
})
Template.image.onRendered(function () {
const instance = this
const $image = instance.$(`[data-id="${instance.id}"]`)
const image = $image.get(0)
if (!image) {
return
}
const observer = lozad(image)
observer.observe()
instance.autorun(function () {
const data = Template.currentData()
const newDataSrc = data.src
const dataSrc = $image.prop('src')
if (newDataSrc && dataSrc && newDataSrc !== dataSrc) {
$image.prop('src', '*')
$image.removeAttr('data-loaded')
observer.observe()
}
})
})
1 Like