UPDATE: Jiri made the point that using ic-poll
I can simplify the example even more.
Thanks Jiri!
In my last post I mentioned a nifty little live stock quote app that I built using only twelve intercooler attributes
and a couple of lines of javascript. I restructured things a bit and managed to knock it down to just ten attributes just eight!
Even better.
Again, here is the demo:
In this post, I will explain the details of the app, which was built in SparkJava, looking at each piece of functionality.
The ticker input form consists of the following html:
<form id="form" ic-post-to="/" ic-target="#main" autocomplete="off"> <input type='text' id='ticker-input' class='form-control input-lg' name='ticker' placeholder="Enter a stock ticker..."/> </form>
There are two intercooler attributes here, telling the form to post to /
and to target the #main
div, which surrounds the entire main body of the application.
You will notice a green flash on the row when a ticker is added to the table. To do this, a class is added to the
row of a newly added ticker, new-ticker
. Then the following CSS was added:
.ic-transitioning .new-ticker td { background-color: #a5d1a6; } .new-ticker td { background-color: transparent; transition: all 1s; }
This sets the background of the newly added row to a light green when intercooler first swaps in the content (the
ic-transitioning
class is on the parent content) and then transitions it to transparent. This gives the
flashing effect you see above.
On each row you will see a trashcan icon that can be used to remove a given ticker. The HTML for this element looks like so:
<a ic-target="#main" ic-delete-from="/$ticker.symbol"> <i class="fa fa-trash" aria-hidden="true"></i> </a>
This tells intercooler to issue a DELETE
to the URL corresponding to the tickers symbol, which rerenders
the table and then replaces the content of the #main
div (just like the form above).
The link to clear all tickers is implemented very similarly to the link to clear a single ticker. Here is the HTML:
<a ic-target="#main" ic-delete-from="/"><i>Clear All</i></a>
We issue a DELETE
but to /
, which clears the tickers and re-renders the main UI.
Now the tricky part, making the table update. To do this, we add the following intercooler attributes a div surrounding the table:
<div ic-poll="5s" ic-src="/">
This div will hit the /
URL every five seconds. The returned content is going to be just the
table of updated ticker information.
We use /
to serve both the top level page as well as this request. How do we do that?
Intercooler includes a parameter, ic-request
, when it issues an AJAX request, so we can test for that
parameter when determining what to render to the client:
if( "true".equals( req.queryParams( "ic-request" ) ) ) { return View.renderRaw( "ticker_table.html.vm", "tickers", tickers, "states", states ); } else { return View.renderPage( "index.html.vm", "tickers", tickers, "states", states); }
We could get even fancier and test for the target of the request, which is also included as a parameter, but this is enough for now.
In order to make the price flash green or red, depending on if it has gone up or down relative to the last price
we saw. This is done by adding an up
or down
class to the td
holding the asking
price, and then adding this bit of CSS:
.ask { color: rgb(51, 51, 51); transition: all 2s ease; } .ic-transitioning .ask.up { color: green; } .ic-transitioning .ask.down { color: red; }
When intercooler inserts the new table, cells with the up
class will start with color set to green. Then
intercooler removes the .ic-transitioning class from the element that was updated and the CSS transition takes the colors
back to the default semi-black, causing the nice flash effect.
I said there were two lines of javascript. That was exaggerating a bit, there are nine lines if you include the boilerplate as well, so lets look at it:
$(function(){ $('body').on('applicationError', function(elt, msg){ $.jGrowl(msg, { header: 'ERROR' }); }); }) Intercooler.ready(function(){ $("#ticker-input").focus() })
There are two sections here: first the standard jQuery ready function which hooks up an event handler on the
applicationError
event and shows a jGrowl notification. This is used on the server side to communicate
error messages to the client side using the X-IC-Trigger response
header, like so:
res.header( "X-IC-Trigger", "{\"applicationError\":[\"Ticker Not Valid!\"]}" );
This is a very clean way to communicate from the server to the client.
The second bit of javascript is run in the Intercooler.ready()
method, which is the intercooler equivalent
of the jQuery ready concept, but is run on every completed Intercooler request. We use this to refocus the ticker input.
And that's it! Not a lot of code for a pretty slick little UI with some nice visual effects. I hope this gives you an idea of how powerful intercooler is.
Here are links to the raw code: