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

Add native lazy loading callback #155

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
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
2 changes: 1 addition & 1 deletion assets.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
"version": 1690813628192
"version": 1691082391092
}
7 changes: 4 additions & 3 deletions assets/scripts/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,10 @@ const CSS_CLASS = Object.freeze({
LOADED: 'is-loaded',
READY: 'is-ready',
FONTS_LOADED: 'fonts-loaded',
LAZY_CONTAINER: 'c-lazy',
LAZY_LOADED: '-lazy-loaded',
// ...
IMAGE: "c-image",
IMAGE_LAZY_LOADED: "-lazy-loaded",
IMAGE_LAZY_LOADING: "-lazy-loading",
IMAGE_LAZY_ERROR: "-lazy-error",
Comment on lines +32 to +35
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Respect the existing quotation style and prioritize single quotes.

Suggested change
IMAGE: "c-image",
IMAGE_LAZY_LOADED: "-lazy-loaded",
IMAGE_LAZY_LOADING: "-lazy-loading",
IMAGE_LAZY_ERROR: "-lazy-error",
IMAGE: 'c-image',
IMAGE_LAZY_LOADED: '-lazy-loaded',
IMAGE_LAZY_LOADING: '-lazy-loading',
IMAGE_LAZY_ERROR: '-lazy-error',

})

// Custom js events
Expand Down
6 changes: 6 additions & 0 deletions assets/scripts/globals.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import svg4everybody from 'svg4everybody';
import { ENV } from './config';
import { triggerLazyloadCallbacks } from './utils/image';

// Dynamic imports for development mode only
let gridHelper;
Expand All @@ -20,4 +21,9 @@ export default function () {
* Add grid helper
*/
gridHelper?.();

/**
* Trigger lazyload
*/
Comment on lines +25 to +27
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Superfluous comment given the called function name.

Suggested change
/**
* Trigger lazyload
*/

triggerLazyloadCallbacks();
}
17 changes: 15 additions & 2 deletions assets/scripts/modules/Load.js
Original file line number Diff line number Diff line change
@@ -1,22 +1,35 @@
import { module } from 'modujs';
import modularLoad from 'modularload';
import { resetLazyloadCallbacks, triggerLazyloadCallbacks } from "../utils/image";

export default class extends module {
constructor(m) {
super(m);
}

init() {
const load = new modularLoad({
this.load = new modularLoad({
enterDelay: 0,
transitions: {
customTransition: {}
}
});

load.on('loaded', (transition, oldContainer, newContainer) => {
this.load.on('loaded', (transition, oldContainer, newContainer) => {
this.call('destroy', oldContainer, 'app');
this.call('update', newContainer, 'app');

/**
* Trigger lazyload
*/
Comment on lines +22 to +24
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Superfluous comment given the called function name.

Suggested change
/**
* Trigger lazyload
*/

triggerLazyloadCallbacks();
});

this.load.on("loading", () => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Respect the existing quotation style and prioritize single quotes.

Suggested change
this.load.on("loading", () => {
this.load.on('loading', () => {

/**
* Remove previous lazyload callbacks
*/
Comment on lines +29 to +31
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Superfluous comment given the called function name.

Suggested change
/**
* Remove previous lazyload callbacks
*/

resetLazyloadCallbacks();
});
}
}
42 changes: 18 additions & 24 deletions assets/scripts/modules/Scroll.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { module } from 'modujs'
import { lazyLoadImage } from '../utils/image'
import LocomotiveScroll from 'locomotive-scroll'

export default class extends module {
Expand All @@ -19,29 +18,6 @@ export default class extends module {
// }
}

/**
* Lazy load the related image.
*
* @see ../utils/image.js
*
* It is recommended to wrap your `<img>` into an element with the
* CSS class name `.c-lazy`. The CSS class name modifier `.-lazy-loaded`
* will be applied on both the image and the parent wrapper.
*
* ```html
* <div class="c-lazy o-ratio u-4:3">
* <img data-scroll data-scroll-call="lazyLoad, Scroll, main" data-src="http://picsum.photos/640/480?v=1" alt="" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" />
* </div>
* ```
*
* @param {LocomotiveScroll} args - The Locomotive Scroll instance.
*/
lazyLoad(args) {
lazyLoadImage(args.target, null, () => {
//callback
})
}

scrollTo(params) {
let { target, ...options } = params

Expand All @@ -53,6 +29,24 @@ export default class extends module {
this.scroll?.scrollTo(target, options)
}

/**
* Observe new scroll elements
*
* @param $newContainer (HTMLElement)
*/
addScrollElements($newContainer) {
this.scroll?.addScrollElements($newContainer)
}

/**
* Unobserve scroll elements
*
* @param $oldContainer (HTMLElement)
*/
removeScrollElements($oldContainer) {
this.scroll?.removeScrollElements($oldContainer)
}
Comment on lines +32 to +48
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Misaligned block comment syntax and invalid parameter tags.

Suggested change
/**
* Observe new scroll elements
*
* @param $newContainer (HTMLElement)
*/
addScrollElements($newContainer) {
this.scroll?.addScrollElements($newContainer)
}
/**
* Unobserve scroll elements
*
* @param $oldContainer (HTMLElement)
*/
removeScrollElements($oldContainer) {
this.scroll?.removeScrollElements($oldContainer)
}
/**
* Observe new scroll elements
*
* @param {HTMLElement} $newContainer
*/
addScrollElements($newContainer) {
this.scroll?.addScrollElements($newContainer)
}
/**
* Unobserve scroll elements
*
* @param {HTMLElement} $oldContainer
*/
removeScrollElements($oldContainer) {
this.scroll?.removeScrollElements($oldContainer)
}


destroy() {
this.scroll.destroy();
}
Expand Down
129 changes: 76 additions & 53 deletions assets/scripts/utils/html.js
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Out of scope coding style corrections. Ideally, these corrections should be their own commit either in a different pull request or directly on the main branch.

Respect the existing quotation style and prioritize single quotes.

Original file line number Diff line number Diff line change
Expand Up @@ -4,76 +4,74 @@
* @return {string} escaped string
*/

const escapeHtml = str =>
str.replace(/[&<>'"]/g, tag => ({
'&': '&amp;',
'<': '&lt;',
'>': '&gt;',
"'": '&#39;',
'"': '&quot;'
}[tag]))

const escapeHtml = (str) =>
str.replace(
/[&<>'"]/g,
(tag) =>
({
"&": "&amp;",
"<": "&lt;",
">": "&gt;",
"'": "&#39;",
'"': "&quot;",
}[tag])
);

/**
* Unescape HTML string
* @param {string} str - string to unescape
* @return {string} unescaped string
*/

const unescapeHtml = str =>
str.replace('&amp;', '&')
.replace('&lt;', '<')
.replace('&gt;', '>')
.replace('&#39;', "'")
.replace('&quot;', '"')

const unescapeHtml = (str) =>
str
.replace("&amp;", "&")
.replace("&lt;", "<")
.replace("&gt;", ">")
.replace("&#39;", "'")
.replace("&quot;", '"');

/**
* Get element data attributes
* @param {HTMLElement} node - node element
* @return {array} node data
*/

const getNodeData = node => {

const getNodeData = (node) => {
// All attributes
const attributes = node.attributes
const attributes = node.attributes;

// Regex Pattern
const pattern = /^data\-(.+)$/
const pattern = /^data\-(.+)$/;

// Output
const data = {}
const data = {};

for (let i in attributes) {
if (!attributes[i]) {
continue
continue;
}

// Attributes name (ex: data-module)
let name = attributes[i].name
let name = attributes[i].name;

// This happens.
if (!name) {
continue
continue;
}

let match = name.match(pattern)
let match = name.match(pattern);
if (!match) {
continue
continue;
}

// If this throws an error, you have some
// serious problems in your HTML.
data[match[1]] = getData(node.getAttribute(name))
data[match[1]] = getData(node.getAttribute(name));
}

return data;

}



};

/**
* Parse value to data type.
Expand All @@ -83,58 +81,83 @@ const getNodeData = node => {
* @return {mixed} value in its natural data type
*/

const rbrace = /^(?:\{[\w\W]*\}|\[[\w\W]*\])$/
const getData = data => {
if (data === 'true') {
return true
const rbrace = /^(?:\{[\w\W]*\}|\[[\w\W]*\])$/;
const getData = (data) => {
if (data === "true") {
return true;
}

if (data === 'false') {
return false
if (data === "false") {
return false;
}

if (data === 'null') {
return null
if (data === "null") {
return null;
}

// Only convert to a number if it doesn't change the string
if (data === +data+'') {
return +data
if (data === +data + "") {
return +data;
}

if (rbrace.test(data)) {
return JSON.parse(data)
return JSON.parse(data);
}

return data
}

return data;
};

/**
* Returns an array containing all the parent nodes of the given node
* @param {HTMLElement} $el - DOM Element
* @return {array} parent nodes
*/

const getParents = $el => {

const getParents = ($el) => {
// Set up a parent array
let parents = []
let parents = [];

// Push each parent element to the array
for (; $el && $el !== document; $el = $el.parentNode) {
parents.push($el)
parents.push($el);
}

// Return our parent array
return parents
}
return parents;
};

// https://gomakethings.com/how-to-get-the-closest-parent-element-with-a-matching-selector-using-vanilla-javascript/
const queryClosestParent = ($el, selector) => {
// Element.matches() polyfill
if (!Element.prototype.matches) {
Element.prototype.matches =
Element.prototype.matchesSelector ||
Element.prototype.mozMatchesSelector ||
Element.prototype.msMatchesSelector ||
Element.prototype.oMatchesSelector ||
Element.prototype.webkitMatchesSelector ||
function (s) {
var matches = (
this.document || this.ownerDocument
).querySelectorAll(s),
i = matches.length;
while (--i >= 0 && matches.item(i) !== this) {}
return i > -1;
};
}

// Get the closest matching element
for (; $el && $el !== document; $el = $el.parentNode) {
if ($el.matches(selector)) return $el;
}
return null;
};
Comment on lines +129 to +154
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unnecessary polyfill removed in f527488 (2022-06) and replaced in 082f3b5 (2021-10) with Element.prototype.closest.

Suggested change
// https://gomakethings.com/how-to-get-the-closest-parent-element-with-a-matching-selector-using-vanilla-javascript/
const queryClosestParent = ($el, selector) => {
// Element.matches() polyfill
if (!Element.prototype.matches) {
Element.prototype.matches =
Element.prototype.matchesSelector ||
Element.prototype.mozMatchesSelector ||
Element.prototype.msMatchesSelector ||
Element.prototype.oMatchesSelector ||
Element.prototype.webkitMatchesSelector ||
function (s) {
var matches = (
this.document || this.ownerDocument
).querySelectorAll(s),
i = matches.length;
while (--i >= 0 && matches.item(i) !== this) {}
return i > -1;
};
}
// Get the closest matching element
for (; $el && $el !== document; $el = $el.parentNode) {
if ($el.matches(selector)) return $el;
}
return null;
};


export {
escapeHtml,
unescapeHtml,
getNodeData,
getData,
getParents,
}
queryClosestParent,
};
Loading