HOWTO: Create a Bar with interactive multiple select
- Introduction
- Persisting state with the localData variable (HTML5 local storage)
- Persisting state with AJAX
Introduction
You can, relatively simply, create a Bar chart
that permits the
selection of
bars - and which then sends that information back to the server.
This allows
you to select bars on the Bar chart
and have that information recorded by the
server so that when the Bar chart
is shown again the same bars are selected.
Optionally, you can also have the selection control something else based on
the selection (also by using ajax
and communicating with your server -
the possibilities are down to you).
And by using the local storage api
- ie the window.localData
variable) you can have
the data persist on just the client - so no sending it back to the server
with ajax
.
Here's an example of the code that's necessary to get the basic multiple selection up and running.
<script> // // This state variable remembers the state of the bars and whether they're selected or not // state = { selected: [] }; // // Create and configure the Bar chart // bar = new RGraph.Bar({ id: 'cvs', data: [4,8,6,3,5,8,9], options: { marginInner: 30, backgroundGridVlines: false, backgroundGridBorder: false, yaxis: false, xaxis: false, xaxisLabels: ['Monday','Tuesday','Wednesday','Thursday','Friday','Saturday','Sunday'], title: 'A Bar chart with multiple select enabled', titleBold: true, titleSize: 16 } }).draw() // // The mousemove event just returns true so that the pointer is changed when it's over the bars. Note that // this on() function is chained to the draw function above - I've just put it on its own line for clarity. // .on('mousemove', function (e, shape) { return true; }) // // Again - this on() function is chained to the above function - it's just separated out for clarity. // It uses the index of the bar (which is the same as the dataset property) that was clicked (it can // be found in the shape object) and toggles that index between true and false in the state array. // .on('click', function (e, shape) { state.selected[shape.dataset] = !state.selected[shape.dataset]; RGraph.redraw(); // // Again - this on() function is chained to the above function - it's just separated out for clarity. // It's a function that uses the RGraph draw event to draw highlighting over the relevant bars. // }).on('draw', function (obj) { for (var i=0; i<obj.data.length; ++i) { if (state.selected[i]) { var coords = obj.coords[i]; obj.path( 'lw 3 b r % % % % f rgba(255,255,255,0.8) s #a00 lw 1', coords[0], coords[1], coords[2], coords[3] ); } } }); </script>
Persisting state with the localData variable (HTML5 local storage)
The html5
Storage api
can be used to enable persistent state. ie The
selected
bars are remembered across page refreshes. This doesn't communicate the
information back to the server though - so the usefulness of this is
limited.
If what you need the persistence for is client-side though - this will work fine.
By using the ajax
option below - you can communicate the selection
back to the server.
<script> // Initialise the state1 variable if it doesn't exist if (!localStorage['state1']) { state1 = []; } else { state1 = JSON.parse(localStorage['state1']); } bar1 = new RGraph.Bar({ id: 'cvs1', data: [4,8,6,3,5,8,9], options: { backgroundGridVlines: false, backgroundGridBorder: false, yaxis: false, xaxis: false, xaxisLabels: ['Monday','Tuesday','Wednesday','Thursday','Friday','Saturday','Sunday'], title: 'A Bar chart with multiple select enabled' } }) // Again, the mousemove event just returns true so that the pointer is changed .on('mousemove', function (e, shape) { return true; }) .on('click', function (e, shape) { var idx = shape.dataset; // Update the state2 variable with the new status state1[idx] = !state1[idx]; // Save the state1 variable to localStorage localStorage['state1'] = JSON.stringify(state1); RGraph.redraw(); }) // Draw the highlight over the relevant bars .on('draw', function (obj) { for (var i=0; i<obj.data.length; ++i) { if (state1[i]) { var coords = obj.coords[i]; obj.path( 'lw 3 b r % % % % f rgba(255,255,255,0.8) s #a00 lw 1', coords[0], coords[1], coords[2], coords[3] ); } } }).draw(); </script>
Persisting state with AJAX
This is a far more useful example that is very similar to the one above but
with one key difference - whenever you select or unselect a bar the
current state of whatever is highlighted is sent back to the server via
an ajax
post
request.
The RGraph.AJAX.post
function is used to send the ajax
request.
The callback function is a simple one - it just shows the output of the
server-side script (which is an array of the state of the bars) using an
alert
dialog.
The code is very similar to the above example - the difference is highlighted in red.
<script> // Initialise the localData variable if need be if (!localStorage['state2']) { state2 = []; } else { state2 = JSON.parse(localStorage['state2']); } bar2 = new RGraph.Bar({ id: 'cvs2', data: [4,8,6,3,5,8,9], options: { backgroundGridVlines: false, backgroundGridBorder: false, yaxis: false, xaxis: false, xaxisLabels: ['Monday','Tuesday','Wednesday','Thursday','Friday','Saturday','Sunday'], title: 'A Bar chart with multiple select enabled (plus AJAX)' } }).on('mousemove', function (e, shape) { return true; }).on('click', function (e, shape) { var idx = shape.dataset; // Update the state variable state2[idx] = !state2[idx]; /// Save the state to localStorage localStorage['state2'] = JSON.stringify(state2); // Send the state information to the server so it can be saved // (the question mark ensures that this page is the one // that's requested. There's no need to serialise the state2 // variable as the RGraph.AJAX.post() function does that for you. The only // thing that's done in the AJAX callback function is that the // output of the AJAX request is displayed. RGraph.AJAX.post('?', {state: state2}, function (str) { alert('This is the output of the AJAX request:\n\n' + str); }); RGraph.redraw(); }).on('draw', function (obj) { for (var i=0; i<obj.data.length; ++i) { if (state2[i]) { var coords = obj.coords[i]; obj.path( 'lw 3 b r % % % % f rgba(255,255,255,0.8) s #a00 lw 1', coords[0], coords[1], coords[2], coords[3] ); } } }).draw(); </script>