Implement lazy load
This commit is contained in:
parent
f19382cd17
commit
8b557262c6
|
@ -54,9 +54,9 @@
|
||||||
{{> footer}}
|
{{> footer}}
|
||||||
|
|
||||||
{{!-- Common scripts shared between pages --}}
|
{{!-- Common scripts shared between pages --}}
|
||||||
|
<script crossorigin="anonymous" src="https://polyfill.io/v3/polyfill.min.js?features=IntersectionObserver%2CPromise%2CArray.prototype.includes%2CString.prototype.endsWith%2CString.prototype.startsWith%2CObject.assign%2CNodeList.prototype.forEach"></script>
|
||||||
<script defer src="https://unpkg.com/@tryghost/content-api@1.2.7/umd/content-api.min.js"></script>
|
<script defer src="https://unpkg.com/@tryghost/content-api@1.2.7/umd/content-api.min.js"></script>
|
||||||
<script defer src="{{asset "js/manifest.js"}}"></script>
|
<script defer src="{{asset "js/manifest.js"}}"></script>
|
||||||
<script defer src="{{asset "js/polyfill.js"}}"></script>
|
|
||||||
<script defer src="{{asset "js/vendor.js"}}"></script>
|
<script defer src="{{asset "js/vendor.js"}}"></script>
|
||||||
<script defer src="{{asset "js/app.js"}}"></script>
|
<script defer src="{{asset "js/app.js"}}"></script>
|
||||||
|
|
||||||
|
|
|
@ -40,7 +40,7 @@ into the {body} of the default.hbs template --}}
|
||||||
{{/if}}
|
{{/if}}
|
||||||
<div class="m-featured-article__picture">
|
<div class="m-featured-article__picture">
|
||||||
{{#if feature_image}}
|
{{#if feature_image}}
|
||||||
<div style="background-image: url({{feature_image}});"></div>
|
<div class="lozad" data-background-image="{{feature_image}}"></div>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
<div class="m-featured-article__meta">
|
<div class="m-featured-article__meta">
|
||||||
|
|
|
@ -28,10 +28,9 @@ into the {body} of the default.hbs template --}}
|
||||||
{{#foreach authors}}
|
{{#foreach authors}}
|
||||||
<article class="m-article-card as-author">
|
<article class="m-article-card as-author">
|
||||||
{{#if profile_image}}
|
{{#if profile_image}}
|
||||||
<div class="m-article-card__picture" style="background-image: url({{profile_image}})">
|
<div class="m-article-card__picture lozad" data-background-image="{{profile_image}}">
|
||||||
{{else}}
|
{{else}}
|
||||||
<div class="m-article-card__picture"
|
<div class="m-article-card__picture lozad" data-background-image="{{asset "images/default-avatar-rectangle.jpg"}}">
|
||||||
style="background-image: url({{asset "images/default-avatar-rectangle.jpg"}})">
|
|
||||||
{{/if}}
|
{{/if}}
|
||||||
<a href="{{url}}" class="m-article-card__picture-link" aria-label="Author"></a>
|
<a href="{{url}}" class="m-article-card__picture-link" aria-label="Author"></a>
|
||||||
<h3 class="m-article-card__name">{{name}}</h3>
|
<h3 class="m-article-card__name">{{name}}</h3>
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
{{/is}}
|
{{/is}}
|
||||||
{{#if feature_image}}
|
{{#if feature_image}}
|
||||||
<article class="m-article-card {{post_class}}">
|
<article class="m-article-card {{post_class}}">
|
||||||
<div class="m-article-card__picture" style="background-image: url({{feature_image}});">
|
<div class="m-article-card__picture lozad" data-background-image="{{feature_image}}">
|
||||||
{{else}}
|
{{else}}
|
||||||
<article class="m-article-card no-picture {{post_class}}">
|
<article class="m-article-card no-picture {{post_class}}">
|
||||||
<div class="m-article-card__picture">
|
<div class="m-article-card__picture">
|
||||||
|
|
|
@ -37,9 +37,9 @@ Also it includes the big submenu.
|
||||||
<a href="{{url}}" class="m-recent-article">
|
<a href="{{url}}" class="m-recent-article">
|
||||||
<div class="m-recent-article__picture">
|
<div class="m-recent-article__picture">
|
||||||
{{#if feature_image}}
|
{{#if feature_image}}
|
||||||
<div style="background-image: url({{img_url feature_image size="m"}});"></div>
|
<div class="lozad" data-background-image="{{img_url feature_image size="m"}}"></div>
|
||||||
{{else}}
|
{{else}}
|
||||||
<div style="background-image: url({{asset "images/no-image.png"}});" class="no-image"></div>
|
<div class="no-image lozad" data-background-image="{{asset "images/no-image.png"}}"></div>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
<h3 class="m-recent-article__title">{{title}}</h3>
|
<h3 class="m-recent-article__title">{{title}}</h3>
|
||||||
|
|
|
@ -1,17 +1,20 @@
|
||||||
import cssVars from 'css-vars-ponyfill'
|
import cssVars from 'css-vars-ponyfill'
|
||||||
import $ from 'jquery'
|
import $ from 'jquery'
|
||||||
|
import lozad from 'lozad'
|
||||||
import Headroom from "headroom.js"
|
import Headroom from "headroom.js"
|
||||||
import slick from 'slick-carousel'
|
import slick from 'slick-carousel'
|
||||||
import tippy from 'tippy.js'
|
import tippy from 'tippy.js'
|
||||||
import AOS from 'aos'
|
import AOS from 'aos'
|
||||||
import Fuse from 'fuse.js'
|
import Fuse from 'fuse.js'
|
||||||
|
import {
|
||||||
|
isRTL,
|
||||||
|
formatDate
|
||||||
|
} from './helpers'
|
||||||
|
|
||||||
cssVars({})
|
cssVars({})
|
||||||
|
|
||||||
$(document).ready(() => {
|
$(document).ready(() => {
|
||||||
const isRTL = $('html').attr('lang') === 'ar' || $('html').attr('lang') === 'he'
|
if (isRTL()) {
|
||||||
|
|
||||||
if (isRTL) {
|
|
||||||
$('html').attr('dir', 'rtl').addClass('rtl')
|
$('html').attr('dir', 'rtl').addClass('rtl')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -95,21 +98,6 @@ $(document).ready(() => {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
function formatDate(date) {
|
|
||||||
if (date) {
|
|
||||||
return new Date(date).toLocaleDateString(
|
|
||||||
document.documentElement.lang,
|
|
||||||
{
|
|
||||||
year: 'numeric',
|
|
||||||
month: 'long',
|
|
||||||
day: 'numeric'
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
return ''
|
|
||||||
}
|
|
||||||
|
|
||||||
$openMenu.click(() => {
|
$openMenu.click(() => {
|
||||||
$menu.addClass('opened')
|
$menu.addClass('opened')
|
||||||
toggleScrollVertical()
|
toggleScrollVertical()
|
||||||
|
@ -217,6 +205,9 @@ $(document).ready(() => {
|
||||||
$('[data-aos]').addClass('no-aos-animation')
|
$('[data-aos]').addClass('no-aos-animation')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const observer = lozad()
|
||||||
|
observer.observe()
|
||||||
|
|
||||||
tippy('.js-tooltip')
|
tippy('.js-tooltip')
|
||||||
|
|
||||||
trySearchFeature()
|
trySearchFeature()
|
||||||
|
|
23
src/js/helpers.js
Normal file
23
src/js/helpers.js
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
export const isRTL = () => {
|
||||||
|
const $html = document.querySelector('html')
|
||||||
|
return $html.getAttribute('lang') === 'ar' || $html.getAttribute('lang') === 'he'
|
||||||
|
}
|
||||||
|
|
||||||
|
export const isMobile = (width = '768px') => {
|
||||||
|
return window.matchMedia(`(max-width: ${width})`).matches
|
||||||
|
}
|
||||||
|
|
||||||
|
export const formatDate = (date) => {
|
||||||
|
if (date) {
|
||||||
|
return new Date(date).toLocaleDateString(
|
||||||
|
document.documentElement.lang,
|
||||||
|
{
|
||||||
|
year: 'numeric',
|
||||||
|
month: 'long',
|
||||||
|
day: 'numeric'
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return ''
|
||||||
|
}
|
|
@ -1,8 +1,8 @@
|
||||||
import $ from 'jquery'
|
import $ from 'jquery'
|
||||||
import slick from 'slick-carousel'
|
import slick from 'slick-carousel'
|
||||||
|
import { isRTL } from './helpers'
|
||||||
|
|
||||||
$(document).ready(() => {
|
$(document).ready(() => {
|
||||||
const isRTL = $('html').attr('lang') === 'ar' || $('html').attr('lang') === 'he'
|
|
||||||
const $featuredArticles = $('.js-featured-articles')
|
const $featuredArticles = $('.js-featured-articles')
|
||||||
|
|
||||||
if ($featuredArticles.length > 0) {
|
if ($featuredArticles.length > 0) {
|
||||||
|
@ -12,7 +12,7 @@ $(document).ready(() => {
|
||||||
prevArrow: '<button class="m-icon-button in-featured-articles slick-prev" aria-label="Previous"><span class="icon-arrow-left"></span></button>',
|
prevArrow: '<button class="m-icon-button in-featured-articles slick-prev" aria-label="Previous"><span class="icon-arrow-left"></span></button>',
|
||||||
nextArrow: '<button class="m-icon-button in-featured-articles slick-next" aria-label="Next"><span class="icon-arrow-right"></span></button>',
|
nextArrow: '<button class="m-icon-button in-featured-articles slick-next" aria-label="Next"><span class="icon-arrow-right"></span></button>',
|
||||||
mobileFirst: true,
|
mobileFirst: true,
|
||||||
rtl: isRTL
|
rtl: isRTL()
|
||||||
})
|
})
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
|
|
|
@ -1,90 +0,0 @@
|
||||||
import 'promise-polyfill/src/polyfill';
|
|
||||||
|
|
||||||
if (!Array.prototype.includes) {
|
|
||||||
Object.defineProperty(Array.prototype, 'includes', {
|
|
||||||
value: function (searchElement, fromIndex) {
|
|
||||||
|
|
||||||
if (this == null) {
|
|
||||||
throw new TypeError('"this" is null or is not defined');
|
|
||||||
}
|
|
||||||
|
|
||||||
var o = Object(this);
|
|
||||||
var len = o.length >>> 0;
|
|
||||||
|
|
||||||
if (len === 0) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
var n = fromIndex | 0;
|
|
||||||
var k = Math.max(n >= 0 ? n : len - Math.abs(n), 0);
|
|
||||||
|
|
||||||
function sameValueZero(x, y) {
|
|
||||||
return x === y || (typeof x === 'number' && typeof y === 'number' && isNaN(x) && isNaN(y));
|
|
||||||
}
|
|
||||||
|
|
||||||
while (k < len) {
|
|
||||||
if (sameValueZero(o[k], searchElement)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
k++;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!String.prototype.endsWith) {
|
|
||||||
String.prototype.endsWith = function (search, this_len) {
|
|
||||||
if (this_len === undefined || this_len > this.length) {
|
|
||||||
this_len = this.length;
|
|
||||||
}
|
|
||||||
return this.substring(this_len - search.length, this_len) === search;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!String.prototype.startsWith) {
|
|
||||||
Object.defineProperty(String.prototype, 'startsWith', {
|
|
||||||
value: function (search, pos) {
|
|
||||||
pos = !pos || pos < 0 ? 0 : +pos;
|
|
||||||
return this.substring(pos, pos + search.length) === search;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (typeof Object.assign != 'function') {
|
|
||||||
Object.defineProperty(Object, "assign", {
|
|
||||||
value: function assign(target, varArgs) {
|
|
||||||
'use strict';
|
|
||||||
if (target == null) {
|
|
||||||
throw new TypeError('Cannot convert undefined or null to object');
|
|
||||||
}
|
|
||||||
|
|
||||||
var to = Object(target);
|
|
||||||
|
|
||||||
for (var index = 1; index < arguments.length; index++) {
|
|
||||||
var nextSource = arguments[index];
|
|
||||||
|
|
||||||
if (nextSource != null) {
|
|
||||||
for (var nextKey in nextSource) {
|
|
||||||
if (Object.prototype.hasOwnProperty.call(nextSource, nextKey)) {
|
|
||||||
to[nextKey] = nextSource[nextKey];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return to;
|
|
||||||
},
|
|
||||||
writable: true,
|
|
||||||
configurable: true
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (window.NodeList && !NodeList.prototype.forEach) {
|
|
||||||
NodeList.prototype.forEach = function (callback, thisArg) {
|
|
||||||
thisArg = thisArg || window;
|
|
||||||
for (var i = 0; i < this.length; i++) {
|
|
||||||
callback.call(thisArg, this[i], i, this);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
|
@ -3,6 +3,10 @@ import slick from 'slick-carousel'
|
||||||
import stickybits from 'stickybits'
|
import stickybits from 'stickybits'
|
||||||
import mediumZoom from 'medium-zoom'
|
import mediumZoom from 'medium-zoom'
|
||||||
import fitvids from 'fitvids'
|
import fitvids from 'fitvids'
|
||||||
|
import {
|
||||||
|
isRTL,
|
||||||
|
isMobile
|
||||||
|
} from './helpers'
|
||||||
|
|
||||||
let $aosWrapper = null
|
let $aosWrapper = null
|
||||||
let $progressCircle = null
|
let $progressCircle = null
|
||||||
|
@ -12,10 +16,6 @@ let lastDocumentHeight = 0
|
||||||
let circumference = 0
|
let circumference = 0
|
||||||
let isTicking = false
|
let isTicking = false
|
||||||
|
|
||||||
function isMobile(width = '768px') {
|
|
||||||
return window.matchMedia(`(max-width: ${width})`).matches
|
|
||||||
}
|
|
||||||
|
|
||||||
function onScrolling() {
|
function onScrolling() {
|
||||||
lastScrollingY = window.pageYOffset
|
lastScrollingY = window.pageYOffset
|
||||||
requestTicking()
|
requestTicking()
|
||||||
|
@ -102,8 +102,6 @@ function prepareProgressCircle() {
|
||||||
}
|
}
|
||||||
|
|
||||||
$(document).ready(() => {
|
$(document).ready(() => {
|
||||||
const isRTL = $('html').attr('lang') === 'ar' || $('html').attr('lang') === 'he'
|
|
||||||
|
|
||||||
$aosWrapper = $('.js-aos-wrapper')
|
$aosWrapper = $('.js-aos-wrapper')
|
||||||
const $scrollButton = $('.js-scrolltop')
|
const $scrollButton = $('.js-scrolltop')
|
||||||
const $loadComments = $('.js-load-comments')
|
const $loadComments = $('.js-load-comments')
|
||||||
|
@ -153,7 +151,7 @@ $(document).ready(() => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
rtl: isRTL
|
rtl: isRTL()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
5
src/package-lock.json
generated
5
src/package-lock.json
generated
|
@ -8357,6 +8357,11 @@
|
||||||
"integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==",
|
"integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"lozad": {
|
||||||
|
"version": "1.14.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/lozad/-/lozad-1.14.0.tgz",
|
||||||
|
"integrity": "sha512-uMGxpXBW15JDGVly3p121Y4jlb/OwmXpnMQR5vnb4GxMeK45NGcmlMrRr47fmLxtSdnGRFm0YdJaVXuudPKDaA=="
|
||||||
|
},
|
||||||
"lru-cache": {
|
"lru-cache": {
|
||||||
"version": "5.1.1",
|
"version": "5.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
|
||||||
|
|
|
@ -37,6 +37,7 @@
|
||||||
"fuse.js": "^3.4.2",
|
"fuse.js": "^3.4.2",
|
||||||
"headroom.js": "^0.10.3",
|
"headroom.js": "^0.10.3",
|
||||||
"jquery": "^3.3.1",
|
"jquery": "^3.3.1",
|
||||||
|
"lozad": "^1.14.0",
|
||||||
"medium-zoom": "^1.0.3",
|
"medium-zoom": "^1.0.3",
|
||||||
"promise-polyfill": "8.1.0",
|
"promise-polyfill": "8.1.0",
|
||||||
"slick-carousel": "^1.8.1",
|
"slick-carousel": "^1.8.1",
|
||||||
|
|
|
@ -59,6 +59,20 @@ fieldset {
|
||||||
z-index: 5;
|
z-index: 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
div[data-loaded="true"],
|
||||||
|
img[data-loaded="true"] {
|
||||||
|
opacity: 0;
|
||||||
|
@include animation('fadeIn 0.5s forwards');
|
||||||
|
@include keyframes(fadeIn) {
|
||||||
|
0% {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
::-webkit-input-placeholder {
|
::-webkit-input-placeholder {
|
||||||
color: $gray;
|
color: $gray;
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,7 @@ mix.webpackConfig({
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
mix.js('js/polyfill.js', 'js/')
|
mix.js('js/helpers.js', 'js/')
|
||||||
.js('js/app.js', 'js/')
|
.js('js/app.js', 'js/')
|
||||||
.js('js/home.js', 'js/')
|
.js('js/home.js', 'js/')
|
||||||
.js('js/post.js', 'js/')
|
.js('js/post.js', 'js/')
|
||||||
|
|
Loading…
Reference in a new issue