READ THE TEA LEAVES
Managing focus in the shadow DOM. Posted by Nolan Lawson in accessibility, Web . 40 Comments. One of the trickiest things about the shadow DOM is that it subverts web developers’ expectations about how the DOM works. In the normal rules of the game, document.querySelectorAll ('*') grabs all the elements in JAVASCRIPT PERFORMANCE BEYOND BUNDLE SIZE MANAGING FOCUS IN THE SHADOW DOM JAPANESE NAME CONVERTER The Japanese Name Converter uses a combination of dictionary lookup, substitution rules, and machine learning to convert English characters into katakana. For common English names, a dictionary lookup of about 4,000 English names is used. For other names, a learned substitution model trained on these names is applied instead. FIXING MEMORY LEAKS IN WEB APPLICATIONS When you click the “take snapshot” button, you’ve captured all the live objects in a particular JavaScript VM on that web page. This includes objects referenced by the window, objects referenced by setInterval callbacks, etc. Think of it as a frozen moment in time representing all the memory used by that web page.. The next step is to reproduce some scenario that you think may be leaking HOW TO DE-GOOGLE YOUR ANDROID PHONE First, download a ROM from this Russian message board. It's okay! You can totally verify the GPG signature. Allow yourself 30 minutes to remember how GPG works, then verify that forum poster LeetAndrej420 has indeed signed the file. Next, root your Android phone. You will need to hold the volume-up and power buttons for ten HOW TO WRITE A JAVASCRIPT PACKAGE FOR BOTH NODE AND THE This is an issue that I've seen a lot of confusion over, and even seasoned JavaScript developers might have missed some of its subtleties. So I thought it was worth a short tutorial. Let's say you have a JavaScript module that you want to publish to GREAT-GRANDMOTHER
First cousins, for instance, have two common ancestors, and the generation distance via each one is 4. Therefore their relatedness is 2 x (1/2)^4 = 1/8. If A is B’s great-grandchild, the generation distance is 3 and the number of common ‘ancestors’ is 1 (B himself), so the relatedness is 1 x (1/2)^3 = 1/8. GRANDMOTHER'S SISTER'S GRANDDAUGHTER The relatedness between two people is expressed with two measures: Relatedness coefficient: what percentage of your genes you share. Degree of relation: how far you are from that person in your family tree. So, your grandmother's sister's granddaughter is 3.125% related to you and 6. steps removed from you in your family tree. INDEXEDDB, WEBSQL, LOCALSTORAGE Update June 2019: This blog post was written in 2015. The benchmarks are out-of-date. WebSQL is still deprecated and in fact being removed from iOS Safari. Web Workers are not necessarily a panacea. I'd recommend using IndexedDB for large data, and LocalStorage for small amounts of data that you need synchronous access to. When it READ THE TEA LEAVES
Managing focus in the shadow DOM. Posted by Nolan Lawson in accessibility, Web . 40 Comments. One of the trickiest things about the shadow DOM is that it subverts web developers’ expectations about how the DOM works. In the normal rules of the game, document.querySelectorAll ('*') grabs all the elements in JAVASCRIPT PERFORMANCE BEYOND BUNDLE SIZE MANAGING FOCUS IN THE SHADOW DOM JAPANESE NAME CONVERTER The Japanese Name Converter uses a combination of dictionary lookup, substitution rules, and machine learning to convert English characters into katakana. For common English names, a dictionary lookup of about 4,000 English names is used. For other names, a learned substitution model trained on these names is applied instead. FIXING MEMORY LEAKS IN WEB APPLICATIONS When you click the “take snapshot” button, you’ve captured all the live objects in a particular JavaScript VM on that web page. This includes objects referenced by the window, objects referenced by setInterval callbacks, etc. Think of it as a frozen moment in time representing all the memory used by that web page.. The next step is to reproduce some scenario that you think may be leaking HOW TO DE-GOOGLE YOUR ANDROID PHONE First, download a ROM from this Russian message board. It's okay! You can totally verify the GPG signature. Allow yourself 30 minutes to remember how GPG works, then verify that forum poster LeetAndrej420 has indeed signed the file. Next, root your Android phone. You will need to hold the volume-up and power buttons for ten HOW TO WRITE A JAVASCRIPT PACKAGE FOR BOTH NODE AND THE This is an issue that I've seen a lot of confusion over, and even seasoned JavaScript developers might have missed some of its subtleties. So I thought it was worth a short tutorial. Let's say you have a JavaScript module that you want to publish to GREAT-GRANDMOTHER
First cousins, for instance, have two common ancestors, and the generation distance via each one is 4. Therefore their relatedness is 2 x (1/2)^4 = 1/8. If A is B’s great-grandchild, the generation distance is 3 and the number of common ‘ancestors’ is 1 (B himself), so the relatedness is 1 x (1/2)^3 = 1/8. GRANDMOTHER'S SISTER'S GRANDDAUGHTER The relatedness between two people is expressed with two measures: Relatedness coefficient: what percentage of your genes you share. Degree of relation: how far you are from that person in your family tree. So, your grandmother's sister's granddaughter is 3.125% related to you and 6. steps removed from you in your family tree. INDEXEDDB, WEBSQL, LOCALSTORAGE Update June 2019: This blog post was written in 2015. The benchmarks are out-of-date. WebSQL is still deprecated and in fact being removed from iOS Safari. Web Workers are not necessarily a panacea. I'd recommend using IndexedDB for large data, and LocalStorage for small amounts of data that you need synchronous access to. When it OPTIONS FOR STYLING WEB COMPONENTS When I released emoji-picker-element last year, it was my first time writing a general-purpose web component that could be dropped in to any project or framework. It was also my first time really kicking the tires on shadow DOM.. In the end, I think it was a natural fit. Web components are a great choice when you want something to be portable and self-contained, and an emoji picker fits the INTRODUCING EMOJI-PICKER-ELEMENT: A MEMORY-EFFICIENT EMOJI The Unicode Consortium is never going to stop adding emoji, so at some point keeping all the emoji and their metadata in-memory is going to become unsustainable (or at least, unwieldy). It should be a custom element. Web components are a thing; using an emoji picker should be as simple as dropping into your HTML. CUSTOMIZING FONTS IN FIREFOX ON LINUX Firefox relies on an OS-level utility called fontconfig to choose fonts. On Ubuntu 20.04, fontconfig has a default config file that automatically replaces proprietary fonts like Helvetica with free fonts like Nimbus Sans. If a web page’s CSS has Helvetica in the font-family property, Firefox will ask the OS, “Hey, do you have Helvetica?”.
ACCURATELY MEASURING LAYOUT ON THE WEB Update (August 2019): the technique described below, in particular how to schedule an event to fire after style/layout calculations are complete, is now captured in a web API proposal called requestPostAnimationFrame. There is also a good polyfill called afterframe. We all want to make faster websites. The question is just what to measure, and how HIGH-PERFORMANCE WEB WORKER MESSAGES Update: this blog post was based on the latest browsers as of early 2016. Things have changed, and in particular the benchmark shows that recent versions of Chrome do not exhibit the performance cliff for non-stringified postMessage() messages as described in this post. In recent posts and talks, I've explored how Web Workers can vastly HOW TO THINK ABOUT DATABASES As a maintainer of PouchDB, I get a lot of questions from developers about how best to work with databases. Since PouchDB is a JavaScript library, and one with fairly approachable documentation (if I do say so myself), many of these folks tend toward the more beginner-ish side of the spectrum. However, even with experienced INDEXEDDB, WEBSQL, LOCALSTORAGE Update June 2019: This blog post was written in 2015. The benchmarks are out-of-date. WebSQL is still deprecated and in fact being removed from iOS Safari. Web Workers are not necessarily a panacea. I'd recommend using IndexedDB for large data, and LocalStorage for small amounts of data that you need synchronous access to. When it BETTER SYNONYM HANDLING IN SOLR Even if you don’t have multi-word synonyms, the Solr docs mention a second good reason to avoid query-time expansion: unintuitive IDF boosting. Consider our “dog,” “hound,” and “pooch” example. In this case, a query for any one of the three will be expanded into: + (dog hound pooch) Since “hound” and “pooch” are much less
HOW TO FIX A BUG IN AN OPEN-SOURCE PROJECT So, you've found a bug in an open-source project. First off: don't panic! This is perfectly normal. Software is written by humans, and humans make mistakes. You might also be thinking to yourself, "Gee, I'd love to fix this bug." I mean, who wouldn't RELATEDNESS CALCULATOR Welcome to the Relatedness Calculator. Ever wondered how you're related to your half-cousin ? How about your great uncle? And what is a second cousin twice removed, anyway? Ask the relatedness calculator . Just enter the name of a relative in plain English. For instance, you can type brother, mom's cousin, or even grandpa's cousin's daughter.
READ THE TEA LEAVES
Managing focus in the shadow DOM. Posted by Nolan Lawson in accessibility, Web . 40 Comments. One of the trickiest things about the shadow DOM is that it subverts web developers’ expectations about how the DOM works. In the normal rules of the game, document.querySelectorAll ('*') grabs all the elements in JAVASCRIPT PERFORMANCE BEYOND BUNDLE SIZE MANAGING FOCUS IN THE SHADOW DOM JAPANESE NAME CONVERTER The Japanese Name Converter uses a combination of dictionary lookup, substitution rules, and machine learning to convert English characters into katakana. For common English names, a dictionary lookup of about 4,000 English names is used. For other names, a learned substitution model trained on these names is applied instead. FIXING MEMORY LEAKS IN WEB APPLICATIONS When you click the “take snapshot” button, you’ve captured all the live objects in a particular JavaScript VM on that web page. This includes objects referenced by the window, objects referenced by setInterval callbacks, etc. Think of it as a frozen moment in time representing all the memory used by that web page.. The next step is to reproduce some scenario that you think may be leaking HOW TO DE-GOOGLE YOUR ANDROID PHONE First, download a ROM from this Russian message board. It's okay! You can totally verify the GPG signature. Allow yourself 30 minutes to remember how GPG works, then verify that forum poster LeetAndrej420 has indeed signed the file. Next, root your Android phone. You will need to hold the volume-up and power buttons for ten HOW TO WRITE A JAVASCRIPT PACKAGE FOR BOTH NODE AND THE This is an issue that I've seen a lot of confusion over, and even seasoned JavaScript developers might have missed some of its subtleties. So I thought it was worth a short tutorial. Let's say you have a JavaScript module that you want to publish to GREAT-GRANDMOTHER
First cousins, for instance, have two common ancestors, and the generation distance via each one is 4. Therefore their relatedness is 2 x (1/2)^4 = 1/8. If A is B’s great-grandchild, the generation distance is 3 and the number of common ‘ancestors’ is 1 (B himself), so the relatedness is 1 x (1/2)^3 = 1/8. GRANDMOTHER'S SISTER'S GRANDDAUGHTER The relatedness between two people is expressed with two measures: Relatedness coefficient: what percentage of your genes you share. Degree of relation: how far you are from that person in your family tree. So, your grandmother's sister's granddaughter is 3.125% related to you and 6. steps removed from you in your family tree. INDEXEDDB, WEBSQL, LOCALSTORAGE Update June 2019: This blog post was written in 2015. The benchmarks are out-of-date. WebSQL is still deprecated and in fact being removed from iOS Safari. Web Workers are not necessarily a panacea. I'd recommend using IndexedDB for large data, and LocalStorage for small amounts of data that you need synchronous access to. When it READ THE TEA LEAVES
Managing focus in the shadow DOM. Posted by Nolan Lawson in accessibility, Web . 40 Comments. One of the trickiest things about the shadow DOM is that it subverts web developers’ expectations about how the DOM works. In the normal rules of the game, document.querySelectorAll ('*') grabs all the elements in JAVASCRIPT PERFORMANCE BEYOND BUNDLE SIZE MANAGING FOCUS IN THE SHADOW DOM JAPANESE NAME CONVERTER The Japanese Name Converter uses a combination of dictionary lookup, substitution rules, and machine learning to convert English characters into katakana. For common English names, a dictionary lookup of about 4,000 English names is used. For other names, a learned substitution model trained on these names is applied instead. FIXING MEMORY LEAKS IN WEB APPLICATIONS When you click the “take snapshot” button, you’ve captured all the live objects in a particular JavaScript VM on that web page. This includes objects referenced by the window, objects referenced by setInterval callbacks, etc. Think of it as a frozen moment in time representing all the memory used by that web page.. The next step is to reproduce some scenario that you think may be leaking HOW TO DE-GOOGLE YOUR ANDROID PHONE First, download a ROM from this Russian message board. It's okay! You can totally verify the GPG signature. Allow yourself 30 minutes to remember how GPG works, then verify that forum poster LeetAndrej420 has indeed signed the file. Next, root your Android phone. You will need to hold the volume-up and power buttons for ten HOW TO WRITE A JAVASCRIPT PACKAGE FOR BOTH NODE AND THE This is an issue that I've seen a lot of confusion over, and even seasoned JavaScript developers might have missed some of its subtleties. So I thought it was worth a short tutorial. Let's say you have a JavaScript module that you want to publish to GREAT-GRANDMOTHER
First cousins, for instance, have two common ancestors, and the generation distance via each one is 4. Therefore their relatedness is 2 x (1/2)^4 = 1/8. If A is B’s great-grandchild, the generation distance is 3 and the number of common ‘ancestors’ is 1 (B himself), so the relatedness is 1 x (1/2)^3 = 1/8. GRANDMOTHER'S SISTER'S GRANDDAUGHTER The relatedness between two people is expressed with two measures: Relatedness coefficient: what percentage of your genes you share. Degree of relation: how far you are from that person in your family tree. So, your grandmother's sister's granddaughter is 3.125% related to you and 6. steps removed from you in your family tree. INDEXEDDB, WEBSQL, LOCALSTORAGE Update June 2019: This blog post was written in 2015. The benchmarks are out-of-date. WebSQL is still deprecated and in fact being removed from iOS Safari. Web Workers are not necessarily a panacea. I'd recommend using IndexedDB for large data, and LocalStorage for small amounts of data that you need synchronous access to. When it OPTIONS FOR STYLING WEB COMPONENTS When I released emoji-picker-element last year, it was my first time writing a general-purpose web component that could be dropped in to any project or framework. It was also my first time really kicking the tires on shadow DOM.. In the end, I think it was a natural fit. Web components are a great choice when you want something to be portable and self-contained, and an emoji picker fits the INTRODUCING EMOJI-PICKER-ELEMENT: A MEMORY-EFFICIENT EMOJI The Unicode Consortium is never going to stop adding emoji, so at some point keeping all the emoji and their metadata in-memory is going to become unsustainable (or at least, unwieldy). It should be a custom element. Web components are a thing; using an emoji picker should be as simple as dropping into your HTML. CUSTOMIZING FONTS IN FIREFOX ON LINUX Firefox relies on an OS-level utility called fontconfig to choose fonts. On Ubuntu 20.04, fontconfig has a default config file that automatically replaces proprietary fonts like Helvetica with free fonts like Nimbus Sans. If a web page’s CSS has Helvetica in the font-family property, Firefox will ask the OS, “Hey, do you have Helvetica?”.
ACCURATELY MEASURING LAYOUT ON THE WEB Update (August 2019): the technique described below, in particular how to schedule an event to fire after style/layout calculations are complete, is now captured in a web API proposal called requestPostAnimationFrame. There is also a good polyfill called afterframe. We all want to make faster websites. The question is just what to measure, and how HIGH-PERFORMANCE WEB WORKER MESSAGES Update: this blog post was based on the latest browsers as of early 2016. Things have changed, and in particular the benchmark shows that recent versions of Chrome do not exhibit the performance cliff for non-stringified postMessage() messages as described in this post. In recent posts and talks, I've explored how Web Workers can vastly HOW TO THINK ABOUT DATABASES As a maintainer of PouchDB, I get a lot of questions from developers about how best to work with databases. Since PouchDB is a JavaScript library, and one with fairly approachable documentation (if I do say so myself), many of these folks tend toward the more beginner-ish side of the spectrum. However, even with experienced INDEXEDDB, WEBSQL, LOCALSTORAGE Update June 2019: This blog post was written in 2015. The benchmarks are out-of-date. WebSQL is still deprecated and in fact being removed from iOS Safari. Web Workers are not necessarily a panacea. I'd recommend using IndexedDB for large data, and LocalStorage for small amounts of data that you need synchronous access to. When it BETTER SYNONYM HANDLING IN SOLR Even if you don’t have multi-word synonyms, the Solr docs mention a second good reason to avoid query-time expansion: unintuitive IDF boosting. Consider our “dog,” “hound,” and “pooch” example. In this case, a query for any one of the three will be expanded into: + (dog hound pooch) Since “hound” and “pooch” are much less
HOW TO FIX A BUG IN AN OPEN-SOURCE PROJECT So, you've found a bug in an open-source project. First off: don't panic! This is perfectly normal. Software is written by humans, and humans make mistakes. You might also be thinking to yourself, "Gee, I'd love to fix this bug." I mean, who wouldn't RELATEDNESS CALCULATOR Welcome to the Relatedness Calculator. Ever wondered how you're related to your half-cousin ? How about your great uncle? And what is a second cousin twice removed, anyway? Ask the relatedness calculator . Just enter the name of a relative in plain English. For instance, you can type brother, mom's cousin, or even grandpa's cousin's daughter.
READ THE TEA LEAVES SOFTWARE AND OTHER DARK ARTS, BY NOLAN LAWSON * Home
* Apps
* Code
* Talks
* About
22 Sep
THE JOY AND CHALLENGE OF DEVELOPING FOR KAIOS Posted by Nolan Lawson in Webapps . Tagged: KaiOS
. 3 Comments
Recently I spent some time getting Pinafore to run on a KaiOS device. Overall, I found it to be challenging but enjoyable. In this post, I’ll talk about some of the tricks that helped me to work with this curious little feature phone. Why KaiOS? Well, I guess I’ve always been a bit of a gadget geek. I’ve been developing for Android since the early days of the HTC Dream , I managed to get my Nexus 5 to triple-boot into Android, Firefox OS, and Ubuntu Touch , and I’ve also
played around with the Amazon Fire Phone, Windows Phone, iPod Touch… You get the idea.
Recently though, I’ve found the mobile landscape a bit boring. Android and iOS are the two big players, and it’s been that way for nearly a decade. Firefox OS, Blackberry OS, Windows Phone, and other would-be contenders have long since bitten the dust. That’s why I’m excited about KaiOS. It’s a platform that’s growing surprisingly fast and is actually based on Firefox OS (may it rest in peace). It’s especially popular in India, where it’s already the second-most popular mobile OS after Android .
KaiOS can run regular websites, but it can also run “packaged” apps, ala Firefox OS. So how can an aspiring KaiOS developer get started?
STEP ONE: BUYING A DEVELOPMENT PHONE I like to test on real devices, because I want to experience my app with real-world hardware and performance constraints, as an actual user would. I decided to get the Nokia 8110 4G because it was
available on Amazon for $70. Note that this phone only supports AT&T in the U.S., so if you plan on using it as your actual personal phone, you may be out of luck. When you first unbox the phone, you’ll have about 5 minutes’ worth of setup screens, after which you’re ready to go. I’d also recommend going into the settings and upgrading the OS, since mine needed an upgrade right away. NEXT STEPS: DEVELOPMENT ENVIRONMENT The best resources I’ve found for KaiOS development are the official developer guide and Paul Kinlan’s quick start guide
.
Paul’s guide is the best place to start, since it’s short and will get you up and running quickly. Paul says that he could only get WebIDE to work in
Firefox 48, but I found that Firefox 59 also worked (per the KaiOS developer guide). So let’s use that. First you’ll want to download Firefox 59 for your OS (in my case, Ubuntu) via Mozilla’s download site . Sadly I could not get Firefox 59 to run alongside the latest Firefox (which is my go-to browser), and I also found that Firefox 59 tried to aggressively update itself, so every time I reopened it, it would be running the latest version. To work around that, you can run this script: 1
2
3
4
rm -fr firefox profile mkdir profile
tar -xjf firefox-59.0.3.tar.bz2 ./firefox/firefox-bin -profile profile This will delete Firefox’s stored data and restart it with a fresh profile every time. It’s handy for quickly restarting Firefox! After you input the “secret” code that Paul mentions (*#*#33284#*#*), you should see a little bug icon in the corner: At this point you should be able to run: 1
adb devices
…and see your device in the list of devices: 1
2
List of devices attached 4939400 device
If adb isn’t running, you can run adb kill-server && adb start-server to restart it. This didn’t work for me out of the box – I got an error saying it couldn’t connect to my device due to faulty udev rules. Luckily the KaiOS developer guide has a “Setting USB access” script that will fix that. After running that script, I used Paul’s trick of setting up adb forwarding:
1
adb forward tcp:6000 localfilesystem:/data/local/debugger-socket After this, you should be able to connect in Firefox WebIDE by clicking “Remote Runtime.” One thing I noticed is that occasionally my device would get disconnected from WebIDE. In that case, you can just forward to another port:
1
adb forward tcp:6001 localfilesystem:/data/local/debugger-socket …and then reconnect WebIDE to the new port, and it should work. NEXT STEPS: ACTUALLY WRITING CODE As far as I can tell, KaiOS is based on Firefox 48. You can tell by the user agent string: 1
Mozilla/5.0 (Mobile; Nokia_8110_4G; rv:48.0) Gecko/48.0 Firefox/48.0 KAIOS/2.5.1
This means that you won’t necessarily have all the latest-and-greatest JavaScript or Web API features. Here’s a brief list of what I found didn’t work: * async functions
* ServiceWorker
* Intl
_UPDATE: it turns out ServiceWorker is supported! But you have to enable a permission in the manifest . Thanks, Fabrice
!_
As a quick gut-check of whether your app will run on KaiOS, you can try downloading Firefox 48, loading your website, and seeing if it works. (I found this easier than trying to debug on KaiOS right out of the gate.) You can use the same script above to run Firefox 48 with a fresh profile.
Once your code is sufficiently backwards-compatible (I found that @babel/preset-env with the default settings plus an Intl polyfill was good enough for me as a starting point), you have two options for testing your app: * as a packaged app
* as a hosted app
(If you’ve done Firefox OS development before, you’ll find these options familiar.)
I tried both techniques, but found that the hosted app was easier for quick testing. If your development machine and phone are on the same WiFi network, then you can create a manifest.webapp file per KaiOS’s documentation and then load a URL like so: 1
http://192.168.1.2:4002/manifest.webapp (If you’re not sure what IP address, to use, run ifconfig -a | grep inet.)
Then you should see your app listed, and you can run it on the device by clicking the “play” button: You can also try the packaged-app route, but I found that it didn’t play well with the routing library in my framework of choice (Sapper ) due to the extra /index.html. Plus, if I ever actually submit this app to the KaiStore, I’ll probably go with the hosted route since it’s less maintenance work. OPTIMIZING FOR KAIOS In terms of web development, there are a few good things to be aware of when developing for KaiOS, and in particular for the Nokia 8110 4G. First off, the available screen size is 240×294 pixels, which you can check by using window.innerWidth in JavaScript, @media (max-width: 240px) in CSS, etc. If you set "fullscreen": true to hide the status bar, you can get slightly more breathing room: 240×320. I had already optimized my app for the iPhone 4’s screen size (which is 320×480), but I found I had to do extra work to make things show up correctly on an even tinier screen. The iPhone 4 is already pretty small, but it’s a giant compared to the Nokia 8110 4G.
Next, the input methods are quite limited. If you’ve actually taken the time to make your webapp keyboard-accessible, then you should be most of the way there. But there are still some extra optimizations you may have to make for KaiOS. By default, the ↑ and ↓ arrows will typically scroll the page up or down. I decided to use the ← and → arrows to change the focus – i.e. to act as proxies for the Tab and Shift + Tab keys. I wrote some fairly simple logic to navigate through the focusable elements on the page, taking special care to allow the arrow keys to work properly inside of text inputs and modal dialogs.
I also found that the focus outlines were a bit hard to see on the small screen, so I scaled them up for KaiOS and added some extra styling to make the focus more obvious. Some apps may opt to display an onscreen cursor (this seems to be the default behavior of the web browser), but I found that to be a bit of a clumsy experience. So I think managing the focus is better. OTHER KAIOS WEB DEVELOPER HURDLES The next most difficult thing about KaiOS is still the lack of modern browser standards. For instance, I couldn’t get SVG