Currency masking in React

I just open sourced a currency masker for React!

Check it out:

An input that is getting masked (really, re-evaluated) as currency.

An input that is getting masked (really, re-evaluated) as currency.

It takes a normal number input, and converts the last two digits into cents.

Using the mask makes number inputting faster, since a user only has to input digits, not dots too. It works great on mobile, with pattern="\d*", which launches the numeric keypad. Bigger numbers means less typing errors.

I just added it into Farely. The speed and accuracy on a numeric keypad will keep the impatient and the creeps at bay when you're trying to refill your metrocard.

Source code is on Github.

And it's published to npm!

So: npm install react-currency-masked-input!

Making BEM easier in Sass

I came across a great way to start writing BEM in Sass.

Say you have the following markup:

// HTML
<div class="container">
  <div class="container__header">hey</div>
</div>

To make the container full-width and the header text pink (which, duh, why wouldn't you?), you'd probably write:

// CSS
.lookahead {
  height: 100%;
}
.lookahead__cancel {
  color: pink;
}

But you can use Sass's & to shorcut the repeated .lookahead:

// Sass
.lookahead {
  
  height: 100%;
  
  &__cancel {
    color: pink;
  }  
  
}

Which avoids the nasty side effects you normally get with nesting, the typos and the long and ugly selectors (sorry BEM, but you're not easy on the eyes).

Testing input change in React

Today I was adding tests to Farely. I wanted to test that when you input a new value, it updates the state.

According to React's testing documentation, I should be able to trigger a change with:

var newValue = '27';
React.addons.TestUtils.Simulate.change(input.getDOMNode(), {target : {value : newValue}});

(Note: there's really no documentation on the second argument {target: ...}. Grumble.)

Then I could assert:

expect(component.state.inputValue).toEqual(newValue);

But, as my tone might have implied, it's not that straightforward. I finally landed on a relevant Github issue. What you have to do is change the input's value manually, then call `change`:

var newValue = '27';
input.getDOMNode().value = newValue;
React.addons.TestUtils.Simulate.change(input.getDOMNode());

Then you can assert to your heart's content, because the change will take place.

Update: it's been fixed. No more manually setting the value!

Scrolling a page with a background image

I noticed some jank (a.k.a. non-smoothness) while scrolling a page with a background image.

The performance looked like this (green is browser paints) :

At the start of scroll, performance hovered a little too closely to 60 frames per second.

The solution was to change the background-attachment. By setting it to fixed, you don’t allow the background image to scroll with the page. This means the browser doesn’t have to rasterize and paint the image while you’re scrolling.

You’re left with a nice, flat timeline:

tl;dr

[container-with-bg-image] {
  background-attachment: fixed;
}

Testing API calls regardless of domains

To test an API call in Angular (with jasmine), you inject $httpBackend, having it expect a method & URL call, then verify there aren’t any outstanding requests or expectations:

afterEach(function(){
    this.$httpBackend.verifyNoOutstandingExpectation();
    this.$httpBackend.verifyNoOutstandingRequest();
});

it('should GET from the API with parameters', function(){
  $httpBackend.expectGET('yourapi.com/api/parameters')).respond([]);
  TheResource.get();
})

But what if your API switches based on environment? Then your tests might fail when running outside of development.

Luckily, $httpBackend has got your back (I’ll take that pun, thankyouverymuch). You can add regular expressions to the expectGET (and the other METHODS), so your expectation is domain agnostic:

var apiUrl = function(params) {
  return new RegExp('http.*(.com|000)\\/api\\' + params);
};

The regular expression is up to you. I wrote this one quickly to capture localhost:x000 or company.com.

Now my tests run free, and yours will too.

PropertyUnits rule in SCSS Lint

Feeling proud about my latest open source contribution. This time, it’ to SCSS Lint.

I added a rule that enforces the units used on element(s).

From the docs:

PropertyUnits

Configure which units are allowed for property values.

By default a value may have any kind of unit. You can adjust which units are allowed globally by setting the global option. Alternately, you can specify a list of units for a single property by adding it to the properties option, e.g.

PropertyUnits:
global: ['em', 'rem', '%'] # Allow relative units globally
properties:
border: ['px'] # Only pixels
line-height: [] # No units allowed
margin: ['em', 'rem']

With the above configuration, the following issues would be reported:

p {
  border: 1rem solid blue; // rem not in `border` list
  line-height: 55px; // px not in `line-height` list
  padding: 10px; // px not in `global` list
  margin: 10%; // % not in `margin` list
}