View
Repeats

AJAX requests with PATCH or DELETE method will not redirect with GET

When you make an AJAX request PATCH /foo and the /foo action redirects to /bar, browsers will request PATCH /bar. You probably expected the second request to be GET /bar, since we're used to redirects always resulting in a GET request.

# Browser sends
PATCH /foo HTTP/1.1

# Server responds
HTTP/1.1 302 Found
Location: /bar

# Browser follows redirect
PATCH /bar

# Server responds
HTTP/1.1 404 Not Found

This is also true on some browsers for DELETE, or in general for any AJAX call that is neither GET or `POST…

Repeats

Event order when clicking on touch devices

Touch devices have their own set of events like touchstart or touchmove. Because mobile browsers should also work with with web applications that were build for mouse devices, touch devices also fire classic mouse events like mousedown or click.

When a user follows a link on a touch device, the following events will be fired in sequence:

  • touchstart
  • touchend
  • mousemove
  • mousedown
  • mouseup
  • click

Canceling the event sequence ——————-…

Repeats

Generating test images on the fly via JavaScript

When you need test images, instead of using services like lorempixel or placehold.it you may generate test images yourself. You can do this via JavaScript.

Here is an ES6 function that generates a simple SVG image and returns it as a data: URI. All browsers support SVG, and you can easily adjust it yourself.

function svgUri(text) {
  let svg = `
    <svg width="320" height="240" xmlns="http://www.w3.org/2000/svg">
      <rect x="0" y="0" width="320" height="240" style...
Repeats

Sass partial names must always begin with an underscore

Be careful to name any file @imported by SASS with a leading underscore.

SASS files not beginning with an underscore will be rendered on their own, which will fail if they are using variables or mixins defined elsewhere. (For me it broke only in production, which may be due to some settings in SASS-GEM/lib/sass/plugin/rails.rb.)

From the SASS docs:

The underscore lets Sass know that the file is only a partial file and that it should not be generated into a CSS file.

Repeats

Grep through the DOM using the Capybara API

When your Cucumber feature needs to browse the page HTML, and you are not sure how to express your query as a clever CSS or XPath expression, there is another way: You can use all and find to grep through the DOM and then perform your search in plain Ruby.

Here is an example for this technique:

Then /^I should see an image with the filename...
Repeats

HTML5: disabled vs. readonly form fields

Form fields can be rendered as noneditable by setting the disabled or the readonly attribute. Be aware of the differences:

disabled fields

  • don’t post to the server
  • don’t get focus
  • are skipped while tab navigation
  • available for button, fieldset, input, select, textarea, command, keygen, optgroup, option

Browser specific behavior:

  • IE 11: text inputs that are descendants of a disabled fieldset appear disabled but the user can still interact with them
  • Firefox: selecting text in a disabled text field is no…
Repeats

Fix PNG colors in IE, old Safaris and new Firefoxes

Some browsers render PNG images with color profiles and other shenanigans, some don't. Remove some PNG chunks to render colors uniformly.

Geordi brings a command png-optimize which conveniently optimizes your PNGs for the web. See Github for a description

  • Single file and batch optimization is supported
  • optimize-png will overwrite the original files

Without Geordi

Linux:
sudo apt-get install pngcrush
  • Single file:

    pngcrush -rem...
    
Repeats

Difference between respond_to/format and params[:format]

To return non-HTML responses (like XLS spreadsheets), we usually use the

respond_to do |format|
  format.xls do
    # send spreadsheet
  end
end

This is often, but not always the same as checking for params[:format] == :xls, so don't rely on this when e.g. one format checks for authorization and the other doesn't.

params[:format] is only set when a user explicitly puts a .xls at the end of the URL.

The format.xls block also responds when the user's browser requests the application/excel MIME type.

If Intern…

How to skip Sprockets asset compile during Capistrano deployment

For applications coming with lots of stylesheets and scripts, asset compilation might take quite long. This can be annoying when deploying a release that does not actually change assets.

When your app uses Sprockets, you can simply skip asset compilation and re-use the previous release's assets. [1]
That is especially easy via Capistrano. Capistrano will automatically symlink your release's public/assets to a shared directory, so all you need to do is skip the deploy:assets:precompile task.

Put the following code where you'd put other …

Auto-destruct in 24 days

Unpoly 0.54.0 released

There were a number of Unpoly releases addressing issues that we encountered in our current development projects:

0.54.0

Passive updates

  • [up-hungry] elements will now also be updated when the server responds with an error code. This helps when [up-hungry] is used to display error messages.

Forms

  • When a form is submitted you can now consistently refer to that form element as ampersand (&) in CSS selectors ([like in Sass](…

VNC browser disappears while typing

We often use the Then console step from spreewald in combination with geordi vnc from geordi to debug tests within a real browser. Sometimes when you type in the browser it suddenly disappears. You will only see a grey screen then.

This will always happen if you press the d key. Press the d key again and the browser will appear again.

Repeats

Traversing the DOM tree with jQuery

jQuery offers many different methods to move a selection through the DOM tree. These are the most important.

$element.find(selector)
Get the descendants of each element in the current set of matched elements, filtered by a selector. Does not find the current element, even it matches. If you wanted to do that, you need to write $element.find(selector).addBack(selector).
$element.closest(selector)
Get the first ancesto…
Repeats

Webpacker: Configuring browser compatibility

Webpacker uses Babel and Webpack to transpile modern JavaScript down to EcmaScript 5. Depending on what browser a project needs to support, the final Webpack output needs to be different. E.g. when we need to support IE11 we can rely on fewer JavaScript features. Hence our our output will be more verbose than when we only need support modern browsers.

Rails 5.1+ projects often use Webpacker to preconfigure the Webpack pipeline for us. The default configuration works something like this:

  1. Webpack chec…
External content

Flexbox vs. Grid

CSS Flexbox has become extremely popular amongst front-end developers the last couple of years. This isn’t surprising, as it has made it a lot easier for us to create dynamic layouts and align content within containers.
However, there’s a new kid in town called CSS Grid, and it’s got a lot of the same capabilities as Flexbox. In come cases it’s better than Flexbox, while in other cases it’s not.

If you are to take one lesson from this article, let it be this one:

Flexbox is made for one-dimensional layouts and Grid is made for tw…

Repeats

How DECIMAL columns deal with numbers exceeding their precision or scale

When storing floating-point numbers such as prices or totals in an SQL database, always use a DECIMAL column. Never use FLOAT or kittens will die.

DECIMAL columns are parametrized with a precision and a scale. These parameters describe which numbers can be stored in that column. E.g. a decimal with a precision of 5 and a scale of 2 can store numbers from -999.99 to 999.99, but not 1000 or 1.234.

This card explains what various databases do when you try to store a number in a DECIMAL field, and that number exceeds that colum…

Repeats

Detect the current Rails environment from JavaScript or CSS

Detecting if a Javascript is running under Selenium WebDriver is super-painful. It's much easier to detect the current Rails environment instead.

You might be better of checking against the name of the current Rails environment. To do this, store the environment name in a data-environment of your <body>. E.g., in your application layout:

%body{'data-environment' => Rails.env}

Now you can say in a piece of Jav…

Nested Spreewald patiently blocks are now patient

In Spreewald 1.10.4+, nested patiently blocks are now patient.

Here is an example:

patiently do
  outer_code
  patiently do
    inner_code
  end
end

On spreewald 1.11.2+ the inner block will wait for the full configured wait time (by default 5 seconds). The outer patiently block would now be out of time, but it will always be retried at least a second time.

In versions 1.10.4 - 1.11.1, inner blocks would keep giving the outer block additional time to finish, which solves the same issues, but as a downside can cause the wh…

Repeats

CSS: Opacity is not inherited in Internet Explorer

Elements will not inherit their parent's opacity in IE for no good reason. This can lead to unexpected behaviour when you want to fade/hide an element and all its children.

To fix it, give the element defining the opacity a non-static positioning. For example:

.foo {
  opacity: 0.2;
  position: relative; /* for IE */
}

While the linked article describes this problem for IE9 and below, I have encountered the same issue in IE10 and IE11.

Just go away, Internet Explorer!

View