Another post in favor of PWAs

This post — Your Site—Any Site—Should be a PWA — makes the argument in its title and also includes some helpful links.

PWAs don’t require you use a particular JavaScript framework or any JavaScript framework at all. You don’t need to be building a Single Page App either. In fact, it will probably be easier if you’re not.

You do, however, need a service worker.

Some handy Python tricks, and a Python3 cheat sheet

This blog post demonstrates 10 cool Python tricks that are not covered in introductory lessons, involving tuples, lists, join, etc. I have documented some of these already here in Code Notes, but the format of the blog post is really excellent for a quick skim.

There are many Python3 cheat sheets available out there, but this one is actually clear and easy to read — unlike many others!

Fixing Jupyter Notebook startup error

I previously wrote about Jupyter Notebooks here.

Before the MacOS Sierra 10.12.5 update, to launch Jupyter in your browser, you only needed to do this:

  1. Open Terminal.
  2. Enter the desired directory.
  3. Activate your virtualenv (if using one).
  4. At the command line, type:
jupyter notebook

A new window would open in your default web browser, and there were all your Jupyter files.

But after the MacOS update, instead we got an execution error: localhost doesn’t understand the “open location” message. And the browser window did not open.

The way to fix it (do it once) is here.

Note: In the config file, I had to search for 

#c.NotebookApp.browser =

instead of the string the author provided.

Useful sites for CSS, browser support issues

Found today while searching for answers to some coding questions:

Unminify: It’s impossible to read minified CSS, JavaScript, etc. This site accurately reformats minified code for you, making it human-readable.

Can I Use … ? Find out which browsers fully or partially support any given front-end web technology (such as box-sizing: all browsers!).

Should I Prefix? For some CSS properties, we need to include extra versions for Chrome, Firefox, or both (using the prefixes -webkit- or -moz-) — find out which properties still need these.

DiffChecker: Compare two text files. The differences between the two files (even spacing and tabs) are shown clearly with side-by-side highlighting.

Combining lists in Python

Another cool shortcut method in Python! So, you have two lists. You want to pair them up, in order. That is, you want to associate the first item in list A with the first item in list B, the second item in list A with the second item in list B, and so on.

grades = ["B", "D", "A", "B"]
students = ["Ken", "Ben", "Wendy", "Sandy"]
for student, grade in zip(students, grades):
   print( student + ": " + grade )

This would be nice for creating a list of dictionaries, which is essentially JSON format:

student_records = []
for student, grade in zip(students, grades):
   student_records.append( {"student":student, "grade":grade} )

for record in student_records:
   print(record)

{'student': 'Ken', 'grade': 'B'}
{'student': 'Ben', 'grade': 'D'}
{'student': 'Wendy', 'grade': 'A'}
{'student': 'Sandy', 'grade': 'B'}

So easy! zip() does it all.

Tuple unpacking in Python

With the typical list-based for-loop in Python, we don’t use indexes:

foods = ["bread", "milk", "eggs"]
for food in foods:
   print(food)

But if we also need the index number for each list item (which does, of course, exist):

foods = ["bread", "milk", "eggs"]
for i, food in enumerate(foods):
   print( str(i) + ": " + food )

I learned that today from this 25-minute video about loops in Python (also covers while-loops):

Tuple unpacking is explained at 11:58 in the video. It’s what makes enumerate() possible.

(PyCon 2017)

More about using fetch()

From this:

  1. “The fetch() method takes the path to a resource as input.
  2. “The method returns a promise that resolves to the Response of that request.”

Refer to the brief code examples in my earlier post. You’ll see that the .then() statements following the promise are different depending on the expected response data type, e.g. text or JSON.

“Evaluating the success of responses is particularly important when using fetch because bad responses (like 404s) still resolve.” This means that any response at all is a valid response to the fetch() method. The example below looks fine — until you realize that.

fetch('example.json')
.then(function(response) {
   // do stuff with the response
})
.catch(function(error) {
   console.log('Looks like there was a problem: \n', error);
});

So what we really need in the .then() statement is this:

.then(function(response) {
   if (!response.ok) {
      throw Error(response.statusText);
   }
   // do stuff with the response
})

The Response includes response.ok, response.status, response.statusText, etc. Use response.status, for example, to see if you got a 404 or similar error (more info).

The code following the sentence (here) “This code will be cleaner and easier to understand if it’s abstracted into functions” is very helpful. It demonstrates promise chaining and is explained below the code.

The same article contains examples for fetching images and fetching text.

We can add a method such as POST or HEAD (to get metadata) when requesting a resource with fetch (the default method is GET):

fetch( 'examples/words.txt', { method: 'HEAD'} )

Custom headers can be added in the same way (using the init parameter with headers: instead of method:).

Cross-origin requests

These can really mess up your day, as I learned one time when trying to use two APIs together in one web app. Cautions are explained near the end of the resource. It describes how to use no-cors mode with fetch.

  1. Fetch supports Cross Origin Resource Sharing (CORS).
  2. Testing generally requires running a local server.
  3. Note that although fetch does not require HTTPS, service workers do, and so using fetch in a service worker requires HTTPS. Local servers are exempt from this.

If you are using fetch without a service worker, you can use HTTP.

Service worker: Important to PWAs

Service worker: “Essentially a JavaScript file that runs separately from the main browser thread, intercepting network requests, caching or retrieving resources from the cache, and delivering push messages.” Service workers also “provide offline access to cached content.” (Source)

A web worker is “an object created using a constructor (e.g. Worker()) that runs a named JavaScript file — this file contains the code that will run in the worker thread; workers run in another global context that is different from the current window.” (Source)

A service worker is a type of web worker.

How about browser support for service workers? Check here.

A service worker can allow your app to show push notifications even when the app is not open in the browser. This is one of the hallmarks of progressive web apps (PWAs). What about when the browser itself is not open? Android will “wake up any browser when a push message is received” (source), but other operating systems (currently) will not.

“To communicate with the page, the service worker uses the postMessage() method to send data and a ‘message’ event listener to receive data.” (Same source.)

More (from the same source):

  • Service workers only run over HTTPS.
  • Service workers make extensive use of promises.
  • For making an app work offline, service workers depend on these two APIs: Fetch and Cache.
  • When you register a service worker (in your script), you can explicitly set its scope. (“The default scope is the location of the service worker file, and extends to all directories below.”)
  • After the service worker is registered, it is installed, and after that, it is activated. However, activation only occurs after all pages still using the old service worker have been closed. You can never have more than one version of the service worker running concurrently.
  • Use self.addEventListener() to detect 'install' and 'activate' events.

Python 3.x for the win

Good news, I think.

“Today, there are very few libraries that do not support Python 3. Python 3 Readiness shows that 342 of the 360 top packages for Python support 3.x.” (Read more. A link-filled resource.)

I learned Python from Zed Shaw’s Learn Python the Hard Way, which predisposed me to use Python 2.x. Also, as a Mac OS user, I already have Python 2.x without downloading or installing anything. Little by little, though, I’ve started to do all new projects in Python 3.x.

Fetch API: better than AJAX?

“A Promise-based mechanism for programmatically making web requests in the browser.” Replaces most uses of XMLHttpRequest in traditional web applications.

See more links at the end of this post.

Example 1 (run in console):

fetch('http://mindymcadams.com/index.html').then(response => {
   return response.text();
}).then(text => {
   console.log(text);
});

Example 2 (run in console with animals.json file in same dir as the currently open page):

fetch('animals.json').then(response => {
   return response.json();
}).then(json => {
   console.log(json);
});

Each of the examples returns the full contents of the file.

Some good stuff:

  • Working with the Fetch API — this is really clear, step by step, complete (from Google Developers; part of the PWAs workshop, but this can stand alone)
  • Slides that provide an overview of fetch()
  • Introduction to fetch() (also from Google Developers)
  • A window.fetch JavaScript polyfill (on GitHub): “Chrome and Firefox both implement the window.fetch function natively, [so] no code from this project actually takes any effect in these browsers.”