Having a unique selector for an element is useful to later select it from JavaScript or to update a fragment with an Unpoly.
Haml lets you use square brackets ([]
) to generate a unique class name and ID from a given Ruby object. Haml will infer a class
attribute from the given object's Ruby class. It will also infer an id
attribute from the given object's Ruby class and #id
method.
This is especially useful with ActiveRecord instances, which have a persisted #id
and will hence **generate the same selector o...
In config/webpack/environment.js
you can get inspect environment
which includes all webpack config options set for the current environment:
const { environment } = require('@rails/webpacker')
const webpack = require('webpack')
throw JSON.stringify(environment, null, 2)
...
You can also debug the config in your browser directly with a newer version of Webpacker:
process.env.NODE_ENV = process.env.NODE_ENV || 'development'
const environment = require('./environment')
...
As a web developer, you know Google Analytics (GA). Probably you've dropped the GA snippet into more than one website, maybe you've even used its Javascript API to implement tracking at the event level.
Google Tag Manager (GTM) is a related tool, but on a higher level and thus with much more power. GTM is not a replacement for GA. Rather, it can make GA configurable without changing anything in the application's code base (and much more beyond, see below).
Only prefer GTM if the customer requests it, or if he is updating his tracking r...
Cookies have an optional secure
flag. It tells the browser to not send the cookie for a non-https request.
It used to be important to activate the secure
flag even on sites that automatically redirect users from http://
to https://
. The reason was that most users will only enter a scheme-less domain like makandra.de
into their location bar, which will default to `http://m...
The linked article lists a number of techniques that were best practices with ES5, but have better alternatives in modern JavaScript.
Best practices don’t last forever. This is especially true when a field is changing fast, and JavaScript development has changed a lot over the past 10 years. The old best practices go stale, and new ones take their place. Here are 5 JavaScript best practices that have gone stale recently.
If possible your code should detect features, not browsers. But sometimes you just need to sniff the browser. And when you do, you're probably fighting a Microsoft product.
The following function returns a Number
like 10, 11, 12, 13 for Internet Explorer or Edge (anything above 11 is Edge). It returns undefined
for any other browser.
function ieVersion(uaString) {
uaString = uaString || navigator.userAgent;
var match = /\...
CoffeeScript and JavaScript (ECMAScript) both have operators in
and of
. Each language use them for more than one purpose. There is not a single case where the same operator can be used for the same purpose in both languages.
var hasFoo = 'foo' of object
var hasFoo = 'foo' in object;
Iterate through all properties of an object
================================...
Using the JS fullscreen API is painful because all browers use different methods and events and you need to use lots of boilerplate code to make your application work in all browsers.
The "screenfull" library wraps that for you, including events.
The linked GitHub repo contains some information. You basically use the library like this:
// Make an element go fullscreen
screenfull.request(element)
// Leave fullscreen
screenfull.exit()
...
When your JavaScript bundle is so massive that you cannot load it all up front, I would recommend to load large libraries from the compilers that need it.
Compilers are also a good place to track whether the library has been loaded before. Note that including same <script>
tag more than once will cause the browser to fetch and execute the script more than once. This can lead to memory leaks or cause duplicate event handlers being registered.
In our work we mostly load all JavaScript up front, since our bundles are small enough. We recent...
You know that you can use jQuery's text()
to get an element's contents without any tags.
If you want to remove only some tags, but keep others, use contents()
and unwrap()
. Here is how.
Consider the following example element.
$container = $('<div><strong>Hello</strong> <em>World</em></div>')
Let's say we want to discard any <em>
tags, but keep their contents.
Simply find
them, then dive into their child nodes via contents
, and use unwrap
replace their ...
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 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:
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
-------------------...
When you need test images, instead of using services like lorempixel or placehold.it you may generate test images yourself.
Here we build a simple SVG image and wrap it into a data:
URI. All browsers support SVG, and you can easily adjust it yourself.
Simply set it as an image's src
attribute.
Simple solution in modern JavaScript, e.g. for use in the client's browser:
function svgUri(text) {
let svg = `
<svg width="320" height="240" xmlns="http://www.w3...
You need to update a lof gems. Make sure you don't have any version constraints in your Gemfile
or your bundle update
won't do anything!
Upgrade cucumber_priority
:
bundle update cucumber_priority
Upgrade spreewald
:
bundle update spreewald
Upgrade cucumber_factory
:
bundle update cucumber_factory
Upgrade parallel_tests
:
bundle update parallel_tests
Even on the latest version, parallel_tests
will print some deprecation warnings due to using an older formatter A...
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. This behavior allows with_scope
to be patient, and it must be patient, as explained below.
In versions 1.10.4 - 1.11.1, inner blocks would keep giving the ou...
Form fields can be rendered as noneditable by setting the disabled
or the readonly
attribute. Be aware of the differences:
button
, fieldset
, input
, select
, textarea
, command
, keygen
, optgroup
, option
Browser specific behavior:
Font Awesome version 5 changed some icon names, and introduces new prefixes fab
, far
, and fas
.
There is a JavaScript shim that you can use as a "quick fix". It allows you to keep v4 icon names on v5.
The linked page includes details on using that, and a migration guide including a list of icon renames.
To check if a method has been called in Jasmine, you first need to spy on it:
let spy = spyOn(window, 'alert')
codeThatAlerts()
expect(window.alert).toHaveBeenCalledWith('Important message')
To expect an object of a given type, pass the constructor function to jasmine.any()
:
expect(spy).toHaveBeenCalledWith(jasmine.any(Object))
expect(spy).toHaveBeenCalledWith(jasmine.any(String))
expect(spy).toHaveBeenCalledWith(jasmine.any(Number))
To expect an object with given key/value properties, use `jasmine.objectContaining(...
If you try to listen to events on elements that are nested inside a <fieldset disabled>
, Firefox will stop event propagation once the event reaches the fieldset. Chrome and IE/Edge will propagate events.
Since we often bind event listeners to document
this can be annoying.
You could solve it by...
<fieldset>
, around your eleme...By default, browsers will not wrap text at syllable boundaries. Text is wrapped at word boundaries only.
This card explains some options to make browsers wrap inside a long word like "Donaudampfschifffahrt"
.
Modern browsers are able to hyphenate natively with the CSS property hyphens
:
hyphens: auto
There is also hyphens: none
(disable hyphenations even at ­
entities) and hyphens: manual
(hyphenation at ­
only).
This feature was integrated [just ...
Checking if a JavaScript value is of a given type can be very confusing:
typeof
and instanceof
which work very differently."foo"
) and sometimes an object (new String("foo")
) and each form requires different checksnull
(null
, undefined
and NaN
) and each has different rules for...If you deliver files from a public folder it might be that the Content-Disposition
header is not set. That's why the following spreewald step might raise an error:
Then I should get a download with filename "..."
expected: /filename="some.pdf"$/
got: nil (using =~) (RSpec::Expectations::ExpectationNotMetError)
One solution...
An end-to-end test (E2E test) is a script that remote-controls a web browser with tools like Selenium WebDriver. This card shows basic techniques for fixing a flaky E2E test suite that sometimes passes and sometimes fails.
Although many examples in this card use Ruby, Cucumber and Selenium, the techniques are applicable to all languages and testing tools.
Your tests probably look like this:
When I click on A
And I click on B
And I click on C
Then I should see effects of C
A test like this works fine...
Slides for Henning's talk on Sep 21st 2017.
print('script start')
html = get('/foo')
print(html)
print('script end')
Script outputs 'script start'
, (long delay), '<html>...</html>'
, 'script end'
.
print('script start')
get('foo', done: function(html) {
print(html)
})
print('script end')
Script outputs 'script start'
, `'...