by James Priest
Log 1 | Log 2 | Log 3 | Log 4 | Log 5 |
---|---|---|---|---|
100 Days Round 1 | 100 Days Round 2 | this log | 100 Days Round 4 | 100 Days Round 5 |
This is part of Alexander Kallaway’s 100DaysOfCode challenge. More details about the challenge can be found here: 100daysofcode.com.
Commitment: I will code daily for the next 100 days.
Start Date | End Date |
---|---|
May 9, 2018 | October 2, 2018 |
Project: Google Udacity Nanodegree (Mobile Web Specialist)
Progress: Continued the Restaurant Reviews App - Stage 3 project.
I finished another round of 100DaysOfCode! Yay! I was hoping to be done with this project by now but it looks like it’ll take me into Round 4.
This latest set of code changes represented significant updates to my Restaurant Review app. This included
offline
IDB object store for saving unhandled http requestsSee the code notes here: Restaurant Review App - Stage 3: Section 9 Offline Reviews.
Links:
Project: Google Udacity Nanodegree (Mobile Web Specialist)
Progress: Continued the Restaurant Reviews App - Stage 3 project.
Next I needed to create an object store to hold data so users can have an uninterrupted offline experience.
I this case I added the reviews
object store as well as an index (foreign key) that relates the review back to the restaurant.
See the code notes here: Restaurant Review App - Stage 3: Section 8 Review Store.
Links:
Project: Google Udacity Nanodegree (Mobile Web Specialist)
Progress: Continued the Restaurant Reviews App - Stage 3 project.
I created a new set of Gulp build tasks to successfully transform & bundle my IDB code.
// DBHelper
gulp.task('dbhelper', function () {
var bundler = browserify([ // ['1.js', '2.js']
'./app/js/idbhelper.js', // include these files
'./app/js/dbhelper.js'
], { debug: false }); // no sourcemaps
return bundler
.transform(babelify, {sourceMaps: false}) // required for 'import'
.bundle() // concat
.pipe(source('dbhelper.min.js')) // get text stream w/ dest filename
.pipe(buffer()) // use stream w/ other plugins
.pipe(gulp.dest('.tmp/js/')); // outout here...
});
This combines multiple script files and automatically imports dependencies like the one shown below…
import idb from 'idb';
const dbPromise = idb.open('udacity-restaurant-db', 1, upgradeDB => {
switch (upgradeDB.oldVersion) {
case 0:
upgradeDB.createObjectStore('restaurants',
{ keyPath: 'id', unique: true });
}
});
self.idbKeyVal = idbKeyVal; // <- This line exposes the object literal.
There are now easier ways to do this with tools like Parcel.js and WebPack but Grunt & Gulp are what the lessons taught so I stuck with those.
See the code notes here: Restaurant Review App - Stage 3: Section 7 Refactor IDB Code.
Links:
Project: Google Udacity Nanodegree (Mobile Web Specialist)
Progress: Continued the Restaurant Reviews App - Stage 3 project.
Stage 3 required me to update the object store schema for restaurants
.
As you can see above, I had previously just saved the entire json list of restaurants as one IDB store record.
This no longer works since I now need to update data on an individual restaurant basis. Here’s what the updated schema looks like now.
You can read more about the code changes in my code notes.
See the code notes here: Restaurant Review App - Stage 3: Section 6 Redesign IDB Storage.
Links:
Project: Google Udacity Nanodegree (Mobile Web Specialist)
Progress: Continued the Restaurant Reviews App - Stage 3 project.
Added code to save a review from the Add Review modal pop-up to the database. This consisted of adding two pieces of code.
const saveAddReview = (e) => {
e.preventDefault();
const name = document.querySelector('#reviewName').value;
const rating = document.querySelector('input[name=rate]:checked').value;
const comments = document.querySelector('#reviewComments').value;
DBHelper.createRestaurantReview(self.restaurant.id, name, rating, comments,
(error, review) => {
if (error) {
console.log('Error saving review');
} else {
console.log(review);
window.location.href = `/restaurant.html?id=${self.restaurant.id}`;
}
});
};
// http://localhost:1337/reviews/
static createRestaurantReview(id, name, rating, comments, callback) {
const data = {
'restaurant_id': id,
'name': name,
'rating': rating,
'comments': comments
};
fetch(DBHelper.DATABASE_URL + '/reviews/', {
method: 'POST',
body: JSON.stringify(data)
})
.then(response => response.json())
.then(data => callback(null, data))
.catch(err => callback(err, null));
}
See the code notes here: Restaurant Review App - Stage 3: Section 5.5 Database Updates.
Links:
Project: Google Udacity Nanodegree (Mobile Web Specialist)
Progress: Continued the Restaurant Reviews App - Stage 3 project.
I copied the relevant modal popup code to a CodePen (Modal popup with star rating) in case anyone wants to see how this thing is constructed.
The star rating was the most complex part of the form since it required me to manually specify proper ARIA, accessibility, and roles within the control.
This CodePen proof of concept contains:
Links:
Project: Google Udacity Nanodegree (Mobile Web Specialist)
Progress: Continued the Restaurant Reviews App - Stage 3 project.
This consisted of implementing an “Add Review” form with a hidden radio group modified to mimic a favorite star rating control.
This was the most complex part of form since it required proper ARIA, accessibility, and role specification.
I also added the following:
See the code notes here: Restaurant Review App - Stage 3: Section 5. Add Review Form.
Links:
Project: Google Udacity Nanodegree (Mobile Web Specialist)
Progress: Continued the Restaurant Reviews App - Stage 3 project.
In order to get the modal popup to happen I had to:
See the code notes here: Restaurant Review App - Stage 3: Section 4.2 Create a Modal Popup.
Links:
Project: Google Udacity Nanodegree (Mobile Web Specialist)
Progress: Continued the Restaurant Reviews App - Stage 3 project.
In order to get the reviews to display properly I had to do the following:
fetchRestaurantReviewById
methodcreateReviewHTML
& fillReviewsHTML
methodsSee the code notes here: Restaurant Review App - Stage 3: Section 4.1 Display Reviews.
Links:
Project: Google Udacity Nanodegree (Mobile Web Specialist)
Progress: Continued the Restaurant Reviews App - Stage 3 project.
This last few days consisted of:
See the code notes here: Restaurant Review App - Stage 3: Section 3. Favorite Control.
Links:
Project: Google Udacity Nanodegree (Mobile Web Specialist)
Progress: Began the Restaurant Reviews App - Stage 3 project.
The first step of this project involved understanding the new requirements. These come down to the following:
Next I documented in my Code Notes each of the new API Endpoints.
I used an app called PostMan to test each of these CRUD (Create, Read, Update, Delete) operations which fall into the following categories.
See the code notes here: Restaurant Review App - Stage 3: Section 2.0 API Endpoints.
Links:
Project: Google Udacity Nanodegree (Mobile Web Specialist)
Progress: Continued Lesson 1: HTTP Request Response Cycle from
These lesson covers
Read more: Notes - Client-Server Communication - Lesson 1.6 Multiple Requests
Links:
Project: Google Udacity Nanodegree (Mobile Web Specialist)
Progress: Continued Lesson 1: HTTP Request Response Cycle from
These lesson covers
Read more: Notes - Client-Server Communication - Lesson 1.2 HTTP Requests
Links:
Project: Google Udacity Nanodegree (Mobile Web Specialist)
Progress: Started Lesson 1: HTTP Request Response Cycle from
These lesson covers
Read more: Notes - Client-Server Communication - Lesson 1.1 Course Intro
Links:
Project: Google Udacity Nanodegree (Mobile Web Specialist)
Progress: Submitted & completed the Restaurant Reviews App - Stage 2 project.
The project passed on my first submission!
Here are my scores.
See the code notes here: Restaurant Review App - Stage 2: Section 9. Stage 2 Review.
Links:
Project: Google Udacity Nanodegree (Mobile Web Specialist)
Progress: Continued Restaurant Reviews App - Stage 2 project.
Completed my notes on the following:
See the code notes here: Restaurant Review App - Stage 2: Section 8. Progressive Web App.
Links:
Project: Google Udacity Nanodegree (Mobile Web Specialist)
Progress: Continued Restaurant Reviews App - Stage 2 project.
Today I needed to improve my Lighthouse PWA score in order to satisfy the Stage 2 Project requirements. They were in the low 70s and needed to be brought up above 90.
The Lighthouse stats page gave a checklist of items to fix.
Once I fixed as many of these as I could the score came up tremendously.
I used the Firebase’s Web App Manifest Generator (https://app-manifest.firebaseapp.com/)
Here’s my new score!
Yay!!! Go me!
Links:
Project: Google Udacity Nanodegree (Mobile Web Specialist)
Progress: Continued Restaurant Reviews App - Stage 2 project.
Finished integrating IndexedDB into the Service Worker for graceful offline performance!
Now the data is showing up and available for offline use. This means that if internet is lost the app can still show data and provide a seamless offline browsing experience.
In fact, if the restaurant page had previously been visited it will seemlessly bring in the map and any associated images as well as the data.
Otherwise it will show placeholders for images that have not been cached but the information will still display.
Now when I run a performance test is scores in the mid to high 70’s and works for offline browsing as well.
You can read a more detailed breakdown in the Code Notes.
See the code notes here: Restaurant Review App - Stage 2: Section 7 SW with IndexedDB.
Links:
Project: Google Udacity Nanodegree (Mobile Web Specialist)
Progress: Continued Restaurant Reviews App - Stage 2 project.
At some point these nested calls get pretty crazy. The code fails mercilessly if you miss a comma, a bracket, a parenthesis, etc.
That’s manageable to find with syntax highlighting in your editor, but when you need to insert a nested then()
with conditional statements, it gets tough to keep it straight.
Case in point. The code below took hours over days to get all pieces in the right place.
function idbResponse(request) {
return caches.open(staticCacheName).then(function (cache) {
return cache.match(request).then(function (response) {
return (
response || fetch(request).then(function (networkResponse) {
cache.add(request, networkResponse.clone());
return networkResponse;
})
);
});
}).catch(error => {
if (request.url.includes('.jpg')) {
return caches.match('/img/fixed/offline_img1.png');
}
return new Response(error, {
status: 404,
statusText: 'Not connected to the internet'
});
});
}
I’m sure it looks clean and straightforward to read the logic now but now
I guess it’ll get faster with practice.
Links:
Project: Google Udacity Nanodegree (Mobile Web Specialist)
Progress: Continued Restaurant Reviews App - Stage 2 project.
Finished fine-tuning the Gulp scripts for development & distribution builds.
This final part of the build system involved serving the pages and providing live reload on code changes. This was done with a plugin called browsersync
.
I did this by creating three main tasks.
gulp serve
- creates a development server with live reloadgulp serve:dist
- optimizes code and create a preview for a production buildgulp
- builds a production ready site without spinning up a serverThe build system will efficiently lint, bundle, transpile, concatenate, minify, autoprefix, & optimize my code on every save.
Now that this is automated, I can spend more time focusing on the code!
See the code notes here: Restaurant Review App - Stage 2: Section 6.8 Build & Serve.
Links:
Project: Google Udacity Nanodegree (Mobile Web Specialist)
Progress: Continued Restaurant Reviews App - Stage 2 project.
This was the most involved task to build. It provides the following:
See the code here: Restaurant Review App - Stage 2: Concat & Optimize notes.
Links:
Project: Google Udacity Nanodegree (Mobile Web Specialist)
Progress: Continued Restaurant Reviews App - Stage 2 project.
Today I implemented responsive image optimization code in the build system to produce four copies of each image at a different resolution.
This will allow the site to responsively serve whichever size image is most appropriate for the requesting device.
The code is pretty straight forward and much more concise in Gulp than the same configuration in Grunt.
// Build responsive images
var gulp = require('gulp');
var $ = require('gulp-load-plugins')();
gulp.task('images', ['fixed-images'], function () {
return gulp.src('app/img/*.jpg')
.pipe($.responsive({
'*.jpg': [
{ width: 300, rename: { suffix: '-300' }, },
{ width: 400, rename: { suffix: '-400' }, },
{ width: 600, rename: { suffix: '-600_2x' }, },
{ width: 800, rename: { suffix: '-800_2x' }, }
]
}, {
quality: 40,
progressive: true,
withMetadata: false,
}))
.pipe(gulp.dest('.tmp/img'))
.pipe(gulp.dest('dist/img'));
});
Read more here: Restaurant Review App - Stage 2: Responsive Images notes.
Links:
Project: Google Udacity Nanodegree (Mobile Web Specialist)
Progress: Continued Restaurant Reviews App - Stage 2 project.
Added Section 5. Evaluate Build Tools & 6. Using Gulp to my Code Notes.
This details The process of evaluating various build systems, task runners & bundlers.
My notes then cover the old school way of creating a set of Gulp tasks to do the following.
I then set up a browser-sync and run everything on a dev server.
Links:
Project: Google Udacity Nanodegree (Mobile Web Specialist)
Progress: Continued Restaurant Reviews App - Stage 2 project.
Added Section 4. Fix Grunt Tasks to my Code Notes.
This details the changes I made to my existing Grunt config file in order to make it work with the new directory structure.
It also details hiding my Google Maps API key so that it doesn’t get posted on GitHub.
Grunt now does the following tasks.
clean
- cleans the dist/ foldercopy
- copies all source code folders & files that don’t need pre-processing to dist/string-replace
- copies the Google Maps API key to the HTML filesresponsive_images
- creates each image at various pixel densities to adjust for various device pixel ratios and viewport sizesLinks:
Project: Update Windows 10 Terminal with tabs, split screens, & themes
Progress: This was a three day project due to much reading and research.
Here were my terminal minimum requirements:
This lead me to some great articles on how to do this. The first one I read was How to Use ‘Tmux Terminal’ to Access Multiple Terminals Inside a Single Console.
This introduced tmux (Terminal Multiplexer), which allows you to access multiple terminals inside a single terminal. This is a Linux tool though and I wasn’t sure whether Windows 10 WSL could support it. Here’s what I found.
I then read the following three Win 10 specific walk-through’s
What I finally ended up doing was installing a Windows Tab solution called Groupy which allows you to organize multiple applications into grouped tabs. Very simple drag and drop functionality.
Links:
Project: Google Udacity Nanodegree (Mobile Web Specialist)
Progress: Continued Restaurant Reviews App - Stage 2 project.
The last three days was spent creating a code log for Stage 2 of my Restaurant App project.
So far I have the following sections.
These notes will detail the steps I take to satisfy my project requirements. I’ll also include screenshots and code samples where necessary.
Links:
Project: Google Udacity Nanodegree (Mobile Web Specialist)
Progress: Continued Restaurant Reviews App - Stage 2 project.
Today was spent figuring out how to Transpile & Bundle dependency scripts into a single JavaScript file.
This means I was able to use Babel to target the latest two versions of each major browser to ensure the JavaScript would run properly.
I also added the following
This increased my benchmark scores for Performance & Progressive Web App.
Will continue tomorrow.
Links:
Project: Google Udacity Nanodegree (Mobile Web Specialist)
Progress: Continued Restaurant Reviews App - Stage 2 project.
Today I started down the rabbit hole that is Gulpfile.js. Gulp uses a code-based build process as opposed to Grunt’s config based approach.
So far I have the following tasks working.
clean
- cleans the dist/
& tmp/
directorieshtml
- copies html & injects Google Maps API keycss
- copies cssjs
- copies jsWhat I need to get working in each of these tasks.
html
- processes html (remove comments, remove whitespace, etc. )css
- processes css (autoprefixer, sass)js
- processes js (bundle, browserify, transpile)watch
- dev server with live reload when source changesWill continue tomorrow.
Links:
Project: Google Udacity Nanodegree (Mobile Web Specialist)
Progress: Continued Restaurant Reviews App - Stage 2 project.
Today was about getting my existing Grunt tasks to work with my new (proper) build process folder structure. Added the following tasks.
clean
- cleans the dist/
foldercopy
- copies all source code folders & files that don’t need pre-processing to dist/
string-replace
- copies the Google Maps API key to the HTML filesresponsive_images
- creates each image at various pixel densities to adjust for various device pixel ratios and viewport sizesI created a separate Google Maps API key file that does not get copied GitHub. I placed the file name in .gitignore
and added a Grunt task to copy the key to the HTML files when the project is built.
Now when I push my project to GitHub my API key will not get published.
Links:
Project: Google Udacity Nanodegree (Mobile Web Specialist)
Progress: Continued Restaurant Reviews App - Stage 2 project.
Today I updated the structure of the client app by placing all source code files in an app/
folder and then updating the gruntfile to output to a dist/
folder.
This will provide a clean segmentation between our working source and the final compressed and optimized site.
Next steps are to migrate from Grunt to Gulp which will allow for better code based configuration and the create an additional set of build tasks to do the following:
Links:
Project: Google Udacity Nanodegree (Mobile Web Specialist)
Progress: Continued Restaurant Reviews App - Stage 2 project.
Spend the day looking into the best way to put together a Gulp Build Environment & Workflow.
This consisted of:
Decided to roll my own in order to get granular control over the build process.
The next step is to copy all source files into an app/
directory and then have everything output to a dest/
folder.
Links:
Project: Google Udacity Nanodegree (Mobile Web Specialist)
Progress: Continued Restaurant Reviews App - Stage 2 project.
Today was about replacing the old XHR code with Fetch API and Promise based error handling.
Old XHR code
let xhr = new XMLHttpRequest();
xhr.open('GET', DBHelper.DATABASE_URL);
xhr.onload = () => {
if (xhr.status === 200) { // Got a success response from server!
const json = JSON.parse(xhr.responseText);
const restaurants = json.restaurants;
callback(null, restaurants);
} else { // Oops!. Got an error from server.
const error = (`Request failed. Returned status of ${xhr.status}`);
callback(error, null);
}
};
xhr.send();
New fetch code
fetch(DBHelper.DATABASE_URL)
.then(response => response.json())
.then(restaurants => callback(null, restaurants))
.catch(err => callback(err, null));
Additional changes included updates to the supporting DBHelper routines for proper responsive image handling.
Links:
Project: Google Udacity Nanodegree (Mobile Web Specialist)
Progress: Started Restaurant Reviews App - Stage 2 project.
Today I began work on stage 2 of my Restaurant App project. This requires that we do the following:
Once these requirements are met I can submitted everything for review. Successful submission of stages 1, 2, and 3 are required to complete the nanodegree program.
Links:
Project: Code Log Improvements
Progress: This was slow going and required a lot of back and forth testing.
The scroll code requires each section to be wrapped so that height can be calculated in order to properly set the active
class. Unfortunately, the code sets and removes the class dozens of times for each scroll event. This needs to be fixed.
It also dynamically adds and removes the active
class on each nav item between the one you are on and the destination menu item so that each menu item in between also highlights during smooth scroll. This is fine for small nav menus but gets clunky with large menus.
In the end I wasn’t able to use it for this log but I’ll try some other options as time permits.
Links:
Project: Google Udacity Nanodegree (Mobile Web Specialist)
Progress: Completed Lesson 14: Optimizations & Lesson 15: Scaffolding from
These lessons covered:
Read more: Notes - Web Tooling and Automation - Lesson 14.8 Minification
Links:
Project: Google Udacity Nanodegree (Mobile Web Specialist)
Progress: Continued Lesson 14: Optimizations from
This lesson covered:
dist/
directory for production buildRead more: Notes - Web Tooling and Automation - Lesson 14.6 JS Concatenation
Links:
Project: Google Udacity Nanodegree (Mobile Web Specialist)
Progress: Started Lesson 14: Optimizations from
This lessons covered:
Read more: Notes - Web Tooling and Automation - Lesson 14 Optimizations
Links:
Project: Google Udacity Nanodegree (Mobile Web Specialist)
Progress: Finished Lesson 13: How to Prevent Disasters from
This lessons covered:
Read more: Notes - Web Tooling and Automation - Lesson 13.7 Unit Testing in Gulp
Links:
Project: Google Udacity Nanodegree (Mobile Web Specialist)
Progress: Started Lesson 13: How to Prevent Disasters from
This lessons covered:
Read more: Notes - Web Tooling and Automation - Lesson 13 How to Prevent Disasters
Links:
Project: Google Udacity Nanodegree (Mobile Web Specialist)
Progress: Completed Lesson 12: Browser Sync from
This lessons covered:
Here’s the minimum required for Browser Sync in Gulp. See the notes for links and more info.
var browserSync = require('browser-sync').create();
browserSync.init({
server: "./"
});
browserSync.stream();
Read more: Notes - Web Tooling and Automation - Lesson 12 Browser Sync
Links:
Project: Google Udacity Nanodegree (Mobile Web Specialist)
Progress: Continued Lesson 11: Build Automation from
This lessons covered:
gulp-sass
and gulp-autoprefixer
Here’s part of the ‘styles’ task configured to transpile .scss
files to standard CSS.
var gulp = require('gulp');
var sass = require('gulp-sass');
gulp.task('styles', function() {
gulp.src('sass/**/*.scss')
.pipe(sass().on('error', sass.logError))
.pipe(gulp.dest('./css'));
});
Read more: Notes - Web Tooling and Automation - Lesson 11.8 Sass & Autoprefixer
Links:
Project: Google Udacity Nanodegree (Mobile Web Specialist)
Progress: Started Lesson 11: Build Automation from
This lessons covered:
Read more: Notes - Web Tooling and Automation - Lesson 11 Build Automation
Links:
Project: Google Udacity Nanodegree (Mobile Web Specialist)
Progress: Completed Lesson 9: Tools & Automation and Lesson 10: Editor Config from
These lessons covered:
Read more: Notes - Web Tooling and Automation - Lesson 9.1 Course Intro
Links:
Project: Google Udacity Nanodegree (Mobile Web Specialist)
Progress: Completed Lesson 3: Ajax with Fetch from
These lessons covered
Here’s a sample fetch/promises chain from the course
fetch(`https://api.unsplash.com/search/photos?page=1&query=${queryText}`, {
headers: {
Authorization: 'Client-ID abc123'
}
})
.then(response => response.json())
.then(addImage)
.catch(err => requestError(err, 'image'));
fetch(`http://api.nytimes.com/svc/search/v2/articlesearch.json?
q=${queryText}&api-key=abc123`)
.then(response => response.json())
.then(addArticles)
.catch(err => requestError(err, 'articles'));
Read more: Notes - Asynchronous JavaScript Requests - Lesson 3 Ajax with Fetch
Links:
Project: Google Udacity Nanodegree (Mobile Web Specialist)
Progress: Completed Lesson 2: Chaining Promises from
These lessons covered
Promise.all()
method.map
& .forEach
with PromisesRead more: Notes - JavaScript Promises - Lesson 2.7 .map Promises
Links:
Project: Google Udacity Nanodegree (Mobile Web Specialist)
Progress: Continued Lesson 2: Chaining Promises from
These lessons covered
Read more: Notes - JavaScript Promises - Lesson 2.4 Series vs Parallel Requests
Links:
Project: Google Udacity Nanodegree (Mobile Web Specialist)
Progress: Started Lesson 2: Chaining Promises from
These lessons covered
.catch
vs reject
function
.catch(function(error) { })
get('example.json').then(undefined, rejectFunc)
.catch
is preferred cause it’s easier to read and write.catch
and reject
functionresolve
& reject
functions
get('example.json').then(resolveFunc, rejectFunc)
.then
and .catch
blocks
.then
can execute and have an error which triggers .catch
to executeget('example.json')
.then(resolveFunc)
.catch(rejectFunc);
Here’s a short code example with thening and multiple .catch
blocks.
getJSON('../data/earth-like-results.json')
.then(function (response) {
addSearchHeader(response.query);
console.log(response);
return getJSON(response.results[0]); // return result for chaining
}).catch(function () { // catch err in search request
throw Error('Search Request Error');
}).then(function (planetData) { // receive result in planetData
createPlanetThumb(planetData);
console.log(planetData);
}).catch(function (error) { // catch any other error
addSearchHeader('unknown');
console.log(error);
});
Read more: Notes - JavaScript Promises - Lesson 2: Chaining Promises
Links:
Project: Google Udacity Nanodegree (Mobile Web Specialist)
Progress: Completed Lesson 1: Creating Promises from
These lessons consisted of exercises and quizzes to gain practice with
Here’s a short code example using the Fetch API.
function get(url) {
return fetch(url);
}
function getJSON(url) {
return get(url).then(function(response) {
if (!response.ok) {
throw Error(response.statusText ? response.statusText : 'unknown network error');
}
return response.json();
});
}
getJSON('../data/earth-like-results.json')
.then(function (response) {
addSearchHeader(response.query);
console.log(response);
return response.results[0];
}).then(function(url) {
console.log(url);
}).catch(function (error) {
addSearchHeader('unknown');
console.log(error);
});
Read more: Notes - JavaScript Promises - Lesson 1.11 Wrap XHR
Links:
Project: Google Udacity Nanodegree (Mobile Web Specialist)
Progress: Continued Lesson 1: Creating Promises from
function ready() {
return new Promise(resolve => {
function checkState() {
if(document.readyState !== 'loading') {
resolve();
}
}
document.addEventListener('readystatechange', checkState);
checkState();
});
};
ready().then(wrapperResolved);
Key concepts:
.then()
performs an action after a promised resultThis lesson covered:
.then()
.ready()
methoddocument.ready
: ‘loading’, ‘interactive’, ‘complete’
Read more: Notes - JavaScript Promises - Lesson 1.9 Wrap & Chain
Links:
Project: Google Udacity Nanodegree (Mobile Web Specialist)
Progress: Started Lesson 1: Creating Promises from
Key concepts:
resolve
and reject
.resolve
and reject
are the two callbacks used to specify when a promise has either fulfilled (because something worked) or rejected (because something went wrong).This lesson covered:
resolve()
on successful completion of async code within the Promise wrapper..then()
to the end in order to execute a callback upon successful fulfillment.Read more: Notes - JavaScript Promises - Lesson 1.7 Promise Syntax
Links:
Project: Google Udacity Nanodegree (Mobile Web Specialist)
Progress: Started Lesson 1: Creating Promises from
This lesson covered:
Read more: Notes - JavaScript Promises - Lesson 1 Creating Promises
Links:
Project: Google Udacity Nanodegree (Mobile Web Specialist)
Progress: Finished Lesson 2: Ajax with jQuery from the Udacity course: Asynchronous JavaScript Requests by Google, AT&T, & GitHub.
This lesson covered:
$.ajax()
call stack$.ajax()
as a wrapper to the XHR object$.ajax()
.get()
.getJSON()
.getScript()
.post()
.load()
Read more: Notes - Asynchronous JavaScript Requests - Lesson 2.6 Peek inside $.ajax()
Links:
Project: Google Udacity Nanodegree (Mobile Web Specialist)
$.ajax({
url: `http://api.nytimes.com/svc/search/v2/articlesearch.json?
q=${searchedForText}&api-key=<api-key-here>`
}).done(function(data) {
// do some stuff with the data...
let htmlContent = '';
if (data.response && data.response.docs && data.response.docs.length > 1) {
htmlContent = '<ul>' + data.response.docs.map(article =>
`<li class="article">
<h2><a href="${article.web_url}">${article.headline.main}</a></h2>
<p>${article.snippet}</p>
</li>`
).join('') + '</ul>';
} else {
htmlContent = '<div class="error-no-articles">No articles available</div>';
}
responseContainer.insertAdjacentHTML('beforeend', htmlContent);
}).fail(function(e) {
handleError(e, 'data')
});
function handleError(e, errType) {
console.log(`uh-oh.😞 A ${errType} error:`, e);
}
Progress: Started Lesson 2: Ajax with jQuery from the Udacity course: Asynchronous JavaScript Requests by Google, AT&T, & GitHub.
This lesson covered:
$.ajax()
methodRead more: Notes - Asynchronous JavaScript Requests - Lesson 2.1 jQuery & Ajax
Links:
Project: Google Udacity Nanodegree (Mobile Web Specialist)
Progress: Continued Lesson 1: Ajax with XHR from the Udacity course: Asynchronous JavaScript Requests by Google, AT&T, & GitHub.
This lesson covered:
.setRequestHeader()
Read more: Notes - Asynchronous JavaScript Requests - Lesson 1.11 Set Request Header
Links:
Project: Google Udacity Nanodegree (Mobile Web Specialist)
Progress: Continued Lesson 1: Ajax with XHR from the Udacity course: Asynchronous JavaScript Requests by Google, AT&T, & GitHub.
This lesson covered:
.open()
method.send()
methodRead more: Notes - Asynchronous JavaScript Requests - Lesson 1.6 The XHR Object
Links:
Project: Google Udacity Nanodegree (Mobile Web Specialist)
Progress: Started Lesson 1: Ajax with XHR from the Udacity course: Asynchronous JavaScript Requests by Google, AT&T, & GitHub.
This lesson covered the basics of
Read more: Notes - Asynchronous JavaScript Requests - Lesson 1.1 Course Intro
Links:
Project: Google Udacity Nanodegree (Mobile Web Specialist)
Progress: Started Udacity Mobile Web Specialist Stage 2 prep.
This consisted of
Links:
Project: Google Udacity Nanodegree (Mobile Web Specialist)
Progress: Completed Restaurant Reviews App - Stage 1 project from the Udacity Nanodegree course: Web Accessibility.
I resubmitted my Stage 1 project for review with the following changes:
Once this was done I resubmitted everything for review.
Read more: Notes - Restaurant Review App - Stage 1 - 9. Review Round 1
Links:
Project: Google Udacity Nanodegree (Mobile Web Specialist)
Progress: Finished Lesson 15: Styling from the Udacity course: Web Accessibility.
This lesson covered
Read more: Notes - Web Accessibility - Lesson 15.5 Styling with ARIA
Links:
Project: Google Udacity Nanodegree (Mobile Web Specialist)
Progress: Started Lesson 15: Styling from the Udacity course: Web Accessibility.
This lesson covered
Read more: Notes - Web Accessibility - Lesson 15 Focus
Links:
Project: Google Udacity Nanodegree (Mobile Web Specialist)
Progress: Continued Lesson 14: ARIA from the Udacity course: Web Accessibility.
This lesson covered
Read more: Notes - Web Accessibility - Lesson 14.7 ARIA Hidden
Links:
Project: Google Udacity Nanodegree (Mobile Web Specialist)
Progress: Continued Lesson 14: ARIA from the Udacity course: Web Accessibility.
This lesson covered
Read more: Notes - Web Accessibility - Lesson 14.7 ARIA Labels
Links:
Project: Google Udacity Nanodegree (Mobile Web Specialist)
Progress: Started Lesson 14: ARIA from the Udacity course: Web Accessibility.
This lesson covered
Read more: Notes - Web Accessibility - Lesson 14. ARIA
Links:
Project: Google Udacity Nanodegree (Mobile Web Specialist)
Progress: Finished Lesson 13: Navigation from the Udacity course: Web Accessibility.
This lesson covered
Read more: Notes - Web Accessibility - Lesson 13.8 Navigation: Link Text
Links:
Project: Google Udacity Nanodegree (Mobile Web Specialist)
Progress: Started Lesson 13: Navigation from the Udacity course: Web Accessibility.
This lesson covered
Read more: Notes - Web Accessibility - Lesson 13 Navigation
Links:
Project: Google Udacity Nanodegree (Mobile Web Specialist)
Progress: Completed Lesson 12: Semantics from the Udacity course: Web Accessibility.
This lesson covered
Read more: Notes - Web Accessibility - Lesson 12.7 - Role, Name, & Value
Links:
Project: Google Udacity Nanodegree (Mobile Web Specialist)
Progress: Started Lesson 12: Semantics from the Udacity course: Web Accessibility.
This lesson got into
Read more: Notes - Web Accessibility - Lesson 12.1 - Semantics Introduction
Links:
Project: Google Udacity Nanodegree (Mobile Web Specialist)
Progress: Completed Restaurant Reviews App - Stage 1 project from the Udacity Nanodegree course: Web Accessibility.
Today I performed final touch ups to the app including:
Once this was done I submitted everything for review.
Read more: Notes - Restaurant Review App - Stage 1 - 8. Audit Restaurant App
Links:
Project: Google Udacity Nanodegree (Mobile Web Specialist)
Progress: Continued Restaurant Reviews App - Stage 1 project from the Udacity Nanodegree course: Web Accessibility.
Today I focused on getting some final touches completed for this project. Between today and tomorrow I should have everything ready for submission.
Today included the following.
Read more: Notes - Restaurant Review App - Stage 1 - Generic offline image
Links:
Project: Google Udacity Nanodegree (Mobile Web Specialist)
Progress: Continued Restaurant Reviews App - Stage 1 project from the Udacity Nanodegree course: Web Accessibility.
This section of the code caches assets on service worker install and then serves these cached assets as requests are made.
const staticCacheName = 'restaurant-static-001';
self.addEventListener('install', event => {
event.waitUntil(
caches.open(staticCacheName)
.then(cache => {
return cache.addAll([
'/index.html',
'/css/styles.css',
'/js/dbhelper.js',
'/js/register_sw.js',
'/js/main.js',
'/js/restaurant_info.js',
'/data/restaurants.json',
'/restaurant.html?id=1',
'/restaurant.html?id=2',
'/restaurant.html?id=3',
]).catch(error => {
console.log('Caches open failed: ' + error);
});
})
);
});
The cached assets were served if available otherwise a fetch operation is performed.
self.addEventListener('fetch', event => {
event.respondWith(
caches.match(event.request).then(response => {
return response || fetch(event.request);
}).catch(error => {
return new Response('Not connected to the internet', {
status: 404,
statusText: "Not connected to the internet"
});
console.log(error, 'no cache entry for:', event.request.url);
})
);
});
Read more: Notes - Restaurant Review App - Stage 1 - Cache assets on install
Links:
Project: Google Udacity Nanodegree (Mobile Web Specialist)
Progress: Continued Restaurant Reviews App - Stage 1 project from the Udacity Nanodegree course: Web Accessibility.
The next section of the project consisted of creating the registration code for a Service Worker.
if (navigator.serviceWorker) {
navigator.serviceWorker.register('sw.js')
.then(registration => {
console.log(`Registration successful, scope is ${registration.scope}`);
}).catch(error => {
console.log(`Service worker registration failed, error: ${error}`);
});
}
This was then included on each page.
<script src="js/dbhelper.js"></script>
<script src="js/register_sw.js"></script> <!-- new -->
<script src="js/main.js"></script>
Read more: Notes - Restaurant Review App - Stage 1 - Service Worker
Links:
Project: Google Udacity Nanodegree (Mobile Web Specialist)
Progress: Continued Restaurant Reviews App - Stage 1 project from the Udacity Nanodegree course: Web Accessibility.
The part of the project consisted of ensuring Accessibility requirements were met. This includes:
Read more: Notes - Restaurant Review App - Stage 1 - Accessibility
Links:
Project: Google Udacity Nanodegree (Mobile Web Specialist)
Progress: Continued Restaurant Reviews App - Stage 1 project from the Udacity Nanodegree course: Web Accessibility.
The next part of the project consisted of creating responsive images for the site. The steps were as follows
srcset
and sizes
Read more: Notes - Restaurant Review App - Stage 1 - Responsive Images
Links:
Project: Google Udacity Nanodegree (Mobile Web Specialist)
Progress: Continued Restaurant Reviews App - Stage 1 project from the Udacity Nanodegree course: Web Accessibility.
This part of the project dealt with creating a responsive layout for the app so that it displayed nicely across multiple viewports and device display sizes.
This is done through:
Read more: Notes - Restaurant Review App - Stage 1 - Responsive Design
Links:
Project: Google Udacity Nanodegree (Mobile Web Specialist)
Progress: Completed Lesson 11: Focus from the Udacity course: Web Accessibility.
The final part of this lesson discussed:
Read more: Notes - Web Accessibility - Lesson 11.9 - Modal Dialogs & Keyboard Traps
Links:
Project: Google Udacity Nanodegree (Mobile Web Specialist)
Progress: Continued Lesson 11: Focus from the Udacity course: Web Accessibility.
This lesson discussed:
Read more: Notes - Web Accessibility - Lesson 11.9 - Managing Focus
Links:
Project: Google Udacity Nanodegree (Mobile Web Specialist)
Progress: Continued Lesson 11: Focus from the Udacity course: Web Accessibility.
This lesson discussed:
Read more: Notes - Web Accessibility - Lesson 11.4 - DOM Order Matters
Links:
Project: Google Udacity Nanodegree (Mobile Web Specialist)
Progress: Started Lesson 11: Focus from the Udacity course: Web Accessibility.
This lesson provided an overview of:
Read more: Notes - Web Accessibility - Lesson 11 - Focus
Links:
Project: Google Udacity Nanodegree (Mobile Web Specialist)
Progress: Started Restaurant Reviews App - Stage 1 project from the Udacity Nanodegree course: Web Accessibility.
This project puts into practice the last 4 weeks worth of classes. Including the following.
The project requires that we take what we’ve learned and apply it to a non-responsive and statically layed out web application. This is due in one week so I started now to ensure I have enough time to complete.
Read more: Notes - Restaurant Review App - Stage 1
Links:
Project: Google Udacity Nanodegree (Mobile Web Specialist)
Progress: Completed Lesson 10: Accessibility Overview from the Udacity course: Web Accessibility.
This lesson provided an overview of:
Read more: Notes - Web Accessibility - Lesson 10 - Accessibility Overview
Links:
Project: Google Udacity Nanodegree (Mobile Web Specialist)
Progress: Completed Lesson 9: Full Responsiveness from the Udacity course: Responsive Images.
This lesson completed the entire Responsive Images course. As the last project we had to completed the Responsive Images Blog with the following:
<picture>
and <source>
elementssrcset
to specify various pixel densities for a set of imagesmedia
attributes to specify media queries for a particular imageRead more: Notes - Responsive Images - Lesson 9 - Full Responsiveness - Project Part 3
Links:
Project: Google Udacity Nanodegree (Mobile Web Specialist)
Progress: Continued Lesson 9: Full Responsiveness from the Udacity course: Responsive Images.
This lesson covered basic accessibility and the importance of the image alt
attribute for devices such as screen readers.
Other things discussed in the lesson were:
Read more: Notes - Responsive Images - Lesson 9 - Full Responsiveness - Accessibility
Links:
Project: Google Udacity Nanodegree (Mobile Web Specialist)
Progress: Continued Lesson 9: Full Responsiveness from the Udacity course: Responsive Images.
This lesson covered the <picture>
element and how it’s used in art direction.
Here’s an example of what the code looks like for the kitty above:
<picture>
<source media="(min-width: 650px)" srcset="kitten-large.png">
<source media="(min-width: 465px)" srcset="kitten-medium.png">
<img src="kitten-small.png" alt="Cute kitten">
</picture>
The browser chooses the first matching media query.
This markup says:
<picture>
element.Read more: Notes - Responsive Images - Lesson 9 - Full Responsiveness - The Picture Element
Links:
Project: Google Udacity Nanodegree (Mobile Web Specialist)
Progress: Continued Lesson 9: Full Responsiveness from the Udacity course: Responsive Images.
This lesson covered the combination of srcset
and sizes
attributes.
Here’s an example:
<img src="small.jpg"
srcset="small.jpg 500w,
medium.jpg 1000w,
large.jpg 1500w"
sizes="(max-width: 250px) 100vw,
50vw"
alt="Wallaby">
This says we have three images sized at 500px, 1000px, & 1500px, respectively, and that the display size will be 100% the viewport width for viewport widths under 250px and will be 50% the viewport width for viewport widths over 250px.
The following items were covered
srcset
with sizes
attributeRead more: Notes - Responsive Images - Lesson 9 - Full Responsiveness - Sizes Attribute
Links:
Project: Google Udacity Nanodegree (Mobile Web Specialist)
Progress: Started Lesson 9: Full Responsiveness from the Udacity course: Responsive Images.
This lesson discussed the limitations of using media queries to determine which image size to download. Instead the lesson discusses the following:
srcset
attributeRead more: Notes - Responsive Images - Lesson 9 - Full Responsiveness
Links:
Project: Google Udacity Nanodegree (Mobile Web Specialist)
Progress: Finished Lesson 8: Images with Markup from the Udacity course: Responsive Images.
This lesson gave the requirements to complete part 2 of this responsive blog project:
Read more: Notes - Responsive Images - Lesson 8 - Images with Markup: Project Part 2
Links:
Project: Google Udacity Nanodegree (Mobile Web Specialist)
Progress: Continued Lesson 8: Images with Markup from the Udacity course: Responsive Images.
This lesson talked about:
Read more: Notes - Responsive Images - Lesson 8 - Images with Markup: Icon Fonts
Links:
Project: Google Udacity Nanodegree (Mobile Web Specialist)
Progress: Continued Lesson 8: Images with Markup from the Udacity course: Responsive Images.
This lesson talked about:
Read more: Notes - Responsive Images - Lesson 8 - Images with Markup: Symbol Characters
Links:
Project: Google Udacity Nanodegree (Mobile Web Specialist)
Progress: Started Lesson 8: Images with Markup from the Udacity course: Responsive Images.
This lesson talked about the following:
Read more: Notes - Responsive Images Course - Lesson 8 Images with Markup
Links:
Project: Google Udacity Nanodegree (Mobile Web Specialist)
Progress: Continued Lesson 7: Units, Formats, Environments from the Udacity course: Responsive Images.
The course material was great at exposing me to new concepts of how to responsively serve images based on viewport size or device pixel density.
But it only scratched the surface on how to fully implement these responsive image techniques. I devoted some time to additional online resources to accomplish the following:
srcset
and sizes
attributes of <img>
tag.
<picture>
& <source>
elements.
<img>
element.Those links are in my notes but I’ve included them below as well
Read more: Notes - Responsive Images Course - Resources & Links
Links:
Project: Google Udacity Nanodegree (Mobile Web Specialist)
Progress: Continued Lesson 7: Units, Formats, Environments from the Udacity course: Responsive Images.
Created a Build Environment for my Responsive Images Blog Project. This includes:
I also spent the last 5 days learning how to use Grunt and properly configure a Gruntfile. I learned how to
Read more: Notes - Responsive Images Course - My Build Environment
Links:
Project: Google Udacity Nanodegree (Mobile Web Specialist)
Progress: Continued Lesson 7: Units, Formats, Environments from the Udacity course: Responsive Images.
Lesson 7.16 Project Solution covered
max-width: 100%
50em
(800px) widthRead more: Notes - Responsive Images Lesson - 7.16 Project Solution
Links:
Project: Google Udacity Nanodegree (Mobile Web Specialist)
Progress: Continued Lesson 7: Units, Formats, Environments from the Udacity course: Responsive Images.
Lesson 7.16 covered
Read more: Notes - Responsive Images Lesson - 7.16 Project Part 1
Links:
Project: Google Udacity Nanodegree (Mobile Web Specialist)
Progress: Continued Lesson 7: Units, Formats, Environments from the Udacity course: Responsive Images.
Lessons 7.9-7.15 covered
Read more: Notes - Responsive Images Lesson - 7.9 Raster and Vector
Links:
Project: Google Udacity Nanodegree (Mobile Web Specialist)
Progress: Continued Lesson 7: Units, Formats, Environments from the Udacity course: Responsive Images.
Lessons 7.6-7.8 covered
calc()
for alignment of images that includes padding & marginRead more: Notes - Responsive Images Lesson - 7.6 Quiz: calc()
Links:
Project: Google Udacity Nanodegree (Mobile Web Specialist)
Progress: Continued Lesson 7: Units, Formats, Environments from the Udacity course: Responsive Images.
Lessons 7.2-7.5 dealt with
max-width: 100%
so an image doesn’t expand beyond its natural widthcalc()
function to properly size images by combining absolute and relative values. For example, combining a percentage width with a fixed marginRead more: Notes - Responsive Images Lesson 7.2 - All About Bits & Pixels
Links:
Project: Google Udacity Nanodegree (Mobile Web Specialist)
Progress: Started Lesson 7: Units, Formats, Environments from the Udacity course: Responsive Images.
This lesson shows how to use Chrome DevTools to determine:
Read more: Notes - Responsive Images Lesson 7.1
Links:
Project: Google Udacity Nanodegree (Mobile Web Specialist)
Progress: Completed Lesson 6: Up & Running from the Udacity course: Responsive Images.
This lesson introduces the concepts of responsive image design. The main take-aways were:
Read more: Notes - Responsive Images Lesson 6
Links:
Project: Google Udacity Nanodegree (Mobile Web Specialist)
Progress: Completed the Home Town App for Lesson 5: Optimizations from the Udacity course: Responsive Web Design Fundamentals.
The assignment was to take an existing app designed for desktop and modify it to be completely responsive across multiple devices.
This required:
Read more: Notes - Responsive Web Design Lesson 5.11 Wrap Up
Links:
Project: Google Udacity Nanodegree (Mobile Web Specialist)
Progress: Created a new GitHub repo for my Round 3 code log.
This now uses a purple theme and has an updated nav which I’ve migrated over to my previous two logs.
Other updates for today include:
Links: My GitHub repo https://github.com/james-priest/100-days-of-code-log-r3