Linked contentRepeats

Native share dialog on mobile Chrome

Mobile Chrome (and the Safari Technology Preview) support the "web share API" which allow you to use the native share functionality of an Android phone. When clicking a share button using this API, the browser will automatically show all installed applications that support content sharing, such as Whatsapp, Facebook, Twitter, e-mail etc.

The API is extremely simple to use:

if ( typeof(navigator.share) === 'function' ) {
let data = {
url: '', title: '', text: '', } ...

Linked contentRepeats

CSS: Matching against attributes and their values (or parts of them)

You probably know that you can use CSS selectors to match against elements and their attributes, such as:

a[title] { /* any <a> that has a "title" */ }
a[data-fancy="true"] { /* any <a> that has their "data-fancy" attribute set to "true" */ }

But there is more: You do not need to match against "full" attribute values but can match against parts of them.

They work in all somewhat modern browsers, and IE9 or later.

Exact match (CSS2)
[foo="bar"] (matches <div foo="bar" />, but not `<div…

How to: Run geordi in a single proccess with parallel test setup

Geordi uses parallel_tests if available for running the test suite. To debug an application it is very unhandy to have multiple processes as your terminal I/O will not work as expected once a breakpoint is hit.

Even parallel_tests support an option to enable a single process run, it is not possible to pass this option through geordi. But you can set the number of processes via ENV variable manually:

PARALLEL_TEST_PROCESSORS=1 bundle exec geordi cucu…


How to create memory leaks in jQuery

jQuery doesn't store information about event listeners and data values with the element itself. This information is instead stored in the global $.cache object. Every time you add an event listener or data value to a jQuery object, $.cache gains another entry.

The only way that a $.cache entry gets deleted is when you call remove() on the element that put it there!

Since cache entries also have a pointer back to the element that spawned them, it is easy to create DOM elements that can never be garbage-collected.

Below are …

Unpoly 0.57.0 released: New params API, compiler improvements and scrolling fixes

This is a major rewrite with many bugfixes, performance improvements and some minor breaking API changes.

Request parameters

To prevent confusion with [up-data], Unpoly now uses the word "params" when talking about form values or request parameters:

  • up.request() option { data } has been renamed to { params }.
  • up.replace() option { data } has been renamed to { params }.

Parameters may be passed in one of the following type…

Minify Font Awesome fonts with webpack

Font Awesome 5 is a comprehensive solution for vector icons on your website.

Originally, Font Awesome came as an icon font (plus stylesheets), but recently it can also be used as a pure JavaScript solution (which will render icons as inline <svg> tags), or even as SVG sprites.

All solutions have their pros and cons:

Icon font:

  • little CPU load (no JavaScript)
  • fonts are relatively large
  • 1 extra HTTP request

Javascript + inline SVG:

  • higher CPU load (needs to watch the DOM via mutation observers to ad…
Linked content

Drawing diagrams with is a web application that lets you draw flow charts and other diagrams. It works much nicer than office suite tools like LibreOffice Draw.

Its UI is easy to use: Simply drag and drop shapes or arrows from the left-hand side onto your sheet. Drag start/end of arrows to shapes to automatically connect them. You can add text to shapes by selecting them and typing. To add colors, select a shape and use the right-hand panel.

While you can, you don't need to store your charts online. "Offline" storage can be files…


Debugging cucumber feature with javascript + firefox vnc

TL;DR Debugging problems with javascript errors in cucumber tests is sometimes easier in the browser. Run the test, stop at the problematic point (with Then pause from Spreewald 1.7+) and open VNC for Firefox.



A quick introduction to CORS


Cross-Site Request Forgery (CSRF) is an attack pattern for websites. A CSRF attack is usually relevant in a browser context, where state is kept for multiple domains (as opposed to independent requests made e.g. with curl). The most common example is authentication via cookies. If a script on made requests to, the browser would send all cookies for along, effectively given the script access to anythin…


Javascript: Calling a function with a variable number of arguments

This card describes how to pass an array with multiple element to a JavaScript function, so that the first array element becomes the first function argument, the second element becomes the second argument, etc.

Note how this is different from passing the entire array as the first argument. Compare these two different ways of calling fun() in Ruby:

# Ruby
array = [1, 2, 3]
fun(array)  # same as fun([1, 2, 3]) (1 argument)
fun(*array) # same as fun(1, 2, 3)   (3 arguments)

Depending on your culture the spreading of array e…


Raising JavaScript errors in Cucumber scenarios and how to silence them for particular scenarios

Raising JavaScript errors in Cucumber

With selenium JavaScript errors do not cause any failture in your cucumber scenarios. To archive a failture we can use the the Ruby bindings to Selenium Webdriver expose the Webdriver logging API introduced in version 2.38 .

The following step can be used:

Then /^there should be no JavaScript errors$/ do
if alert_present?
# Chrome 54 and/or Chromedriver 2.24 introduced a breaking change on how
# accessing browser logs work.
# Apparently, while an alert/confirm is open, Chro…

Linked contentRepeats

Getting permanent links to files on Github or Gitlab

Please don't simply copy line number links from Github. The URL usually contains a branch name like master:

If someone now posts an insertion or deletion to that file into master your link points to the wrong line!

A better way is to (Github) press the Y key after clicking on a line number or (Gitlab) clicking the "Permalink" button in the top bar.

This will transform the URL to another URL that points to the particular commit:



Capybara: Find an element that contains a string

There is no CSS selector for matching elements that contains a given string ¹. Luckily, Capybara offers the :text option to go along with your selector:

page.find('div', text: 'Expected content')

You can also pass a regular expression!

page.find('div', text: /Expected contents?/i)

Note that if your CSS selector is as generic as div, you might get a lot more results than you expect. E.g. a <div class="container"> that surrounds your entire layout will probably also contain that text (in a descendant) and Capybara wil…


CSS: Combining different length units with calc()

calc() lets you mix CSS units. Ever wanted to give an element "the container's width minus 20px on each side"? Here you go:

width: calc(100% - (20px * 2));

When using Sass, you need to interpolate Sass expressions:

width: calc(100% - #{$margin})

Supported by all modern browsers and IE9+.

Linked contentRepeats

HTML file inputs support picking directories

HTML's <input type="file"> accepts a single file. You can allow multiple files via <input type="file" multiple>.
But sometimes, selecting multiple files is not enough and can be cumbersome for the user. Enter webkitdirectory:

<input type="file" webkitdirectory multiple>

Using webkitdirectory switches the browser's file picker to select a directory. All files inside that directory, and inside any nested subdirectories, will be selected for the file input.

This can be useful when users want to upload all files from a nested dire…

Linked content

Pivotal Tracker now supports story description templates

When writing a story description in Pivotal Tracker, there is now a tiny button at the bottom of the description field where you can paste a template.

You can define your own templates by following "More" at the top, then "Templates".
We recommend you define a template following our suggested story description.

Note that the three default templates currently can not be removed or changed.

Linked contentRepeats

Do not use "flex: 1" or "flex-basis: 0" inside "flex-direction: column" when you need to support IE11

Flexbox is awesome. Most of it even works in IE11, but flex: 1 won't work reliably in Internet Explorer.
This it because implicitly sets flex-basis: 0 which IE fails to support properly.


Consider the following HTML and CSS.

<div class="container">
  <div class="child">
  <div class="bar">
.container {
  display: flex;
  flex-direction: column;

.child {
  flex: 1;

See it in action at Plunker.


Linked content

The Definitive Guide to Cookie Domains

Restricting access to cookies is essential for security in many web apps. For example, the session ID, the secret token used to identify a particular session, is typically stored in a cookie. Cookies have several important settings. Previously, I discussed the secure flag. This time, let’s dive into the cookie domain.

The cookie domain is an important security feature, probably even more important than the secure flag. It tells the browser that this cookie must only be sent to matching domains. Matching however, can happen in several w…

This website uses cookies to improve usability and analyze traffic.
Accept or learn more