A collection of graph and diagram tools
- Plot graphs in Ruby
- WebGraphviz renders in your browser via JavaScript (to store the rendered graph, extract the SVG using your browser's DOM inspector)
- GraphViz with DOT: Online http://graphs.grevian.org/graph https://graphviz.christine.website/ or offline https://makandracards.com/makandra/1589-auto-generate-state_machine-graphs-as-png-images
- Balsamiq
- Draw.io
- [Excalidraw](https:...
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.
Features:
- It does not freeze your server like when you're using a debugger. (Compared to the
Then console
step) - It enables interacting with the server. (Compared to taking screenshots in Capybara)
- It is a faster alternat...
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 ...
Copy to clipboard without flash (clipboard.js)
We used zeroclipboard.js
in some of our projects but now we switched to clipboard.js
because it does not rely on flash. Flash support of the major browsers has ended.
Some more advantages of clipboard.js:
- it consists only of a single javascript file, so it does not trigger additional requests with rails
- it automagically provides user feedback by selecting the text it has copied
- it provides callbacks for success and error which make it easier to add custom behaviour after copying to the clipboar...
tesseract.js: Pure Javascript OCR for 62 Languages
This might be relevant for us since we're often managing customer documents in our apps.
I played around with the library and this is what I found:
- A 200 DPI scan of an English letter (500 KB JPEG) was processed in ~6 seconds on my desktop PC. It does the heavy lifting in a Web worker so you're rendering thread isn't blocked.
- It detected maybe 95% of the text flawlessly. It has difficulties with underlined text or tight table borders.
- When you feed ...
Debugging flickering VCR tests
We often use VCR to stub external APIs. Unfortunately VCR can have problems matching requests to recorded cassettes, and these issues are often hard to debug.
VCR's error messages mostly look like this and are not very helpful:
An HTTP request has been made that VCR does not know how to handle:
POST http://another-site.de:9605/json/index
VCR fails if the request does not exactly look like the request it has recorded. If the request is d...
VCR fails if the same request is triggered multiple times
Same requests are recorded only once in vcr. Replaying a test fails, if you trigger the same request multiple times. The error message is somehow confusing, as your cassette contains the request:
An HTTP request has been made that VCR does not know how to handle
If you want to allow to match a request multiple times, you need to configure this explicit with allow_playback_repeats: true. Some exa...
Javascript: Read params from url
There is no build in functionally in jQuery and Prototype to extract params from a url.
-
You can use this library (not tested): jquery-deparam
-
Use Unpoly and the following code snippet
ClockPicker: Android-style time picker for Bootstrap
ClockPicker is a JavaScript and Bootstrap implementation of an Android-style time picker which looks and feels great.
Unfortunately, it is no longer maintained.
An intro to Javascript promises
Promises are the new way™ to express "Do this, and once you're done, do that". In contrast to callbacks, promises are easily chainable. From the readme of Q
, an early implementer of the pattern:
The callback approach is called an “inversion of control”. A function that accepts a callback instead of a return value is saying, “Don’t call me, I’ll call you.”. Promises un-invert the inversion, cleanly separating the input arguments from control flow arguments. This simplifies the use and creation of APIs, p...
How to human-join an array in JavaScript
To simulate Rails' to_sentence
in your JavaScript application, you can use these few lines of CoffeeScript code:
joinSentence = (array) ->
if array.length > 1
array[0..-2].join(', ') + ', and ' + array[-1..]
else
array.join ', '
Examples:
> joinSentence(['cats', 'dogs', 'pandas'])
# => 'cats, dogs, and pandas'
^
> joinSentence(['llamas'])
# => 'llamas'
Here is some plain JavaScript, should you prefer that:
function joinSentence(array) {
if (array.length > 1) {
return ar...
Middleman does not fingerprint asset paths by default
We're using Middleman for some static sites like our blog.
Despite being very similar to Rails, Middleman does not add a fingerprint hash to its asset paths by default. This means that when you write this:
<%= javascript_include_tag 'all.js' %>
... you always get the same path, regardless of the contents of all.js
:
<script src='/javascripts/all.js'>
Because browsers tend to cache assets for a while, this means that users might not get your changes until their cac...
Represent astral Unicode characters in Javascript, HTML or Ruby
Here is a symbol of an eight note: ♪
Its two-byte hex representation is 0x266A.
This card describes how to create a string with this symbol in various languages.
All languages
Since our tool chain (editors, languages, databases, browsers) is UTF-8 aware (or at least doesn't mangle bytes), you can usually get away with just pasting the symbol verbatim:
note = '♪'
This is great for shapes that are easily recognized by your fellow programmers.
It's not...
Using Google Analytics with Unpoly
The default Google Analytics might not work as expected with your Unpoly app. This is because your app only has a single page load when the user begins her session. After that only fragments are updated and the <script>
tag that sends the page view to Google Analytics is probably never evaluated again.
Luckily you can fix this.
Simple mode: You just want to track all the page views
Embed your Google Analytics code as always.
Now add the following code snippet:...
object-fit polyfill by lazysizes
All new browsers support the new object-fit
CSS property. It allows to specify how an element behaves within its parent element and is intended for images and videos. The most useful values are contain
(fit-in) and cover
(crop).
Unfortunately, IE does not support this yet. However, if you're already using lazysizes, you can use its object-fit polyfill!
Usage
In your Javascript manifest, require them like this:
#= require plugins/object-fit/ls.obj...
Tasks, microtasks, queues and schedules - JakeArchibald.com
The way that Javascript schedules timeouts and promise callbacks is more complicated than you think. This can be the reason why callbacks are not executed in the order that they are queued.
Please read this article!
This is an extract of the example in the article which demonstrates the execution order of tasks and microtasks.
console.log('script start');
setTimeout(function() {
console.log('setTimeout');
}, 0);
Promise.resolve().then(function() {
console.log('promise1');
}).then(function() {
console.log('promise2');
})...
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 andhas_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...
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()
.
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;
}
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.
How to: Client-side language detection
When you have a localized website, you may want to redirect users to their preferred language when they visit the root path.
Here is how to do it without a server-side component (like a Rails application).
- Use JavaScript's
navigator.language
(real browsers and IE11+) andnavigator.userLanguage
(old IEs). - Use a
<meta>
refresh as fallback - Provide buttons for paranoid users that disabled JavaScript and meta refreshs.
JavaScript
The following JavaScript will try to auto-detect a user's preferred language.
It understands string...