preload
Jul 29

Ok so I love using text based editors like vim and emacs. I suck at emacs though. I think I’m good at vim, but almost everyday another coder (matt) shows me something new that makes me wonder how I was even using vim before he showed it to me. I don’t like having to be surgical with my mouse to open declarations of functions and click on tabs to move between files, and whatever else I do while not playing flash games. I read stuff about improving my editing skills like Efficient Editing and the ever popular Steve Yegges Emacs to learn how to do things more efficient and faster, and in general, be more productive.

Steve gives advice on rearranging your keyboard layout to not move you fingers of home row. Many vim guides tell you to use the home row keys instead of the arrows to move through text to avoid the extra hand motions.

Srsly you aren’t that productive.

I am imagining cubes of coders where the typing never stops. All day long they just bang out code, they never leave home row unless the absolutely need to type a Q. They think in C, and artfully paint LISP all over their screens and all the other crap that people say to pretend that real world problems always have elegant A+ compsci solutions.

Am I really the only one that has to alt-tab back to the email to remember the process outlined in whatever spec I’m implementing?

Is it just me that needs to IM somebody about why bug 69 was resolved the way it was and explain why that impedes my ability to implement customer request 7?

I refuse to believe that nobody else looks at the last three functions they wrote and actually stops to think “Could I do this better?”

I’m just saying the stuff that slows me down while I code is thinking. Not the 1.5 centimeters between my shift key and my arrow keys. Or the difference between moving my left pinky .5cm left, over 2cm down. I think the time/mistakes it would take me to get used to using hjkl as movement keys instead of the arrow keys would be more then the time saved from reducing the extra miniscule movement.

I read this post by Yehuda Katz and, while I find it interesting that using his mouse lead him to the ‘/’ and ‘o’ and ‘ci’ commands, he is right. Don’t sacrifice the ability to code comfortably for these silly little “performance gains”. You are optimizing the wrong part of your algorithm. If you really need to speed up your ability to copy/paste, maybe you should slow down and think about what your doing.

Jun 11

In the last part I concentrated on how to load and unload menus by binding to events. This time I’m focusing on loading the data for our menus. I want to achieve the following:

  1. Get data for our menus using an ajax call
  2. Use local storage to cache results
  3. Create an easy to use method to get and display data

I would like to make one function call that will give me menu data. I want the ajax loading to be handled behind the scenes. So I’m really looking for this kind of code

 Javascript |  copy code |? 
01
db = new DB();
02
db.createFruitTable();
03
$('#jqt').append('<div class="progress"></div>');
04
db.getFruitList(
05
     function(trans, result) {
06
          for(var i=0;i<result.rows.length;i++) {
07
                   var li = $('<li></li>');
08
                   li.append('<a>' + result.rows.item(i).name + '</a>');
09
                   li.addClass('arrow');
10
                   li.appendTo($('#fruitMenu'));
11
          }
12
          $('.progress').remove();
13
     });

I’ll always treat the result of getFruitList() as a database result set. If we have just started our app, then getFruitList should be responsible for populating that result set from the database, or via AJAX. This is how I’ve done the database and ajax code for the getFruitList function.
If there are no entries in the local storage:

  1. Bind to the ‘fruitListPopulated’, with the users callback function in the event data, and run getFruitList once more.
  2. Make an ajax call, and pass ‘insertFruit’ as the success function
  3. insertFruit will insert whatever data, and trigger the ‘fruitListPopulated’ event, which will run getFruitList once more.
  4. Now we should have results in the database

So this is what our database code should resemble:

 Javascript |  copy code |? 
01
this.getFruitList = function(callback) {
02
 
03
  /* We lose 'this' context after the database call, and if we have to make an ajax
04
      call and use our event callback, 'this' will also be invalid.  So we have to pass
05
      along the context as data in our event. */
06
  var ctx;
07
  if( typeof callback == 'object' ) ctx = callback.data.context;
08
  else ctx = this;
09
 
10
  try {
11
    ctx.dbh.transaction(
12
             function(trans) {
13
                 trans.executeSql('SELECT * FROM fruit', [],
14
                                  function(t,r) {
15
                                      /* If we had no results, we'll have to load the list by an ajax call. */
16
                                      if( r.rows.length == 0 ) {
17
                                          $('#fruitList').bind('fruitListPopulated', {cb: callback, context: ctx}, ctx.getFruitList);
18
                                          $.ajax(
19
                                                {url: 'http://theurl/fruitlist/',
20
                                                 type: "GET",
21
                                                 dataType: "json",
22
                                                 contentType: "application/json; charset=utf-8",
23
                                                 success: ctx.insertFruit,            // This function should insert the fruit, and trigger our event when done
24
                                                 error: function(xhr, txt, err) {
25
                                                           alert('Database unreachable, try again!' + txt + err);
26
                                                        }
27
                                                });
28
                                      } else {
29
                                          /* If we have results, call the user's callback. It may be in the event
30
                                             data, if we are coming from the ajax call. */
31
                                          if( typeof callback == 'function' ) callback(t,r);
32
                                          if( typeof callback == 'object' ) {
33
                                              $('#fruitList').unbind('fruitListPopulated');
34
                                              callback.data.cb(t,r);
35
                                          }
36
                                      }
37
                                  },
38
                                  function(t, res) { debug.error('Error reading DB: ' + res); });
39
                          });
40
  } catch (e) {
41
       debug.error('DB error: ' + e);
42
  }
43
};    
44

We can use this pattern over and over to load the list on startup, or to refresh the list on the users command.

What about invalidating the cached objects in the database? Well, that all depends on your data. I simply include a button that deletes all the rows from whichever SQL table, then the next time you grab this list, it has to refresh via AJAX.
here

Apr 25

Finally a little bit of time to learn something new and put some code up about it! I’ve been playing with jQtouch and PhoneGap for mobile development. Just as all my other stuff, this has an enterprise feel to it. I’ve been trying to come up with some good ways to communicate with a backend database, utilize local storage, and keep many lists of objects without code getting too out of control. Local storage and the backend communication is going to be part two of this. To start, here is how I’m trying to keep pages up to date without too much headache.

The idea is to catch hashchange events, and trigger a load and unload every time we get a hashchange event. Some browsers support this event(chrome, ie8), and others do not(mobile safari). So I use Ben Alman’s hashchange plugin for jQuery. If the browser supports hashchange, then you get the browser support. Otherwise it triggers the event for you.

I catch the hashchange event, and trigger two new events, load and unload

 Javascript |  copy code |? 
1
// global
2
var last_hash;
3
 
4
$(window).bind( 'hashchange',
5
                                function(){
6
                                       $(window).trigger('unload' + last_hash);
7
                                       last_hash = location.hash;
8
                                       $(window).trigger('load' + location.hash);
9
                                });

Now I can bind to these new events and find out when individual sections of my page are being loaded by jQtouch.
For example, you have a simple menu:

 HTML |  copy code |? 
1
<div id="usersMenu">
2
   <div class="toolbar"><h1>System Users</h1>
3
           <a href="#" class="button back">Back</a>
4
   </div>
5
   <ul id="usersMenuContent"></ul>
6
</div>

This menu has dynamic content that will change from time to time, so we have to load it with an ajax call. You may have a lot of users, and when you select one user, you don’t want all the other menu items taking up memory while you deal with that user.

What we need here is a way to load/unload those user items. What this method does is bind to the load#usersMenu and unload#usersMenu events, and either load data for #usersMenuContent from a data source, or remove the elements from #usersMenuContent.

 Javascript |  copy code |? 
01
02
$(window).bind('unload#usersMenu', 
03
                        function() { 
04
                               $('#usersMenuContent > *').remove();
05
                        });
06
 
07
$(window).bind('load#usersMenu', 
08
                        function() {
09
                                var dataArray = loadUsersData();
10
                                for( var i in dataArray ) {
11
                                      $('<li>' + dataArray[i] + '</li>').appendTo($('#usersMenuContent'));
12
                                }
13
                        });

Theres some psuedo code there to change depending on just what you are loading into the users menu of course. The idea is when your Users Menu loads, it will populate with data, and when you navigate away, the data is removed.

Here is an example we can use. You can view it here.
A simple page that has 3 menus: A primary menu, and two submenus. Each item in the submenus can be clicked on, and loaded into a form for modification(although we don’t implement modification here). Each menu has to load its items, and also remove its items when unloaded.

First, it is important to see the HTML template we will be working with.

 HTML |  copy code |? 
01
    <body>
02
        <div id="jqt">
03
            <div id="start">
04
                <div class="toolbar"><h1>Produce</h1>
05
                </div>
06
                <ul>
07
                   <li><a href="#fruitMenu">Fruits</a></li>
08
                   <li><a href="#vegetableMenu">Vegetables</a></li>
09
                </ul>
10
            </div>
11
 
12
            <div id="fruitMenu">
13
                <div class="toolbar"><h1>Fruits</h1>
14
                    <a href="#" class="button back">Back</a>
15
                </div>
16
                <ul id="fruitMenuContent"></ul>
17
            </div>
18
 
19
            <div id="vegetableMenu">
20
                <div class="toolbar"><h1>Vegetables</h1>
21
                    <a href="#" class="button back">Back</a>
22
                </div>
23
                <ul id="vegMenuContent"></ul>
24
            </div>
25
 
26
            <div id="fruitClickThru">
27
                <div class="toolbar"><h1 name="title"></h1>
28
                    <a href="#" class="button back">Back</a>
29
                </div>
30
                <ul class="form">
31
                    <label>Name</label><li><input name="name"></li>
32
                    <label>Other</label><li><input name="other"></li>
33
                </ul>
34
            </div>
35
 
36
            <div id="vegetableClickThru">
37
                <div class="toolbar"><h1 name="title"></h1>
38
                    <a href="#" class="button back">Back</a>
39
                </div>
40
                <ul class="form">
41
                    <label>Name</label><li><input name="name"></li>
42
                    <label>Other</label><li><input name="other"></li>
43
                </ul>
44
            </div>
45
        </div>
46
    </body>
47
</html>
48

Here is the javascript and HTML put together. I trigger a load and unload event every time the hash changes. I bind to the load and unload events for the menus to update, and clean themselves up after use.

 Javascript |  copy code |? 
001
<!doctype html>
002
<html>
003
    <head>
004
        <meta charset="UTF-8" />
005
 
006
        <title>Dynamic Menus using jQTouch</title>
007
        <style type="text/css" media="screen">@import "jqtouch/jqtouch.css";</style>
008
        <style type="text/css" media="screen">@import "themes/jqt/theme.css";</style>
009
        <script src="jqtouch/jquery-1.4.2.min.js" type="text/javascript" charset="utf-8"></script>
010
        <script src="jqtouch/jqtouch.js" type="application/x-javascript" charset="utf-8"></script>
011
        <script src="jquery.ba-hashchange.js" type="text/javascript" charset="utf-8"></script>
012
        <script type="text/javascript" charset="utf-8">
013
 
014
            var jQT = new $.jQTouch({
015
                icon: 'jqtouch.png',
016
                addGlossToIcon: false,
017
                startupScreen: 'jqt_startup.png',
018
                statusBar: 'black'
019
            });
020
 
021
            /* For this example I think globals are fine. 
022
               For real though, the selected item should be stored
023
               inside the object controlling that item type */
024
 
025
            var activefruit;
026
            var activeveg;
027
            var last_hash;
028
 
029
 
030
            $(function(){
031
                /* Setup our load events for page changes. The idea is that
032
                   we trigger an unload<hash> and load<hash> event whenever
033
                   the page location hash changes. The event handlers can
034
                   do whatever they want with that information. */
035
                $(window).bind( 'hashchange', 
036
                                function(){
037
                                       console.log('unloading ' + last_hash);
038
                                       $(window).trigger('unload' + last_hash);
039
 
040
                                       /* Handle the previous hash ourselves because some browsers won't support the
041
                                          hash change event, and others will. So we don't want to modify the plugin
042
                                          because it may not always be handling the events */
043
                                       last_hash = location.hash;
044
 
045
                                       console.log('loading ' + location.hash);
046
                                       $(window).trigger('load' + location.hash);
047
                                });
048
 
049
 
050
                /* Handle our fruit menu
051
                   Our fruit menu is dynamic. In this example it really isn't,
052
                   but real world it would be loaded through an ajax call. Since
053
                   the fruit menu is dynamic, we want to bind to the 
054
                   unload#fruitMenu event, and erase the menu contents when we
055
                   navigate away from the page. This makes it easier to keep the
056
                   menu free from duplicates, but it also keeps us from having
057
                   a lot of DOM objects lying around. */
058
                $(window).bind('unload#fruitMenu', function() { $('#fruitMenuContent > *').remove(); });
059
                $(window).bind('load#fruitMenu', 
060
                           function() { 
061
                                console.log('Fruit menu loaded');
062
 
063
                                // On a touch event, we set the activefruit global, and link to the fruit click thru
064
                                $('<li onclick="activefruit=1;"><a href="#fruitClickThru">Apple</a></li>').appendTo($('#fruitMenuContent'));
065
                                $('<li onclick="activefruit=2;"><a href="#fruitClickThru">Banana</a></li>').appendTo($('#fruitMenuContent'));
066
                           });
067
 
068
                /* Handle our vegetable menu
069
                   Same as for the fruits. Clean up when the menu is unloaded. */
070
                $(window).bind('unload#vegetableMenu', function() { $('#vegMenuContent > *').remove(); });
071
                $(window).bind('load#vegetableMenu', 
072
                           function() { 
073
                                console.log('Vegetable menu loaded');
074
                                $('<li onclick="activevegetable=1;"><a href="#vegetableClickThru">Carrots</a></li>').appendTo($('#vegMenuContent'));
075
                                $('<li onclick="activevegetable=2;"><a href="#vegetableClickThru">Broccolli</a></li>').appendTo($('#vegMenuContent'));
076
                           });
077
 
078
 
079
 
080
                /* Fill our fruit click thru
081
                   Once this section is loaded, we access the activefruit global to determine
082
                   what information to populate the form with. Again, in the real world
083
                   this info would be grabbed from a database, or an ajax call. */
084
                $(window).bind('load#fruitClickThru', 
085
                                function() { 
086
                                     if( activefruit == 1 ) {
087
                                         $('#fruitClickThru > .form > li > input[name=name]').val('Apple');
088
                                         $('#fruitClickThru > .form > li > input[name=other]').val('Red');
089
                                         $('#fruitClickThru > .toolbar > :header').html('Apple');
090
                                     } else if( activefruit == 2 ) {
091
                                         $('#fruitClickThru > .form > li > input[name=name]').val('Banana');
092
                                         $('#fruitClickThru > .form > li > input[name=other]').val('Yellow');
093
                                         $('#fruitClickThru > .toolbar > :header').html('Banana');
094
                                     }
095
                                 });
096
 
097
                /* Fill out vegetable click thru
098
                   Same as the fruit sections. We aren't bother to bind to the unload
099
                   event here because the form fields are static and we replace their
100
                   values during each load event anyway. */
101
                $(window).bind('load#vegetableClickThru',
102
                                function() { 
103
                                     if( activevegetable == 1 ) {
104
                                         $('#vegetableClickThru > .form > li > input[name=name]').val('Carrots');
105
                                         $('#vegetableClickThru > .form > li > input[name=other]').val('Orange');
106
                                         $('#vegetableClickThru > .toolbar > :header').html('Carrots');
107
                                     } else if( activevegetable == 2 ) {
108
                                         $('#vegetableClickThru > .form > li > input[name=name]').val('Broccolli');
109
                                         $('#vegetableClickThru > .form > li > input[name=other]').val('Green');
110
                                         $('#vegetableClickThru > .toolbar > :header').html('Broccolli');
111
                                     }
112
                                 });
113
            });
114
        </script>
115
    </head>
116
    <body>
117
        <div id="jqt">
118
            <div id="start">
119
                <div class="toolbar"><h1>Produce</h1>
120
                </div>
121
                <ul>
122
                   <li><a href="#fruitMenu">Fruits</a></li>
123
                   <li><a href="#vegetableMenu">Vegetables</a></li>
124
                </ul>
125
            </div>
126
 
127
            <div id="fruitMenu">
128
                <div class="toolbar"><h1>Fruits</h1>
129
                    <a href="#" class="button back">Back</a>
130
                </div>
131
                <ul id="fruitMenuContent"></ul>
132
            </div>
133
 
134
            <div id="vegetableMenu">
135
                <div class="toolbar"><h1>Vegetables</h1>
136
                    <a href="#" class="button back">Back</a>
137
                </div>
138
                <ul id="vegMenuContent"></ul>
139
            </div>
140
 
141
            <div id="fruitClickThru">
142
                <div class="toolbar"><h1 name="title"></h1>
143
                    <a href="#" class="button back">Back</a>
144
                </div>
145
                <ul class="form">
146
                    <label>Name</label><li><input name="name"></li>
147
                    <label>Other</label><li><input name="other"></li>
148
                </ul>
149
            </div>
150
 
151
            <div id="vegetableClickThru">
152
                <div class="toolbar"><h1 name="title"></h1>
153
                    <a href="#" class="button back">Back</a>
154
                </div>
155
                <ul class="form">
156
                    <label>Name</label><li><input name="name"></li>
157
                    <label>Other</label><li><input name="other"></li>
158
                </ul>
159
            </div>
160
        </div>
161
    </body>
162
</html>
163

Moving forward
The next step is to have the menus load from the local cache. If the cache doesn’t have the requested information, then it should be retrieved. This way when you load a menu, you can always show a spinner and if the cache has been invalidated, new information will automatically be populated. But that is for next time.

Apr 08

todays xkcd just hits sooooo many different levels of life right now its amazing.

xkcd

Feb 25

Nothing interesting has been happening lately. A few side projects that are neat, but other then that no new coding advancements. I was playing with memoization a bit. Of course, in my everyday job I have absolutely zero need for this. But maybe I will find something useful. I think that I could try to implement some advanced code techniques at work, but we would have to do things better first. Hundreds of different pages all using sql queries, no real structure. It gets mind bottling after awhile.

But anyways. To explore memoization, lets use my favorite advanced math algorithm interpreter, PHP. Then we will experiment in something new to me, C#!!!!

The fibonacci:

 PHP |  copy code |? 
1
function fib($c) {
2
   if( $c == 0 ) return 0;
3
   if( $c == 1 ) return 1;
4
   return fib($c-2) + fib($c-1);
5
}

Ok, so we have a nice recursive function to calculate the nth number in the fib sequence. Lets use it to calculate the 20th, 30th, and 40th numbers.

    Start
    6765: Time: 0.012
    832040: Time: 1.178
    63245986: Time: 135.191

Whoa, so times really start to add up quick. But we have to calculate this number or we get fired(this makes as much sense as anything else I do so I’m going to stick with it) and we have to calculate it quickly! We can use memoization on this fib() function to speed up the calls. This means that we will cache results as we calculate them, and then if we try to calculate the same number, we will grab the result from cache instead of running all the calculations again. This works because the results for fib(x) are always the same. There is no user input, time values, or any other real world nonsense getting in the way. We are going to add a static array to the fib() function, and store/retrieve the results from that array. Here is the code:

 PHP |  copy code |? 
1
function fib($c) {
2
   static $map;
3
   if( !is_array($map) ) $map = array();
4
   if( $c == 0 ) return 0;
5
   if( $c == 1 ) return 1;
6
   if( !isset($map[$c]) )        // Have we already calculated this?
7
   	$map[$c] = fib($c-2) + fib($c-1);
8
   return $map[$c];
9
}

We have a check to see if the request value has already been calculated. If not, we calculate it and store it. Then we return the stored version. This should speed things up. Lets run it again:

    Start
    6765: 0.001
    832040: 0.002
    102334155: 0.002

That is a serious improvement. It should be, we are only making 40 calls instead of the previous huge number. Now I just need to find a situation where this may be useful in my day to day programming.

What about a new language, C#? Lets run the same code again:

 C# |  copy code |? 
01
        static int fib(int x)
02
        {
03
            if (x < 2) return x;
04
            return fib(x - 2) + fib(x - 1);
05
        }
06
 
07
        static void Main(string[] args)
08
        {
09
            DateTime startTime = DateTime.Now;
10
            DateTime endTime;
11
            Console.WriteLine("Place 20: {0}", fib(20));
12
            endTime = DateTime.Now;
13
            Console.WriteLine("Time: {0}", startTime - endTime);
14
            Console.WriteLine("Place 30: {0}", fib(30));
15
            endTime = DateTime.Now;
16
            Console.WriteLine("Time: {0}", startTime - endTime);
17
            Console.WriteLine("Place 40: {0}", fib(40));
18
            endTime = DateTime.Now;
19
            Console.WriteLine("Time: {0}", startTime - endTime);
20
 
21
            Console.ReadKey();
22
        }

Note: I’m posting all the code on the off chance somebody reads my blog and would like bolster their self image by destroying my skills here. Look at the times though:

    Place 20: 6765
    Time: 00:00:00
    Place 30: 832040
    Time: -00:00:00.0901296
    Place 40: 102334155
    Time: -00:00:09.8040976

I mean, come on, 9 seconds as compared to PHP’s 135 seconds!? I’m running 2 virtual machines on my host machine with only 2 gigs of ram, listening to a podcast, and c# runs under windows of all things. Reality is shattering before my eyes.

Anyways. The goal here is to implement the map in C#. Obviously C# will scoff at trying to use key=>value arrays. I’ve come across a few different way to do this, and it looks like a Hashtable is the simplest.

 C# |  copy code |? 
1
        static Hashtable map;
2
 
3
        static int fib(int x)
4
        {
5
            if (x < 2) return x;
6
            if(!map.ContainsKey(x))
7
                map.Add(x, fib(x - 2) + fib(x - 1));
8
            return (int)map[x];
9
        }

Our times?

    Place 20: 6765
    Time: -00:00:00.0100144
    Place 30: 832040
    Time: -00:00:00.0100144
    Place 40: 102334155
    Time: -00:00:00.0100144

Not bad. There are some other ways to do this without the hashtable. You can use a ListCollection for example. But this seems like it works. Now to learn the more indepth aspects of hashtables in c#.

Jan 31

I needed to add Excel capability to some of my reports in Recess! so I decided a plugin would be the best way to go. There isn’t too much documentation on plugins so far, so I hope this can help a little. This may not be the best way to go, but it can at least be a guide to get started. I chose PHPExcel to be the engine I use to generate the Excel files. Its easy to generate several different versions of files, and csv and pdf, and I like the library.

The entire plugin is downloaded here.

The Recess! way to do this is create a View that Recess can use to display data. The views are called from the controller, so I want to use the view as follows:

 PHP |  copy code |? 
1
/*
2
 * !RespondsWith Layouts, ExcelView
3
 */

The first thing I had to do was create the plugin directory structure and copy the PHPExcel files in. I copied the PHPExcel Classes/ directory into plugins/ryanday/PHPExcel/. Because the Library::import() method assumes FILE.class.php, I had to link PHPExcel.class.php to the actual PHPExcel.php file for things to function smoothly. There may be a way around that, but I figure its part of Recess!izing the library. This is probably a little confusing, so this is what the directory looks like:

  • Classes/
  • ExcelView.class.php
  • PHPExcelPlugin.class.php
    Classes/

  • PHPExcel/
  • PHPExcel.class.php -> PHPExcel.php
  • PHPExcel.php

Please download a copy of the plugin to make it a little more clear.

I started by viewing thebeeline’s post about plugins to get a jumping off point. Then I created the plugin file, PHPExcelPlugin.class.php

 PHP |  copy code |? 
01
<?php
02
Library::import('recess.framework.Plugin');
03
Library::import('ryanday.PHPExcel.Classes.PHPExcel');
04
Library::import('ryanday.PHPExcel.ExcelView');    // This will let us create our own view
05
 
06
class PHPExcelPlugin extends Plugin {
07
 
08
        function init(Application $app) {
09
                MimeTypes::register('xls','application/vnd.ms-excel');
10
        }
11
 
12
};
13

In the init() function I register a new MimeType, ‘xls’. When Recess! can’t find a layout to display data, it will pass registered mimetypes to all the views, so we have to register the ‘xls’ mimetype so our plugin can respond. Recess! will automatically create the headers for xls, and the applications type. Next we create the actual view.

 PHP |  copy code |? 
01
<?php
02
Library::import('recess.framework.AbstractView');
03
 
04
class ExcelView extends AbstractView {
05
        //  This is were we respond to the MimeType we previously registered
06
	public function canRespondWith(Response $response) {
07
		return 'xls' === $response->request->accepts->format();
08
	}
09
 
10
        /*  Most views render the model in a specific way, a spreadsheet is a little different
11
         * though. I require the xls property to be a two dimensional array containing
12
         * the data to be displayed.
13
         */
14
	protected function render(Response $response) {
15
		$objPHPExcel = new PHPExcel();
16
		require_once PHPEXCEL_ROOT . 'PHPExcel/IOFactory.php';
17
		require_once PHPEXCEL_ROOT . 'PHPExcel/Writer/Excel5.php';
18
		$objPHPExcel->setActiveSheetIndex(0);
19
 
20
                /*
21
                 * The following is loosely based on the JsonView code. If we have a model
22
                 * with the xls property set, we create the spreadsheet from that array
23
                 */
24
		$response = clone $response;
25
		foreach($response->data as $key => $value) {
26
			if($value instanceof Model) {
27
				if( isset($value->xls) ) {
28
					foreach($value->xls as $rowId=>$row) {
29
						foreach($row as $colId=>$cell) {
30
							$objPHPExcel->getActiveSheet()->setCellValueByColumnAndRow($colId, $rowId+1, $cell);
31
						}
32
					}
33
				}
34
			}
35
			if($value instanceof Form) {
36
				unset($response->data[$key]);
37
			}
38
			if(substr($key,0,1) == '_') {
39
				unset($response->data[$key]);
40
			}
41
		}
42
 
43
		if(isset($response->data['application'])) unset ($response->data['application']);
44
		if(isset($response->data['controller'])) unset ($response->data['controller']);
45
 
46
                /* I have gone through the docs and can't get ExcelWriter to dump to stdout,
47
                 * this way is a little hack I think, but it works.
48
                 */
49
		$objWriter = PHPExcel_IOFactory::createWriter($objPHPExcel, 'Excel5');
50
		$tempfile = tempnam('/tmp', 'recessxls');
51
		$objWriter->save($tempfile);
52
 
53
                // We don't have to mess with headers, Recess! will do that based 
54
                // on the registered Mimetype
55
		readfile($tempfile);
56
	}
57
};
58

So now all our plugins files are setup, and we have to import the plugins into our application. In your app/YourApp/YourAppApplication.class.php add the following lines

 PHP |  copy code |? 
1
Library::import('ryanday.PHPExcel.PHPExcelPlugin');   // Add this import
2
 
3
class YourAppApplication extends Application {
4
   ...
5
   $this->plugins = array(new PHPExcelPlugin());   // instantiate the class to import the library
6
   $this->plugins[0]->init($this);                    // Important!!
7
}

Note the init() call! The MimeType is verified before the plugin is initialized by the Controller. That means the MimeType won’t be registered when the controller looks for it. So we do it ourselves. Finally, in our controller, we create a little example.

 PHP |  copy code |? 
01
/**
02
 * !RespondsWith Layouts, Excel
03
 * !Prefix mainModel/
04
 */
05
class MainModelController extends Controller {
06
 
07
. . .
08
 
09
       /** !Route GET, $id */
10
        function details($id) {
11
                $this->mainModel->id = $id;
12
                if($this->mainModel->exists()) {
13
                        $this->mainModel->xls = array(array("col1","col2","col3"),
14
                                        array("newrow","newcol","keepgoing"),
15
                                        array("lastrow","k","lastcol"));
16
                        return $this->ok('details');
17
                } else {
18
                        return $this->forwardNotFound($this->urlTo('index'));
19
                }
20
        }
21

Now when you visit that particular route, you will get an Excel spreadsheet with the data set in $this->mainModel->xls.

This is just a basic intro on how to create a View plugin. Please comment with any updates, or better way to explain things! This works for me so far, but it hasn’t been tested along a wide distribution of sites.