HTML5, CSS3, jQuery, JSON, Responsive Design...

Basic React Tutorial - Part 2

Michael Brown  April 18 2015 12:05:33 AM
As threatened in my previous post, Basic ReactJS Tutorial, I've now updated my sample ReactJS checkboxes app into "a kind of questions and answers, survey form thing".

This post will take through the steps that I went through to achieve that.  As you read this explanation, I hope it comes across to you just how easy this was for me to do.  Not because I'm any genius coder, or even that much of an expert in ReactJS yet.  It's just the way that ReactJS leads you into developing your app, especially the compositional design that it encourages.  While it would be a stretch to say that the code wrote itself, it did pretty much design itself.  That's to say that before I sat down to type a single line of code, I already knew pretty much how I it was all going to break down.  In ReactThink (and I may just trademark that term) it means that knowing my from the previous exercise, I just needed some higher level ones to put the existing components to work a bit more.


CheckBoxInputFields Component

The highest level React component that I was left with from my previous exercise was CheckBoxInputField.  This component groups together a number of CheckBoxInput components, to give us a "field" of HTML input elements of type "checkbox".  The number of elements in the field is determined by the array of data (or props) that we passed into the CheckboxInputField component.

The next step to turning this single question in to list of questions - i.e. a survey - is to create a new React component called CheckboxInputFields.  The clue to what it does is in the name, or is intended to be so anyway!  CheckboxInputFields is a plural of CheckboxInputField, so guess what it does?  Yep, the CheckboxInputFields component renders a number of CheckboxInputField components.  How many CheckboxInputField components the CheckboxInputFields component renders is determined, once again, by the array props data that is passed into it.

Enough blurb.  Let's look at some code.

Example 1 - React Survey App, state in wrong place



You'll see that my source data is now an array of questions and answers, stored in the global variable, questions.  This data is passed into the CheckboxInputFields component, as props, by another React component called SurveyApp (of which more later).  The CheckboxInputFields component's render method maps through the questions array and creates a new CheckboxInputField component for each member, passing that member down as props to each new CheckboxInputField.  Each CheckboxInputField component so created is pushed onto an array variable called mappedInputFields.  Finally, the mappedInputFields variable, which is now a collection of CheckboxInputField components, is rendered via the return statement.

I've no idea how easy that all looks to you, but I can tell you it took me about two minutes to type it out, and it ran perfectly the first time.   Furthermore, it did so without me having me to change anything in the CheckboxInputField component.  In fact, I'm not sure that I even had to look at the CheckboxInputField component!!!  I knew what that CheckboxInputField component does and what its props were from last time, so no real need to look at it again now.  Cool as!

(Actually, I did modify CheckboxInputField later on, to have it render the question - or the blurb property as I've called it - just before the list of answers.)


That pesky state again

In my earlier post, I said the following:

This is one of React's underlying principles: state should be handled at the highest level possible in your application.  High level state is then passed down to lower level components as props.


Is that how state - i.e. are the checkboxes checked or unchecked? - is being handled in this new version of the app?  Most definitely not!   The state is still being handled down at the CheckboxInputField level.  The CheckboxInputFields component has no easy way of knowing whether any of the CheckboxInputField components that it created have been checked by a user.  Once again, the state is being handled at too low a level.  State needs to be handled at the CheckboxInputFields level.

Or does it?

Thinking ahead, what if we want our app to display a collection of CheckboxInputFields components?  In other words, we want a survey to consist of a collection of different groups of questions, each grouped by a theme or topic?  In that case, our state would again be at too low a level if it were handled in the CheckboxInputFields component.  We've have to refactor yet again to move the state to our new, higher level.  So let's skip that mistake and do it right first time, this time.


If you want something done, then go to the top!

I only have one CheckboxInputFields element in my Example 1 version above, but I never intended to handle state within it.  Instead, I've created a higher level React component, which is the SurveyApp component.  In Example 1, all it does is render my one CheckboxInputFields element with the necessary props, and nothing more.  But it was my intention from the beginning to handle my state in this top most element, so let's do that now.



Example 2 - React Survey App, state in correct place




In Example 2, state is handled in the SurveyApp component.  The state data is updated and setState() call is made within that component.  A setState call causes the SurveyApp to re-render, which causes the whole app to re-render, like so:

SurveyApp -> CheckboxInputFields -> CheckboxInputField -> CheckboxInput

With each CheckboxInputFields owning multiple CheckboxInputField components, and each CheckboxInputField owning multiple CheckboxInput components, the diagram of re-renders would actually look like a pyramid.  I just couldn't be arsed to draw one.

And if you're thinking "re-rendering the whole app = performance nightmare", remember that React's virtual DOM and super fast diffing engine mean that this isn't the case.


Passing the buck upwards again

In order to have the SurveyApp component handle the state, I did have to rewrite the lower level components to ensure that the when events are triggered down there (i.e the user checks or unchecks a checkbox) the relevant information from that event reaches up to SurveyApp level.

CheckboxInput required no changes because it was already passing its state changes upwards (to CheckboxInputField).

CheckboxInputField gets the biggest rewrite because this is where we were handling state previously.  So, its getInitialState() method is removed.  Instead of looping through the (now non-existent) state array, its render() method now maps through an array of passed in props.  CheckboxInputField's handleFieldChange() method, which was resetting the state earlier, now simply passes the relevant data, with a little preprocessing, back up to CheckboxInputFields via the supplied (via props) callback function, i.e. this.props.handleChange().

CheckboxInputFields does even less with that data!   There's no equivalent handleChange() or handleFieldChange() method in CheckboxInputFields.  The callback function that was passed down from CheckboxInputFields to CheckboxInputField is actually one that was originally passed from from SurveyApp to CheckboxInputFields.  So when the new event data is heading back upwards, the CheckboxInputFields component simply hands it on up to SurveyApp.  Think if of it as like how a passthrough server works.

Finally, the new event data gets all the way up to SurveyApp's handleFieldChange() method, where the state is reset.  The method uses two passed up indexes, the index of the question where an element has been (un)checked and the index of element (i.e. which answer) within that question, to determine which data point to change.  The change is to add a .checked property if the underlying checkbox field has been ticked, and to delete that property if the field has been unticked.   Once the relevant data point is modified, we call a setState(), so re-rendering our whole app, and our work here is done.



















Netflix and Chromecast

Michael Brown  April 13 2015 04:36:22 AM
Netflix
I signed up to the Aussie Netflix a couple of weeks ago.

To be honest, I’d expected to be completely under whelmed by the content available, especially knowing what was available in the U.S. Netflix store.  But while it’s still only a fraction of what our American cousins get, there’s still a lot of good stuff in there.

For example, we’ve just finished the second series of The Fall, and I’ve started again on Lost.  I was disappointed that there was no Breaking Bad, like the Americans have, but then I made an interesting discovery almost by accident.  It seems that Netflix serves up its content based upon where you are geographically located, rather than upon where you registered your Netflix account.

Let that sink in a minute...

If you take a trip to the U.S., and you have your Aussie iPad, with your Aussie dowloaded copy of the iOS Netflix app, which has your Aussie registered user name and password in it, then you’ll see U.S. Netflix content, not Australian.

Now if only there was some way to make your PC, tablet or phone think that you’re in the U.S. without you actually having to fly there….


Chromecast

I started off playing Netflix though my Home Theatre PC (HTPC).  This is a bit of beast that I put together about in 2010, principally in order to record that year’s Football World Cup.  (Our Foxtel box at the time was unable to record terrestrial stations, due to limitations of the wall wiring at the unit where we were then living.)

The HTPC has done its job... just about.  It’s been a nightmare to setup and keep going, which I put down to one thing: Microsoft Windows.  Windows 7’s Media Centre works well enough when it works at all, but there’s been far too many times when it just doesn't.  I’d try and watch something that I thought I’d recorded, only to be greeted by a blue screen, or a boot error or an update error - i.e., all things that we know and love (not much) about the world’s most “popular” operating system.

Trying to control Netflix through the HTPC is fiddly at best.  Apparently, there’s a Media Centre plugin for Netflix, which I’ve not tried.  I’ve been using it through a web browser, which is less than ideal on a TV screen.  Plus the HTPC is too big to go in our new entertainment cabinet, so its days are numbered anyway!

Which led me to get a Chromecast.  They’re currently $43 at Harvey Norman, but sadly the one in the CBD, at Martin Place, appears to closed down now.  I managed to get one a Dick Smith for $46 though.

So far, my experience has been overwhelmingly positive, although with major one downer that I’ll to later.

Setup
First, it’s a breeze to set up.  You plug it into a spare HDMI socket on your TV or preferably, your surround sound receiver if you have one (more on that later).  You’ll need to power it up via a USB charger via a supplied micro-USB cable.   I was able to plug the USB into my TV’s USB socket for power, and the supplied cable was still long enough to stretch to my receiver.  If you don’t have that option, there’s a wall-mounted USB charger supplied in the Chromecast box too.

Once plugged in, and with your TV set to the appropriate HDMI input, you setup your Chromecast via a PC, Mac, tablet or phone (Android or iOS).  You’ll need to download an app for whichever platform you’re using.  When you run that app (and I used the Mac version) it locates your Chromecast automatically.  I’m not sure how it manages this little trick, because you’re Chromecast isn’t on your network yet!!!   In fact, that’s the first thing your Chromecast setup app will ask you to do once it’s found your Chromecast: fill in your wifi user name and password to get your Chromecast on your network.

Remote Control (lack thereof!)
That’s about it for the setup.   So, how do you play stuff on it?  There’s no remote supplied for your Chromecast.  You’ll have to use your own device - PC, Mac, tablet or Phone - as the remote.  Don’t worry, that’s not as bad as it sounds!

I’ll explain how to do it for Netflix.  First, you need to download the Netflix app if you’re using a tablet or a phone.  If you’re using a PC or Mac then you need to download an extension for the Chrome browser (and only the Chrome browser will work) before navigating to the netflix.com site.

Find the program you want to play and start playing it whatever device you’re using, then click on the Chromecast icon.

The program you started playing should then start showing on your TV screen rather than your controlling device.  You can pause, rewind fast forward your program on your device and that will control what happens on your TV screen through your Chromecast.

Chromecast's Internet Connection

At this point you might be thinking, as I did, about what happens if you were to switch your controlling device off.  I was using my iPhone for this, and the iPhone had some updates that it needed, one of which required a reboot.  I let this process go though, fully expecting the Chromecast program that was currently playing to stop at that point.  But it didn’t.  It just kept on playing.  “The Chromecast must have cached some content”, I thought.  But 20 minutes later, and with no further communication to it from my iPhone, the Chromecast was still playing the Netflix content!!!

It seems that the Chromecast has more to it than I originally thought.  Although it’s touted as a device that lets you “cast” content from your device to your TV, there’s more to it than that, at least for Netflix and other Chromecast-enabled services.  When you start playing Netflix content from your phone to your Chromecast, the latter actually makes its own direct connection to the internet to do the streaming.  The content doesn’t go through your phone.

All of which is great, because you’re then free to do whatever with your phone or tablet, without worrying that it’s going to break off your Chomecast/TV content!  You only need to return to the Netflix app on your phone when you want control it further - e.g pause it.  Be warned though, when you do return to Netflix on your phone, there is often a very long delay while it syncs to where your Chromecast has actually got to with your program.  You’ll see the progress bar for your program on the phone leap across to the new location when that sync has happened.  After that, you can pause rewind etc.

Which brings me to the one major downer.  Because the Chromecast makes its own connections to the internet for the like of Netflix, it does not work with VPNs.  If your VPN on your iPad, for example, is set to the U.S., and you try to play an episode of Breaking Bad, well sorry, that’s not going to work.  The Chromecast isn’t getting its content through your iPad's VPN, so it’s not going to able to see that U.S. content.  You may able to do something by changing your router’s DNS settings, but I’ve not tried that yet.


Surround Sound

Does the Chromecast do surround sound?  Does it ever!!  Not Dolby Digital, but its HD big brother, Dolby Digital Plus!

Here's what I see on my Denon receiver panel when I'm watching Lost through the Chromecast:

Dolby Digital Plus from the Chromecast


There's just something so sweet when that blue HD diode lights up!!

I didn't have a spare HDMI input on my receiver, unfortunately.  I had to unplug the HTPC for the time being.  I managed to pick up a remote HDMI switcher from Jaycar, which gives me another two inputs.  I can even control that as part of an Activity on my Harmony One universal remote, so I don't have to keep switching it manually.


















Basic ReactJS Tutorial

Michael Brown  April 3 2015 10:15:00 PM
Of JavaScript Frameworks
To say that JavaScript Frameworks have been in a state of flux in the last few years would be a truism.  Every developer seemed to zero in on jQuery and/or Bootstrap, and those two have proved to be stickers.  But then followed Backbone, Backbone+Marionette, Amber/Ember and Angular, each one the flavour of the month in a dizzying succession.  I often felt that I was spending more time attempting to learn the strengths and weaknesses of each JavaScript framework than I ever did actually writing any code in them!!

I still have a soft spot for Backbone.js, which was the first JavaScript framework at which I looked. If it doesn't do all that much for you as a developer, it's still a great way of organising your code, and its models rock! I like the way you can use as much of Backbone or as little of it as you wish, making it easy enough to add to an existing project, not just new ones. Too many of the other frameworks which I looked seem to take a "my way or the highway” approach, requiring you to rewrite everything from scratch.  You had to follow that framework's own ideology (for want of a better word) and forcing you to subscribe to its own idiosyncrasies.  Anything that you wanted to do that wasn't of its particular box seemed to be a massive pain.

Also, many of those other frameworks did not actually make much sense to me.  I tried my hardest with Ember.js and especially with Angular.js, but could not wrap my head around either of them.

Angular’s “directives embedded in HTML” approach, in particular, put me off in a big way. It just didn't look right to me, and still doesn’t.  And from what I've read in various forums, the two way data binding that is one if Angular's big selling points seems to cause as many problems as it solves, especially when applications scale to larger sizes.

Angular sure has a lot of developers using it.  How many of them still like it now is another question.  Backwards compatibility does not seem to be one of its core strengths.  I’ve seen the up-and-coming Angular.js 2.0 described as a "course change", a description that should send a shudder through any developer that's relying on it. How many of those developers are going to take kindly to rewriting their entire code base from scratch, I wonder? I think many of them may just look elsewhere instead.

In fact, I believe the Angular.js is heading for a demise that’s going to be even more rapid that was its original rise. Maybe I'm being too hard on it; and I’m not an Angular guy, after all.   Angular people can make their feelings known in the comment section of this post if they feel inclined!


Enter ReactJS

For my money, Facebook's ReactJS JavaScript library is set to dominate the Web programing world over the next year.  Even if it doesn't get as many developers as Angular or Ember, the latter two libraries are rapidly assimilating many of React's best ideas, so React will win out one way or another.

React's best features:
  1. Encourages component-based design based on composition.  Practically mandates it, in fact!
  2. Implements a one-way, top-down data flow.
  3. Has a super fast diffing engine that minimises updates to the DOM (always a performance pain).


The Tutorial

I'll attempt to demonstrate these features by a way of a small tutorial.  In this tutorial, I'll be setting up a simple, checkbox Input field.  (I said it was simple!)  But I'll set it up as a React component, to which you pass in parameters (called "props") and manage the state of that field (called, ermmm.. "state" in React!).

By "field", I mean a collection of Input fields of course, because that's how checkbox and radio fields are defined in HTML: as a collection of Input fields, grouped by their Name tag.


Let's start with an individual checkbox box element, as you might set it up in React

Example 1 - Single, Uncontrolled Checkbox Element



We start with CheckboxInput, an instance of the React class.  The class implements a single method, called "render".  This method must be supplied for every React component (the only method to be so mandated).  As you've probably guessed, the render() method tells the React component what to render as its final output.

But what's that stuff inside the render() method's return brackets?  Raw HTML?  What's that doing there?  That stuff's not legal there, surely?!!

JSX

What's actually in between the render() method's return brackets is something called JSX.  As described by Facebook, "JavaScript syntax extension that looks similar to XML".  I actually don't think it looks anything like XML, which is a good thing in my book, as I happen to loathe XML.  (Wake up!!  Use effing JSON!!!)  But I digress...

Think of JSX as a way of letting you embed raw(ish) HTML directly in your JavaScript.  It's a convenient alternative to creating a JavaScript string out of HTML to return as your output.  Does this kind of code look familiar to you?

var returnHTML = '<label><input type="checkbox" name="' + varName + '" value="' + varValue + '" \/>' + varLabel + '<\/label>'

Did I get all the double and single quotes in the right order there?  Because just one of those babies out of place and I'm stuffed, right?  Oh and you did know that every forward slash that appears in a JavaScript string has to be escaped with with backwards slash, yes?

Look at that code, and compare it again to the JSX in my first JSFiddle above it.  Which one makes it easier to understand what's going on, would you say?

JSX has other benefits too, which I'll come to later.  But for now, you should be aware that there's a cost to using JSX.  Obviously, the browser won't understand it because it's not standard JavaScript.  So, you must add a translator (or "transpiler") file called JSXTransformer.js to your project.  This file transpiles JSX to standard JavaScript on the fly, so the browser can understand it.  Yes, there's a pre-processor available so you don't have to include JSXTransformer.js in your production code.  But for development, and this tutorial, JSXTransformer is fine.

Back to Example 1 in the JSFiddle above.  After creating my CheckboxInput component, I set up some data to pass to it (the question variable), before finally calling the React.render() method to render the component.  The React.render() method takes two parameters.

The first parameter is the name of the component to render, written like an HTML tag.  Within that tag, you can pass down any number of parameters to the React component.  In React parlance, parameters passed down from to an "owned" component like this are called "props", which is short for "properties".  Note that props are said to be immutable.  They are not to be changed by the lower level component once passed down from above.  More on this later.

The second parameter the React.render() method takes is a JavaScript representation of the HTML element upon which the component is to be rendered.  (If you don't supply the second parameter, then the component will render on the page's Body tag.)

Phew!  That was a lot to go through just to get a single, input checkbox element on the page!  And one that's really doesn't do much for us either.  By which I mean, you could have done just as easily, probably more so, if you'd just used a bit of jQuery and HTML.

In particular, there's no state being monitored here.  By which I mean, if you wanted to find out whether the element was checked or not, where would you look?  There's nowhere our React code that tells you.  At the moment, you'd have to query the DOM directly to find that out, using a bit of JavaScript, and that's a big no-no.

So let's start getting React to do some more work for us.


Controlled Vs Uncontrolled

In my first example, I called my checkbox element "uncontrolled" in the title.  What does this mean?  It means what I was referring to in the previous paragraphs: i.e. that React isn't doing anything with the checkbox element in the CheckboxInput component, other than its initial render.  After that we're on our own.

With a "controlled" element, its parent React component takes care of its state and all of its updates, not just its initial render() as we had it in our first example.  See the React doco on Forms for more info on this subject.

In Example 2 below, we'll take the first steps to making our checkbox element a controlled one.

Example 2 - Single, controlled Checkbox Element, No State Update



In example 2, we've made two additions.  First, we've set up an initial state for the component, via a getInitialState() method call.  This another special React method, like the render() method.  This method must return an object that is to be the initial state of the component.  Very often, the initial state is taken, in part at least, from the props that were passed down to the component.  That's what we have done here, taking the checked parameter from props and creating a checked state from it.  (Remember, the props themselves are immutable; they should not be changed within the component that received them.)

The second addition is that we are now setting the input's checked state from the React component's checked state.  This is the line checked={this.state.checked} within our Input JSX does.

There's a step that I've deliberately left out of Example 2, however.  Before I add that step (in Example 3) I want you see what is the result of omitting that step.  Switch to the Results tab for Example 2, and then click on the "Apples" checkbox a few times.  Did you see what happened?  Absolutely nothing!

And that's as it should be.  Because we're now having the React component set the input element's "checked" state from the React component's own state, i.e. this.checked.state.  And the latter is always set to false in our code as it stands now.

Let's fix that now in Example 3.

Example 3 - Single, controlled Checkbox Element, With State Update



Two more additions here.  The first the onClick={this.handleClick} click handler line that we've added to the Input JSX.  What's that?  A click handler set up as an HTML event attribute?  Aren't we supposed to all be using JavaScript events now?   Don't worry; we are!   What you see here isn't actually an HTML event attribute.  It just looks like one for familiarity's sake.  (An actual click handler event attribute would be in all lower case: "onclick", not "onClick"!)  Once it's been through the JSXTransformer transpiler, it will be a JavaScript event.  In fact, it will become part of one big, delegated JavaScript event, along with any other "event attributes" that you might have set up in JSX.  All this you get for free, and you don't even have to think about it!

The second addition is a method that will be called by our new click handler.  I've called this method handleClick() (although we could have called it anything).  Let's take a closer look at what's going on in that method:
handleClick: function(e) {
this.setState({checked: e.target.checked});
}

The setState() method is another built-in method for a React component.  It set's the components internal state for the parameters and value supplied.  In this case, we set the React component's internal checked state to match whatever the input element's state has been set to (by the user clicking on it!) which is what we want.  (FYI, the e parameter that we've passed into the handleClick() method is an event, or to be more precise, a "synthetic event"; one which has all browser inconsistencies smoothed out.)

But the setState() method does more.  Any call to the setState() method causes the component to re-render.  Let's say that again, because it's important.  Any time you make a call the setState() method, your whole, stinking component is going to re-render onto your page.   Wow!  How crazy is that!!  I mean the performance problems alone make the dumbest thing that you could possibly do, right?

Actually, wrong.  React's superfast diffing engine, with its "shadow DOM" or "virtual DOM" feature takes care of that.  Only the parts of the DOM that really need to change are actually re-rendered to the real DOM.  And any such renders are automatically batched up, so your performance won't take a nosedive into the compost.  (This is one of those features I mentioned that the likes of Angular and Ember are now planning to add to their own frameworks.)

Here's the proof that our checkbox input is now controlled.   Switch to the Results tab for Example 3, and then click on the "Apples" checkbox a few times again.  The checkbox should now update correctly.  More importantly, the element's current DOM state is now in sync with the React component's internal checked state.  You can check this in your favourite JavaScript debugger.  Here's how it looks in the Chrome debugger, and you can see how the DOM state of the checkbox input matches that of the React component's this.state.checked.

this.state.checked in the Chrome Debugger



From Element To A Field

A single, checkbox element can be useful - think of a "Please accept these terms before proceeding" tickbox, for example.  More often that not though, you'll be wanting to present users with a range of checkbox options from which to choose.  I'll refer to such a collection of checkboxes as a "field" from this point on.  As I said earlier, a "field" in this tutorial is a collection of checkbox inputs, grouped on their name tags.

Example 4 shows how I've created such a new field-based React element, which I've called CheckboxInputField.

Example 4 - Controlled Checkbox FIeld, Poor State Implementation



If you read through the code of the new CheckboxInputField component's render() method, you can see the basic approach.  We loop through a supplied array of checkbox options (courtesy of a rewritten question variable) and return an array of CheckboxInput components.  This simple composition technique is, as I said in my introduction, one of React's key strengths.  We already have a tried and tested component, in the CheckboxInput component.  See how easy JSX makes it to compose a number of those components, before passing them to CheckboxInputField's own render() method, as the mappedInputElements array variable.

I've also included an attempt at state management in Example 4, in the form of the getRefsState() method.  The approach that I've used is a deliberately poor one, which I came up with before I'd really got my head around the way ReactJS works and what its intentions are.  (Example 5 below shows a better way to do this.)  This method works by querying each of the "owned" CheckboxInput components, in turn, to find out what each one's state is.  The see how the CheckboxInputField component is tied to its "owned" CheckboxInput components via the this.refs property.  This a pre-built React property.  In order to make use of it, you need to supply a ref value to each new, "owned" component as you are creating it, which I've done in "ref={data.value}" line in CheckboxInputField's render() method.

Although this method of state management will work, it has a major flaw: the state is in the wrong place!   If you want to know the state of CheckboxInputField component, then the state should really be held within that component.  And not in the half-assed way that I've done it, where the CheckboxInputField has to query each of its "owned" CheckboxInput components in order to determine its own state.  In truth, the individual CheckboxInput components don't even need to know what their own states are.  Their individual states only have validity insofar as they are part of the CheckboxInputField component that owns them.

This is one of React's underlying principles: state should be handled at the highest level possible in your application.  High level state is then passed down to lower level components as props.

So, let's put the state in the CheckboxInputField component in Example 5.


Example 5 - Controlled Checkbox FIeld, Better State Implementation



First, let's look at the change to the CheckboxInput component.  We still have a handleChange() method, but it doesn't do anything with the CheckboxInput component itself; certainly not setting state in there, because state is no longer handled at that level.  (And for that reason, we can also lose the CheckboxInput component's getInitialState() method.)  All the handleChange() method does now is pass some values up to it's owner CheckboxInputField component.  It does this by calling the latter's handleFieldChange() method, which was passed down as a callback funciton in the CheckboxInput component's props.  This is the line "handleChange={that.handleFieldChange}" in the CheckboxInputField's render() method.

The CheckboxInputField component now gets a getInitialState() method, because that's where we're holding the state now, remember.  At this level, of course, we need to hold the state as an array, which I've called values.

The CheckboxInputField component's handleFieldChange() method is, as I said earlier, called as a callback function from within each owned CheckboxInput component, when its element is clicked by the user.  Again, the state that we're dealing with at this level is an array, so we have to take care to update the correct member of that array!  The index parameter passed up from the call from within CheckboxInput call takes care of this.  This index was, in turn, passed down from CheckboxInputField to CheckboxInput as another prop, in the line "index={x}".

Gravy!  Now we have what we wanted: state is handled at the CheckboxInputField level, giving us one place to look for the state of our field:

State handled at the CheckboxInputField level

Beware that when passing objects (and arrays are objects in JavaScript), as function parameters, they are passed by reference.  So if you're updating such objects within your function, you do need to make a copy of them first (I've used a .slice() call here to do that) otherwise you'll find yourself inadvertently updating the original object too.  This can have serious repercussions for a ReactJS setState() call, for example.


Future Enhancements

One checkbox field like this is just dandy, but what if we wanted a group of such fields?  You know, as a kind of questions and answers, survey form thing?

Well, thinking in the React way, we could create a new component called CheckboxInputFieldGroup.  This could take an array of questions and answers as its data props, and in turn, could pass that data down to an array of CheckboxInputField components that it would create.  It's that design by composition again!

There's a problem though: where would the state for a CheckboxInputFieldGroup component live?  At the moment, our state is in the CheckboxInputField components.  Damn!  Now it's a too low a level again?  "Will that boy never learn?"

Yes, we would have to refactor things to move the state higher up again.  Ideally, to higher level than even the CheckboxInputFieldGroup, to save us refactoring a third time, when we decide that level isn't high enough either!  Really, you need to be thinking at holding state at the top application level, where you deem that level to be.  The React Facebook people have an entire design approach, called Flux, to help you with that.  Flux is beyond the scope of this tutorial, however, and to be honest, I've lot looked to deeply into it myself, as yet.

Chromebook auto-update - stop, already!!!

Michael Brown  April 3 2015 09:04:43 PM
Of Chromebooks
I sure do love my Chromebook!  (I got the 2013 Samsung, ARM-based model.)

If you can live within its limitations, it’s a more than serviceable companion on the road.  I mean, a 9 hour battery life, and pretty much guaranteed to be virus-free, all for under $300?  (Yes, I know that they’re nearer $200 in the U.S. but I don’t happen to live there.  I have to pay the inflated, “Australia Tax” prices.)

About those limitations:
  • It doesn’t run Windows or any of its applications.  Everybody will have their own opinion as to whether this counts as a limitation or as a blessing in disguise!!!

  • Severely limited printing abilities.  That’s “limited” as in non-existent, unless you happen to have one of the small list of printers with which Google’s Cloud Print service is compatible.

  • A small (but growing!) number of Chrome apps that will work offline.  This is not the problem that it was a year or two back.  Gmail, Google Calendar and all of the Google Drive apps now work offline.  You just need to remember to offline enable them, and you will need an internet connection to do that.  For all the detractors that are still holding this problem against Chrombooks, I would say try giving the average user a Windows laptop with no internet connection, and let’s see how productive they are with that!!

You can work around many of these limitations by installing a full Linux version alongside ChromeOS.  Sure, this is cheating in a way, but no more cheating than I have with any Windoze PC that I’ve owned in last eight years.  Google “chrome linux crouton” for instructions on how to do this.  Note: requires Developer Mode (of which more in a moment).

Auto-update Woes

One undoubted problem that I’ve been facing with my Chromebook, however, is its auto-update feature.  Normally, I’d tout this feature as a good thing.  The OS keeps itself automatically up to date over the internet.  No need to bother with the nightmare that they call Windows Update.

But damn Google for not giving users any easy way to control when and where this auto-update happens.  According to Google, ChromeOS is clever enough to sense when your Chromebook is tethered to your mobile phone, and it won’t auto-update in that situation.

Sadly, that’s not my experience!  Just yesterday, my Chromebook chewed through over a 100 Meg of my phone’s 4G data in a matter of seconds, before I could stop it.  On another occasion, it went through 400 Meg in about a minute.  (Really, until that time I had no idea that my 4G connection could actually go that fast!)

How To Fix

Anyway, I’ve finally found a way to stop this nonsense, but it’s not a particularly easy way, I’m afraid.  You need to have your Chromebook’s Developer Mode enabled.  (That’s Developer Mode; not to be confused with the Developer Channel, which is something else.)  Setting up Developer Mode on your Chromebook (Google for instructions on how to do it) will power wash (i.e. wipe and resinstall) your Chromebook, so make sure any local data is backed up first.

Assuming that you’re in Developer Mode, here's how to stop the OS from auto updating itself:
  1. Hit Ctrl->Alt->t on your keyboard, to launch a Crosh shell window

  2. Within that window, type “shell” (without the quotes)

  3. Now type ”sudo initctl stop update-engine” (again, without the quotes)

Your Chromebook's auto-update engine should now be switched off.

You’ll need to do this before you tether your Chromebook to your phone, obviously!

Be warned that this setting is not "sticky".  The next time you reboot your Chromebook, the auto update engine will be turned back on again.

Many thanks to "will" for this tip.





React Bootstrap Slider component

Michael Brown  March 1 2015 10:29:07 PM
I've just written a ReactJS, wrapper for the HTML5 input type=”range” slider component, but using [seiyria’s Bootstrap Slider component] (https://github.com/seiyria/bootstrap-slider) as a polyfill where the HTML5 version is not available (IE 9) or otherwise suffers from a problematic implementation (any other version of IE).

The code and full documentation is available on Github.  There's a demo available too.

Overview

I like the HTML5 native range control, especially how easy it is manipulate via ReactJS, my current favourite JavaScript library.  (I'll be writing a lot more about React in future.)  You set up an HTML5 range control like so:

<input type="range" value="20" min="0" max="100" step="10">


This will give a slider control, ranging from 0 to 100 in steps of 10, with a starting value of 20.  Nice and easy!

Here’s how the native JavaScript control is rendered in my ReactJS plug-in:
render: function () {
   return (
        <input id="mySlider"
           type="range"
           value={this.props.value}
           min={this.props.min}
           max={this.props.max}
           onInput={this.props.handleChange}
           step={this.props.step} />
       );
}


It’s about as simple a rendering as you could want in React. You’d pass some props into your component, and render them as the corresponding attributes on the input field. Sweet as!
But knock me down with a feather if there aren’t problems with IE.


Internet Explorer Problems

The first problem is that input type="range" element simply isn't supported on IE 9 and below. It will actually display as a type=”text” element, so instead of slider, you’ll get a text box with a number in it.  This is what prompted me to create a React control that would fall back to the Bootstrap Slider for browsers that didn’t support the native HTML5 element.

The second problem is that IE10 and 11, where the control does display, doesn't respond correctly to right events when you need to track the slider value being changed.  I go into more detail on that on my Github page.  I probably could have worked around that one, but ran into my third and final problem with IE.

The third problem in IE is that the HTML5 range control looks like crap!  It’s not just ugly, IMHO. It’s inpractical too.  Its handler (the bit on the control that you actually slide) is the same height as the rest of the slider, making it to pick out with your eye, not to mention with your finger if you’re on a tablet. (Thankfully, the latter would only ever be an issue on Microsoft tablets, of which there's next to zero in the real world).

In the end, I made an executive decision in my React Bootstrap Slider component: I don’t display the native HTML5 slider control on IE. At least not for IE 10 or IE 11.  Maybe it looks better in the new, webkit powered IE 12?  I haven't test this myself.

How to use
You can follow the example code in the app.jsx file on the Github page to see how to use.  The component is called SliderNativeBootstrap. Here’s an example of how you might call it in your ReactJS’s render method:

<SliderNativeBootstrap
         value={this.state.currentValue}
         handleChange={this.changeValue}
         step={this.state.step}
         max={this.state.max}
         min={this.state.min} />
.

The value, step, max and min parameters should be self-explanatory. handleChange is the callback method that will be called when the slider actually changes. (NB: this is the onInput event for the native HTML5 control, and the “change” event for the Bootstrap slider.)

Forcing the Bootstrap version all the time
An optional parameter is polyfill. When set to true (the default if you leave the parameter out) the component acts as I’ve described it above, i.e. displaying the HTML5 native slider for these browsers that support it properly, and the Bootstrap version for those that don’t. If you want to force the use of the Bootstrap slider for all browsers then you should set this parameter to false, like so:

<SliderNativeBootstrap
       polyfill={false}
       value={this.state.currentValue}
       handleChange={this.changeValue}
       step={this.state.step}
       max={this.state.max}
       min={this.state.min} />

Demo
Is here.
On load, the slider range is 1,000 to 20,000 with a step of 1,000.
Click on the Change axes! button, and the slider range changes from 0 to 2,000 with a step of 100


Update 11/03/2015

Now available on React Components.

Delegate your JavaScript events!

Michael Brown  February 20 2015 04:16:59 AM
I looked at a web project today where Allan Jardine's Visual Event plug-in reported nearly 20,000 event handlers on a single page app!

The app was generating a huge table of information, and every row in that table needed something to happen when the user double-clicked on that row.  So to achieve this, the developer had a added a separate event to each row of the table.  "The fool", I thought!  Doesn't the guy know about event delegation?

Well, I was wrong.  The developer did know about event delegation, and had added his events that way.  There was only one event on that table, not 20,000.  But the Visual Event plug-in is incapable of distinguishing between delegated events and individual events when doing its count.  The developer is aware of the problem.

So what's the difference between delegated events and individual events, and why should you be using the former in preference to the latter?


Individual Events

Here's a sample table with about 1000 rows in it:
http://www.users.on.net/~mikeandgeminoz/event.test/non-delegated.html

Each row will pop-up a alert box when you click on that row.  To achieve this, I added events to each individual row in the table using jQuery, like so:
$('#myTable tbody tr').click(function () {
alert("hey " + $(this).attr("data-payload"));
});



Firefox's HTML Inspector tool (note: the built-in one, and not Firebug) shows you this:

Image:Delegate your JavaScript events!

See how each row in the table is marked with a separate "ev" tag?  That's because each row in the table has its own associated event tag.   This is bad.  Each event handler takes up browser resources.  Too many event handlers on your page and your app will slowly grind to a halt.

So, wouldn't it be good if we could achieve the same result, but with only a single event handing all of our tables?  Yes, it would - is, in fact!  This is what event delegation gives us.


Delegated Events

Here's that same 1000 row table again, but this time it's using a delegated event:
http://www.users.on.net/~mikeandgeminoz/event.test/delegated.html

Here's how to add a single event handler for the table's rows, using event delegation:
// For jQuery before version 1.7
$('#myTable tbody').delegate('tr', 'click', function () {
alert("hey " + $(this).attr("data-payload"));
});

// For jQuery 1.7 and higher, where the .delegate() method is deprecated.
$('#myTable tbody').on('click', 'tr', function () {
   alert("hey " + $(this).attr("data-payload"));
});



Note that we're telling the select handler here to target the table's tbody, instead of targeting all of its tr rows, as we did in the first example.  This will give us a single click event, on the table's tbody.  The .on() call or the (now deprecated) delegate() call denotes which elements within that tbody we're actually interested in, which is all of its tr rows.  NB: the syntax of the .on() call is important here: it must contain our target element, "tr" in this case, as its second parameter, otherwise it won't delegate the event handler.

The Firefox HTML Inspector confirms that we have only a single event now:

Image:Delegate your JavaScript events!

What we end up with is a single event handler, at the tbody level, which is still able to ascertain which TR row within the tbody you the user actually clicked on.  Bingo!


Update 21/02/2015

Incorporated Mark Roden's comments below, to say that the .delegate() is now deprecated and that we should now be using the .on() method instead.

    How I predicted Tony Abbott’s demise a year ago!

    Michael Brown  February 7 2015 11:55:56 PM
    Why do people always say "I hate say 'I told you so'" when they actually love to say exactly that!  Well, I know I do anyway.

    So back in April 2014, I wrote the comment below on a post on Renai LeMay's Delimiter site.  Sadly, the site is no longer active, but the post and my comment are still there as read only.  In that comment, I predicted that sooner or later, our much maligned (and deservedly so) Prime Minister, Tony Abbott, would be kicked out of his job, to be replaced by the man that he originally knifed, Malcolm Turnbull.

    And blow me down if it isn't all happening exactly as I predicted!  (Okay, not quite how I predicted it: Joe Hockey's well out of the equation now.)  But the Libs' poll numbers are now "through the floor".  And as I write this, we are four days away from a Liberal Party leadership spill that could well see the back of Abbott.

    Here's what I wrote:

    "The real problem is that poor Malc doesn’t want to be doing this job at all. He wants to be Prime Minister. Thinks he *should* be Prime Minister, in fact.

    And in any fair world, he would be. Sadly though, while Leader of the Opposition, he supported Kevin Rudd’s Carbon Emissions Scheme, which marked him out as a Liberal with half a dozen brain cells – five more than his party’s normal prerequisite. Fed up with making the rest of them look *really* stupid like that, the Liberals knifed him. And just to make sure that their self esteem would never suffer in that same way again, replaced him with a borderline retard.

    Malc’s reaction? Why, what any normal member of the “grown ups” party would be: he spat his dummy. Big time. He said he’d serve out his current term as Earl of Wentworth, but would not seek re-election thereafter.

    Time passes…

    Malc has a change of heart, and in 2010 is re-elected, after all.

    Why bother? To spend the rest of his political career kissing the arse of a man that he clearly despises? Don’t think so. He’s about as happy a Vegemite as Communications Minister as Rudd was as Julia Gillard’s Foreign Minister.

    So try this on for size: Malc’s really waiting for the big job to come up again, as it most assuredly will. After all, there’s only so long that you can stand a gibbon up in a suit before the people say “that’s no Prime Minister – it’s just a gibbon that you’ve dressed up in a suit!”

    How best for Malc to achieve his goal though? Why, by fucking up every aspect of his current portfolio, of course! Let chaos reign and wait for their poll numbers to drop through the floor. Same goes to Joe Hockey raising the retirement age to 70 years old. Totally insane, you see? And when the polls drop, you know who gets the chop, the man at the top! (Wow, that even rhymed.) Another Liberal spill flushes Abbott away. Malc and Joe give us all their “mad Tony made us do it, and we’ll be normal from now on, honestly” speech, then get to duke it out for the Prime Ministership that, in their minds, should have been theirs all along.

    Sounds like a bonkers theory, I know, but you have to admit, it does fit the facts!"

    Citrix GeoTrust error on Macintosh

    Michael Brown  October 27 2014 04:23:12 AM
    Sometime in the last few days my Citrix login for work has stopped working on my home Macintoshes.  (Presumably, it still works on Windows; I haven't tried!)  The error I get is:  You have not chosen to trust "GeoTrust DV SSL CA", the issuer of the server's security certificate.
    GeoTrust Citrix error on Macintosh
    Quite right: I haven't trusted GeoTrust DV SSL CA because I've never heard of it before!

    In order to work around this problem, what I needed to do was install the missing certificate into my Macintosh Keychain application.  Here's how you do this:

    1. First, you need to download the certificate itself from http://my.25sevenit.co.uk/attachments/token/9dsdq1ddv8gpliv/?name=1GeoTrust+DV+SSL+CA.cer

    2. Open the Macintosh Keychain application.  Type "keychain" in Spotlight Search to quickly find and open it.

    3. Within the Keychain app, make sure you have "System" highlighted under the "Keychains" section, and then "Certificates" highlighted under the "Category" section.

    4. Click on File->Import Items from the main Keychain menu.  Go and fine the .cer file that you saved in Step 1.  You'll need an admin password to actually import it.

    That's it.  You should now see the GeoTrust DV SSL CA in our list of Keychain certificates, like so:
    GeoTrust Certificate in Macintosh Keychain

    Many thanks to Peter Rowden on 24sevenIT for this info.  What I've posted here is really just a rewrite of his post there.  He's also hosting the GeoTrust certificate on that site.

    Android on ChromeOS - the revolution begins?

    Michael Brown  September 13 2014 12:49:34 AM
    Despite what you might read from pro-Microsoft trolls in the various forums about how "ChromeOS needs an always-on internet connection",  the OS actually boasts an increasing number of offline-enabled apps.  Check out Google's own word processor and spreadsheet apps, for example.  You can edit spreadsheets and documents locally, with not connection.  When ChromeOS does detect a connection, it syncs those changes up with your Google Drive, just as you'd expect.

    Still, far too many Chrome Apps are little more than jumped-up URLs that really do nothing if you're not online.  The Evernote ChromeOS "app" is just such a beast.

    But now there's an alternative.   You can now ... drum roll, please ... run the Android version of Evernote under ChromeOS! You can install it from the Chrome Web Store.

    And here's how it looks on my Samsung Chromebook (the ARM-based 2013 model):

    Android Evernote on ChromeOS


    The good news is, that it works!  And it works off-line, unlike "Evernote Web" (which is still available as a separate, Chrome App, FYI).

    The bad news:
    • It's slow in operation
    • The window is a fixed size and can't be maximised.   It remains at, what I guess is an "Android size".
    • The fonts are small and hard to read.  I could see no way of resizing them either.

    Still, it's a start!  There's three other such apps: Vine, Duolingo and Sightwords.  But Evernote was the only one that I was already using (or had even heard of).

    Note: you a need the full ChromeOS to get this to work.  It won't work on the Chrome browser for Windows, Mac or Linux.

    See Chrome Owners Get Access to Android Apps (PCPro).

    Responsive CSS Sprites

    Michael Brown  May 4 2014 02:36:00 AM
    On my earlier post Rocket your website speed with CSS sprites!, I showed (I hope!) how can really speed up your page load times by loading a single, combined sprite image instead of multiple individual images.  As I said at the near the end of that post, however, things get a little trickier when you have to take Responsive Web Design into consideration.

    Let's examine the two pages again.  This time I've added a media query to them both.  The media query kicks in when your browser width drops below 700px, so you just need to drag the edge of your browser in to see the effect.  Or if in Firefox, use Ctrl->Shift->M (Command->Alt->M to call up the Responsive Design View.

    Here's the CSS:

    @media all and (max-width: 699px) {
         .flag {
                 width: 32px;
                 height: 21px;
         }
    }


    All it does is set the elements to be half of their normal size.  Let's see how it works in the multiple img tag version first:

    http://www.users.on.net/~mikeandgeminoz/spritetest/index2.html

    No probs there.  The flags all reset to half size, and the flags are shrunk down nicely with them.  No let's try the CSS prite version with the same media query code:

    http://www.users.on.net/~mikeandgeminoz/spritetest/index.html

    Woah!  What's going on here?  The flag div tags are resizing okay when I narrow the browser's width, but the sprite images aren't.  Suddenly, we have an abundance of Union Jacks!  That's because instead of resizing the images, the CSS code is cropping them instead.  So the Australian flag loses all its stars, and we're just left with the Union Jack at the top left.  (What's that at the back?  "That's actually an improvement", you say?  Well, you may have point there, but...)


    So is there way that we can resize the sprite divs and have their images resize correctly too?  Yes, there is, but it takes little bit of work.  The only way that I could find to do it is to specify the image sizes as percentages instead of pixels.


    Percentage for Sprites

    For the calculations on how convert pixel values into percentages, I followed this Stack Overflow thread.  Particular thanks to vals, who got me most of the way there, although there were some errors in his calcs.  I posted my corrections (as ChillyPenguin) on the same thread.

    First off, you have to add a new CSS attribute to your divs.  This is called background-size, and it has to be set as a percentage.  It takes X and Y values, and the percentage calculations go like this:
    x percentage width = (total image width / display image width) x 100
    y percentage width - (total image height / display image height) x 100


    My combined flags image is 1110px wide by 799 px high.  My flags sizes (handily, all the same) are 64px wide by 42px high.  So the background-size values go like this:
    x percentage width = (1110 / 64) x 100 = 1734.375%
    y percentage width - (799 / 42) x 100 = 1902.380952%


    Because all my flags are the same size, I can apply to background-size attribute to a flag class, which I add to all my flag divs:
    .flag {
          display: inline-block;
          background: url('../images/sprite.png') no-repeat;
          width: 64px;
          height: 42px;
          background-size: 1734.375% 1902.380952%;
    }



    Now the hard bit: we have to reset the background-position attributes on all of the flags.  So here's the calcs for that:
    x percentage pos = (x pixel pos / (total image width - display image width)) x 100
    y percentage pos - (y pixel pos / (total image height - display image height)) x 100


    So for my first flag, which is Afghanistan, my absolute background size looks like this:
    .flag.flags-afghanistan {
          background-position: -5px -0px;
    }


    So the percentage calc for the x dimension goes.  Note that the negative x pixel position is converted to positive when you do the percentage calculation:
    x percentage pos = (5 / (1110 - 64) x 100) = 0.4780114723%


    The y percentage is zero in this case, because the pixel y position is also zero.  Here's the resulting background-position code:
    .flag.flags-afghanistan {
          background-position: 0.4780114723% 0;
    }


    Phew!  Got there.  Repeat and rinse for all the other flags, and here's the result: fully responsive sprite images!!

    http://www.users.on.net/~mikeandgeminoz/spritetest/index3.html

    Note: I've reduced it to only eight flags to try and prevent RSI!!  Yes, the calculations are fiddly but you ought to be able to set up a simple spreadsheet to help you.






    About