Skip to content

Commit

Permalink
Added settings for youtube thumbnails
Browse files Browse the repository at this point in the history
  • Loading branch information
vb committed Oct 19, 2021
1 parent e47237c commit dfd82ab
Show file tree
Hide file tree
Showing 3 changed files with 96 additions and 23 deletions.
21 changes: 20 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,8 @@ lazyframe(elements, {
debounce: 100,
lazyload: true,
autoplay: true,

youtubeThumbnailQuality: 'hq',
youtubeThumbnailImage: 'default',
// Callbacks
onLoad: (lazyframe) => console.log(lazyframe),
onAppend: (iframe) => console.log(iframe),
Expand All @@ -108,6 +109,14 @@ Set this to `false` if you want all API calls and local images to be loaded on p

Set this to `false` to remove autoplay from the `allow` attribute on the iframe tag i.e if set this to `false` if you want don't want your Youtube video to automatically start playing once the user clicks on the play icon.

### youtubeThumbnailQuality

Defines the thumbnail quality to use from Youtubes thumbnail service. Possible values are '', 'sd', 'mq', 'hq' and 'maxres'

### youtubeThumbnailImage

Defines the thumbnail image to use from Youtubes thumbnail service. Possible values are 'default', '1', '2' and '3'

### `onLoad`

Callback function for when a element is initialized.
Expand All @@ -131,6 +140,8 @@ Callback function with the thumbnail URL
data-src=""
data-ratio="1:1"
data-initinview="false"
data-youtube-thumbnail-image="default"
data-youtube-thumbnail-quality="hq"
></div>
```

Expand Down Expand Up @@ -158,6 +169,14 @@ The ratio of the lazyframe. Possible values: 16:9, 4:3, 1:1

Set this to true if you want the resource to execute (for example video to play) when the element is in view.

### data-youtube-thumbnail-image

Defines the thumbnail image to use from Youtubes thumbnail service. Possible values are 'default', '1', '2' and '3'.

### data-youtube-thumbnail-quality

Defines the thumbnail quality to use from Youtubes thumbnail service. Possible values are '', 'sd', 'mq', 'hq' and 'maxres'

## License

[MIT](https://opensource.org/licenses/MIT). © 2016 Viktor Bergehall
94 changes: 74 additions & 20 deletions src/lazyframe.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,22 @@ interface LazyframeObject extends LazyframeSettings {
node: HTMLElement
}

interface LazyframeSettings {
interface LazyframeOptions {
debounce: number
lazyload: boolean
autoplay: boolean
youtubeThumbnailQuality: '' | 'sd' | 'mq' | 'hq' | 'maxres'
youtubeThumbnailImage: 'default' | '1' | '2' | '3'
onLoad: (node: HTMLElement) => void
onAppend: (node: HTMLElement | null) => void
onThumbnailLoad: (url: string) => void
}

type OverrideAbleSettings = Pick<
LazyframeOptions,
'youtubeThumbnailImage' | 'youtubeThumbnailQuality'
>
interface LazyframeSettings extends OverrideAbleSettings {
src: string
embed: string
title: string | null
Expand All @@ -18,23 +33,27 @@ interface LazyframeSettings {
iframeNode: DocumentFragment
}

interface LazyframeOptions {
debounce: number
lazyload: boolean
autoplay: boolean
onLoad: (node: HTMLElement) => void
onAppend: (node: HTMLElement | null) => void
onThumbnailLoad: (url: string) => void
}

const Lazyframe = () => {
const findVendorIdAndQuery = new RegExp(
/^(?:https?:\/\/)?(?:www\.)?(youtube-nocookie|youtube|vimeo)(?:\.com)?\/?.*(?:watch|embed)?(?:.*v=|v\/|\/)([\w-_]+)(?:\&|\?|\/\?)?(.+)?$/
)

const classNames = {
loaded: 'lazyframe--loaded',
title: 'lazyframe__title',
const youtube = {
quality: {
values: ['', 'sd', 'mq', 'hq', 'maxres'],
default: 'hq' as LazyframeSettings['youtubeThumbnailQuality'],
},
image: {
values: ['default', '1', '2', '3'],
default: 'default' as LazyframeSettings['youtubeThumbnailImage'],
},
isYoutube: (vendor: LazyframeSettings['vendor']) =>
vendor && vendor.indexOf('youtube') > -1,
}

enum Classes {
LOADED = 'lazyframe--loaded',
TITLE = 'lazyframe__title',
}

const nodes: LazyframeObject[] = []
Expand All @@ -43,6 +62,8 @@ const Lazyframe = () => {
debounce: 100,
lazyload: true,
autoplay: true,
youtubeThumbnailQuality: youtube.quality.default,
youtubeThumbnailImage: youtube.image.default,
onLoad: () => {},
onAppend: () => {},
onThumbnailLoad: () => {},
Expand Down Expand Up @@ -75,7 +96,7 @@ const Lazyframe = () => {
}

function create(node: HTMLElement) {
if (node.classList.contains(classNames.loaded)) {
if (node.classList.contains(Classes.LOADED)) {
return
}

Expand Down Expand Up @@ -106,7 +127,7 @@ const Lazyframe = () => {
const fragment = document.createDocumentFragment()
const titleNode = document.createElement('span')

titleNode.className = classNames.title
titleNode.className = Classes.TITLE
fragment.appendChild(titleNode)

if (lazyframe.title) {
Expand All @@ -122,6 +143,8 @@ const Lazyframe = () => {
const thumbnail = node.getAttribute('data-thumbnail')
const initinview = node.getAttribute('data-initinview') === 'true'

const youtube = getYoutubeSettings(node)

if (!src) {
throw new Error('You must supply a data-src on the node')
}
Expand Down Expand Up @@ -152,6 +175,23 @@ const Lazyframe = () => {
query,
initialized: false,
iframeNode: createIframeNode(vendor, query, src, id),
youtubeThumbnailQuality: youtube.quality,
youtubeThumbnailImage: youtube.image,
}
}

function getYoutubeSettings(node: HTMLElement) {
let quality = node.getAttribute('data-youtube-thumbnail-quality')
if (!quality || !youtube.quality.values.includes(quality)) {
quality = settings.youtubeThumbnailQuality
}
let image = node.getAttribute('data-youtube-thumbnail-image')
if (!image || !youtube.image.values.includes(image)) {
image = settings.youtubeThumbnailImage
}
return {
image: image as LazyframeSettings['youtubeThumbnailImage'],
quality: quality as LazyframeSettings['youtubeThumbnailQuality'],
}
}

Expand All @@ -163,7 +203,21 @@ const Lazyframe = () => {
lazyframe.title = json.title
}
if (json.thumbnail_url) {
lazyframe.thumbnail = json.thumbnail_url
if (youtube.isYoutube(lazyframe.vendor)) {
if (
lazyframe.youtubeThumbnailImage === youtube.image.default &&
lazyframe.youtubeThumbnailQuality === youtube.quality.default
) {
lazyframe.thumbnail = json.thumbnail_url
}
lazyframe.thumbnail = json.thumbnail_url.replace(
new RegExp(youtube.quality.default + youtube.image.default),
lazyframe.youtubeThumbnailQuality +
lazyframe.youtubeThumbnailImage
)
} else {
lazyframe.thumbnail = json.thumbnail_url
}
}
return lazyframe
})
Expand All @@ -178,7 +232,7 @@ const Lazyframe = () => {
}

function populatePlaceholder(lazyframe: LazyframeObject) {
const titleNode = lazyframe.node.querySelector('.lazyframe__title')
const titleNode = lazyframe.node.querySelector(`.${Classes.TITLE}`)

if (lazyframe.title && titleNode && titleNode.innerHTML === '') {
titleNode.innerHTML = lazyframe.title
Expand All @@ -191,7 +245,7 @@ const Lazyframe = () => {
}

function onLoad(lazyframe: LazyframeObject) {
lazyframe.node.classList.add(classNames.loaded)
lazyframe.node.classList.add(Classes.LOADED)
lazyframe.initialized = true
if (lazyframe.initinview) {
lazyframe.node.click()
Expand Down Expand Up @@ -242,7 +296,7 @@ const Lazyframe = () => {
}

function createIframeNode(
vendor: LazyframeObject['vendor'] | '' = '',
vendor: LazyframeSettings['vendor'],
query: string,
src: string,
id: string
Expand All @@ -251,7 +305,7 @@ const Lazyframe = () => {
const iframeNode = document.createElement('iframe')

let embed = src
if (vendor && vendor.indexOf('youtube') > -1) {
if (youtube.isYoutube(vendor)) {
embed = `https://www.${vendor}.com/embed/${id}/?${query}`
} else if (vendor === 'vimeo') {
embed = `https://player.vimeo.com/video/${id}/?${query}`
Expand Down
4 changes: 2 additions & 2 deletions test/browser.js
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ test('should append optional query params from data-src', async (t) => {
node.click()
const iframe = node.querySelector('iframe')
const src = iframe.getAttribute('src')
const [, iframQuery] = src.split('?autoplay=1&')
const [, iframeQuery] = src.split('?autoplay=1&')

t.is(iframQuery, query)
t.is(iframeQuery, query)
})

0 comments on commit dfd82ab

Please sign in to comment.