Sunday, September 11, 2011

My first knockout.js experience

Because I wanted to see what the hype is all about, I dove in the documentation and tutorials of knockout.js.

The tutorial site is great!
But the first thing that bothered me was the data-bind attribute everywhere.

So I pulled up my sleeves and pimped the 'templates and lists' tutorial

The easiest way to test the code is to copy and paste the gist content from the article in the html and javascript fields of the tutorial site.

The html

The final markup of the tutorial looks like this:

As you can see the data-bind attribute is all over the place.

And this is my markup:

The data-bind attribute is only in the template.
The other bound elements have an id.

Instead of putting the seat count in the title, I put it together with the surcharge sum.
The tutorial code displays the surcharge sum when there actually is a surcharge, my code displays it from the moment a passenger is present.

The javascript code

The tutorial code looks like this:

Very readable if you are used to do all the legwork in jQuery.
I'm in the knockout camp if I need to create complicated interfaces from now on.

Before I show you my code I will do a blow-by-blow on what I did and what the hurdles were.

The first thing I wanted was to remove the data-bind attribute from the markup.
I knew someone wrote a jQuery plugin to make this possible.

It works fine until you want to use the plugin to bind the html elements in the template.
Because I didn't want to spend too much time looking for a way to make it work, I left the data-bind attributes.

Instead of using a ko.dependentObservable to make a sum of the surcharges I added it to the view model.
You should only use the method if the code depends on outside factors.

When I added the remove functionality it didn't work. I did some debugging and found out the this in the remove function was the view model object where it needs to be the seatReservation object.

I guess the unobtrusive plugin has to do something with it, but the quick solution is to bind the seatReservation object to the remove function.
Because jQuery is loaded I used $.proxy.

The tutorial adds an anonymous passenger but because that isn't allowed anymore, I added a prompt to the addSeat function.

So my code comes down to:

Conclusion

Amazing you can achieve so much with so little code. And the tutorial is still verbose because the availableMeals will be fetched using AJAX or generated by a server language, <?php echo json_encode($availableMeals); ?>

I grabbed it and I will not let it loose until something better comes along.

Tuesday, September 06, 2011

Ugling: the start of the template engine

The changes

If you look at the previous build.xml file you know processing content in phing will turn in spaghetti code very soon. So I moved it to the template task.

The new build.xml file is easy to read because now you just have two tasks.

To get the build result I want i needed to add an attribute to the markdown task, removefilesetdir.
For me it was a cleaner way to process the markdown files and add the processed files to another directory than the way the rSTTask documentation shows.

The template engine vision

I want working with the generator to be as easy as possible so I try to stay away from code-like constructions as much as possible.
But at the same time it has to be as flexible as possible too.

The first problem I encounter is how can I provide a default template but allow specific templates at the same time.

Because i started to work with base template I got the idea that each directory could have a template.html that wraps all files in that directory and its subdirectories.
The only exception is the root template directory, it's required to have a template.html there.

To allow file specific templates it seemed the most logical to use the name of the file, so if your content file is called test.md and you want a file template you create a test.html file in the templates directory.

The template task today

I took my MarkdownTask.php code to start the TemplateTask.php code.
I concentrated on getting it to work so the code isn't that clean yet.

The default template code is working.

To prevent placeholders showing up in the online files they are set to an empty string before the actual content is added or generated.

Next time

The next blog post I will have the template vision working and have come up with a plan to add generated navigation content.

Saturday, September 03, 2011

Ugling: the phing powered static site generator (the begin)

Preface


I was looking for a project to use phing in a way that isn't expected.

Using it to remove version software directories or run tests is done so many times before.


The cool programmers started using static site generators like jekyll and petrify.

Why would you need a database if most of your content is static.


So why not use phing to do the same thing.


I also want to make the threshold as low as possible.
Markdown is one thing but other elements like the navigation are going to be not that easy.


Transforming the markdown


Creating a task in phing is easy, certainly if someone already did a similar task.


I just copied the code from the rSTTask, removed the parts i didn't need and changed the code to use the markdown class.



The source layout



  • content

    • index.md



  • media

  • online

  • templates

    • base.html



  • build.xml


As you can see the content directory holds the markdown files.


You can add as many subdirectories as needed. And use index.md files to display content for an url without the html extension.


The media directory will hold css files, js files, and other public content.

I'm not sure i'm going to keep it because the only phing action will coppy the files to the online directory.


The online directory holds all the files you can place online.


The templates directory holds html files that have placeholders.
This will be for the 'expert' users.


The build.xml file is the phing hook which will take care of all the actions.


Later there can come a build.properties file to move the user accessible properties outside the build script.


Build.xml content



I think it's a readable file.



  1. Set the start target: default="loop"

  2. Add properties

  3. Add markdown task

  4. Find all markdown files and send the file names to the single target

  5. Process the markdown file and move it to the online directory


The future


Now that the easy part is over I can go to work on the necessary plugins.
Navigation is the first that needs attention.

Wednesday, August 17, 2011

My first phing buildscript

Because I get more and more components from version management tools it gets harder and harder to move from development to staging level. SVN repositories are the worst offenders, certainly if you see how clean the get and mercurial repositories are.

If you clone or checkout a repository most of the time it also includes test files, build files, and so on. It's stuff you don't need for your application.
Swiftmailer for example comes with a full blown test suite. What if hackers find a way to use it to their advantage?

The phing installation via pear is painless.

The way to delete a directory didn't appear in any of the searches i did. So i moved on to the documentation and I found what i needed.



It's not very elegant but i'm taking babysteps at the moment.

Sunday, July 03, 2011

Being a good programmer

First of all this is not a post about best practices, being smart and all that jazz. It's about me exploring new areas to use my programming knowledge.


Update


I put the code on github


The problem


I'm a fan of the WFMU radiostation. They have a wide variety of music and they archive all their shows.
The downside is that after a month they delete the mp3 archive of the shows and because I don't listen all the time I'm missing episodes of my favorite shows.
That is why I started to download the mp3's but it takes too many steps and I needed to switch programms.



  1. Download the m3u file.

  2. Open the m3u file

  3. Copy the content

  4. Open a browsertab

  5. Paste the m3u content in the locationbar


So i went in developer-mode and started to work out a faster way to download the mp3's.


The brainstorm session


As i'm getting the mp3 archives as an rss feed and i'm using google reader to view it, the step to making it a browser add-on was taken quickly.


The easiest way to download the mp3 for me is to right click the link, click on a context item and the download starts.


The development process


I've done only a little chrome extension development, but the browser makes it a painless process with it's extension developers-mode.

This mode lets you choose a directory on your pc where the extension files are located and once you 'installed' the extension you can reload it when you changed the source code.


Because i never used contextmenu code i donwloaded the sample code from the google code site, which i also use to learn more about the api's.


The contextmenu item


The code is simple enough to understand.



  • Define when the menu item has to be added, the contexts.

  • Iterate over all the defined contexts to add the menu item and click handler, the genericOnClick.


The m3u content


From the sample I learned the first parameter of the click handler, info, holds the m3u url, linkUrl. Not a lot of brainpower needed here.


From my previous experience i know to get the file content i have to do an ajax request.

To make a cross-origin request possible you need to add the sites to the permissions variable of the manifest.json. This file contains all the metadata of the extension.


The download


Now we come to the head scratching part. As much as I searched I couldn't find a way to use the ajax responseText to automate the download.


I was trying to inject the mp3 url in the originating tab and then programmatically clicking on it. To do this i had to use the tabs.executeScript method but as i found out the code is executed in a sandbox so it can not use values from the click handler.


So i had to settle with opening a new tab which has as url the mp3 url.


The future


Now the number of actions has reduced to 3 and i can stay in the browser.



  1. Right click the link.

  2. Click the contextmenu item.

  3. Save file from tab.


I'm not going to show the code now because I want to make it more robust and universal.

There are no messages when something went wrong. I assume the content of the file only contains one mp3 link but i know it can contain multiple files.


Later i could support more metadata files and use a converting service like zamzar to make it an allround downloading extension.