Tuesday, October 29, 2013

AngularJS table sort

I've had a chance to play around with AngularJS recently. The first thing I came up against was having a table where you could sort each column by clicking the header. At first I did all sorts of crazy things like writing my own directive until I stumbled upon the orderBy filter.

The first thing I found out is that you need to keep it simple by calling a property on an object - using getter functions won't quite work. But knowing that we can take a look at the orderBy example in the AngularJS documentation. It looks handy but there is a problem around how reverse works:

<div ng-controller="Ctrl">
<pre>Sorting predicate = {{predicate}}; reverse = {{reverse}}</pre>
<hr/>
[ <a href="" ng-click="predicate=''">unsorted</a> ]
<table class="friend">
<tr>
  <th><a href="" ng-click="predicate = 'name'; reverse=false">Name</a>
    (<a href="" ng-click="predicate = '-name'; reverse=false">^</a>)</th>
  <th><a href="" ng-click="predicate = 'phone'; reverse=!reverse">Phone Number</a></th>
  <th><a href="" ng-click="predicate = 'age'; reverse=!reverse">Age</a></th>
</tr>
<tr ng-repeat="friend in friends | orderBy:predicate:reverse">
  <td>{{friend.name}}</td>
  <td>{{friend.phone}}</td>
  <td>{{friend.age}}</td>
</tr>
</table>
</div>


In the example we can view "name" normally by clicking it or in reverse by clicking on the arrow. I wanted it so that clicking again would reverse the order. It looks like phone and age do this, but can you spot the problem? the issue is they both change reverse, so if I click on phone then things will be reversed and clicking on age will give me age without reverse. What I needed was that clicking a column the first time would reset reverse, so how do we go about that?

<div ng-controller="Ctrl">
<pre>Sorting predicate = {{predicate}}; reverse = {{reverse}}</pre>
<hr/>
[ <a href="" ng-click="predicate=''">unsorted</a> ]
<table class="friend">
<tr>
  <th><a href="" ng-click="reverse = predicate == 'name' && !reverse; predicate = 'name'">Name</a></th>
  <th><a href="" ng-click="reverse = predicate == 'phone' && !reverse; predicate = 'phone'">Phone Number</a></th>
  <th><a href="" ng-click="reverse = predicate == 'age' && !reverse; predicate = 'age'">Age</a></th>
</tr>
<tr ng-repeat="friend in friends | orderBy:predicate:reverse">
  <td>{{friend.name}}</td>
  <td>{{friend.phone}}</td>
  <td>{{friend.age}}</td>
</tr>
</table>
</div>

The magic happens with ng-click and we use && to work as a control statement. Because it's an && it will only continue if the first expression is true, in this case we check to see if we're already sorting by that column. If we're not sorting by the column then we return false - so clicking on a new column will put reverse as false. The second part will then flip reverse for us if we are already sorted by that column.

Last thing to note is that we have set reverse but still need to set what we're sorting by so we put that last (so it doesn't get in the way of checking if we're already set at the column).

And there we have it, the expected behaviour without the need of a new directive or controller.

Thursday, October 3, 2013

Edge Conference

I was lucky enough to go to the Edge Conference in New York. It's a lot different to other conferences in that it is more of a round table with audience members asking the questions and it was brilliant. Most conferences you go to is full of beginner to intermediate level talks while this was jam packed 7 hours straight of high level advanced information. Even the sections I did no believe would interest me did and I learned a lot. The event isn't meant to be about learning though, it's about getting people together and have discussions that may help to shape the future of the web platform. Mission accomplished. For those of you who couldn't attend here is where you can find the videos: http://www.youtube.com/playlist?list=PLNYkxOF6rcIAhg58YwoKFHDsVBCUtNFMj

So it's a couple of weeks later and I haven't reviewed the live stream, so what follows below hopefully are the things that stuck with me, my thoughts on what was important and the takeaways. I'll break them up in to sessions:

Responsive Images


I wasn't too keen when this began. I know there are several techniques used out there and I'm sure like most web technologies one of them will win out due to ease of use and then become a standard. Boy was I wrong. The thing I didn't know about was Art Direction.

Sending an image down that's scaled differently or has different levels of compression should be easy, but what happens if you'd like to crop the picture differently for different sizes. On a large screen you might want to show a whole person while on a small screen just show the face. Progressive enhancement (which is what I always thought would win out) can't quite cater to this case.

For my money there will have to be a new file format which will hold information about the different sizes and cropping, then have the smallest image first and then the rest of the image bytes come after that (including any diffs that are needd for progressive enhancement of the original cropped image). I remember something like this being shown in the initial 10 minute presentation and seems to be the best of all worlds. The browser can read the headers and decide what parts it needs and we keep everything in a single file - now we just need a file format and editors to handle it. In the meantime though we're stuck with HTML and JavaScript hacks.

Rendering Performance


This was the one I was most excited about. Unfortunately it didn't really touch on a lot of ground I wasn't already familiar with. Doubly unfortunate was that the conference app wasn't working that well and by the time I got in the queue to ask the session was over. So I'll put forward the question now:

It is better to have stable FPS than high FPS. Is there a way we can restrict to 30FPS if we know that we're going to get spikes of computation?

I know that the first thing you should try is put these in to webworkers or split them up, but this isn't always possible. I don't believe there is a way now unfortunately except by using JavaScript to push rendering to the next frame. As a proof of concept I made: GoSloMoFo where you can see a box animate for 4 seconds with the initial 2 at 30FPS and the last 2 at 60FPS. Unfortunately it has to do this using JavaScript so it will tax the CPU more than if there was a native way to tell the browser to stay at 30FPS.

Third Party Scripts


This one was pretty unrelated to me. I realized when they asked if most people in the audience worked on web pages - not web apps and it was true. Then there is the issue of what's a web page vs a web app but luckily no-one bit. The truth is it's a matter of semantics and everyone has a different idea.  It was mostly finger pointing and basically it all boiled down to a matter of trust (at least until document.write is removed).

Real Time Data


For me this was perhaps the most exciting session. Although there wasn't a lot new that was being said - just that webRTC isn't quite ready for prime time yet, and the difference between that and websockets is one is client to server while the other is server to server - it's one of the most exciting pieces of technology coming. In fact what it got me thinking about was the possibility of a decentralized network within a network where each client page can run as a server to each other, passing the details of how to run as a server around as well as getting things from other clients. The client is the server and the server is the client - how meta. Next stop, Skynet.

Offline


I really enjoyed this one, more than I would. I haven't had the chance to work on an app that would even be useful offline (actually at catch it may have, but we were chasing other goals first). The big take away from this is something called serviceWorkers. I'd really like to look in to this more, but it seems like a proxy that can sit in between the browser's calls out and the network. If this is true then there will be a whole range of possibilities for it, from caching to offline and even invading privacy - It'll be interesting just how secure they'll be able to make it.

Legacy Clients


Basically the old "when should we drop support for X" argument. Some talk about building things for the Lowest Common Denominator and just upping everything with stylesheets and scripts. I'm a bit surprised the browser sniffing vs feature detection didn't come up a bit more as to make some of the LCD method to work you'd have to know the browser so it would have to work through sniffing. Basically this is a business decision, not a technology decision in my book.

Payments


Another surprisingly interesting session, although a fair few people left before this session. It was all new to me, but from what I gather is that there needs to be some sort of standard worked up for a "payment tunnel" (my name for it) that will be able to connect any two "payment services" to send and receive payment. That should mean that you can pay with whatever you want and the website will pick it up and send that through to whatever they have to receive payment. It just needs some buy in from the new wave of payment places like Stripe, Square, Paypal, Amazon - and hopefully the banks will follow.


Conclusion


A very worthwhile day. I went home more tired than usual and my head buzzing with information trying to form themselves in to ideas. If anything it was too much in too little time, but now I've had a chance for it to all settle down I feel like I understand more about the direction of the web as a platform and hopefully now you do to.