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

fix(ui/height_limit): height limit not working while loading images #849

Merged
merged 1 commit into from
May 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 31 additions & 23 deletions ui/artalk/src/comment/height-limit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,33 +16,40 @@ export interface IHeightLimitRule {
max: number

/** Whether or not the element contains `<img />` */
imgContains?: boolean
imgCheck?: boolean
}

export type THeightLimitRuleSet = IHeightLimitRule[]

/** Check all elements below the max height limit */
export function check(conf: IHeightLimitConf, rules: THeightLimitRuleSet) {
rules.forEach(({ el, max: maxHeight, imgContains }) => {
rules.forEach(({ el, max, imgCheck }) => {
if (!el) return

// set max height to limit the height
el.style.maxHeight = `${max + 1}px` // allow 2px more for next detecting

const _apply = () => {
if (!el) return
if (!conf.scrollable)
applyHeightLimit({
el,
maxHeight,
postBtnClick: conf.postExpandBtnClick,
})
else applyScrollableHeightLimit({ el, maxHeight })
const postBtnClick = conf.postExpandBtnClick
!conf.scrollable
? applyHeightLimit({ el, max, postBtnClick })
: applyScrollableHeightLimit({ el, max })
}

// checking
const _check = () => {
if (el && Utils.getHeight(el) > maxHeight) _apply() // 是否超过高度
if (Utils.getHeight(el) > max) _apply() // 是否超过高度
}

_check() // check immediately

// image check
if (imgCheck) {
// check again when image loaded
el.querySelectorAll<HTMLImageElement>('.atk-content img').forEach((img) => {
img.onload = () => _check()
})
}
_check() // check now
if (imgContains && el)
// check again if img contains
Utils.onImagesLoaded(el, () => _check())
})
}

Expand All @@ -52,15 +59,15 @@ const HEIGHT_LIMIT_CSS = 'atk-height-limit'
/** Apply height limit on an element and add expand btn */
export function applyHeightLimit(obj: {
el: HTMLElement
maxHeight: number
max: number
postBtnClick?: (e: MouseEvent) => void
}) {
if (!obj.el) return
if (!obj.maxHeight) return
if (!obj.max) return
if (obj.el.classList.contains(HEIGHT_LIMIT_CSS)) return

obj.el.classList.add(HEIGHT_LIMIT_CSS)
obj.el.style.height = `${obj.maxHeight}px`
obj.el.style.height = `${obj.max}px`
obj.el.style.overflow = 'hidden'

/* Expand button */
Expand All @@ -86,16 +93,17 @@ export function disposeHeightLimit($el: HTMLElement) {
if (e.classList.contains('atk-height-limit-btn')) e.remove()
})
$el.style.height = ''
$el.style.maxHeight = ''
$el.style.overflow = ''
}

/** Height limit scrollable CSS class name */
const HEIGHT_LIMIT_SCROLL_CSS = 'atk-height-limit-scroll'

/** Apply scrollable height limit */
export function applyScrollableHeightLimit(obj: { el: HTMLElement; maxHeight: number }) {
if (!obj.el) return
if (obj.el.classList.contains(HEIGHT_LIMIT_SCROLL_CSS)) return
obj.el.classList.add(HEIGHT_LIMIT_SCROLL_CSS)
obj.el.style.height = `${obj.maxHeight}px`
export function applyScrollableHeightLimit(opt: { el: HTMLElement; max: number }) {
if (!opt.el) return
if (opt.el.classList.contains(HEIGHT_LIMIT_SCROLL_CSS)) return
opt.el.classList.add(HEIGHT_LIMIT_SCROLL_CSS)
opt.el.style.height = `${opt.max}px`
}
6 changes: 3 additions & 3 deletions ui/artalk/src/comment/render.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,10 +88,10 @@ export default class Render {
},
[
// 评论内容限高
{ el: this.$content, max: contentMaxH, imgContains: true },
{ el: this.$replyTo, max: contentMaxH, imgContains: true },
{ el: this.$content, max: contentMaxH, imgCheck: true },
{ el: this.$replyTo, max: contentMaxH, imgCheck: true },
// 子评论区域限高(仅嵌套模式)
{ el: this.$childrenWrap, max: childrenMaxH, imgContains: false },
{ el: this.$childrenWrap, max: childrenMaxH, imgCheck: false },
],
)
}
Expand Down
21 changes: 0 additions & 21 deletions ui/artalk/src/lib/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,27 +106,6 @@ export function timeAgo(date: Date, $t: Function = (n: string) => n) {
}
}

/** 所有图片加载完毕后执行 */
export function onImagesLoaded($container: HTMLElement, event: Function) {
if (!$container) return
const images = $container.getElementsByTagName('img')
if (!images.length) return
let loaded = images.length
for (let i = 0; i < images.length; i++) {
if (images[i].complete) {
loaded--
} else {
// eslint-disable-next-line @typescript-eslint/no-loop-func
images[i].addEventListener('load', () => {
loaded--
if (loaded === 0) event()
})
}

if (loaded === 0) event()
}
}

export function getGravatarURL(opts: { params: string; mirror: string; emailMD5: string }) {
return `${opts.mirror.replace(/\/$/, '')}/${opts.emailMD5}?${opts.params.replace(/^\?/, '')}`
}
Expand Down