Blog Posts

ONE Conference 2012: Learning the latest in web development and business

On Wednesday five Liipers spoke at the ONE Schweiz Conference in the Messe Zürich.

Kicking off the "Development and Design" track as the first talk in the morning, Gerhard Andrey, Christian Stocker and David Buchmann presented the most important web technologies and topics to watch for.

The ten topics for web developers to consider:

1. Serverside Javascript like node.js bring one common language to the frontend and the backend. With that most of the code is recycled. As a bonus feature Javascript servers work event driven which boosts performance of interaction rich frontends.

2. HTML5 has been around for some time and many APIs are available for expanding the browser. Yet, developers still meet some "troubles" in certain areas (e.g. Local Storage). But you can work around many of those spots with the help oflibraries like jQuery or YUI.

3. Maps OpenStreetMap in combination with OpenLayers Leaflet is a very powerful alternative to Google Maps. Liip has released advanced applications like http://plaene.uzh.ch with custom graphics.

4. Semantic Web: With RDFa, Apache Stanbol and more capable content editors the building blocks are here, and the reference data is out there for more semantic web applications. Liip demonstrated with the Symfony Content Editor the technology successfully.

5. NoSQL / Big Data: As an alternative to relational data bases NoSQL promises better scalability in decentralized cloud situations. NoSQL solutions like MongoDB or CouchDB should definitely be a tool in every web developers toolbox.

6. Content Repositories / PHPCR: PHP meets corporate Java based content repositories (JCR). Through PHPCR your web application is ready to connect to hierarchic file systems with big amounts of data. Liip pushes the development of PHPCR and advocates it's usage in more and more CMSs.

7. NIWEA: The Browser wins again when it comes to the mobile web, because it has won before on the desktop. The stack of web technologies paired with frameworks for mobile development like PhoneGap and Sencha Touch can do for many more devices like smartphones and tablets what apps can do only developed specifically for one platform.

8. Distribution: Companies that want to go free from the dominant players in the app distribution market will increasingly choose the mobile web as an alternative. That is true for media publishers and also for game developers.

9. Mobile Payment: Not many of the existing models were a big success so far. We are hoping for debit solutions that eliminate the hassle with credit cards for the end user .

10. Open Government Data: When data owned by the public is made available to the public, new ways of participation for citizens and new data journalism is possible. The potential of such applications has been demonstrated in the Make.Opendata hackdays.

This wide field of expertise presented by Liip may have sparked many an idea in the developers in the audience. The slides of this talk can be viewed here:

Later in the program Timo Bezjak talked about models for agile contracts. He argued that Agile processes be better suited for fixed-price contracts than more rigid approaches — if the team is free to negotiate and develop the features and architecture of the product. Unless it is hindered by a strict contract based on a detailed requirements document, an Agile team will consequently maximise their customer's return on investment.

At the end of the day Steve Holyer spoke on how "How to Fail at Agile". An Agile (or Lean) team needs to develop and test hypothesas in order to learn and become more effective. As Donald G. Reinertsen says, "Failure is actually a good thing in learning systems…this is one of the ways most information is generated." To learn from failure an Agile team must reflect regularly. Steve, a few hints on structuring Agile Retrospectives to support the advice of political commentator Molly Ivins who coined the homespun Texan saying, "The first rule of holes, when you're in one stop digging." Steve's conclusion? If you want to make your Agile project fail don't hold retrospectives, or--even better--hold retrospectives, but don't act on the learning or the outcome. But, if you want to fail well at Agile build and nurture a reflective culture. Find the slides here

In between the Liiper's talks, I ventured out to listen into the other tracks. One common theme I noticed was multichannel strategies in eCommerce and in Social Media and Content Marketing. The consumer today expects consistent service no matter what device he or she uses. It has even been called Noline Commerce in Thomas Lang's E-Commerce Trends 2012. The opportunities for mobile applications lies exactly here, as do the challenges for brands to constantly tell their stories, which Rolando Baron pointed out in his talk.

The day ended for us with many exchanged ideas about trends in web development and business. It was an interesting conference with good speakers. For Zurich it's good to have an event like this.

Related Entries:
- Agile Tour Lausanne 2011
- My thoughts on the J.Boye 2011 conference
- Web Performance Summit 2011
- LIFT11: Liipalized!
- New Adventures in Nottingham

Comments [0]

Wsunit - the first release

It's always the same issue... you write unit tests for a web-service, giving you a feeling of confidence about the correctness of your code. Then the service provider changes the response without notifying you. Suddenly your implementation doesn't work anymore, but even your continuous integration server says it's "all green".

So what happened?

Surely the fixture files you used are outdated, and since they won't get updated automatically your tests don't stand a chance to detect the change.

Wsunit to the rescue

Implemented as a PHPUnit test listener, once configured wsunit will request a new response every time you run your test suite. It saves the response to your test's fixture file to verify the correct behavior of your implementation. Therefore you probably want to run this test suite as a separate job on your continuous integration server so you don't disturb the developers when doing their job.
Furthermore, wsunit keeps every 'old' responses (aka fixture files) enabling you to find the differences between the current response and an old response.

How does it work?

After configuring the test listener in the PHPUnit configuration file, the central point of interest is the wsunit configuration file. Here you define which test (identified by it's name) will send a request to which location together with what query parameters.
If you now run the test suite the test listener detects that there is a request to be sent and fetches the requested data from the defined location. After a conversion to XML the response will be stored in a fixture file named after the executed test.
The test now just uses the fixture file to verify the correct implementation of your code.
Since the header and response body are converted into a XML structure it is fairly easy to check it's content by using PHPUnit's 'assertXml*' assertion methods.

Further reading

A complete description how to install and set up wsunit is written down in Bastian's blog.

Related Entries:
- Liip @ linuxwochen.at
- A workaround for the missing git submodule support in Bamboo 3.1
- Jackalope - JCR for PHP started
- whereami extension: now privacy enabled
- the whereami firefox extension

Comments [0]

"Conférence Romande sur l’Accessibilité du Web" wrap up

Yesterday took place the first Conférence Romande sur l’Accessibilité du Web" organized by Telono in Geneva and Liip was well represented by me, Brian King and Jonas Vonlanthen.

This was also a great opportuniy to have a closer look at some of the real-life accessibility problems and the solutions proposed.

The organizazion was perfect and everything went fine.

I was also surprised by the high number of participants and the interest they had in almost all of the topics proposed and discussed.

The schedule was very "dense" with 8 presentations to be followed from 9 to 18 with a lunch break, of course.

Liip contribution

I presented the talk "Optimisation de l’accessibilité and Responsive Design: étude de cas" where I showed the efforts we made during the development of Liip.ch relaunch to improve the accessibility and the semantic of the whole site.

Also had the opportunity to present the implementation of the responsive design that shaped up after the dedicated hackday in November and the recent mini-sprint.

People showed their interest and also asked questions. Definitely not a boring talk ;-)

The other talks

The first two presentations have been given by two visually impared people (Julien Conti and Christophe Oberson) showing how to overcome common accessibility issues in everyday web browsing.

The great thing was that they also suggested/proposed how to not do things that are a known source of problems.

Julien Conti also introduced the (soon to be released) "BrailleTouch" iPhone app.

Yannick Guerdat (Artionet) presented the work done to make jura.ch fully accessible and certified.

Very valuable contributions came from the two Telono organizers, Carine Rivière and Laetitia Giannettini who talked, among other things, about the relationship between ergonomy and accessibility.

Markus Riesch of Access for all foundation let us know the state of accessibility in Swiss public institutions and the Swiss laws currently applying to the accessibility subject.

The most interesting contributions came from Jean-Pierre Villain (Qelios) and his co-relator Romain who went through the WCAG 2.0 directives and proposed some concrete ARIA solutions to make Javascript implementations accessible.

They also showed the great accessibility support on the iPhone.

Conclusion

Not that much to add, only looking forward to the 2013 edition for another great apportunity to learn and share.

Feel free to check the slides of the presentation.

And finally some pics.....

Telono organizers introducing the program

Attendees following the talks

Jean-Pierre Villain about the ARIA in forms

Romain explaining how to use Voice Over on iPhone

Related Entries:
- Techday Slides: Flash and the Quest for Accessibility
- Flash & the Quest for Accessibility - Part #2
- Flash & the Quest for Accessibility - Part #1
- Hiding parts of a page from Google
- Accessible websites with Flux CMS

Comments [0]

Game development with JavaScript

Recently, we had a hackday at Liip, where we dived into game development with JavaScript. Our goal was to see how hard it is to produce a simple cross platform game using just JavaScript and HTML5 elements. Since we didn't want to reinvent the wheel, we decided to use a JavaScript game framework.

To make it short: we were very impressed at the state of the different frameworks around. We were able to put together a simple game in a suprisingly short time. Check it out here! (Thx to Chrigu for letting us use the graphics of his awesome iPhone game Herbert, the misanthropical fly).

Technical details

We developed our game using ImpactJS, a high-level JavaScript game framework that did a lot of work for us. While we briefly looked at some alternatives like Crafty and LimeJS, we didn't want to spend our time comparing libraries but get our hands dirty. We went with ImpactJS simply because Chrigu had already looked into it a bit, and because of their awesome demo game. The downside of ImpactJS is the fact that it's proprietary, though it's well worth the price of 99$.

In ImpactJS, one generally has three different types of objects: screens, levels and entities. Screens control the different game states. For example you could have a settings screen, a highscore screen and an actual playing screen. Because your game (unlike our demo) probably has different levels, there are simple JSON files that describe how a level looks and can be automatically loaded by ImpactJS. Background images, collision maps and entities are placed in there. Finally, entities are all interacive objects: The hero, enemies, coins, bombs and so on. Entities are distributed over the level, they are animated and interact with other entities.

In our case we put together a startscreen, the main screen with a level map behind it and an endscreen that appears when one accomplished the level. Within the game we have our hero entity, whose goal it is to navigate through the map without hitting enemies or walls. He also wants to pick up coins. Coins are entities as well and can be picked up by the hero increasing his health a little. When the hero hits a wall or an enemy, he loses health. Of course, these actions are accompanied by sounds. The hero, enemies and coins are animated, which is achieved by simply looping through different frames in a sprite sheet.

Our Experiences

- ImpactJS does a lot of work for you. It handles animations, collision detection, scene management, controls and scrolling of the screen

- ImpactJS is documented very well, and there seems to be an active discussion forum on their website

- The level editor bundled with ImpactJS ("Weltmeister") makes it very easy to set up level layouts fast. That said, the user interface isn't always intuitive (right-click to drag around the map, press space to insert something) and the level editor sometimes feels buggy

- We had quite some issues with the playback of sound, since there are still several tricks needed to have sound working in a wide range of browsers. We did not get the built in sound manager of ImpactJS running properly. We instead used SoundManager2 but we still had to do a hack to get it to work on iOS devices. The problem is, that iOS won't start the download of media until there is a user-input event, so we just required the user to touch the screen, before the game can be started

- Porting to mobile phones or tablets can be achieved by simply wrapping the game in Phonegap, but we weren't sure how to deal with different screen / viewport sizes and resolutions without making the game look distorted or blurry

- Performance was surprisingly good, even on mobile phones. That said, on an iPhone 3G, we only reached 30 FPS, which is the "lagging limit". So a game that has more elements would probably need performance optimisations in addition to ImpactJS

- We played around a bit with different ways to navigate, including using the accelerometer or touch gestures, but didn't get much support from ImpactJS in that regard

Overall we are very happy with the outcome and we are impressed, how fast a simple game could be put together. Have a look at the source code to see how straightforward it was. ImpactJS helps a lot in handling the interactive parts, allowing you to spend more time on the look and feel, which is one of the key factors for games. We're all looking forward to using ImpactJS on a customer project, but also to playing around with free alternatives and seeing if they measure up to the high bar that ImpactJS has set!

Alain, Chrigu, Colin

Related Entries:
- Applying Niwea: TV Sélection iPad app
- Barcode reader Hackday
- Vanilla is a NIWEA
- Open Sourcing Radios - A PhoneGap iPhone/iPad app
- The technical details behind the Radios App

Comments [0]

Table Inheritance with Doctrine

Introduction

Lately we had several projects where we had to store in a database very different items that shared a common state.

As an example take the RocketLab website you are reading: Events and BlogPosts are aggregated in the LabLog list as if they were similar items. And indeed they all have a Title, a Date and a Description.

But if you get the detail page of an Event or a BlogPost you can see that they actually don't contain the same information: a BlogPost contains essentially formatted text when an Event contains more structured information such as the place where the event will take place, the type of event it is, if people need to register to attend, etc..

Still we have to access those entities sometimes as similar items (in the LabLog list) or as different items (in the events list and in the blog posts list).

Naïve database model

Our first idea, and it was not that bad, Drupal does just the same, was to have a database table with the common fields, a field containing the type of item (it's either an event or a blog post) and a data field where we serialized the corresponding PHP object. This approach was ok until we had to filter or search LabLog items based on fields that were contained in the serialized data.

Indeed SQL does not know anything about PHP serialized data, thus you cannot use any of it's features on that data.

So how do you get all the LabLog items that are Events, happen in April 2012 and are "techtalks"? The only way is to go through all the Events records of April, unserialize the data and check if it's a techtalk event. In SQL you would normally only do a single request to find those items.

A better database model

There is a better way to model this in a database, it's called table inheritance. It exists in two forms: single table inheritance and multiple table inheritance.

Multiple table inheritance

Multiple table inheritance requires to use three tables instead of a single one. The idea is to keep the common data in a "parent" table, which will reference items either in the Event table or in the BlogPost table. The type column (called the discriminator) helps to find out if the related item should be searched in the Event table or in the BlogPost table. This is called multiple table inheritance because it tries to model the same problem as object inheritance using multiple database tables.

Multiple table inheritance

When you have a LabLogItem you check the type field to know in which table to find the related item, then you look for that item with the ID equals to related_id.

Single table inheritance

Alternatively the same can be modelled in a single table. All the fields are present for all the types of LabLogItem but the one that do not pertain to this particular type of item are left empty. This is called single table inheritance.

Single table inheritance

Single or multiple table inheritance

The difference is really only in how the data is stored in the database. On the PHP side this will not change anything. One may notice that single table inheritance will promote performance because everything is in a single table and there is no need to use joins to get all the information. On the other hand, multiple table inheritance will allow a cleaner separation of the data and will not introduce "dead data fields", i.e. fields that will remain NULL most of the time.

Table inheritance with Symfony and Doctrine

Symfony and Doctrine make it extremely easy to use table inheritance. All you need to do is to model your entities as PHP classes and then create the correct database mapping. Doctrine will take care of the hassle of implementing the inheritance in the database server.

Please note that the code I present here is not exactly what we use in RocketLab; we are developers and as such we always have to make things harder. But the idea is there...

The parent entity

In the case of RocketLab we created a parent (abstract) entity, called LabLogItem, that contains the common properties.

/**
 * This class represents a LabLog item, either a BlogPost or an Event.
 * It is abstract because we never have a LabLog entity, it's either an event or a blog post.
 * @ORM\Entity
 * @ORM\Table(name="lablog")
 * @ORM\InheritanceType("SINGLE_TABLE")
 * @ORM\DiscriminatorColumn(name="type", type="string")
 * @ORM\DiscriminatorMap( {"event" = "Event", "blogpost" = "BlogPost"} )
 */
abstract class LabLogItem
{
    /**
     * @ORM\Id
     * @ORM\Column(type="integer")
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    protected $id;

    /**
     * @ORM\Column(type="date")
     */
    protected $date;

    /**
     * @ORM\Column(type="string")
     */
    protected $title;

    /**
     * @ORM\Column(type="text")
     */
    protected $description;

    /***** Getters and setters *****/

    public function getId()
    {
        return $this->id;
    }

    public function setDate($date)
    {
        $this->date = $date;
    }

    public function getDate()
    {
        return $this->date;
    }

    // And so on...
}

There are several things to note about the mapping:

  • @ORM\InheritanceType: indicates that this entity is used as parent class in the table inheritance. This example uses single table inheritance, but using multiple tables inheritance is as easy as setting the parameter to "JOINED". Doctrine will create an manage the unique or multiple database tables for you !
  • @ORM\DiscriminatorColumn: indicates which column will be used as discriminator (i.e. to store the type of item). You don't have to define this column in the entity, it will be automagically created by Doctrine.
  • @ORM\DiscriminatorMap: this is used to define the possible values of the discriminator column as well as associating a specific entity class with each type of item. Here the discriminator columns may contain the string "event" or "blogpost". When its value is "event" the class Event will be used, when its value is "blogpost", the class BlogPost will be used.

Basically that's the only thing you need to use table inheritance, but let's have a look at the children entities.

The children entities

We have two regular entities to model the events and blog posts. Those entities extend LabLogItem.

/**
 * Represent a blog post item.
 * Note that this class extends LabLogItem
 */
class LabLogItemBlog extends LabLogItem
{
    /**
     * @ORM\Column(type="text")
     */
    protected $content;

    /***** Getters and setters *****/

    public function getContent()
    {
        return $this->content;
    }

    public function setContent($content)
    {
        $this->content = $content;
    }
}

/**
 * Represent an event item.
 * Note that this class extends LabLogItem
 */
class LabLogItemEvent extends LabLogItem
{
    /**
     * @ORM\Column(type="string")
     */
    protected $eventType;

    /**
     * @ORM\Column(type="string")
     */
    protected $location;

    /**
     * @ORM\Column(type="boolean")
     */
    protected $requiresRegistration;

    /***** Getters and setters *****/

    public function getEventType()
    {
        return $this->eventType;
    }

    public function setEventType($type)
    {
        $this->eventType = $type;
    }

    // And so on...
}

There is not much special in the children entities. An important thing to note is that the common fields defined in the parent entity LabLogItem SHOULD NOT be repeated here. Also you may notice that there is no annotations in the children such as @ORM\Entity to indicate that they are entities. Indeed they will inherit the annotations of LabLogItem and become entities.

From now on, when you create a PHP object of type Event and ask the entity manager to persist it, Doctrine will automatically do the complex work for you. From the developper point of view, Events and BlogPosts are just entities like any other.

It's easy to do operations on items which you don't know exactly the type:

$item = $entityManager->getRepository('RocketLabBundle:LabLogItem')->findOneByDate($someDate);

// Here we don't know exactly whether $item contains a blog post or an event...

if ($item instanceof Event) {
    // Then it's an Event
    echo $item->getEventType();
} else {
    // Otherwise it's a BlogPost
    echo $item->getContent();
}

But, if you know the type of item you are using you still can use them as regular entities:

$item = $entityManager->getRepository('RocketLabBundle:Event')->findOneByDate($someDate);

//  We have searched the Event entity repository so what we get in $item MUST BE an Event
echo $item->getEventType();

Conclusion

As you can see above using table inheritance with Symfony and Doctrine is very easy. It's just a matter of creating the parent class and the correct mapping. Furthermore you can switch from single to multiple table inheritance by modifying one line of code.

This technique should be used whenever you need to store items with a common state but that are very different in their nature.


Comments [5]

The making of plaene.uzh.ch

Starting with a lot of information

Last autumn, we were asked to build a new version of plaene.uzh.ch

Alexandra Blankenhorn and her team from University Zurich (UZH) had already done a great deal of work and offered a detailed concept of the information they wanted to provide for every building. And they had a lot of information. Lists of all institutes, lecture rooms, museums, libraries, canteens and computer workstations for every building.

The application should be based on a map with all the buildings on it and some more information on the surroundings of every building. They didn't just provide us with a lot of data, but also with a lot of freedom and trust to create a good and simple solution for the task.

Designing for a small screen

These long lists of buildings and lecture rooms for every building were the major challenge when Zahida started with the first scribbles. She designed mobile first and started with the most difficult situation. A lot of data on a small screen.

To solve the problem, all additional information was banned from the map, since it's purpose is to find a building and see how you can get there. Information about rooms and services inside a building open in a separate layer if you tap on the building name. Loïc called it "Inspector" and the name stuck. The navigation inside the Inspector is smartphone-oriented (with tappable lists and horizontal movement) and we kept this behavior also for tablet and desktop. Designing mobile first helped us to focus on what's essential and also create easier-to-use concepts for the classic website.

Inspector Scripbles

Wireframes for all the different cases

To create the basic grid and functionality of the website, Zahida designed Wireframes for Desktop and for Tablet and Smartphone in both orientations.


Wireframes Inspector

Ala came up with very beautiful designs -- as always! And, they even built a clickable prototype.

Developers are the first test-users

As soon as they started developing, Reto, Colin, Sébi and Marco came back with a lot of feedback. They were the first ones to actually use the application and therefore the first ones to notice, when something didn't work out as we planned. We continually adapted the wireframes and provided solutions for emerging problems like "there are too many building markers on the map, they are overlapping" or "some institutes are distributed on different buildings, how do we solve that in the inspector?". We met with the UZH project team at least once a week to discuss open issues and decided which solution to go on with. The best way for us was to define only the basic functionality of the site, but then stay flexible to adapt the details in collaboration with the team representing the stakeholders.

Choice of the map service

The plan was to display all the buildings with clickable "markers" on an interactive map. The first thing that comes to mind when talking about maps is Google Maps. But because of privacy concerns about the way Google tracks user requests via cookie we also looked for other options. In the end we chose to use the open data solution provided by OpenStreetMap.

OpenStreetMap it is, now what?

Looking at the project from a technical point of view we were facing some challenges. First of all the decision to host the site at the university network has been made. Also the map tiles should have a customized style. That means we couldn't just access the tiles from the OpenStreetMap server. We had to setup our own server and serve customized tiles from there.

Setup the server

To be able to render our own map tiles, we installed Mapnik2[1] with all of its dependencies. Mapnik2 uses PostgreSQL as a database, so we decided to also use PostgreSQL for the project itself. We downloaded the map data from one of the several OpenStreetMap servers[2]. With all that stuff setup we could use the python scripts Mapnik2 provides to generate the tiles according to an xml which specifies how the tiles should look like. Depending on the bounding box of the area you are rendering the tiles for it can take quite a while. 

Openlayers and HTML markers

We have not found any possibility to display markers containing HTML by default, so we have created two classes which enabled us to have HTML-markers. They are called HtmlBox and HtmlMarker. Click here to check it out, there is also an example HTML file provided in the archive, in case you would like to use it too. There is a little catch with this though. You will need to edit two lines in the "lib/OpenLayers/Layer/Markers.js" respectively the OpenLayers.js file. We have opened a pull-request[3] for that matter, but sadly it has not been merged yet. There you can see what needs to be changed to get our classes to work flawlessly. 

Small and big screens

Since the website should be looking good on small devices too, responsive design was the way to go. We used media queries to apply different CSS styles based on the size of the viewport. That is a very easy but powerful way to make a site viewable on differently sized devices. 

And now it gets hollywoodesqe

Everybody involved in this project was very dedicated, committed and constructive. A special "Thank you" for the awesome collaboration goes out to UZH-Project-Team, to Ala and to Steve, who facilitated our regular project retrospectives and further improved our work together.

[1] http://mapnik.org/

[2] http://wiki.openstreetmap.org/wiki/Planet.osm#Country_and_area_extracts

[3] https://github.com/openlayers/openlayers/pull/53


Comments [2]

Liip is turning 5, celebrations on "Liip Day"

We're looking forward to celebrating "Liip Day" on February 29 by raising a glass to the future with our partners and colleagues. All information about our birthday celebration can be found at http://liipday.liip.ch.

5 Years Liip


Comments [0]

Applying Niwea: TV Sélection iPad app

The Tages-Anzeiger TV-Sélection iPad app has been available for download in the Apple app store for about a week now.

Huh?

TV Sélection is an app that lets you watch TV shows on your iPad. The focus is on shows in four different categories, hand-picked by the arts and entertainment editorial staff of Tages-Anzeiger, one of Switzerland's biggest newspapers. At the same time you can watch any other show on a wide range of channels by using the search functionality, with just a few minutes delay from the time it airs on TV.

NIWEA!

From a technical point of view, the app was implemented completely using Javascript, HTML5, and CSS, and wrapped as an iPad application using Phonegap. While we didn't take advantage of Phonegap's big selling point of being able to deploy the same code to multiple device types, being able to use HTML/JS/CSS played to our strengths. The other advantage though, was that we were able to develop and test large parts of the app directly in the browser, without having to constantly rebuild the code and run it on the device or a simulator. And that right there is the concept of NIWEA - writing code that can be re-used with no or very few changes across multiple platforms.

Where NIWEA breaks

When you're running on a device you want to take advantage of that devices native functionality. That may be the camera, accelerometer, or contacts. In our case we had three use-cases: We wanted to show notifications when not in the app, we wanted to use the devices keychain to store login details a bit more safely, and we wanted to take advantage of the fact that millions of users have their credit card information saved in their iTunes store account. We were able to do this by using phonegap plugins, one for local notifications, another to access the keychain and a third to handle In-App purchases.

And that's where the NIWEA concept cracks a little. Since these plugins rely on Objective C code to interact with the system, that functionality won't work on other devices. In some cases there may be plugins for your other device as well, and you can drop them in with little or no changes. In other cases you may have to write your own plugin, or just not offer all the features on every device. Since, again, we were only building for the iPad we weren't impacted much. We wrote a quick mock to simulate the keychain using cookies so we could continue testing in the browser. The missing local notifications hardly impacted us, and In-App purchases ended up being easiest to test on the device itself.

Look ma, no server!

While Phonegap was new to everyone on our team, it wasn't the only interesting thing from a technical point of view. One of the limitations of the whole project was that everything should run on the app - there is no backend, there are no servers.

OK, that's not entirely true - we access the tv shows and playlists through a (non-public, sorry) Zattoo API. We didn't control this ourselves though, and so anything that needed server-side code had to be planned and coordinated with Zattoo's developers. Since this obviously generates some overhead, every feature was examined to see how it could be done without requiring a backend. Want to send an email with debug information? Instead of sending it from a server, use a mailto link to open the iPads Mail app with some prefilled content. Want to use Push notifications to let the user know when his license expires? Sorry, push notifications require a server, but we can use local notifications instead, we just lose some flexibility because we have to trigger them when the subscription starts. In-App Purchases? There's a bunch of back-and-forth between Apple's servers and a callback URL to verify receipts and such - in this case Zattoo ended up extending their API to handle Apple subscriptions, with us simply passing on the receipt data we receive when the purchase is made.

More fun stuff

Other interesting details: We used WebSQL to cache the shows locally and allow you to save shows in your favorites. Probably because the WebSQL spec isn't being developed further there isn't a lot of documentation on what SQL operations you can actually use with it, so that was a bit of trial and error. Also, having database calls be asynchronous just seems like unnecessary complication.

We used the HTML5 video tag to display the video stream of the show. In general this works fine, but one thing to note is that if you use the default iOS media player instead of building your own controls, you lose the possibility to catch javascript events on the player area. For example, we were able to catch the touchmove event everywhere on the page to prevent you from being able to scroll/drag the page up and down, but we weren't able to prevent dragging on the player interface.

Finally, we used YUI3 as a javascript framework, where the main thing worth highlighting is the ScrollView module, which handles the vertically sliding list of shows. This worked well, but as the scrollable area grew, we did start seeing performance problems. To resolve this we decided not to display shows older than 30 days, which made scrolling much less jumpy! The other awesome feature of YUI3 which we used, and missed while using jQuery in another project, is the possibility to set dependencies when loading a module. The module will then wait to be initiated until all the required modules are loaded.

Let me at it!

Go ahead! The app is available for free in the App Store, and you'll receive a seven day trial in which you can watch any show. Unfortunately, you'll only be able to watch the shows if you're within in Switzerland due to licensing restrictions.

Related Entries:
- YUI Training
- Backbone.js, a micro MVC for javascript
- Kinect Hackday
- Vanilla is a NIWEA
- The Tagi iPad App done in NIWEA aka html5/CSS

Comments [2]

6 good reasons to work at Liip

Seven years ago I started working as a developer at one of the two companies that merged together to become Liip.  Why have I stayed so long?  I still like developing, and I still like working here.  Here are a few of the things that I think make Liip a great place to work:

Great people

There are lots of friendly, smart, helpful, interesting people here who are good at what they do. 

Interesting work

Projects come and projects go, and with each project I learn something new.  It's said that variety is the spice of life, and I certainly enjoy a bit of it in my work life.   One of the beauties of open source software is that it can be changed to do something more than before, and this can then be made available to others.  I always get a good feeling when I'm able to contribute something back.

Continual learning

Besides the new technologies or new corners of an old technology that we often explore in the context of a project, Liip provides it's employees other educational opportunities:

Once or twice a week there is a "tech talk" - a 30 minute presentation of some interesting topic.

Monthly hackday - one day in the month is kept clear of other meetings, so that interested people can participate in one of the sessions that has been organized.  Usually the goal is to bring an open source project a bit further, but sometimes it's just about exploring - hands on - an interesting topic.  For more, see reports of some previous hackdays.

Project-related workshops: sometimes, we need to know more to find out the best way to do something for a project.  In this case the team working on the project can organize a special workshop to deepen their knowledge on the subject.

Yearly "Tech day" - a day for and by the whole company, full of presentations and workshops (and good food).

An individual time and money budget for education that can be used as wished (well, not for a ski vacation).  Examples are conferences, language courses, trainings, or participating in the monthly hackdays.

Take a look at rocketlab.liip.ch to see some of the upcoming events, and please join us for one of them if you're passionate about the subject.

Family friendly

I saw a postcard the other day that said "Erziehung ist ... Zeit haben" (Raising a child is ...  having time).  I work at 80% so that I can spend one day during the week with my kids.  This is frowned upon in many companies, but Liip is very open to it; many people here work at 60-90%.

Also unusual for this country, Liip gives new fathers four weeks of paternity leave.  These four weeks can be taken sometime in the year after birth.  For me this was a great opportunity to bond with my kids, and my wife was really happy to me around to help out in the weeks after birth; this made her life easier.  Maternal leave is also augmented a bit, apparently the calculations there are a bit more complicated so I can't say by exactly how much.

Company with a conscience

Liip reserves the right to, and sometimes does, refuse projects because we find the goal of the project unethical.  Liip also takes measures to be environmentally friendly; examples are using "green" electricity and doing CO2 compensation for the energy used by the company.

Zen of a growing business

Liip has grown quite a lot in the past few years.  This has required a number of organizational changes, which, imho, Liip has succeeded at remarkably well, with few growing pains.  There are some organizational structures, but it remains transparent, uncomplicated and efficient.  It is not a hierarchical, decisions-come-from-the-top-live-with-it kind of place.  Constructive discussion of important topics is encouraged.  It's a company that keeps it's eyes and ears open and adapts.

And ...

Well, this post is getting long, so I'll stop.  But I certainly didn't mention all of the reasons that Liip is a great place to work.  If you're interested in working with us, take a look at the currently open jobs.


Comments [0]

Liip with a distinction at "Le Meilleur du Web 2011"

On November 30th, a handful of Liipers attended to "Le Meilleur du Web 2011" award night.

Similar to the "Best of Swiss Web" (BOSW), that takes place in Zurich every year, this award is the first of its kind in Suisse Romande. Born of a joint effort from Victoria Marchand, Thierry Weber and Rodolphe Koller, this first edition had also been prepared in collaboration with the organizers of the BOSW, which probably brought their share of experience. The goal of the event was to give some more visibility to web agencies in Romandie.

The event was well organized and the mood was good, about 200 people joined the ceremony and the Liip team were the only ones to bring with them "virtual team members" (aka Liipers Benoît and Sylvain). 

Basically, the whole Romand web scene was there with all the big agencies, but also small ones never heard of before. They were a bit less than 40 different projects in total. Some of them where submitted in distinct categories, which brought the number of total submissions to about 50 (pretty good for a first edition!).

Here are the awards results : 

On its side, Liip won a distinction in the "Technology and Innovation" category (only category with a special distinction) with the "Football for All" project (basically http://m.uefa.com & http://ac.uefa.com) for the exceptional tech complexity management.

This is an fantastic result for Liip Lausanne, after 8 months of the office creation. I wanted to thank warmly all the Lausanne staff, but also the UEFA and of course :ratio, our UX partner in this project, who all made this distinction possible!

Related Entries:
- Migipedia AND EventManager nominated for the Master Best Of Swiss Web 2011. Your vote counts!
- Best of Swiss Web 2009: The Aftermath

Comments [1]

Next1-10/300