text:
In functional programming there is the concept of a functor. A functor is simply something that can be mapped over. In OOP speak, we'd call it a mappable or some sort of container such as
Array that contains a
map function.
A very simple javascript example would be:
1 2 3 4
The above example is mapping over an Array and it is mapping from an array of
int to an array of
bool. In this example, the
Array is the functor. The functor keeps its shape meaning the same number of elements exist after the mapping operation but each element could potentially change.
A functor can be thought of as a container with a
map function. A functor is mapping between categories, meaning that it can map from type
a to type
b. The functor in the above example is the array and the type
a would be int with type
b the bool.
In haskell, functor has the following type signature:
1 2
You can think of
fmap as functor map.
If we consider the type signature for
fmap again:
What might not be obvious is that
a and
b from the above are actually type parameters. Any lowercase type in haskell is a type parameter.
The more specialised
Functor instance for lists looks like this:
1 2
The existing list
map function is used for the
fmap implementation.
map has the following signture:
If we now start filling in the type parameters for functor, then the
f type parameter is the type constructor
[] or would be the array in the javascript example above. Remember the functor is the box or container that contains the
fmap function.
The functor mapping function
(a, b) -> f a -> f b defines the mapping of a functor of type
a to a functor of type
b. Another way to think of this is an
f of
a and
f of
b or in this case a list of
a or a list of
The more specialised version of
fmap for list looks like this:
Hopefully it is clear that
f is the container or
list in this specific instance that maps a list of
a to a list of
In the above example
f is the higher kinded type and both
a and
b are both type parameters.
A higher kinded type (HKT) is simply a type parameter that takes a type parameter. The equivolence with higher order function HOF is that an HOF can take a function as an argument.
In haskell, there are types and there are kinds. You have concreate types like
Bool and
String. All of these are the kind
*. Why? Because they cannot take any type parameters.
[a] is a parameterised type because it takes one concrete type and has the form
* -> * and is called a first order type.
A higher kinded type abstracts the parameterised type
[] and has the form
(* -> *) -> *.
In functor,
f is of kind
(* -> *) -> * and
a or
b are of kind
* which is often referred to as the ground type.
Now when we try and define functor in typescript, we quickly come unstuck trying to define an
f of
a to an
f of
b because typescript does not support higher kinded types or type parameters that take type parameters.
1 2 3
A number of the functional typescript libraries like fp-ts have come up with a similar work around for the lack of higher kinded types.
They all have a similar interface:
1 2 3 4
HKT takes 2 type parameters
F and
A. Thinking in terms of kinds,
F represents the first class parameterised type
(* -> *) and
_A represents the ground type
We can now define functor like this:
1 2 3
The above code is now equivalent to the haskell version, we have a
map function that maps over a container or box of
A and returns a container or box of
Hopefully higher kinded types will land in typescript soon but until then I think this is a very inventive solution to a difficult problem.]]>
The initial appeal of the SPA was that it negated the need to go to the server to render new content. An SPA that does not transition to different views with different urls makes it not a great experience for any decent sized SPA. The problem is that a newly server rendered page works great with a screen reader but when you change routes in an SPA, the screen reader does not know that there is new content.
One solution is to have a container component that checks for changes in the react-router
location property and focus on an element at the top of the viewport each time the
location changes.
Below is an example of such a container component:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
The above container checks
location prop changes in
componentDidUpdate and will focus on the
ref element tagged in
line 33 if a location change is detected. A
tabIndex of
-1 is set on the
ref which does not add the element to the natural tab order but does allow you to progrmmatically set focus on an element that would not normally receive focus.
As we now have a router and a container component that detects route changes, we should ensure that we can tab up and down the page on all elements that require focus.
There really is not a lot to this if you use sensible html element choices for buttons and links. You should not make a
span tag or a
div a button or a link for example. I'm sure I've been guilty of making a
span clickable in the past but that is now firmly on the banned list.
One gotcha is links, if you have a link with no
href then you need to give it a
tbIndex of
Below is a cut down example of a
Link component.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
Using a component library that is outside of the context of the business rules is a great choice. I have controlled components for even simple html elements like
label etc. This allows me ensure that I am consistent about things like aria attributes. Somebody remarked in a code review that React was broken if I needed to create components for things like an
input but they missed the point. Below is a simple
input component that I use instead of the default react element:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
It is also great to think about components in isolation or out of the context that they will be used. Working in the context of a component library without
mobx etc. leads to better generic components.
All form or input controls should have labels that describe the purpose of the form control.
A label for a form control helps everyone better understand its purpose. In some cases, the purpose may be clear enough from the context when the content is rendered visually. The label can be hidden visually, though it still needs to be provided within the code to support other forms of presentation and interaction, such as for screen reader and speech input users.
With the above in mind, I have the following higher order componet that wraps anything needing a label and tags it appropriately.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
Line 15 assigns an
id for the passed in wrapped component by first of all checking the props or defaulting to a generated id from the
prefixId function.
Line 29 assigns the
htmlFor attribute of the
label to the
id member variable.
line 36 sets the
id of the passed in wrapped component to ensure they are properly assigned.
aria tags are also set for things like
aria-invalid on
line 39 in the wrapped component. The beauty of higher order components is that the wrapped component is loosely coupled from the hoc allowing them to be developed orthogonally with each having little knowledge about each other.
Line 41 uses the
aria-describedby attribute to connect any validation messages that might occur. A correctly tagged error message element is displayed on lines 45-55 if the
invalid prop is true.
With this higher order component in place, I can now add the correct labelling to any component such as the
Input component previously described:
The higher order component above takes care of displaying an error below each invalid field but a screen reader will not automatically pick this up unless the user tabs onto the form control.
To counteract this we supply a validation summary. Below is an exmple of such a validaion summary from gov.uk that I based our validation summary on:
At first glance this is complete overkill for 2 fields but in the context of a screen reader, this is a great practice. In the event of an error, focus is placed on the
h2 element in the
ValidationSummary component and a link is created for each validation error. The link's
href is a bookmark link to the invalid element. When the user tabs off the
h2, they get an explanation of the error and a chance to jump to the form element and fix the problem.
We used redux-form and the following component was used to create a validation summary for all redux-form errors:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
When going for an accessibility review of the website, a knowledgable person said that the first rule of aria is to not use aria. I might have been guilty of going overboard with my aria tagging and would welcome any feedback explaining if I have done this.
One definite place to use aria is to inform the screen reader that invisible content is now visible.
Below is a help container that expands and contracts when a link is clicked:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
A combination of
aria-controls and
aria-live are used to correctly instruct the screen reader that new content is toggled between visible and invisible states.
I think we can make all our work much more accessible if we put just a little bit of effort in. At the very least we should ensure we are keyboard accessible and let the screen reader know that new content is avilable.
If you disagree or agree with any of the above please leave a comment below.]]>
The problem is that every component is reading and writing to the same redux store state element.
If you look at the code below that uses
combineReducers, there is only one key for the autocomplete state on line 7:
1 2 3 4 5 6 7 8 9 10
For the record, I am now firmly of the opinion that using redux to store a component's internal state is actually a bad idea. If I was to code the autocomplete component again then I would store the state internally in the component. I still think there is a place though for an instance reducer.
My autocomplete reducer was working as I would expect with one component so I just needed to ensure that any code change would work with multiple components without changing the working reducer code. I also wanted to make this reusable for other situations. I just needed some layers of indirection in my mapStateToProps and any redux reducer that I wanted to ensure was segrating its global state by instance.
The steps I needed to complete this task would be:
mapStateToProps subscribes a component to redux store updates. I would create a
mapStateToProps that would retrieve the relevant state that would be tagged with the unique identifier mentioned in step 1.
mapDispatchToProps wraps action creators in a
dispatch function which sends an action to a reducer and updates the global store. I could hijack this functionality to send a component identifier with each dispatched action.
For the above requirements, I would create a custom connect function that would call the real connect and add some code to ensure that state was retrived by unique identifier. I would also need a function that added some functionality around calling a reducer.
connect connects a component to the redux store. It does this by returning a higher order component which abstracts away the internals of subscribing to store updates. Higher order components are one of the many things I love about react.
Below is the function that is returned from what I ended up calling
instanceConnect that in turn calls react-redux's connect.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
The above code is what is returned from my
instanceConnect function, I will supply the full listing later in the post or you can view it all here.
mapStateToProps and
mapDispatchToProps, I will discuss this later. The returned function accepts a component as an argument which will be the component that receives store update notifications. This connected component which is assigned to the
finalWrappedComponent variable will be used in the
render function of the higher order component.
InstanceComponent that will be the result of calling
InstanceComponent class is to add a unique id to each instance and also to return the connected component that is constructed on line 3.
instanceId property is assigned to a member variable in the constructor on line 9 and this is added to the
props on line 18 of the
render funtion of the
InstanceComponent renders the connected component with the
instanceId appended to the props on line 18.
Now that I can identify each component instance with an
instanceId property that now exists in the props, I somehow need to communicate this unique id to the reducer so I can only pull back the state that is relevant to each component instance.
Below is my modified
mapDispatchToProps that will call the passed in user supplied
mapDispatchToProps that wraps each action creator with
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
instanceId from the props.
instanceId is appended to the
meta property of the action on lines 17 and 19. The
meta property of an action is just a plain object where additional properties can be added without polluting the original
Now that I can identify a component instance from the action, I need to use this identifier to pull the relevant redux store state information when state changes are published via
mapStateToProps. Below is the modified
mapStateToProps that pulls out the instance state information:
1 2 3 4 5 6 7 8
reducerName argument should marry up to the value you give to the key that is supplied to
instanceId is pulled from the props on line 2.
initialState for this particular slice of the store state pie.
reducerName property on lines 4 -5 is passed in as an argument from the
instanceConnect function that returns the higher order component, you can see the full listing here:
1 2 3 4
The modified
mapStateToProps and
mapDispatchToProps are passed to react-redux's connect.
All that needs to be done is provide a function that can wrap a reducer with some indirection that ensures the state is modified with respect to the
Below is the reducer that accepts another reducer as an argument and ensures that the new version of the state is marked with the
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
instanceId property is retrieved from the
meta property that was appended with the
instanceId in the modified
@@init action. There will be no state at this stage and so we call the reducer with
undefined on line 6, this will give the reducer the opportunity to supply some initial state. We then append this to a property we will name
initialState. This property can then be retrieved in our modified
mapStateToProps when there is no instance state.
instanceId in the props.
instanceId by calling the immutablejs setIn function. This update only happens if the state has actually changed.
With the
instanceConnect function ready to use, then it is simply a matter of calling it like so:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
You also need to wrap the appropriate reducers with the
reducersByInstance function:
1 2 3 4 5 6 7 8 9 10
I think what is missing would be to remove the component's state when the component is unmounted and you could also create the slice when the component is mounted. I'll possibly look at adding that.
If you disagree or agree with any of the above then please leave a comment below.
Here is a full listing of the code file that contains both the
reducerByInstance and
instanceConnect functions.
Here is a test I wrote to drive out the functionality.]]>
Transpilers such as babel allow developers to use tomorrow's unratified features of javascript today and ecmascript7's
async and await could prove to be a game changer.
I've used async and await in
c# where its addition is still great but its impact is not quite as dramatic.
async and await, you can write asynchronous code that for all intensive purposes looks synchronous by marking functions as
async and and prefixing function invocations with
await to indicate execution will be deferred until a promise is returned from the function call after
Below is a very simple async function:
1 2 3 4 5 6 7 8 9 10 11
The function is marked as async with the
async keyword on line 1. Any function that will
await on the result of a function that returns a promise must be marked as
await keyword allows you to
await on the result of a promise. The
getJSON function that is called on line 5 returns a promise and any function that is called with
await must return a promise to ensure execution is returned to the calling code in the event of a resolved promise just as if the function had been called synchronously. In the event of a promise rejection, the rejection is thrown allowing you to deal with it just like you would with a normal catch handler. This is as close as javascript has ever become to having normal looking code for non blocking asynchronous function calls.
It is worth pointing out that promises are the glue that makes all this possilbe and they are still one of the most important primitives in node.
Babel transpiles function calls marked with
await in
async functions to generators.
In order to transpile async and await to javascript generators, you will need to
npm install the babel-plugin-transform-async-to-generator package and add a reference to the package in your
Below is my
.babelrc that allows me to use async await and other features:
1 2 3 4 5 6 7
I recently wrote this csv parser that applies transformations from a csv file input to a destination database table using the excellent knexjs query builder package.
The package uses csv-parse which transforms the csv file of delimitted rows and columns into arrays or objects. CSV-Parse implements the node stream.Transform API.
Csv-parse creates a readable stream that emits
data events each time it encouters a chunk of data. CSV-Parse allows me to bind to a readable event that gets passed a row of a csv file for each row in that particular file.
The package I wrote allows the user to specify transformations from a source csv file to a destination table. Some of these transformations might involve one or more asynchronous actions that could end up as some pretty messy code if I just used promises so
async and await seemed like a great fit. I will post the original code at the end of the post that used promises and it is very hard to follow and deeply nested.
Below is the code that hooks up the csv-parse stream events to member functions in the class that will handle the events:
1 2 3 4 5 6
Line 6 specifies that the
onReadable is bound to the
readable event of the stream.
My first attempt at using async and await with the stream is below where I marked the
onReadable function that gets rows of csv data passed to it as an
async function:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
The code calls
createObjectFrom on line 12 which is itself an async method that returns a promise and adds it to the
this.records array that will be used to persist the transformed values to the database.
Below is a scaled down version
createObjectFrom which transforms the csv record into a JavaScript hash of values:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
The code loops over an array of transformations, one of which might be an async call to
knex on line 9 to retrieve a value from the database.
A promise is returned on line 23 to allow this function to be called with async and await.
I wrote a test to test this function in isolation and I was buoyed when it passed but when running the code for real with stream
readable events being raised, the
this.records array was empty when it the
end event of the stream was reached:
1 2 3
This is because the
onReadable function is not being called async from the csv-parse module that raises the evnets.
After much head scratching the answer was to return a promise from
createObjectFrom. But the interesting part of this solution was that I was able to mark the function that gets passed to the Promise constructor as
async on line 2 of the code below:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
On line 2, I mark the anonyous function that gets passed to the Promise constructor as
async and this allows me to invoke functions with
await and only resolve the promise on line 24 when all the processing has finished.
onReadable event that calls this function now looks like this and is no longer async:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
createObjectFrom now returns a promise that will resolve later and
onReadable works as advertised.
Lines 12 and 13 simply add each promise that is returned from
createObjectFrom to the
this.promises array that can be processed later.
onEnd event now uses
Promise.all to wait for all the promises to resolve before inserting the resolved values into the database:
1 2 3 4 5
This works nicely and is much better than the Promise handling code at the bottom of this post.
Async and await can also be utilised to make your testing code much simpler and synchronous looking.
Below is my test to ensure that the records are being inserted into the database:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
Normally when testing promises from mocha, you have to return a promise from the mocha
it function in order for execution to wait until the promise has resolved but as I have marked the anonymous function on line 2 as
async, I can simply
await (line 6) for the asynchoronous csv parsing code to finish before testing the results.
I can also make further asynchronous calls in the anonymous function like I am on line 14 and
await their results before asserting expectations.
This is flatter and synchronous looking code that we all know well.
Below is the code I mentioned previously which used promises instead of async await and is pretty damn nasty.
The async await version is considerably cleaner.
Feedback is welcomed in the comments below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96
The sass/css of this post can be found on github here.
In the dark ages of at least 4 years ago, jQuery used to be the defacto way of creating smooth transitions between elements but now css animations and their promise of hardware accelaration are becoming a standard in all modern browsers. Vendor prefixed css rules are now disappearing into the ether with the usual exception of internet explorer as the standard becomes ratified.
I've only just recently discovered the 3D qualities of css3 and I found it pretty easy to cobble together this rotating cube. You can find the css/sass here.
I then created a hexagon which was pretty similar. Here is the sass.
I then tried to create the pyramid in the screenshot above which took me considerably longer to acheive the end result.
Before diving into the code, it is important to realise that the coordinate system used by css transforms to position elements is slightly different than the 3D coordinate system you may have previously learned in geometry. In the css coordinate system, the
y-axis and the
z-axis are the positioned the other way round from what I learned in maths with the
y-axis acting as the vertical axis and the
z-axis acting as the guage to slide elements forwards or backwards from the user.
The pyramid will be constructed of five divs with four divs making up the triangular faces and a rectangular div for the base.
Below is the markup of the pyramid structure:
1 2 3 4 5 6 7 8 9 10 11 12 13
Line 6 contains the opening tag for the
pyramid-parent div that will act as a container for the pyramid structure.
The css for the
pyramid-parent is below:
1 2 3
The perspective rule on line 2 defines how the depth of the 3D scene is rendered. Think of perspective as a distance from the viewer to the object. If you apply 3D transforms without setting the perspective, elements appear flattened.
pyramid-parent element encloses a further div with an id of
pyramid that has the following css rules assigned to it:
1 2 3
The transofrm-style rule on
line 6 specifies how the children of an element are positioned in 3D space or are simply flattened. The default is
flat and a value of
preserve-3d instructs the browser to position the elements in 3D-space. Without this property set, the pyramid would appear as a 2d triangle. The screenshot below shows how the pyramid looks without the
preserve-3d value set:
The first challenge was how to create triangles using only css. Some slight of hand and a bit of css skullduggery is required to create an equilateral triangle like below:
Below is the css that creates the effect:
1 2 3 4 5 6 7 8 9
The secret to these triangles is creating giant borders to the two perpendicular sides to the direction you would like the triangle to point. Make the opposite side's border the same size and background colour. The larger the border, the larger the triangle.
Unsurprisingly, positioning elements in 3D is considerably more difficult than in 2D and thankfully, the trigonomic ratios came to the rescue to correctly judge both the length of the elements and the angles of the pyramid.
Below is an image that labels the important parts of the pyramid:
All positioning takes place around the yellow right angle triangle in the above diagram. I first of all determined that I would like an angle of 60° for the slant angle of the triangle or the angle between the apothem and the base. The apothem is the slant height of a lateral face of the pyramid. With this angle and assigining a width to the base of the triangle, I could work out both the height of pyramid and the apothem height.
Once I know this, I can determine the lengths:
One of the nice features of sass is that we can use variables like you would in a normal programming language to stop repeating the same values in css and also mean I can calculate other values from existing variables, something very lacking in current css.
1 2 3 4 5
I am using node-sass and I could not find a way of using the trig functions in the sass. This is possible with compass in ruby sass but I don't know of a way in node-sass of achieving this so I had to calculate the value of the apothem height in a calculator first.
What I wanted to achieve with these vaiables was to be able to only set the
$base width variable and every other value would be derived from that. Sadly as I cannot reference the trigonomic cosine trig function from the sass, I had to manually set the
$apothem or slant height variable.
$apex-angle on line 4 is the angle each triangle will be rotated along the
x axis in order to tilt each triangle into the centre or apex.
I will now break down the steps I took to arrange the base and four sides of the pyramid. I will omit the many wrong turns I took in getting here.
Below is another view of the markup that makes up the pyramid:
1 2 3 4 5 6 7 8 9
Below are the css rules that are assigned to the
base div or rectangular base of the pyramid:
1 2 3 4 5 6 7 8 9 10 11 12 13
The width and height of the div are set on lines 3 and 4 and the transform property on line 6 is arguably the most important css3 property when it comes to positioning elements in the 3D space. This property allows you to rotate or move elements in each of the
y or
z 3D coordinate axes. With the
base div, I use rotateX to rotate the element 90° along the
x or horizontal axis axis to give the impression the div is lying flat and viewed at an angle.
The translate3d property is also used to move the div along the
z axis. The
translate3d property takes 3 values that can be used to move the element along the
y or
z axis respectively. In this example I am using the
$base-move variable that was derived from the base div width to shift the div away from the user along the
z axis.
1 2 3 4
This shifts the div along the
z axis or appears to move the div away from the user. This value is important when it comes to positioning the four bases of the triangle divs. Below is how the base looks with these rules applied:
The following generic rules are applied to the triangle divs:
1 2 3 4 5 6 7 8
The transform-origin property on line 6 provides a convenient way to control the origin about which transforms using the css
transform are applied.
Below is how the front face of the pyramid looks without the
transform-origin property set:
And below is a screenshot with it set:
Each face will be moved along the
x or horizontal axis by half the base width and will be moved down the
y axis by the apothem or slant height.
transform-origin must be used with the
transform property as it only changes the positioning of transformed elements.
Each triangle will be rotated by a multiple of 90° to orient each triangle for a different face of the pyramid (respctively 0°, 90°, 180°, 270°).
With this in mind, each triangle will have its own rules to set this, in the case of the front face, the following css properties are set:
1 2 3 4 5 6 7 8
The next face has the same rules except the
rotateY property which is increased by 90°.
1 2 3 4 5 6 7 8
Until all triangles are positioned:
The keyFrames rules allows you to gradually change one set of css rules for another which is specified in the
from and
to properties in the code below:
1 2 3 4 5 6 7 8
In the above code the a gradual rotation around the
y axis is specified by starting at 0 degrees and completing at 360 degrees. Once the keyframes rules are specified you then need to associate it with an element via the animation property.
1 2 3
The name of the keyframes animation is specified along with the length of the animation. The
infinite values states that the animation will continue infinitely and
linear specifies that the animation speed is constant throughout the animation.
The full and current source can be found here.
Following up from my last post, I have created yet another sine wave animation (YASWA) and I want to blog about how I achieved a smooth animation for the svg path shapes and arcs with d3.js.
I am not going to go over how to set up the basic shapes in the animation, you can find out how that is done by referring to my last post.
The 3 path shapes that I found challenging to animate are the red sine wave that is progressively added and removed from the document as the unit circle rotates along the x axis and the two blue angled arcs that form the small angled arc at the centre of the centre of the larger circle and the blue arc that expands around the circumference of the larger unit circle.
The first step is to append the paths to an svg group element. Their initial position is not important at this stage.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
There is a
state object (line 1) that is used as a container to hold a reference to all the svg shapes that will be transformed on each tick of the animation. The shapes are added as properties of the
state object. The sine curve path shape is added to the
state object on line 10 and the two path shapes that will render the arcs are bound as properties of the
state object on lines 13 and 17 repectively.
Line 3 creates a d3.js line function that will be used to generate the rather cryptic svg path mini language instructions for the d attriute of the svg path shape that will plot the points of the sine curve.
sineData array is initialised on line 8 and the line function will be executed for every element in the array and the
x and
y accessor functions on lines 5 and 6 will be executed exactly once for each element in the array. Obviously as the array is initially empty, these functions will not be invoked until there actually is some data.
Now that the the svg shapes are on the document, the next step is to kick off the animation function:
1 2 3 4 5
line 3 initialises a
state.time variable that will be incremented on each tick of the animation. This variable is central to all calculations that will be used to position.
The body of the
animate function that is called on line 5 of the above code snippit takes the following form:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
state.time counter is either incremented or decremented on each tick of the animation depending on whether the animation is moving forwards or backwards.
Lnes 11 to 18 make a simple check of whether the time is greater than 2π, in which case it is time to start animating backwards or if the animation is moving backwards and time is less than 0 then the shapes need to move forward. The current direction is passed into the
animate function with each call to
Line 20 calls requestAnimationFrame to progress the animation each time.
My first attempt at incrementally drawing the sine wave was to add and remove the sinewave on each call to
animate but this led to a very jerky horrible visual effect as the browser struggled to recreate the curve each time from the origin.
The solution was incredibly simple and I simply make a call to a function called
progressSineGraph that is listed below:
1 2 3 4 5 6 7 8 9
state object that contains references to all the shapes and properties that are needed to perform the animation is passed into the function along with the direction argument that specifies whether the shapes are animating forwards or backwards.
The code between lines 2 and 6 either adds the current value of the
time variable to the
sineData array if the animation is progressing forward or removes the current head of the array if the animation is moving backwards. The elements of this array will be used to plot the sine graph.
On line 8 the
d attribute of the
path shape is set to the
state.sine function that is listed below. As mentioned earlier, the
d attribute contains the mini language instructions to plot the curve. The line function will generate the instructions by calling the function below for each element in the array:
1 2 3 4
The line function will be called for each element int the array and
x and
y coordinates will be created by calling the
x and
y accessor functions that accept the current element as an argument.
I was pretty amazed how easy this technique is to animate shapes progressing or regressing.
The d3.js line function is a great abstraction and you can see what the generated output of the line function looks like below. The
state.sine function has created the
d attribute of the path shape that contains the instructions to draw the sine curve. I know which I would rather work with:
It is also worth noting that montone interpolation is set to ensure a smooth curve is drawn.
All of the shapes in the animation are interlinked in some certain way and all the calculations of where to place the shapes on each tick of the animation are based on the incrementing
state.time counter.
The black line that rotates from the centre of the circle to the circumference can be thought of as the hypotenuse of a right angle triangle. The hypotenuse in this document is an svg line shape with
x2 and
y2 properties that are set using cartesian coordinates to position the shape.
The two arcs that form the angle at the centre of the circle and at the circumference will also use the hypotenuse coordinates once they have been calculated.
Below is the code that positions the svg line shape on each tick of the animation:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
Once the
x2 and
y2 corrdinates have been calculated, they are bound as properties of a
hypotenuseCoords object that can be referrenced later. Lines 15 to 18 positions the shape.
We can now use basic trigonometry and the d3.js arc function to create the arcs. The arc function is also a to the d3.js svg line function as it also generates instructions for the path shape's
d attribute but it also has some additional properties such as the
startAngle and
endAngle properties that are specific to generating arcs.
Below is the code that sets the properties pf the two arcs:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
The main calculation takes place between lines 1 and 10 and I would love somebody to tell me there is a better way than this. I always find that if I have used
let to declare a variable and later reassign the variable after initialisation, this usually tells to me that I have got something wrong or I have taken the wrong path.
In order to set the angle each time, I need a to give the
d3.svg.arc function a
startAngle and an
endAngle each time the function is called.
startAngle properties of the 2 arcs are set on lines 15 and 20 and I am using a static value of
PI \ 2 which is 90 degrees in radians. This is because a
startAngle of 0 will position the
startAngle at 12 o'clock on the circle and I want it to be at 3 o'clock or 90 degrees.
On line 1 the atan2 function is called to find the angle that the hypotenuse makes with the
startAngle of the arc or 0 on the y axis property.
Arctan2 is different than arctan because it takes 2 arguments and returns an angle in the correct quadrant. If you are unfamiliar with the 4 trigonometric quadrants, you can read about it here.
The atan2 function takes into the account the two signs of the arguments that are passed in and places the angle in the correct quadrant. In this example the angle of the
hypotenuse is found by subracting the
y2 and
y1 properties and subtracting
x2 and
x1 of the hypotenuse and passing them into
atan2 returns the angle in radians between π and -π. Thus,
atan2(1, 1) = π/4 and
atan2(−1, −1) = −3π/4.
My first attempt at drawing the arcs did not contain the readjustment of the
angle variable below;
1 2 3
Without this readjustment, the arcs where being rendered like this:
This is because
atan2 returns the angles between π and -π and the angle was being calculated correctly for rays in quadrant 1 and 2 but not what was required for quadrants 3 and 4. The readjustment of
(-2 * (Math.PI) + angle) gives same ray but in the correct direction when in quadrants 3 and 4 by adding the angle onto -2π.
I am very happy with the end result. If you can suggest a better way for any of the above then please a comment below.
I think I need to move on from sine waves.]]>
The full and current source can be found here.
I have spent the last year learning some of the maths I should have learned about 27 years ago. One of the things that I have found interesting while learning maths is the relationship between the unit circle and a sine wave graph of
y = sin(x).
A sine wave is a mathmatical curve that describes a smooth repetitive oscillation and the unit circle is a circle of radius 1 centred at the origin
(0, 0). The unit circle can be used to find special trigonometric ratios as well as aid in graphing. There is also a real number line wrapped around the circle that serves as the input value when evaluating trig functions such as sine and cosine.
A sine wave is a periodic function or a function that repeats itself at regular intervals. The most important examples of periodic functions are the trigonometric functions that repeat themselves over intervals of 2π. One journey around the unit circle is 360 degrees or 2π in radians. A sine wave shows the excursion around the circle happening in time and is ultimately a circle expressed in time. I have used d3.js to illlustrate how the journey around the circle corresponds to the sine wave movement over time.
There are a number of concepts that I wanted to capture in the animation:
Illustrate where the input value of the unit circle corresponds to the
(x, y) coordinate on the horizontal axis of the sine wave.
Demonstrate how the right angle is formed by the angle of the radius moving counter-clockwise around the unit circle.
Show the number scale of the unit circle in radians as ratios in proper mathmatical notation in the browser in both the unit circle and the x axis of the sine graph. MathJax appears to be the only show in town that fits this requiremnt.
This process of creating graphs from the unit circle is often called unwrapping the unit circle.
The first step is to create the basic shapes that will illustrate the unit circle and use cartesian coordinates to position them. D3.js has an excelent scale abstraction that allows you to deal in a finer grained scale than pixels. I can now think of the dimensions of the svg document as a 20 x 20 grid which makes positioning things easier to reason about.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
On lines 6 and 10 of the above code, horizontal
x and vertical
y scales are created and bound to two variables. These d3
scale functions take the input domain of 0 to 20 and map it to an output range of either the viewport width for the horizontal
x axis or the viewport height for the vertical
y axis. It is much easier to think of cartesian coordinates ranging from 0 to 20 than the very fine grained pixel scale.
With the scales in place, it is much easier to start positioning the elements:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
An svg group element or a
g element is created on line 5. All elements will be added to this group or container. Transformations applied to an svg group or
g element are applied to all elements in the group which makes it extremely useful.
The three lines that will form the right angle triangle are created and bound to the
opposite and
hypotenuse variables using the d3.js svg line shape. The initial values of the triangle line's
y1 and
y2 coordinates are irrelevant at this stage, they will be set on each tick of the animation. It is just important to get them onto the document during the initialisation phase.
The larger unit circle is created and appended onto the group on line 10 of the above snippet and another smaller circle is added on line 38 which will be positioned counter-clockwise around the large circle by setting its
cx and
cy coordinates on each tick of the animation. This will give the impression that the small circle is rotating around the larger circle.
Below is how things look so far:
The next stage is to add the number line in radians of the unit circle:
In order to divide the circle into 8 lines and position the labels, I can kill two birds with one stone by creating an array of objects which have label and angle properties that I can iterate over and create the lines and labels:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
Lines 2 to 11 define the array of objects to iterate over. Each object contains a
val property that can be thought of as an angle to move counter-clockwise around the unit circle for each element in the array. There is also a label property which is the text of the angle in radians. The cryptic syntax of the label is written in LaTex, which allows you to define mathmatical notation that can be displayed in the browser. Mathjax will later parse these labels into authentic looking math symbols in the browser. More on my difficulties with MathJax at the end of the post.
On lines 12 and 13 the
x and
y coordinates are determined for each angle value in the array. By finding the
cos(x) * radius and
sin(x) * radius of each angle in the iteration of objects, I can ascertain the (
y) coordinates of the point on the circumference of where to position the radian label and of where do draw the dividing line that will show the number scale on my unit circle.
Lines 15 to 16 add offset values for each
x and
y coordinate to ensure the labels all appear outside of the circle and not flush on the circumference.
Line 18 adds a new svg group element and the textual label is added to this newly created group.
Line 24 simply adds a line from the centre of the circle to the
x and
y coordinates on the circumference.
Before MathJax does the parsing, the circle looks like this:
A similar approach is used to create the sine graph axis but instead of iterating over an array, a pair of d3.js axis are created and latex syntax is used for the tickValues of the x-axis.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
The basic setup is now complete:
My first step is to create a hash of values that I have unimaginatively called
state that serves as a container for all the elements and dimensions that I am going to need to transform the svg elements on the documents. I am going to pass this
state object into the animation function that will set the new position of the elements on each tick of the animation. After that, the animation is kicked off with a call to
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
Arguably the most important value in the above is the
time property on line 15 which will provide the
x value of the horizontal value of the sine graph. This will be incremented on each tick of the animation.
drawGraph function is below:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
Every time the
drawGraph function is called, the
time property of the
state variable is incremented by roughly 1 degree on line 4 to simulate time moving along the x axis. I do the same on line 5 for the circle that travels along the
x axis. I have a separate counter as I need to reset it to zero each time the
xIncrement variable exceeds 2π.
Line 7 calls the
drawSine function that draws the sine wave on each tick of the animation. More on this later.
Lines 9 to 17 positions the small circle that traverses along the horizontal
x. The counter for this coordinate is reset each time it exceeds 2π.
The rest of the code in this function takes care of finding and positoning the shapes on the unit circle to simulate the small circle rotating counter-clockwise on the unit circle and constructing the right angle triangle.
Lines 19 and 20 find the next
x and
y coordinates of the next point on the circumference to position the small circle that rotates the larger circle and bind them to the variables
dy and
dx. I use minus in the expression
radius * -Math.sin(state.time) because we want to simultate rotating back counter-clockwise. Once we have this coordintate it is easy to position the three lines that make up the right angled triangle on lines 26 to 38.
Line 49 calls requestAnimationFrame which tells the browser that you wish to perform an animation and requests the browser call a specific function,
drawGraph in this instance, before the next browser repaint.
I am also using a lesser known overload of bind on line 37 that creates a new partially applied function with some or all of the arguments already bound each time it is called. I have blogged about this previously here. In this case, the
state hash will be bound every time the function is called because I am passing it into
bind as an extra argument after
this. I use this technique a lot in javascript land.
Now to the meat and potato of the piece, namely animating a smooth sine wave. The sine wave is mathmatically a very simple curve and a very simple graph. It is a simple
y plot with the x-axis representing time and the y-axis representing angular displacement around the unit circle.
Below is the
drawSineWave function that is called on each tick of the animation:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
The fist step on line 2 is to remove the previously plotted curve before recreating it on each tick of the animation.
Lines 4 to 8 creates the points that will be used to plot the sine graph against.
One Line 4 the an array of integers is initialized using the d3
range function, this will create an array of 54 elements ranging from 0 to 53:
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13...etc...53]
The upper bound of the array which is 53 is chosen to fill the available width in the viewport
I will come back to why the calculation on line 5 is needed but on line 6 I do a further
map of the array that was initialised on line 4 to create an
x and
y coordinate for each element in the array that can be used to plot the sine wave. The
x coordinate is simply the element of the array and y is calculated by getting the negative
sine of
x because we are simulating the sine wave moving counter-clockwise. For each tick of the animation we simply subtract the
state.time variable that we have used previously from
x. If you look at the animation, you can see how the small circle in the middle of the unit circle moves up and down at exactly the same rate. Maths in action!
Below is how the sine wave looks without the transformation
.map(x => x * 10 / 84) applied to the original array:
If we just use integers to plot the points we get the rough sine wave but if we use floats, we get a much smoother flowing sine wave. I multiply each value by 10 to space it out across the width and then divide by 84 to ensure I get a float back. 84 was arrived at by trial and error to ensure the wave spans across the graph.
Once I have my coordinates to plot the curve, the following code takes care of creating the curve on each animation tick:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
Lines 7 to 10 define a d3 line function that will be used by the svg path element on lines 12 to 15. The d3
line function can be thought of as a path generator for a line or in this case a curve as the interpolation mode is set to montone interpolation in order to create a smooth curve for the sine wave. The
line function will take the data array (
sineData) and convert it into the rather cryptic svg path mini language instructions that the svg path element on lines 12 to 15 will use to construct the curve. We define accessor functions on lines 9 and 10 that will be called for every
x and
y coordinate of the
sineData array on line 1. A monotone interpolation will then be performed by the path function for each point. Every
x and
y is mapped to the correct scale on lines 3 and 4.
Lines 12 to 15 attach the path element and sets its data via the
datum attribute. The
d attribute sets the path data or the mini language of path commands that the line function on line 7 will generate. The
x and
y accessors of the
line function are invoked exactly once for each element in the array.
All that remains is to tell MathJax to parse the latex into math symbols. I cannot believe how hard I found this. Below is how the code ended up after a lot of coffee, profanity and self doubt:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
First of all MathJax did not seem to play nicely with react, I have to use a
wait function to suspend execution until the MathJax is available. On lines 12 to 18 can best be desribed as extreme hackery. I have tagged any element on the svg document that contains latex with the
tick css class. I add a hook to mathjax that is called whenever it has done its first parse, I then remove the svg element that was added by MathJax and re-add it again. This causes MathJax to reparse the markup and the symbols are rendered correctly. I don't know if it was the fact that this is a react site that made this so difficult but it really did not play well with this site.
wait function is below for completeness:
1 2 3 4 5 6 7
I found this hugely enjoyable and I am more than satisfied with the result. This probably means I should get out more.
If you disagree with any of the above or can suggest better ways then please leave a comment below.]]>
Following on from my last post on axes positioning, I have added the functionality to add a tangent to the curve on
mousemove. You can see a working example here by dragging the mouse over the svg document.
Below is a screenshot of the end result:
The first steps are to create the elements that I will use to display the tangent indicator and also to hook up an event listener for
mousemove on the svg document:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
The above creates a circle to indicate where on the curve the mouse is relative to the x axis. A label is created to display the coordinate that the mouse is currently on with respect to the curve and lastly I create a line that will display the tangent.
Line 19 adds a
mousemove handler to the
svg element that has been previously created with the code below:
1 2 3 4 5 6 7 8 9 10
The goal of the
mousemove handler is to draw the tangent of the curve with respect to the x axis as the mouse moves over the svg document.
In geometry, the tangent line to a plane curve at a given point is the straight line that just touches the curve at that point.
I can get the
x for the tangent line from the mouse coordinates of the
mousemove function:
1 2 3 4
With this, I can use mathematical differential calculus to work out the tangent line. If I was to perform these steps with pen and paper, I would take the following steps:
x retreived from the
mousemove event into the derivative to calculate the gradient (or slope for the US listeners) of the line.
y = mx + c.
What was surprising and enjoyable for me was that the steps on paper transferred into machine instructions quite well which is not always the case.
Before I plot the line, I want to position my circle and label onto the curve. I am already using the excellent mathjs library to get the coordinates to draw the curve:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
Line 2 of the above code uses
mathjs's parse function to create an expression from the string input of the form:
Once I have the expression, I can evaluate it with different values. Lines 5 and line 9 evaluates the expression for each
x value in a predetermined range of values. Line 19 plots the line.
As I know what
x is from the mouse event, I can use mathjs to parse my expression with respect to x and get the
y coordinate to position my label on the curve:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
Lines 2 and 4 retrive
x from the mouse event and line 6 evaluates
y by parsing and evaluating the equation of the curve with respect to x. I then use the
x and
y coordinates to position my label elements.
Mathjs does not come with its own differentiation module to work out the derivative of the user entered expression but I found this plugin that seems to work out well for this task.
Armed with this module, it was plain sailing to create an equation for the tangent line that I could use to find out
y values for the tangent.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
c constant or y-intercept of the equation of the line
y = mx + c is retrieved on line 5.
y = mx + c.
getTangentPoint function is created that will be used to get the points at either end of the function.
x that will be far off the length and height of the svg document to give the impression of stretching off to infinity.
y value by calling the
getTangentPoint funtion on line 9 that in turn will solve for
x for the equation of the line function previously created on line 7.
You can see the end result here.
The following util function will return the y-intercept for a point and gradient:
1 2 3
I am available for work right now, if you are interested then email me directly.]]>
Up until now when I have been dealing with d3.js's axes components, I have always kept the axes positive, i.e. both the x and y axes where showing values greater than 0.
I have been hacking around with this fun side project that takes the input of an algebraic expression and plots a graph for a sample range of values for x. You can checkout the source code here if you are interested.
Below is a screenshot of the end result:
It quickly became apparent that in order to show the curve of the expression properly, I would need to construct negative and positive x and y axes.
I have the following function below that constructs the data of x and y coordinates to plot the curve against which uses the excellent mathjs library to transform the string algebraic expression into a javascript function (line 2). I then create a sample range for
x values ranging from
-10 to
11 and evaluate the
y coordinate for each item in the range by applying the function on line 5 to each item:
1 2 3 4 5 6 7 8 9 10 11 12
Armed with this data, I can now construct my axes.
I first create the axis against a scale that is in proportion with the viewport dimensions.
1 2 3 4 5 6 7 8 9 10 11 12 13 14
domain function of
d3 allows you to specify a minimum and maximum value as the range of values that we can use for a particular axis.
Below I am using d3's
extent function that returns the minum and maximum values of an array and is equivalent to calling
d3.min and
d3.max simultaneously.
As I am supplying the values for the range of
x values in the code above, I know that I will always have negative
x values and positive
x values.
The y coordinates are different depending on the function generated from the algebraic expression. Depending on the expression, there are basically 3 conditions I want to capture when displaying a curve.
The first case is when there are only positive y values:
The next case is when there are both negative and positive y values;
Lastly, only negative y values:
With this in mind, the code below creates a domain based on the minimum values of y and the maximum values of y:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
I either start my domain at
0 or use
d3.extent again to get the maximum and minimum values for y like I did before for x.
The last problem to solve was to position the x axis. In the 3 code samples below, I am capturing the domain for y and the x axis position for each condition.
This is easy if I only have negative or positive values for
y. I can simply place the
x axis at the bottom for only positive values:
1 2
When I have only negative values, then I can place the x axis at the top of the document:
1 2
The interesting case was when I have both positive and negative values for
What I ended up doing was selecting all the ticks or labels from the y axis and finding the label that had
0 against it and from that I could use d3 to to select its position and then use that for my x axis position.
Below is the code that does that:
1 2 3 4 5
In the code above, I filter out all the other ticks apart from the
0 label. The zero tick is then passed into the
map function which selects the transform attribute of the tick which might look something like this
translate(0,280). The second value of translate,
280 in this instance gives me the position of the
0 label in the y axis. I can use this value to position my x axis.
Once I have the position of 0 in the y axis, I can position the axis to the document:
1 2 3 4
When it comes to positioning the y axis, I simply divide the width by 2 and position it there:
1 2 3 4
I am available for work right now, if you are interested then email me directly.]]>
Following on from my last two posts, Perpendicular Bisectors of a Triangle With d3.js and Altitude of a Triangle With d3.js, I want to document how I ensured that my svg tranformation is resized to scale during a resize event or if the user selection can change.
Below is the end result of the last two blog posts:
You can see the result at this url.
You can change the current triangle effects by changing the radio buttons at the top. You can also drag and drop the triangle vertices by dragging the red circles at each triangle endpoint or vertex. This led to an interesting problem, which was how to how to maintain the current state or coordinates of all the shapes when the user selects a new effect from the radio buttons.
Another, more challening problem was to make sure that everything resized to the current ratio or scale if the browser window is resized. If you go to this url and resize the browser, you can see that everything re-renders nicely to scale. This does not happen out of the box. You need to code for this eventuality.
The bulk of the work takes place in the render method below:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111
render function as you might expect, creates the svg document and renders all the shapes onto their specific coordinates as I outlined in the previous blog posts here and here. I use this function to both initially draw the shapes and also as the function that is attached to the
resize event.
Below is the end of the render function that creates a hash that will keep track of the current state of the document or the coordinates of the all the shapes at any given time.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
Lines 1 to 3 create a the hash and assign the
xScale and
yScale d3 scale objects that allow you to deal with a finer granuated scale than pixels. The x and y axis in the documment were created using these scale objects and you can think in terms of placing these objects at coordinates on these scales, e.g.
(1, 1).
Lines 6 to 29 assign properties to this
area hash such as the vertices of the triangle that will be used to read and write to when drawing the shapes. I pass this structure into most functions.
Line 31 uses the lesser known partial application properties of the bind function to create a new version of the render function. This partial function when called, will always be called with the
area hash as an argument, that contains all the information we need to reconstruct the document. Line 33 adds this function to the hash, we will use this to remove the event listener each time it is called or else there will be a memory leak. LIne 35 creates an event listener for the resize event and assigns the new version of render to this event.
The beginning of the
render function below uses the new es6 default paramaters feature to allow render to be called with no arguments or called from the resize event with an argument. If it is called in response to a resize event then there will be a state argument. Lines 2 to 5 remove the event listener each time it is called.
1 2 3 4
Everytime render is called, I create new
xScale and
yScale objects that reflect the current window size on line 15 - 21 below:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
Below is the code that will reassign the points of the triangle to scale from the state hash:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
If we have a state hash then the
invert method of the scale objects is used to get the value in pixels before using the scale to recreate the new x and y coordinates that are in scale with the new browser dimensions.
I also use partial application when adding the drag and drop event to the red circles at the vertices of the triangle on line 22 of the below:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
After all this, I take great pleasure in resizing the window and watching everything beautifully scale.
You can checkout the github repo that contains all the code for this.
I am available for work right now, if you are interested then email me directly.]]>
Let us get some definitions for these terms, the perpendicular bisectors of a circle are described as:
the lines passing through the midpoint of each side of which are perpendicular to the given side.
Below is a triangle with one perpendicular bisector running through side
The circumcircle of a triangle is:
The point of concurrency of the 3 perpendicular bisectors of each side of the triangle.
The centre point of the circumcircle is the point of intersection of all the perpendicular bisectors of a triangle.
Below is a triangle with all 3 perpendicular bisectors and the circumcircle drawn with
The first step was to draw one perpendicular bisector of a triangle.
I chose 3 arbitary points for the vertices of the triangle.
1 2 3 4 5
This is all the information I need, to calculate the perpendicular bisectors and the circumcircle.
If I wanted to find the perpendicular bisector of
AB using pen and paper, I would perform the following steps:
y = mx + c.
I have blogged previously in this post about how to set up the graduated x and y axis and a more managable scale for positioning vertices etc.
My first step was to find the perpendicular bisector of the line
Below are two helper functions that take javascript point objects as arguments with x and y properties that map to coordinates and return either a gradient/slope or the perpendicular gradient/slope that occurrs between the 2 coordinates:
1 2 3 4 5 6 7
Below is a helper function to find the midpoint between two vertices or points:
1 2 3
Using these values, I can then find the y-intercept or the point where the perpendicular line will cut the y-axis.
Below is a function that will find the y-intercept given a vertex and a gradient/slope:
1 2 3
You can think of the above function as rearranging
y = mx + c to solve for
c or
c = y - mx.
All that is left is to find the x-intercept or the point where the bisector line cuts the x-axis.
Below is the code that brings this all together:
1 2 3 4 5
The x-intercept on
line 5 is again re-arranging the equation of the line formula
y = mx + c to solve for x.
The finshed function looks like this and there are a number of if statements I had to add for the conditions when the slope or gradient function might end up undefined or equalling infinity when it encounters horizontal or vertical values that have catches with the formula. I would love to know if there is an algorithm that will avoid such checks:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
drawTriangleLine function looks like this and simply adds a
d3.js line:
1 2 3 4 5 6 7 8 9
Every time I call the
perpendicularBisector function, I return an object that contains a vertex and point that I can use to draw the circumcircle.
All that is left is to draw the circumcircle and here is the function I wrote to do just that:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
In order to find the centre of the circumcirle or the point of intersection of the perpendicular bisectors, the function takes two arguments
lineA and
lineB which are two of the perpendicular bisectors of the traingle. The function then arranges these line objects into
y = mx + c format on lines 6 to 11 of the above. I then solve these equations simulataneously using matrices and specifically using cramer's rule to find the point where the line intersect.
Once I have the 2x2 matrix assembled on lines 13-16, I then pass it to the
solveMatrix function with the 2 y-intercept values that will apply cramer's rule:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
I now have the point of intersection of the perpendicular bisectors. All I need to know now is the radius of the circle. The calculation I used is to use the distance formula. From the point of intersection we just found to one of the vertices of the triangle.
Below is a helper function for the distance formuala:
1 2 3
All I have to do now is draw the circle from the two knowns, i.e. the point of intersection and the radius:
1 2 3 4 5 6 7 8 9 10
Here is a working jsbin that illustrates all I have wrote about.
I have also added drag and drop so you can drag the vertices around by the red circles and watch it all redraw.
Please leave a comment below if I could have achieved this in a more efficient way.]]>
In geometry, an altitude of a triangle is a line segment through a vertex (point) and perpendicular (i.e. forming a right angle with) a line containing the base (the opposite side of the triangle). This line containing the opposite side is called the extended base of the altitude.
My first steps are to create a scale that is of much lower resolution than the finely grained pixels and below is the code that creates both the scale and the axis. I blogged about scales in more detail in my last blog post:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
I then created 3 arbitrary vertices for my triangle that would fill the x and y axis as much as possible:
1 2 3
My next task was to then try and draw a triangle from these points. Below is what I ended up with before I explain the solution:
After a bit of trial and error by first of all trying to draw lines with the line function, I came across d3's path function:
1 2 3 4 5 6 7 8
This is effectively a DSL or mini-language for drawing shapes.
I'll add a translation for each line:
'M ' + a.x +' '+ a.y + - This means place a point at the x and y coordinates of the point I previously created with
var a = {x: xScale(1), y: yScale(1)}. This is analgous to the starting point where you might place your pen.
' L' + b.x + ' ' + b.y + - This means draw a line created from the point created above to the point
b that was declared like this
b = {x: xScale(6), y: yScale(18)}. Because we are using scales, we can pick nice friendly points like (6,18) rather than the harshness of pixels.
' L' + c.x + ' ' + c.y + - draw a line to the c point
z command closes the path.
I really like the path function as it is how a human would draw a triangle with pen and paper and is very easy to grok.
With the easy bit done, I now wanted to draw the altitude through point A that would be perpendicular to line BC.
If I was doing this with pen and paper, I would perform the following steps:
y = mx + c format.
BCthat I can use to create an equation of the line that will go through point
A and will be perpendicular to point
C in
y = mx + c format.
A to the point on
BC that was perpendicular to point
What I quickly found out was that transfering pen to paper calculations to machine instructions or javascript was extremelly difficult and different. Here are the steps I took:
Like in the pen and paper version, I found the grandient of
BC and created this function:
1 2 3
I then created a function to find the perpendicular gradient using the graident found in point 1:
1 2 3
In order to get both line equations into
y = mx + c, I needed a function that would take a point and a gradient and give me the
y-intercept or the point where the line cuts the y-axis:
1 2 3
I could then get the y, mx and c values of
y + mx = c for both lines so I could solve the equations simultaneously.
1 2 3 4 5 6 7 8
I would use the substitution method or the addition method to solve a series of equations with pen in paper but writing it in code was a different matter and matrices seemed like the obvious fit. Please write a comment below if there is a more efficient way. There is cramer's law which seemed ideal for my needs. I needed to get my vars into the following format:
1 2
Below is my altitude function that gets the values into matrices before passing to a function that will use cramer's law to find the point of intersection.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
Below is the function I used to first of all find the determinant of the matrix before applying cramer's law:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
The above returns a point that I can then use to join point
A to the point of intersection returned from the
solveMatrix function.
1 2 3 4 5 6 7
I want to add drag and drop to rotate the triangle so I'll probably need to put checks in for vertical and horizontal values for x and y but this will do for now.
Below is the end result of my troubles with the altitudes of all three vertices shown.
The hardest part was to solve the simultaneous equations and I belive there is a better and more efficient way that uses vectors to work this out but I have not covered this with my course as yet.
Here is a working jsbin of my efforts.]]>
Here is a jsbin with the product of my fumblings. You can drag the line by either of the red circles at each end and the calculations will recalculate.
Below is the end result
I will now breakdown the code:
The first code blocks create an x and a y scale that will scale from 0 to 20 units in each axis which is preferable to using the much more granular pixels. These scales are used to create the labels on the x and y axis and also make positioning elements much, much easier.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
The definition of a scale from the d3 wiki is:
Scales are functions that map from an input domain to an output range.
Scales transform a number in a certain interval (called the domain) into a number in another interval called the range. If we look at the code used to create the x axis scale:
1 2 3
The code above returns a converter function and binds it to the variable
xScale. We will use this function a lot to convert the
x coordinate of a point from the real pixel value into the
0 - 20 output range scale we have specified. The code specifies that the scale is linear and that it has a minum value of 0 and a maximum value of 20. This is achieved by passing the array
[0, 20] as an argument to the
domain function on line 2 of the above. The code on line 2 then specifies the
range that is used to equally space out the 0 to 20 units. In this example we are using the available width of the svg document.
The exact same logic is used to create a converter function for the y scale but this time, the height of the svg document is used as the
1 2 3
The next step is to draw the x and y axis complete with graduated labels. The following code creates the x axis:
The x-axis looks like this:
1 2 3 4 5 6
d3.svg.axis on line 1 unsurprisingly returns an instance of the axis object.
xScale converter reference we created earlier. The labels or ticks as they are known as in d3 speak will be graduated with respect to the
[0, 20] domain array of min and max values we specified.
innerTickSize function of the axis object is called to create the horizontal lines that are vertically aligned from each label or tick. I struggled with a good way of creating the gridlines for a long time and it turns out you need to pass in a negarive argument like
-height in line 2 of the above because we want the lines to fill the full document and if we do not pass a negative value then grid lines flow down from the labels and not up. You can see this by adding and removing the line from the jsbin.
The yAxis is created in a similar fashion only the horizontal grid lines are creating by passing in
-width into
innerTickSize to create the horizontal lines.
Positioning the line and circles was very easy after I had my grid created and my scales set up. The line is created below:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
xScale and
yScale converter functions are used to place the line on the 0..20 scale.
The circle and text label objects that specify the coordinates of the end points follow a similar approach:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
What is interesting about the above code is the
data function call on lines 5 and 16. I liken this to data binding and a circle or text object is created for each element in the
lineData array on line 1.
What I found confusing about the above code when I first encountered it is that
selectAll works on elements that you are going to create rather than what you have created. The
enter function on lines 6 and 17 is used to add the new elements to the document as the data changes.
All that is left is to display the code that handles the drag events:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
The above code creates a drag function that I can attach to elements of the document.
I struggled for a while with getting the correct text for labels of the coordinates of the end points of the line and the main header label. The drag event handler on line 3 gets passed a
d argument which is a d3 behaviour object that has the x and y mouse cooridinates of where the mouse was dragged to. I had to use
xScale.invert and
yScale.invert to get the correct scaled cooridinates for the text labels. The invert function returns the inverse mapping of range to domain. The rest of the code just positions the elements to the new mouse positions.
The drag function is then attached to each circle as it is created on the last line of the code below;
1 2 3 4 5 6 7 8 9 10
This was a problem I recently faced on the application that I am working on. We have a large table of infinitely scrolled rows of contact data that had links to the detail of each contact on each row. We started off with the links redirecting to a new route that displayed the individual contact's details. This meant that when you clicked the back button from the detail view, the table would be re-renderd from scratch.
I came up with quite a nice and not so technical solution that avoided many dark hours of development. I came up with the idea of sliding out the view of the contact detail from the same route that contains the table. This means the user never loses their place in the table. Throw in some css3 animations and I am very happy with the solution. Below is an animated gif that shows what I have christened the
x-drawer component:
Here is a working jsbin which shows the code in action. The
x-drawer component is a container for other components and is declared in its nested form and any component can be placed inside it:
I actually use the component helper in the production app as I now use the drawer a lot but in the above gist I simply have a property
showDetail that when set to true will activate the drawer.
x-drawer component is actually very simple and the sliding animation is achieved with css3 animations and specifically css transitons that enables the drawer to slide out slowly rather than just appear. I used a combination of
translateX and
transform to slide out the view.
Another requirement that I had thrust apon me was to make sure the drawer was closed if the user clicked anywhere outside of the drawer. Below is the code that creates an overlay on the remaining screen real estate that when clicked sends the action to close the drawer:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
This was actually quite a simple solution to a difficult problem. My first thoughts where that I need to work on the performance of rendering the table but with this solution, the table is always present as we don't have to naviagate away.]]>
The pendulum between server heavy app and client heavy app. has swung back to the client again for this epoch and single page applications are all the rage. This would have seemed like insanity at the turn of the century but advances in browser technology and a demand for more ambitious applications has led us to the now infamous
SPA. Our programs live a lot longer in the browser than they used to. Gone are the days when we could rely on a browser refresh to reboot the browser code and rebuild clear all our objects from memory.
reactjs has come up with a beautfiul top down, one way data push that can simulate this behaviour by abstracting away that gargantuan side effect known as the DOM into a virtual DOM to diff against the previous state. Reactjs has embraced functional programming and so should you.
Functional programming favours functions that, for a given input, will consistently return the same output. A pure function does not depend on and does not modify the state of variables outside of its scope. When a function performs any other action, apart from calculating its return value, the function is impure. A program or function is said to have side effects if it can produce different outputs given the same input.
A very simple example of a pure function is below:
Referential transparency is the ability to freely replace an expression with its value and not change the behaviour of the program. We can show that the
mult function is both pure and
referentially transparent with the code below:
1 2 3 4 5 6 7 8 9
Replacing the call to
mult with the result does not alter the output of the computation.
Below is an example of a function that relies on a global variable to calculate its output:
1 2 3 4 5 6 7 8 9 10 11 12
We can clearly see that providing the same input each time does not give us the same output each time.
Side effects are functions that rely on the outside OR can be functions that alter the outside world. The ubiquitous
Hello World program is actually a side effect because it alters the state of the output on the screen. A call to
console.log is a side effect. All IO is side effect laden, reading a file from a disk is a side effect because it might throw an exception because the network is unavailable. We therefore cannot guarantee the result of calling the function.
Any function that does not return a value will more than likely have side effects because it is probably mutating some external state.
Our programs would not be very practical without side effects and the goal of functional programming is not to eliminate side effects but instead we want to limit them and also more importantly, isolate them. How can we limit side effects in the sea of mutation that is javascript? The first thing we can do is to use immutable data structrues.
I think the penny is starting to drop with many in the javascript world about how sensible immutable data structures are. A data structure is immutable if it cannot be changed after it has been created.
In the chaotic realm of the single page application, I find it very reassuring to know that after I have created an object or assigned a value to a variable, it will not be changed by some well meaning code outside of my control. A lot of SPA frameworks use two way data binding to bind objects to DOM elements or other structures. I have also had hellish results with using observation through
Object.observe or some other mechanism of reacting to state changes, I now consider this to be an anti-pattern.
es6 has introduced the
const keyword which is analogous to
final in java, it does not mean that all data structures defined with the
const keyword are immuable but it does mean they cannot be reassigned once they have been assigned. The code sample below will illustrate this:
1 2 3 4 5 6 7 8 9 10 11
If we want full immutability then we can use something like immutable-js or mori. Both libraries provide persistent data structures for your use. The data structures are called persistent because they always presist a previous version of themselves when modified.
Below is an example of
immutable-js that illustrates this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
You can see from the above that we can check equality by value and not reference on
line4 when comparing
list1 and
Also illustrated is how
map2 returns a reference to
map1 on
line 7 because no change was made to the underlying hash and on
line 11,
map1 remains unchanged and a new version of the data structure is returned after changing or adding a new value to part of the data strurcture. I hope you can see how we could use persistent data structures to trivially hookup undo and redo functionality (more on this later).
Imperative programming works by changing programming state to produce answers. Conversely, functional programming produces answers through stateless operations.
This brings us back to function purity, our programs are easier to reason about if we can be sure that given the same input, we get the same output. We want to avoid functions that reference member variables or any thing outside of the functions environment wherever possible.
Here are some things to consider everytime you create a function in javascript:
I blogged here here about using a real world example to limit side effects in an emberjs application and here about how you can use persistent data structures in an emberjs application to implement basic undo and redo functionality.
A higher order function is either:
I am going to concentrate on the latter and I am going to first of all use partial application.
Wikipedia gives the following definition of partial application:
partial application (or partial function application) refers to the process of fixing a number of arguments to a function, producing another function of smaller arity
If we return to our
mult function that I showed in the beginning, we can create a new function
double by using partial application:
1 2 3 4 5
line 3 of the above, I am using the lesser known property of bind that after the first argument where you can specify a context, every parameter after the first will be prepended to the list of parameters when invoking the bound function.
We could rewrite the
double to return a function like this:
1 2 3 4 5 6 7 8 9 10 11
We now have a
makeMultiplier that can create many different types of functions based on
A more practical use of a higher order function is the
maybe function below that can take a function and return a null safe version:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
Here we create a new null save function that is returned from the
maybe function. We can now create other functions from this
maybe function that will handle null values.
Another benefit of higher order functions is to take 2 or more functions and combine them into one. Below is an
and function that will perform a logical and on the output of two functions:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
There are a number libraries that go much further with respect to functional programming:
emberjs and as much as I find myself agreeing with
reactjs's take on things, I simply don't have the energy or the will to learn another javascript framework. I also think it is bad to learn another way to do the same thing in your spare time. You need to push your brain into interesting and new avenues.
I'm using
clojure to solve these programs and it is quite nice to not have to worry about persisting data or learning the latest du jour framework.
I have found myself using the same pattern over and over again when iterating a sequence that might decrease due to some condition and accumulating a value while doing this. Below was my bog standard way of doing this:
1 2 3 4 5 6 7
The above code reduces each item in the sequence by the smallest value and then filters out any values that are zero or less (lines 2 and 3). If there are any values left, the function recursively calls itself until the sequence is empty. On each call to the function, the count of remaining elements in the sequence is added to an accumulator argument
I have been using this pattern for a while now but it did not seem to me to be idiomatic clojure. I did some research and the refactoring below is a huge improvement in terms of modularity, readibility and being more idiomatic:
1 2 3 4 5 6 7 8
The first step was to isolate in a new function the logic that performs the filtering on the sequence. I have created a
cuts function on
line 1. This improves the modularity.
process function on line 5 uses the thread last macro. Both the thread macro
-> and the thread last macro
->> make the code easier to read by allowing you to use an imperative style rather than nesting the calls. The thread last macro inserts the first argument that you pass to it as the last argument to each of the forms.
Below are some simpler examples of the thread last macro that should illustrate how the argument fills in the last argument for each of the forms:
1 2 3 4 5 6 7 8 9 10
If we return to our example, we can use
macroexpand to expand out the macro to its nested reality:
1 2 3 4
Below is the output of the
macroexpand call:
The first argument in this case is supplied via the iterate function on
line 6 that generates an infinite lazy sequence by taking two parameters, a function and a seed value. The seed value in this case is the vector
[1 2 3 4 3 3 2 1] and this is initially passed to the
cuts function.
iterate will then infinitely call
cuts passing in as an argument, the previous call to
map is used to apply a function to each item returned from the
iterate form and we use
count as the function to transform the result of each call to
take-while is used to constrain the infinite nature of
iterate and as soon as the
pos? function returns false, the results are returned to the calling function. We use
pos? to check whether there are are any elements that are not zero.
take-while will also accumulate the
count results and return them to the calling function instead of using an accumulator argument like I used in my original example.
I really like how this turned out and it is definitely more idiomatic clojure than my original version and I think this is a good barrier to get past in my journey into clojure.]]>
There are a number of ways of doing this and I, like many have tried to solve this problem myself before realising that it is not a path you should go down.
I can flesh this out with an example that I originally solved using a computed property that resolved a promise.
I inherited a nasty bit of code on the server or API side of the project that I was working on that stored the relationship of different types af object in a generic postgres database column that used serialized yaml as the format to compound the uselessness. This is particularly wrong for a number of reasons such as you can't query the sucker unless you use regular expressions. It is completely unmaintainable and you should never, ever do this and Edgar F. Codd who gave us relational database theory would be turning in his grave.
An example where this was used is in a user's activity feed that contains audited events for a user of the application. For example if the user or contact sent an email then their activity feed would contain an item like this:
1 2 3 4 5 6 7 8
meta field on
line 7 comes from the serialized yaml column and is used as a generic bucket that can contain different types of relationships or other junk, making it extremely difficult to work with. The answer to how to deal with this is refactor the server code and never, ever use serialized YAML but if you are stuck with this type of nonsense then how would you satisfy the
meta.email_id property.
When I first encountered this problem, my answer was to use a computed property that resolved a promise and then set itself:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
line 11 of the above, I set the property when the property resolves.
This will more or less work and here is a jsbin that shows an example of how to do this.
There are a number of things wrong with this approach, namely we are trying to treat something that is inherently synchronous in an asynchronous manner. The cp will fire a number of times due to the promise resolving and I have had a lot of pain with ember and observing dependent keys. This can lead to the property referencing a partially resolved object or you can get cascading events on other cps and observers that reference a key firing in a sometimes recursive manner. These are situations I now avoid like the plague and if you have any sense, you will heed my battle weary tone and avoid them too.
I've also seen computed properties that reference promise objects or have dependent keys on the state of the promise, but that is far too contrived to be credible and will lead to pain. You will have partially resolved data and cascading events triggered. Don't do this.
I develop with ember a lot different now than I did this time 12 months ago.
If you feel you need a computed property that will resolve a promise and you have read this, the answer is…….DON'T.
So what do we do?
Subscribing to data events throughout your application by using observers or waiting for computed property keys to update and trigger actions creates overhead but more importantly makes your application difficult to reason about and in my experience causes unreliable and inconsistent behaviour for reasons I have been writing about for a while now.
When data is passed from above rather than being subscribed to, we can react only when we know something has changed. React's flux has popularised the top down approach and it makes nothing but sense.
So the answer is to let the resolved property be passed in from above in a top down fashion rather than listening for it to happen. Ember is on board with this philosophy and it goes by the meme data up and actions down although I think this could do with some better fleshing out.
So the first refactoring is to create a service that will be charged with resolving the
activity instance and taking care of unwrapping this horrible
meta hash that can contain all kinds of junk. I want this encapsulated and ready to use anywhere in my code. With this in mind, I have created an
ActivityService that is injected into all components through this
1 2 3 4 5 6 7 8 9 10 11 12
A scaled down version of the
ActivityService is below that takes care of loading the activity and unpacking this now infamous
meta field:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
The above code returns a promise that when resolved, will return a simple hash rather than the resolved ember-data instance. I prefer not to bind or work directly with the ember-data instances and I discussed this the benefits of this in this post. I have created a simple
shallowCopy extension to the
DS.Model class that creates a shallow copy of the ember-data instance:
1 2 3 4 5 6 7 8 9 10 11 12 13
In the original example, I iterated over the user's activities like this:
I will replace this with a component:
ActivityFeedComponent creates an array of activity hashes by calling out to the
ActivityService and only pushing the resolved instances onto the
activities array when the service has done what it needs to do:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
This will give me so many fewer problems than resolving the promise in a computed property as I did in the original example. I only push onto the
activities array when the service has done what it needs to do. I am also working with copies of the ember-data instance which will curtail any unwanted side effects that I might encounter. I will sleep better with this code.
activity-feed component's template simply looks like this:
Here is a jsbin that brings it all together.
So my message is clear, don't resolve promises in your computed properties, nor should you have dependent keys on
isFulfilled as I see some advocating.
You have been warned.]]>
The move to ember 2.0 will see ember become more functional but I think it needs to go further and drop a lot of the class based paradigms to make it more robust.
I'll quickly run through the important tenets that could make your code more robust if you can employ them:
You should always strive to make your functions as pure or side effect free as possible. Wikipedia gives the following definition for a pure function:
A pure function is a function where the return value is only determined by its input values, without observable side effects
Another way of expressing the above is that a pure function will always return the same value when given the same arguments.
Below is the most basic of basic examples of a pure function
1 2 3
This function is pure because it will always return the same result, given the same input. It only reads local variables and it only writes to local variables. This is also sometimes referred to as referential tranparency because the expression can be changed with its value without effecting the behaviour of a program. For example if we used the
addOne function like this:
We can replace the expression with its value and still get the same result:
1 2 3
A simple example of an impure function is below:
1 2 3 4 5 6 7 8
The side effect of this function is that it changes the value of the
number variable each time it is executed. The example above is not referentially transparent because if we call
sideEffect with 3 we would get a different result each time.
On the surface dealing with only pure functions is very limiting, we would need to avoid things like
new Date or
Math.Rand because they always return a different value.
console.log is also on the banned list because it accesses a global variable. In fact, any function that takes an object as an argument is potentially subject to impurity. The DOM is one big huge stateful side effect waiting to happen.
The bottom line is that if you are dealing with javascript, you will always be dealing with some degree of impurity or our programs would not be very useful. What we need to do is try and minimize this.
Ember's Handelbars helpers can be pure functions but I have seen an RFC recently that wants to add all sorts of state and life cycle events which is something that made me shudder. I worry that if this rfc is pushed through then it will complicate something that is very useful and can be side effect free.
Idempotence entered the vernacular or at least resurfaced when REST went mainstream. An idempotent operation is one that has no additional effect if it is called more than once with the same input parameters. For example moving an item from a set can be considered an idempotent operation or deleting a record by GUID is idempotent becuase the row stays deleted.
Purity and idempotence are completely orthogonal, a pure function does not have to be orthogonal and vice versa. An idempotent function can cause idempotent side effects, a pure function cannot.
In functional prograaming, the ideal situation is that there is never mutation. I blogged previously about some of the benefits of immutability and gave an example of how it might be used.
One of the traps I fell down when I first started developing with ember was to observe changes on mutable arrays like this.
1 2 3
I see this type of code in a lot of stackoverflow answers and blog posts but I now consider this to be an antipattern. Two way databinding was one of the things that first drew me to ember but ended up causing me no end of pain. I think two way databinding still has its place for binding simple literals like an input's value attribute to a string prop of a value but binding object to object causes pain. I believe in ember 2.0, binding will be one way only by default and this is the right move. You can stop this now by ensuring you use
Ember.computed.oneWay instead of
1 2 3 4 5 6 7
As Charles Lowell rightly pointed out in the comments, it is possible to create
readonly computed properties that will raise an exception if a
set is an attempted.
1 2
I'll certainly be using this from now on.
One of the benefits of immutability is that diffing is done by value and not by reference, just think how easier diffing javascript would be if the following was true out of the box:
Libraries like om in clojurescript use diffing on their immutable datastructures to great effect to negate needless re-renders with reacts virtual DOM.
But the main reason that I am starting to see the main use case for immutability is that, it makes your code much easier to reason about and you can avoid side effects using immutable data structures. For me, the biggest thing about using immutable data structures is that I am completely safe from some unkown mutation happening which in a long running single page application is great for my peace of mind. I've been surprised too many times in the past.
You don't have to use a library like seamless-immutable but you should try and tranfrom or create new objects or arrays rather than mutating existing objects. You should favour
map or
filter over
forEach must have a side effect somewhere to accomplish anything. The only time I would use
forEach is for something like this:
Imperative programming works by changing programming state to produce answers. Conversely, functional programming produces answers through stateless operations.
A good example of the contrast is looping, an imperative approach is to use looping:
1 2 3 4 5 6
The loop produces its results by constantly changing the value of
x. A functional approach would use recursion:
1 2 3 4 5 6 7 8 9 10
Functional programming requires us to write stateless expressions and keep our data immutable.
If you perform a google for functional javascript you will get plenty of examples of sorting lists or simple number crunching. I have found very little about how to use functional techniques for the type of situations you face on a day to day basis as a web dev or your ongoing battle with the DOM. So I am going to use a real world example that I worked on within the last week of writing this blog post.
The last thing I worked on was a custom query builder where the user builds a query on the fly from the html elements he is presented with. Query items can be added and removed: If I had attempted something like this 12 months ago, I would have used rampant mutation, observers and two way binding in a huge chaotic side effect soup. I have my battle scars and I see the world differently. I will now detail my solution. I have created this jsbin that you can play along at home with and is a pretty damn accurate duplicate of how I solved this.
The truth of the matter is that ember is very, very, very stateful and adheres more to a class or object based methodology. If you want to reference data structures in your templates then you need to create member properties and reference them.
My goal for any new piece of code that I create is to keep things as side effect free as possible. I will most definitely never use the
Ember.observer primitive, I use few computed properties if any and rarely use two way databinding. I will work with immutable copies of anything persistable. I want to keep surprises to a minimum and I want to keep things in my control and not be working or waiting for the run loop which is outside of my control.
In this custom query example, there is only ever one active query that you are manipulating, you are either building a new one or you are updating an existing query. These queries are persistable and I have modelled it as a parent query that contains a child collection of query parts. Here is the ember data CustomQuery definition:
1 2 3 4
And here is the queryPart:
1 2 3 4 5
My main goal for working with instances of these ember-data models is to not work with them. I am going to create copies of the data structure and work with those and only copy them back into the models when I want to persist anything. The last thing I am going to do is to use two way databinding to bind directly to the model properties. I have been down that path and it is the road to hell.
At any one time, we are dealing with a collection of query parts and we have query-builder component to add and remove query parts. Below is a screenshot of how the elements look:
IndexRoute in the jsbin, either creates an empty array and assigns it to a
queryParts variable that is passed to a
query-builder component, or if we are dealing with a persisted query from the models above then we create a raw hash to pass to the component:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
The user can navigate to the
IndexRoute via a link that will have the custom query id in the query params that you can see on
line 5 of the above code. I am creating a hash rather than using the ember-data model directly to keep things side effect free. I have already made my life much easier.
Here is the how query-builder component is referenced on the parent template or the index template in the jsbin. The binding of the
queryParts that are passed into
query-builder are sadly still two way bound at this time of writing with
ember 1.11.1 but we will work with them as if they were one way bound.
Below is the template for
On lines
2 to 4, a
query-part component is rendered for each part of the query. The template for
query-part.hbs is below:
query-part component will fire off queries in response to either user input in the textbox or changing the query part operator in the dropdown.
Below is the code for the
query-part component
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
We want to adhere to data down and actions up. So queries are bubbled up from this component to the controller.
If input is entered into the text input, the
keyDown handler on
line 35 calls
sendQuery on
line 12 that will
debounce a call to
The code in
executeQuery on lines
15-34, could definitely be accused of being more jQuery than ember. If that is the case, then I am guilty as charged. I am using simple selectors to extract the values from the element rather than relying on two way databinding. I don't want any surprises about values not being sync'd, I just want to extract the values from the elements when the query is run. There really is no need for it to be any more complicated than that.
I then bubble the newly constructred immutable data structure up to the parent component by calling the
modifyQuery action. I don't necessarily need these structures to be immutable but I want to guard against any side effects I might encounter unexpectedly. This action is then bubbled up to the controller where a it uses the raw hash to execute a
findQuery on the main data that the query is filtering:
1 2 3 4 5 6 7 8
When it comes to saving the query, the
query-builder component calls a
saveCustomQuery action on the parent controller, passing the raw array of query parts which are plain old javascript objects and either creates a brand new
CustomQuery model and persists it or overrides the existing
queryParts collection of the existing instance:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
There are only 2 parts in this piece of functionality where I deal with the actual ember-data instances. The first is when I am creating copies of the structures to feed to the components and here when I am persisting the changes back to the server.
Congratulations if you made it this far, this is a long post. Staying side effect free and dealing with pure functions is next to impossible when working with something as stateful as the DOM. Ember also is very stateful and class based. I've used a real world example because there is no better example to illustrate just how challenging it is. I have 100% failed on the pure function front. But I've tried to stay as side effect free which for me means dealing with copies of anything persistable, avoiding observers, computed properties and two way data binding wherever possible. I've tried the other way and it is not pretty. The code I've described will give me a lot less headaches than other ways I might approach this.
I'm interested to see if we can take a much more functional approach with ember 2.0 but the rfc that wants to pollute handlebars helpers with state and life cycle events is not a step in the right direction.
I've heard of the benefits of functional programming for years but I now realise how sensible they are and how they lead to more robust code. When working in the chaotic world of the single page application, they make nothing but sense.
I would love any feedback at all on this. Good or bad, state your case.]]>
I would then create an observer on this bound value like this:
1 2 3
This has generally led to a world of pain that I lamented about in this post.
What I do now in this situation is use something like the input DOM event:
1 2 3 4 5
I can do any transformations in this event handler without the pain of obsevers or 2 way binding, I am in control of what is happening.
This is all well and good but what is not good is that this is not testable with the current ember test helpers.
There is the
fillIn test helper but this will just set the value of an input to the supplied string without raising any key events:
1 2 3 4 5 6 7 8
What I needed was a way for the appropriate key events to be raised after every character. I might also have code in
keydown and
keyup for example.
With this in mind, I created this test helper to meet my requirements:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
The above helper will input the text one character at a time and raise any supplied events.
For example if I only want to raise an
input event with each character then I would use it like this:
1 2
Or if I want to raise more than one event then I can supply an array of input events:
1 2
You can use the helper like this in an
test-helper and I have created this pull request to get it included with the ember source.
1.7.1 and I've reached the point of no return with regard to passing action names down a component hierarchy and then bubbling them back up using
sendAction. I believe the problem is still present in recent versions of ember and we need to somehow make this more user friendly.
I will illustrate the problem with an easily grokked todo example before giving a couple of solutions.
Here is a list of todos:
Here I am creating a
todo-list component and specifying an action that I want called when a todo is checked to signify it is finished.
Below is a route with a
finishTodo action that is referenced in the above code sample:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
All good so far but with the current state of data down and actions up, I need to pass this action name down to each child component that would use
sendAction to call it.
In the example, I need to specify the action name in each
todo-item component that the
todo-list component creates:
I then need to bubble this up from the child
todo-item component:
1 2 3 4 5 6 7 8 9
This gets bubbled up to the
todo-list component that uses
sendAction to bubble this up to the route:
1 2 3 4 5 6 7 8 9
Here is a jsbin that shows the up and down duplicity in its entirety.
One sure sign of tight coupling is the number of places/files that you need to change for one method name change. As developers, we should be seeing this type of thing as a red flag that requires attention.
One way round this is to create a helper to package up the action, the context and any arguments that are needed to call the action. This can be achieved with a handlebars subexpression and a handlebars helper.
I can refactor the
todo-list component to this:
The above code uses a handlebars subexpression to create a method named
action on each
todo-item component, I pass in the
targetObject which in this case is the
controller but you can reference anything that is accessible and has an actions hash, I also pass the action name I want called and any additional arguments.
The subexpression calls this handlebars helper that returns a higher order function:
1 2 3 4 5 6 7 8
I can then call this action in the
todo-item component:
1 2 3 4 5 6
Here is a jsbin of the above.
This makes things a little more sane for me and I can eliminate a lot of code. Another alternative that I am considering is to enhance the global event bus I previously blogged about.
The alternative is to carry on with what is currently on offer but I've just reached my limit with that.]]>