Implementing social media "like" buttons: Everything you never wanted to know
So you client has asked you to implement a row of buttons to like the URL on Facebook, Twitter and Google+. Here are some things you should know about this.
0. Security considerations
Each "like" button is implemented by including a Javascript on your site. This means you are running fucking remote code on your page. You are giving Facebook, Twitter and Google+ full permission to e. g. copy user cookies. Check with your client if she is cool with that. Also note that if you're site is suggesting security by operating under HTTPS ...
Enable CSRF protection in Javascript tests
You might not know that Rails disables CSRF protection in tests. This means that if you accidentally forget to send the CSRF token for non-GET requests, your tests will be green even though your application is completely broken (a failed CSRF check usually logs out the user). Rails probably does this because CSRF protection sort of requires Javascript.
You want to enable CSRF protection in Cucumber scenarios that can speak Javascript. To do so, copy the a...
Cucumber: Detect if the current Capybara driver supports Javascript
Copy the attached file to features/support. This gets you a convenience method:
Capybara.javascript_test?
Is true for Selenium, capybara-webkit, Poltergeist and a custom driver called :chrome (which we sometimes like to use for Selenium+Chrome).
Similar sounding but completely different card: Detect if a Javascript is running under Selenium WebDriver (with Rails)
You don't need each, collect or select in Coffeescript
Working with lists in Javascript is painful because the native Array class is so poorly designed.
One way to reduce the pain is to to use Underscore.js's functions like _.each, _.map or _.select, which unfortunately clutters your code with awkward calls to the _ helper.
Fortunately when you use CoffeeScript you don't need any of that. CoffeeScript has a very versatile for keyword that can do anything that each, collect or select can do. Enjoy!
each
f...
Understanding AngularJS service types
Angular comes with different types of services. Each one with its own use cases.
All of these services are singletons. You probably want to use Factory all the time.
Provider
- is the parent of all other services (except
constant) - can be configured using `app.config(function(Provider) { ...})
- a little complex
Factory
- simpler than Provider, but without configuration
- definition: `app.factory('name', someFunction)
-
someFunctionis called when thenameservice is instantiated and should return an object
Se...
Compiling Javascript template functions with the asset pipeline
The asset pipeline (which is actually backed by sprockets) has a nice feature where templates ending in .jst are compiled into Javascript template functions. These templates can be rendered by calling JST['path/to/template'](template: 'variables'):
<!-- templates/hello.jst.ejs -->
<div>Hello, <span><%= name %></span>!</div>
// application.js
//= require templates/hello
$("#hello").html(JST["templates/hello"]({ name: "Sam" }));
Whatever is in the <% ... %> is evaluated in Javascript...
Speed up your websites: Put JavaScripts at bottom
For websites that don't do JavaScript rendering on the client, it's best practice to put script tags at the bottom of the HTML. This way, the page can start to render before scripts have been loaded and run.
The caveat is that you also have to move all other script tags from your views to the bottom of the page. This can be done with helpers.
How to implement
- Add the attached javascript_helper to your app.
- Move your `javascript_i...
Trigger a link's click action with Javascript
Use the click method on the DOM element:
let link = document.querySelector('a')
link.click()
Howto remove the location hash without causing the page to scroll
Set the hash to a dummy hash which doesn't hit any id at your page, for example:
window.location.hash = "_";
Note
- If you'd set the hash to
""it causes the page to scroll to the top because the hash"#"by itself is equivalent to"_top". - If you'd set
window.location.href = "..."to get rid of the "#", you cause the browser to reload the page what is most likely not intended.
Upgrading Rails 2 from 2.3.8 through 2.3.18 to Rails LTS
This card shows how to upgrade a Rails 2 application from Rails 2.3.8 through every single patch level up to 2.3.18, and then, hopefully, Rails LTS.
2.3.8 to 2.3.9
This release has many minor changes and fixes to prepare your application for Rails 3.
Step-by-step upgrade instructions:
- Upgrade
railsgem - Change your
environment.rbso it saysRAILS_GEM_VERSION = '2.3.9' - Change your ...
Coffeescript: Caveat when cloning objects with fat-arrow methods
Coffeescript allows you to create classes whose methods are automatically bound to the correct this. You can do this by using a fat arrow:
class Person
constructor: (name) ->
@name = name
sayHello: =>
alert("Hello, I am #{@name}")
An important caveat is that when you clone such an object, all of its methods are still bound to the original instance:
eve = new Person("Eve")
eve.sayHello() # => "Hello, I am Eve"
bob = _.clone(eve)
bob.name = "Bob"
bob.sayHello() # => "Hello, I am Eve"
I don't thin...
Clean up application servers when deploying
Our development process makes us deploy very often. As the number of releases grows, junk clogs up the hard drive of our application servers:
- Old release code
- Old
tmpfolders with compiled view templates etc. - Precompiled assets (Javascripts, images...) that no longer exist. When using the asset pipeline, Capistrano will symlink the
public/assetsdirectory toshared/assets. This is cool since we can still serve previous assets after a new release, in the window where browser caches might still have references to old assets. But i...
JavaScript: How to generate a regular expression from a string
Getting a regular expression from a string in JavaScript is quite simple:
new RegExp('Hello Universe');
# => /Hello Universe/
You can also use special characters:
new RegExp('^(\\d+) users')
# => /^(\d+) users/
Our expression above now works only at the beginning of the matched string, looks for a number (\d+ [1]) and also captures that. Sweet.
However, mind that your input will not be magically escaped because of that:
new RegExp('makandra.com')
# => /makandra.com/
The above expression would match "`...
AngularJS: Access the scope for a rendered DOM element
This trick might be useful to implement more complicated directives in AngularJS. I needed it to do drag'n'drop in a hierarchical tree.
Let's say you have this $scope in your Angular controller:
$scope.tasks = [
{ 'text': 'Task 1' },
{ 'text': 'Task 2' }
]
And you have this template:
<ul ng-repeat="task in tasks">
<li>
{{task.text}}
</li>
</ul>
Which renders this HTML:
<ul>
<li>Task 1</li>
<li>Task 2</li>
</ul>
If you'd like to access the scope bound to the second <li> you can say this in jQ...
How to not die with ActionView::MissingTemplate when clients request weird formats
When HTTP clients make an request they can define which response formats they can process. They do it by adding a header to the HTTP request like this:
Accept: application/json
This means the client will only understand JSON responses.
When a Rails action is done, it will try to render a template for a format that the client understand. This means when all you are HTML templates, a request that only accepts application/json will raise an error:
An ActionView::MissingTemplate occurred in pages#foo:
Missing templa...
Fixing authentication in legacy applications
Authentication is hard: there are many edge cases, and most users (including yourself) usually only go the "happy path" once and never see the edge cases. If you have rolled your own authentication, or been using older authentication solutions, or resorted to HTTP Basic Authentication, this card will tell you what to do to make your application safe.
Any application that stores sensitive data in the browser
That is: cookies, e.g. by offering a login.
- Ask the admins to [turn on SSL](https://makandracards.com/makandra/1416-integrate-s...
kamens/jQuery-menu-aim
jQuery plugin to fire events when user's cursor aims at particular dropdown menu items. For making responsive mega dropdowns like Amazon's.
parallel_tests: Disable parallel run for tagged scenarios
Note: This technique is confusing and slows down your test suite.
Copy the attached code to features/support. This gets you a new Cucumber tag @no_parallel which ensures that the tagged scenario does not run in parallel with other scenarios that are tagged with @no_parallel. Other scenarios not tagged will @no_parallel can still run in parallel with the tagged test. Please read the previous sentence again.
This can help when multiple test processes that access a single resource that is hard to shar...
What `var` actually does in Javascript
TL;DR: Variables not declared using var are stored outside the current scope, most likely in the global scope (which is window in web-browsers).
Declaring a variable in Javascript is done like var x = 5. This creates a new variable in the current scope (e.g. the function you're in). What happens when don't use var?
Javascript needs to be clever when you do an assignment without declaring a variable, e.g. x = 7. To find that variable,
- it first looks up
xin the current scope - next, it goes up the scope chain, lookin...
Test redirects to an external URL with Cucumber/Capybara
When a controller action redirects to an external URL (like http://somehost.com/some/path) you will find that this is hard to test with Cucumber and Capybara:
- A non-Javascript Rack::Test scenario will just ignore the host and try to open
/some/pathin your local application - A Selenium test will actually follow the redirect, which you probably don't want either
There are two workarounds for this. You can use either, or a combination of both.
- Write a controller spec
Controller specs can test if a resp...
The Plight of Pinocchio: JavaScript's quest to become a real language - opensoul.org
Great presentation about writing Javascript like you write everything else: Well-structured and tested.
JavaScript is no longer a toy language. Many of our applications can’t function without it. If we are going to use JavaScript to do real things, we need to treat it like a real language, adopting the same practices we use with real languages.
This framework agnostic talk takes a serious look at how we develop JavaScript applications. Despite its prototypical nature, good object-oriented programming principles are still relevant. The...
What's in a View? A look at the alternatives
Great look at the tradeoffs between progressive enhancement with jQuery or similiar, vs. client-side views.
Chart.js - a promising JavaScript charting library with MIT-license
Chart.js seems to be a good alternative to Google's Chart API and other commercial chart drawing libraries.
- good looking charts
- canvas based (means less memory consumptive, but no interactivity out of the box)
- highly configurable
- good API and documentation
- just 4.5 kilobytes
- MIT license
- Browser support: all browsers supporting the canvas element (for IE8 and below, use the polyfill as describes in the [chart.js documentation...
JavaScript: Comparing objects or arrays for equality (not reference)
JavaScript has no built-in functions to compare two objects or arrays for equality of their contained values.
If your project uses Lodash or Underscore.js, you can use _.isEqual():
_.isEqual([1, 2], [2, 3]) // => false
_.isEqual([1, 2], [1, 2]) // => true
If your project already uses Unpoly you may also use up.util.isEqual() in the same way:
up.util.isEqual([1, 2], [2, 3]) // => false
up.util.isEqual([1, 2], [1, 2]) // => true
If you are wri...