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 JS Loaders #123

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 2 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
118 changes: 90 additions & 28 deletions assets/scripts/app.js
Original file line number Diff line number Diff line change
@@ -1,35 +1,97 @@
import modular from 'modujs';
import * as modules from './modules';
import globals from './globals';
import { html } from './utils/environment';

const app = new modular({
modules: modules
});

window.onload = (event) => {
const $style = document.getElementById('main-css');

if ($style) {
if ($style.isLoaded) {
init();
} else {
$style.addEventListener('load', (event) => {
init();
});
import modular from 'modujs'
import * as modules from './modules'
import globals from './globals'
import { fontsLoader, preloadImages, styleSheetsLoader } from './utils/loaders'
import { html } from './utils/environment'
import config from './config'

class App {
constructor() {
console.log(`${this.constructor.name}:constructor`)

this.options = {
fonts: [
// { name: '<font-name>', style: '<font-style>', weight: '<font-weight>' }
],
preloadImage: [
'img[data-preload]'
],
styleSheets: [
'#main-css'
]
}
} else {
console.warn('The "main-css" stylesheet not found');

// Create app
this.app = new modular({
modules: modules
})

// // Add custom events
// this.addCustomEvents()

// Set vars
this.setVars()

// Window events
window.addEventListener('load', () => this.load())
}

load() {
console.log(`${this.constructor.name}:load`)

// Font load
const fontLoad = new Promise(resolve => {
fontsLoader(this.options.fonts, () => {
html.classList.add(config.CSS_CLASS.FONTS_LOADED)
resolve()
})
})

// Image preload
const imagePreload = new Promise(resolve => {
preloadImages(this.options.preloadImage, () => {
html.classList.add(config.CSS_CLASS.IMAGES_PRELOADED)
resolve()
})
})

// Stylesheets load
const styleSheetLoad = new Promise(resolve => styleSheetsLoader(this.options.styleSheets, () => resolve()))

Promise.all([
fontLoad,
imagePreload,
styleSheetLoad,
]).then(() => {
this.init()
}).catch(e => {
console.log(e)
})
}
};

function init() {
globals();
init() {
console.log(`${this.constructor.name}:init`)

app.init(app);
// Init globals
globals()

html.classList.add('is-loaded');
html.classList.add('is-ready');
html.classList.remove('is-loading');
// Init modular app
this.app.init(this.app)

// Update classes
html.classList.add(config.CSS_CLASS.LOADED)
html.classList.add(config.CSS_CLASS.READY)
html.classList.remove(config.CSS_CLASS.LOADING)
}

addCustomEvents() {
console.log(`${this.constructor.name}:addCustomEvents`)
}

setVars() {
html.style.setProperty('--vh-initial', `${0.01 * html.clientHeight}px`)
}
}

// Instanciate app
new App()
17 changes: 17 additions & 0 deletions assets/scripts/config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
const env = process.env.NODE_ENV

export default config = Object.freeze({
// Environments
ENV: env,
IS_PROD: env === 'production',
IS_DEV: env === 'development',

// CSS class names
CSS_CLASS: {
LOADING: 'is-loading',
READY: 'is-ready',
LOADED: 'is-loaded',
FONTS_LOADED: 'has-fonts-loaded',
IMAGES_PRELOADED: 'has-images-preloaded',
},
})
2 changes: 1 addition & 1 deletion assets/scripts/modules/Scroll.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { module } from 'modujs';
import { lazyLoadImage } from '../utils/image';
import { lazyLoadImage } from '../utils/loaders';
import LocomotiveScroll from 'locomotive-scroll';

export default class extends module {
Expand Down
90 changes: 11 additions & 79 deletions assets/scripts/utils/image.js
Original file line number Diff line number Diff line change
@@ -1,87 +1,19 @@
const LAZY_LOADED_IMAGES = []

export function loadImage(url, options = {}) {
return new Promise((resolve, reject) => {
const $img = new Image();

if (options.crossOrigin) {
$img.crossOrigin = options.crossOrigin;
}

const loadCallback = () => {
resolve({
element: $img,
...getImageMetadata($img),
});
}

if($img.decode) {
$img.src = url
$img.decode().then(loadCallback).catch(e => {
reject(e)
})
} else {
$img.onload = loadCallback
$img.onerror = (e) => {
reject(e);
};
$img.src = url
}
});
}

export function getImageMetadata($img) {
return {
url: $img.src,
width: $img.naturalWidth,
height: $img.naturalHeight,
ratio: $img.naturalWidth / $img.naturalHeight,
};
}

/**
* Lazy load the given image.
* Get an image meta data
*
* @param {HTMLImageElement} $el - The image element.
* @param {?string} url - The URI to lazy load into $el.
* If falsey, the value of the `data-src` attribute on $el will be used as the URI.
* @param {?function} callback - A function to call when the image is loaded.
* @param {HTMLImageElement} $img - The image element.
* @return {object} The given image meta data
*/
export async function lazyLoadImage($el, url, callback) {
let src = url ? url : $el.dataset.src

let loadedImage = LAZY_LOADED_IMAGES.find(image => image.url === src)

if (!loadedImage) {
loadedImage = await loadImage(src)

if (!loadedImage.url) {
return;
}

LAZY_LOADED_IMAGES.push(loadedImage)
}

if($el.src === src) {
return
}

if ($el.tagName === 'IMG') {
$el.src = loadedImage.url;
} else {
$el.style.backgroundImage = `url(${loadedImage.url})`;
}

requestAnimationFrame(() => {
let lazyParent = $el.closest('.c-lazy');
const getImageMetadata = $img => ({
url: $img.src,
width: $img.naturalWidth,
height: $img.naturalHeight,
ratio: $img.naturalWidth / $img.naturalHeight,
})

if(lazyParent) {
lazyParent.classList.add('-lazy-loaded')
lazyParent.style.backgroundImage = ''
}

$el.classList.add('-lazy-loaded')

callback?.()
})
export {
getImageMetadata,
}
Loading