Skip to content

Commit

Permalink
feat: Images now load via vanilla LazyLoad
Browse files Browse the repository at this point in the history
  • Loading branch information
notacouch committed Oct 3, 2018
1 parent a59eaa2 commit aa9d9b4
Show file tree
Hide file tree
Showing 8 changed files with 92 additions and 20 deletions.
23 changes: 11 additions & 12 deletions css/styles.css
Original file line number Diff line number Diff line change
Expand Up @@ -347,25 +347,24 @@ section {
/* Don't do this, can skew aspect ratio of image
min-height: 248px;
Maintain aspect ratio later via
height: auto;
Maintain aspect ratio
*/
height: auto;
}

/* With LazyLoad, we leave src blank, but we still want the images to occupy
their space on the screen. */
their space on the screen. So we create a SVG that always respects aspect ratio,
and use grid to force the img to do the same.
.restaurant-img[src=""] {
height: 0;
padding-bottom: 75%;
}
Credit:
@link https://codeburst.io/keeping-aspect-ratio-with-html-and-no-padding-tricks-40705656808b */

/* This will occupy the same space since our images are all the same size,
hopefully the browser is smart enough to not cause any jank in the process. */
.restaurant-img-sizer {
display: grid;
}

.restaurant-img:not([src=""]) {
height: auto;
padding-bottom: 0;
.restaurant-img-sizer > * {
grid-area: 1 / 1 / 2 / 2;
}

.restaurants-list__restaurant h3 {
Expand Down
21 changes: 21 additions & 0 deletions js/dbhelper.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,24 @@
// Dynamically and conditionally load the proper version of LazyLoad for this
// browser/device. We put this code here in dbhelper.js b/c this script is in both
// pages and before other scripts run.
(function(w, d) {
let b = d.getElementsByTagName('body')[0];
let s = d.createElement('script');
let v = !('IntersectionObserver' in w) ? '-compat' : '';
s.async = true; // This includes the script as async. See the "recipes" section for more information about async loading of LazyLoad.
s.src = '/node_modules/vanilla-lazyload' + v + '/dist/lazyload.min.js';
w.lazyLoadOptions = {
elements_selector: '.restaurant-img',
callback_load: el => {
console.log('element loaded', el);
},
callback_finish: () => {
console.log('lazy load finished');
},
};
b.appendChild(s);
})(window, document);

/**
* Common database helper functions.
*/
Expand Down
32 changes: 30 additions & 2 deletions js/main.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
let restaurants, neighborhoods, cuisines;
let newMap;
let lazyLoadInstance = false;
let firstBreakpoint = window.matchMedia('(min-width: 768px)').matches;
const markers = [];

Expand Down Expand Up @@ -129,6 +130,22 @@ updateRestaurants = () => {
} else {
resetRestaurants(restaurants);
fillRestaurantsHTML();

// Race condition, if LazyLoad has already loaded before the img tags
// are rendered, it will never apply to new tags. So we create a new
// instance or update the existing ones every time we create new img tags.
if (window.LazyLoad) {
console.log('LazyLoad available');
if (!lazyLoadInstance) {
console.log('No lazyLoadInstance, making new one');
lazyLoadInstance = new window.LazyLoad(window.lazyLoadOptions);
} else {
console.log('lazyLoadInstance found, updating...');
lazyLoadInstance.update();
}
} else {
console.log('LazyLoad NOT available');
}
}
}
);
Expand Down Expand Up @@ -168,9 +185,19 @@ createRestaurantHTML = restaurant => {
const li = document.createElement('article');
li.className = 'restaurants-list__restaurant';

const imageWrapper = document.createElement('div');
imageWrapper.className = 'restaurant-img-sizer';

const svgAspectRatio = document.createElement('svg');
svgAspectRatio.setAttribute('viewbox', '0 0 4 3');
imageWrapper.append(svgAspectRatio);

const image = document.createElement('img');
image.className = 'restaurant-img';
image.src = DBHelper.imageUrlForRestaurant(restaurant);
// LazyLoad compatibility
image.setAttribute('src', ''); // LazyLoad best practice is a blank src. We also utilize this in CSS.
image.setAttribute('data-src', DBHelper.imageUrlForRestaurant(restaurant));

// For a11y purposes, every img tag should at least have a blank alt attribute.
// Better than that is to briefly describe the photo, but that information should
// come from the content management system or digital asset manager, basically by
Expand All @@ -182,7 +209,8 @@ createRestaurantHTML = restaurant => {
// repeatedly in screen readers, which is a sub-optimal experience, worse than a
// blank alt attribute.
image.setAttribute('alt', `Photo of or in ${restaurant.name}`);
li.append(image);
imageWrapper.append(image);
li.append(imageWrapper);

const name = document.createElement('h3');
name.innerHTML = restaurant.name;
Expand Down
5 changes: 4 additions & 1 deletion js/register-sw.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
// Register service worker
if ('serviceWorker' in navigator) {
navigator.serviceWorker
.register('/sw.js')
// @todo: There is no way to pass custom data to SW pre-install, e.g. so we
// can determine if IO API is available, so we know which version of
// the LazyLoad package to cache. For now we'll just cache both.
.register('/sw.js', { foo: 'bar' })
.then(register => {
console.log('SW now in the main gibson ', register, register.scope);
// This page was not reached via SW
Expand Down
15 changes: 14 additions & 1 deletion js/restaurant_info.js
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,9 @@ fillRestaurantHTML = (restaurant = self.restaurant) => {

const image = document.getElementById('restaurant-img');
image.className = 'restaurant-img';
image.src = DBHelper.imageUrlForRestaurant(restaurant);
// LazyLoad compatibility
image.setAttribute('src', ''); // LazyLoad best practice is a blank src. We also utilize this in CSS.
image.setAttribute('data-src', DBHelper.imageUrlForRestaurant(restaurant));
// For a11y purposes, every img tag should at least have a blank alt attribute.
// Better than that is to briefly describe the photo, but that information should
// come from the content management system or digital asset manager, basically by
Expand All @@ -98,6 +100,17 @@ fillRestaurantHTML = (restaurant = self.restaurant) => {
// blank alt attribute.
image.setAttribute('alt', `Photo of or in ${restaurant.name}`);

// Race condition, if LazyLoad has already loaded before the img tags
// are rendered, it will never apply to new tags. So we create a new
// instance when we create this new img tag.

if (window.LazyLoad) {
console.log('LazyLoad available');
new window.LazyLoad(window.lazyLoadOptions);
} else {
console.log('LazyLoad NOT available');
}

const cuisine = document.getElementById('restaurant-cuisine');
cuisine.innerHTML = restaurant.cuisine_type;

Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "notacouch-restaurant-review-stage-1",
"version": "0.0.1",
"version": "0.0.2",
"description": "Udacity Mobile Web Specialist Nanodegree Restaurant Review project Stage 1",
"main": "main.js",
"scripts": {
Expand Down
7 changes: 6 additions & 1 deletion restaurant.html
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,12 @@ <h1><a href="/" class="header__title__link">Restaurant Reviews</a></h1>
<!-- Beginning restaurant -->
<section id="restaurant-container" class="restaurant-container" tabindex="-1">
<h2 id="restaurant-name"></h2>
<img alt="" id="restaurant-img">
<!-- maintain aspect ratio of img, credit:
@link https://codeburst.io/keeping-aspect-ratio-with-html-and-no-padding-tricks-40705656808b -->
<div class="restaurant-img-sizer">
<svg viewbox="0 0 4 3"></svg>
<img alt="" id="restaurant-img">
</div>
<div id="restaurant-cuisine"></div>
<div id="restaurant-address"></div>
<table id="restaurant-hours"></table>
Expand Down
7 changes: 5 additions & 2 deletions sw.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
const appVersion = '0.0.1';
const appVersion = '0.0.2';
const cacheID = 'restaurant-reviews-' + appVersion;

// Re-used strings here
const imgFallback = '/img/ouch.png'; // credit: https://pixabay.com/en/connection-lost-no-connection-cloud-3498366/
const offlineText = 'Not online right now';

self.addEventListener('install', event => {
console.log('SW installed!');
console.log('SW installed!', event);
event.waitUntil(
caches.open(cacheID).then(cache =>
cache
Expand All @@ -22,6 +22,9 @@ self.addEventListener('install', event => {
'/js/restaurant_info.js',
'/js/register-sw.js',
'/node_modules/focus-visible/dist/focus-visible.min.js',
// @todo: Use IDB in register-sw to determine which of these should be cached
'/node_modules/vanilla-lazyload/dist/lazyload.min.js',
'/node_modules/vanilla-lazyload-compat/dist/lazyload.min.js',
imgFallback,
])
.catch(error => {
Expand Down

0 comments on commit aa9d9b4

Please sign in to comment.