Tuesday 28 May 2013

A touch with style

JQTouch is a jQuery plug-in for developing native-looking web applications for mobile devices (iOS and Android). One of the great features it offers is smooth transitions between windows (mapped as structural elements in the underlying html, normally <div> elements). You can check some of its outstanding features in their demo page.


A basic example


A basic test may look something like this:
1:  <!DOCTYPE html>  
2:  <meta charset="utf-8">  
3:  <html>  
4:   <head>  
5:     
6:    <!-- Local jqTouch -->  
7:    <link rel="stylesheet" href="lib/jqtouch-1.0-b4-rc/themes/css/apple.css" title="jQTouch">  
8:    <script src="lib/jqtouch-1.0-b4-rc/src/lib/zepto.min.js" type="text/javascript" charset="utf-8"></script>  
9:    <script src="lib/jqtouch-1.0-b4-rc/src/jqtouch.js" type="text/javascript" charset="utf-8"></script>  
10:    
11:    <script type="text/javascript" charset="utf-8">  
12:     var jQT = new $.jQTouch({ });  
13:    </script>  
14:    
15:   </head>  
16:    
17:   <body>  
18:    <div id="colors">  
19:     <div class="toolbar">  
20:       <h1>Colors</h1>  
21:     </div>  
22:     <ul class="edgetoedge">  
23:      <li class="arrow"><a href="#blue" class="flip">Blue!</a></li>  
24:      <li class="arrow"><a href="#red" class="flip">Red!</a></li>  
25:     </ul>  
26:    </div>  
27:    
28:    <div id="blue">  
29:     <div class="toolbar">  
30:       <a class="button back" href="#">Back</a>  
31:     </div>  
32:     <p>Blue</p>  
33:    </div>  
34:    
35:    <div id="red">  
36:     <div class="toolbar">  
37:       <a class="button back" href="#">Back</a>  
38:     </div>  
39:     <p>Red</p>  
40:    </div>  
41:    
42:   </body>  
43:    
44:  </html>  
45:    

The example can be seen on your mobile device (iOS or Android) scanning the QR code below [1].
JQTouch fires transitions on each hyperlink (<a> elements in lines 23 and 24 in the above example.
The JQTouch library hooks these events for you, without having to worry for anything else. You can select the type of transition by specifying the class for the <a> element (a "flip" transition in the example above).


Transitions without hyperlinks


But what happens when you want to attach "click" events and transitions to a non-hyperlink element? For example, if you want to fire transitions on different elements of a SVG.
Things seem to be less easy in that case.
Here is the easiest way I have found to do the job. The idea is to have empty <a> elements that are fired "manually" when the non-hyperlink elements are "clicked".

Here is a minimal, full-working example:
1:  <!DOCTYPE html>  
2:  <meta charset="utf-8">  
3:  <html>  
4:   <head>  
5:    <!-- Remote D3.js -->  
6:    <script src="http://d3js.org/d3.v3.min.js"></script>  
7:    
8:    <!-- Local jqTouch -->  
9:    <link rel="stylesheet" href="lib/jqtouch-1.0-b4-rc/themes/css/apple.css" title="jQTouch">  
10:    <!-- <style type="text/css" media="screen">@import "lib/jqtouch-1.0-b4-rc/themes/css/jqtouch.css";</style> -->  
11:    <script src="lib/jqtouch-1.0-b4-rc/src/lib/zepto.min.js" type="text/javascript" charset="utf-8"></script>  
12:    <script src="lib/jqtouch-1.0-b4-rc/src/jqtouch.js" type="text/javascript" charset="utf-8"></script>  
13:    
14:    <script type="text/javascript" charset="utf-8">  
15:     var jQT = new $.jQTouch({ });  
16:    </script>  
17:    
18:   </head>  
19:    
20:   <body>  
21:    <div id="colors">  
22:     <div class="toolbar">  
23:       <h1>Colors</h1>  
24:     </div>  
25:     <div id="mysvg">  
26:       <a id="redlink" href="#red" class="flip"></a>  
27:       <a id="bluelink" href="#blue" class="flip"></a>  
28:     </div>  
29:    </div>  
30:    
31:    <div id="blue">  
32:     <div class="toolbar">  
33:       <a class="button back" href="#">Back</a>  
34:     </div>  
35:     <p>Blue</p>  
36:    </div>  
37:    
38:    <div id="red">  
39:     <div class="toolbar">  
40:       <a class="button back" href="#">Back</a>  
41:     </div>  
42:     <p>Red</p>  
43:    </div>  
44:    
45:    <script>  
46:     var w = document.documentElement.clientWidth;  
47:     var h = document.documentElement.clientHeight;  
48:     var svg = d3.select("#mysvg")  
49:      .append("svg")  
50:      .append("g");  
51:    
52:     svg  
53:      .append("rect")  
54:      .attr("id", "redrect")  
55:      .attr("width", w)  
56:      .attr("height", h/2)  
57:      .attr("x", 0)  
58:      .attr("y", 0)  
59:      .style("fill", "red");  
60:    
61:     svg  
62:      .append("rect")  
63:      .attr("id", "bluerect")  
64:      .attr("width", w)  
65:      .attr("height", h/2)  
66:      .attr("x", 0)  
67:      .attr("y", h/2)  
68:      .attr("fill", "blue");  
69:    
70:     d3.select("#redrect").on("click", function(){$("#redlink").trigger("tap")});  
71:     d3.select("#bluerect").on("click", function(){$("#bluelink").trigger("tap")});  
72:    </script>  
73:    
74:   </body>  
75:    
76:  </html>  
77:    

In lines 26 and 27 we have a couple of these <a> empty elements.
In lines 70 and 71 we attach "click" event listeners on the svg rects that will fire the "tap" events of the empty <a> elements. It is important to fire the "tap" events, or the flip transition will not fire.

You can play with this example in your mobile device scanning the QR code in [2].

This solution is not what I would call an elegant one. In fact I find ugly having to use the empty <a> elements. But it is the only way that I have found to do the trick (and I have dug in the JQTouch code trying to find a better way to solve the problem)
If anyone knows a better solution, please, leave a message below, I would love to hear about it.

QR codes with the examples shown in this post:
[1]                                                                                      [2]


Monday 13 May 2013

Parallel and ordered

One of Go's greatest features is its built-in support for concurrency. It allows to easily express concurrency algorithms without needing third party libraries or similar solutions as in other programming languages. This feature combined with its multi-core capabilities allow to easily express algorithms that perform several tasks in parallel easily and efficiently. For example, for me it is a common situation to write algorithms that perform a single task over a series of elements or records, like processing a group of input files.

In Go, a naive and simplify way to accomplish this kind of tasks would look something like:
1:  package main  
2:    
3:  import (  
4:       "fmt"  
5:       "runtime"  
6:       "time"  
7:  )  
8:    
9:  func init() {  
10:       runtime.GOMAXPROCS(4)  
11:  }  
12:    
13:  func send(ch chan int, i int) {  
14:       time.Sleep(2e9) // Processing goes here  
15:       // The output is sent via a specialized channel  
16:       ch <- i  
17:  }  
18:    
19:  func main() {  
20:       ch := make(chan int, 4)  
21:       fired := 0  
22:       for _, i := range []int{0, 1, 2, 3} {  
23:            fired++  
24:            go send(ch, i)  
25:       }  
26:    
27:  LOOP:  
28:       for {  
29:            select {  
30:            case v := <-ch:  
31:                 fired--  
32:                 fmt.Println(v)  
33:            default:  
34:                 if fired == 0 {  
35:                      break LOOP  
36:                 } else {  
37:                      continue  
38:                 }  
39:            }  
40:       }  
41:  }  
42:    

If you run the above program you would get something like this:
 $ go build goChans.go && time ./goChans   
 1  
 0  
 3  
 2  
 real     0m2.006s  
 user     0m2.004s  
 sys     0m0.000s  

There are two things to note here:
  • The four goroutines fired in line 24 are effectively run in parallel (the total time of the program is roughly 2 seconds even when the workers slept for 2 seconds each)
  • The order of the output is not ordered, meaning that the order in which the goroutines finish determines the order in which their messages are printed.
This last point means that in real examples, the time a goroutine spends in computing determines the order of the global output of the program. This may or may not be a problem depending on the requirements of your program.

If you want the order to be preserved you have to tweak the program a bit. Here I will present  2 options that rely on channels to do the task. Both helped me to understand better how channels work and how to use them effectively.



Solution 1: Synchronization channels


The first alternative uses specialized channels to synchronize how the results are passed down the main output channel:
1:  package main  
2:    
3:  import (  
4:       "fmt"  
5:       "runtime"  
6:       "time"  
7:  )  
8:    
9:  func init() {  
10:       runtime.GOMAXPROCS(4)  
11:  }  
12:    
13:  func send(ch, prevc, nextc chan int, i int) {  
14:       time.Sleep(2e9)  
15:       <-prevc // wait for prev goroutine to send its result  
16:       ch <- i  
17:       nextc <- 0 // notify next goroutine  
18:  }  
19:    
20:  func main() {  
21:       ch := make(chan int, 4)  
22:       fired := 0  
23:       prevc := make(chan int)  
24:       origc := prevc  
25:       nextc := make(chan int)  
26:       for _, i := range []int{0, 1, 2, 3} {  
27:            fired++  
28:            go send(ch, prevc, nextc, i)  
29:            prevc = nextc  
30:            nextc = make(chan int)  
31:       }  
32:       origc <- 0  
33:    
34:  LOOP:  
35:       for {  
36:            select {  
37:            case v := <-ch:  
38:                 fired--  
39:                 fmt.Println(v)  
40:            default:  
41:                 if fired == 0 {  
42:                      break LOOP  
43:                 } else {  
44:                      continue  
45:                 }  
46:            }  
47:       }  
48:  }  
49:    

These specialized channels are connected in the goroutines in such a way that when the first one finishes its computation, it stores the value in the main output channel and sends a signal to the next goroutine telling her that the output channel is available. This is repeated for all the goroutines.

These synchronization channels are first fired in line 32, after all goroutines have been already spawned.

Note that, because all the goroutines run in parallel, the computation (in this case the sleep) is done in parallel, and only the population of the output channel is synchronized:
 $ go build goChans_ordered1.go && time ./goChans_ordered1   
 0  
 1  
 2  
 3  
 real     0m2.006s  
 user     0m0.004s  
 sys     0m0.000s  


Solution 2: Pre-booking slots


Another approach to achieve the same result is to "book" a place in the final output channel as we create the goroutines:

1:  package main  
2:    
3:  import (  
4:       "fmt"  
5:       "runtime"  
6:       "time"  
7:  )  
8:    
9:  func init() {  
10:       runtime.GOMAXPROCS(4)  
11:  }  
12:    
13:  func send(ch chan int, i int) {  
14:       time.Sleep(2e9)  
15:       ch <- i  
16:  }  
17:    
18:  func main() {  
19:       ch := make(chan chan int, 4)  
20:       for _, i := range []int{0, 1, 2, 3} {  
21:            chval := make(chan int)  
22:            ch <- chval  
23:            go send(chval, i)  
24:       }  
25:       close(ch)  
26:    
27:       for sch := range ch {  
28:            select {  
29:            case v := <-sch:  
30:                 fmt.Println(v)  
31:            }  
32:       }  
33:  }  
34:    

Note the initialization of the output channel in line 19.  Here, we are creating a channel of channels. Instead of accepting ints, the main output channel now accepts unbuffered channels of ints. These channels are created (line 21) and sent to the main output channel (line 22) immediately before spawning the goroutines (line 23). This means that by the time all the goroutines are spawned, the channel is already full and we can close it (line 25), but the four inner (underlying) channels are still open and we can select on them. This simplifies the code collecting the data.

I like the mental representation of this solution a lot: Just before the creation of the workers, we apply a "hose" connecting the worker with the output channel. Once all the hoses are in place, we can close the output channel and wait for the results that come out of the hoses. Because we are ranging over all the hoses in order (line 27), the output will also be ordered as we wanted.

If this channel of channels data structure scares you, there is a slightly different approach that may be a bit simpler: Instead of creating a channel of channels you can create a slice and append the channels to the slice as the goroutines are fired (i.e. substituting the main output channel for a slice).