About IE's Compatibility mode

IE has a "Compatibility Mode" for old browsers. You can keep IE from offering it (and fix some other things, too) by adding this meta tag to your <head>:

<meta http-equiv="X-UA-Compatible" content="IE=edge" />

Or in Haml:

%meta(http-equiv="X-UA-Compatible" content="IE=Edge")

However, there are some things you need to bear in mind:

  • X-UA-Compatible is ignored unless it's present inside the first 4k of you page. If you put it somewhere in the bottom of your head section (or in the body) move it to top. The best place for ...

How to test whether your device has a true Retina display

The linked site hosts a simple test. It shows two images with narrow vertical/horizontal lines. The more they resemble each other, the more Retina your display is.

instance_eval behaves different in Ruby 1.8 and Ruby 1.9, use instance_exec instead

In Ruby 1.9, instance_eval calls the block the with receiver as the first argument:

  • In Ruby 1.8, receiver.instance_eval(&block) calls block.call()
  • In Ruby 1.9, receiver.instance_eval(&block) calls block.call(receiver)

This will blow up in your face in Ruby 1.9, where a lambda crashes when it is called with a different number of arguments:

wrong number of arguments (1 for 0) (ArgumentError)

Forget that instance_eval ever existed. Use instance_exec instead, which behaves consistently across all Rubies.

factory_bot: Re-use partial factory definitions

Let's say you have two factories that share some attributes and traits:

FactoryBot.define do

  factory :user do
    screen_name 'john'
    email 'foo@bar.de'
    trait :with_profile do
      age 18
      description 'lorem ipsum'
    end
  end
  
  factory :client do
    full_name 'John Doe'
    email 'foo@bar.de'
    trait :with_profile do
      age 18
      description 'lorem ipsum'
    end
  end
  
end

You can re-use the shared fields by defining a trait outside the other factory definitions:

FactoryBot.define do

...

Rails Env Widget

Have you ever mistaken one Rails environment for another? The attached helper will help you to never do it again.

Save the attached file to app/helpers/ and use the widget in your layout like this:

%body
  = rails_env_widget unless Rails.env.production?

It'll render a small light gray box in the top left corner of your screen, containing the current Rails environment. On click, it'll disappear. Actually, it has the same UX as our Query Diet widget.

Thunderbird add-on to manually sort accounts and folders

This extension allows you to manually sort (order) your folders in the folder pane of Thunderbird or automatically sort them, but in a better way. This extension also allows you to re-order accounts in the folder pane.

Ruby: Converting UTF-8 codepoints to characters

Converting string characters to or from their integer value (7-bit ASCII value or UTF-8 codepoint) can be done in different ways in Ruby:

  • String#ord or String#unpack to get character values
  • Integer#chr or Array#pack to convert character values into Strings

Character values to Strings

Integer#chr

To get the character for a 7-bit ASCII value or UTF-8 codepoint (0-127) you can use Integer#chr:

116.chr
# => "t"

To get a character for values larger than 127, you need to pass the encoding. E.g. to get codepoint 25...

Lazysizes 2 is here

It claims to be even faster and brings a new plugin that polyfills object-fit and object-position. This allows for easy arrangement of e.g. images and videos inside containers.

As caniuse.com puts it, object-fit/object-position is a:

Method of specifying how an object (image or video) should fit inside its box. object-fit options include "contain" (fit according to aspect ratio), "fill" (stretches object to fill) and "cover" (overflows box but maintains ratio), where object-position allows the object to be repositioned like backg...

Bitmap to Vector Converter

Automatically convert bitmap images like JPEGs, GIFs and PNGs to the crisp, clean, scalable vector art of EPS, SVG, and PDF with the world's best auto-tracing software.

It's true, it does a great job.

How to find disabled fields with Capybara

At least Selenium cannot find disabled fields. Unless you find them explicitly:

find_field 'This is disabled', disabled: true

Making jQuery throw an error when it returns an empty collection

When you are working with jQuery selectors and collections, many times you want to know if the collection actually contains the elements you wanted to select. Here's a tiny jQuery plugin that does just that.

$.fn.ensure = ->
  if (@length == 0) then throw 'Empty jQuery collection'
  this

Use it like this:

$('input[id$=_cache]').ensure()
> Console: "Uncaught Empty jQuery collection"

Dynamically uploading files to Rails with jQuery File Upload

Say we want …

  • to create a Gallery that has a name and has_many :images, which in turn have a caption
  • to offer the user a single form to create a gallery with any number of images
  • immediate uploads with a progress bar per image
  • a snappy UI

Enter jQuery File Upload. It's a mature library that can do the job frontend-wise. On the server, we'll use Carrierwave, because it's capable of caching images.

(FYI, [here's how to do the u...

UI Sortable on table rows with dynamic height

UI sortable helps reordering items with drag 'n drop. It works quite fine.

Proven configuration for sorting table rows

When invoking the plugin, you may pass several options. This set is working fine with table rows:

$tbody.sortable # Invoke on TBODY when ordering tables
  axis: 'y' # Restrict drag direction to "vertically"
  cancel: 'tr:first-child:last-child, input' # Disable sorting a single tr to prevent jumpy table headers
  containment: 'parent' # Only drag within this container
  placehol...

Javascript: Wait until an image has finished loading

The attached ImageLoader helper will start fetching an image and return an image that is resolved once the image is loaded:

ImageLoader.load('/my/image.png').then(function(image) {
  ...
});

The image argument that is yielded to the promise callback is an HTMLImageElement. This is the kind of object you get when you call new Image().

PSA: When Redis (on LRU noeviction) reaches memory limits, keys with (any) expiry are removed, and keys without are not

In production, you (or your ops team) should configure a maximum number of bytes that Redis can use to store data (maxmemory setting).
They may even want to set maxmemory-policy to noeviction to avoid keys being removed that you want to keep around (e.g. for Sidekiq queues!).

The following applies to the noeviction LRU approach.


When you ask Redis to store a value that would exceed this limit, it tries to clean up:

  • Keys for which an expiry value (TTL) was set (explicitly, or when written via SETEX) will be removed.
    ...

jQuery: Find a selector in both descendants and the element itself

jQuery's find looks in the element's descendants. It will never return the current element itself, even if the element matches the given selector.

Require the attached file and you can now say:

$('.container').findWithSelf('.selector')

This is sort of like closest, but it looks in descendants instead of ancestors.

Preloading images with CSS

Sometimes you want to preload images that you will be using later. E.g. if hovering over a an area changes its background image, the new image should be preloaded. If you only load it once the user starts hovering, there will be a delay until the background image flips.

The attached article explains how to preload images with only CSS. No Javascript required.

The gist is:

.element:after {
  content: url(img01.jpg) url(img02.jpg) url(img03.jpg);
  display: none;
}

Testing Cookie Limits

TL;DR If you want to support most browsers, then don't exceed 50 cookies per domain, and don't exceed 4093 bytes per domain (i.e. total size of all cookies <= 4093 bytes)

Behind the link, you'll find a simple HTML page that offers some cookie tests (how large, how many etc) and an overview of this data for various browsers.

Fun fact: You cannot delete cookies with a key that hits the size limit and has a small value.

How to inspect RSS feeds with Spreewald, XPath, and Selenium

Spreewald gives you the <step> within <selector> meta step that will constrain page inspection to a given scope.

Unfortunately, this does not work with RSS feeds, as they're XML documents and not valid when viewed from Capybara's internal browser (e.g. a <link> tag cannot have content in HTML).

Inspecting XML

If you're inspecting XML that is invalid in HTML, you need to inspect the page source instead of the DOM. You may use Spreewald's "... in the HTML" meta step, or add this proxy step fo...

IMAP: Check credentials

Connect to your IMAP server. If you have SSL enabled:

openssl s_client -connect your-server:993

if your server supports STARTTLS:

openssl s_client -starttls imap -connect your-server:143

otherwise use netcat or telnet (you shouldn't do cleartext stuff nowadays...).
You should see something like this:

...
. OK Pre-login capabilities listed, post-login capabilities have more.

To log into IMAP, send the following string (incl. "01"!):

01 LOGIN user@domani.io $password

The server should return something like:

* C...

Enable debugging for BIND 9 on Ubuntu

Edit /etc/default/bind9 and change

OPTIONS="-u bind"

to

OPTIONS="-u bind -d 50 -g"

Restart BIND and you'll see debug log on your console.

How to fix: RubyMine / IntelliJ "find file" dialog losing focus on awesome wm

Many of our developers love to use the "awesome" window manager on Linux. However, RubyMine dialogs occasionally defocus while typing.

Here is a fix for that, tested on awesome 3.4, 3.5 and 4.0 (Ubuntu 14.04 and 16.04).

Problem

Consider the following:

  1. Press Ctrl+Shift+N
  2. "Find file" dialog opens
  3. Type to search, file list appears
  4. Type more, file list is being replaced

If your mouse pointer hovers the file list, the main window is focused when the list is being replaced (or simply when it shrinks and your mouse pointe...

Delay your Jasmine tests until the document is ready

To delay your entire Jasmine test suite until the DOM is ready, add the following:

beforeAll(function(done) {
  $(done);
});

jQuery Core 3.0 Upgrade Guide | jQuery

Since jQuery 3 saw it's first release candidate today, the links has a list of (breaking) changes.