Building a webshop in a week
By: Jan-Erik Revsbech
Today (13. of march 2011) the MOC Hack Week or hackathon is kicked off. The purpose of the week is to educate employees at MOC, and make sure that everyone is aware of- and up-to-date with current and emerging technologies.
Together with Aske Ertmann and Rasmus Skjoldan, my project for this week is to make a HTML5 webshop that shows the potential, versatility and flexibility of the MOC Shop framework, and at the same time learn something about HTML5 and Semantic-web (GoodRelations and RDFa).
Also we will experiment with an agile design implementation process. Traditionally the design process consist of an initial UX/IA wireframing process, then a full Photoshop implementation and first at that point are the HTML/CSS ninjas summoned to do the actual implementation, and often the result might look exactly like the photoshop, but it stil doesnt "feel" right in real life.
Instead we'll try to do all wireframing, blueprints and concept models on paper and whiteboards, designer and programmer together - and then completely skip Photoshop & Axure (our preferred wireframing and prototyping tool) going directly to HTML/CSS implementation, getting the maximum out of all technologies, and ending with a much smoother end result that "feels" right - or so is the idea at least.
I'll try to keep a small diary here of what we accomplish during our Hack Week. Read an inspiring article about how Novell conducted their Hack Week way back in 2007. Some of their notions match ours pretty well.
Day1: Brainstorming and wireframing
The first day was spent with initial startup of the whole hack-week, and by doing a lot of brainstorming on what we wanted to accomplish with our project, and how to actually do it. We decided to create a webshop that will sell colors (as a demo-webshop, no actual purchase possible). Colors have the exceptional property that they are conceptually easy to understand and very easy to generate tons of products, including images, and they can be combined in many ways to make cool product presentations.
Time was spent making diagrams of domain-models, and wireframing on the whiteboard and on paper, and getting inspired by other webshops and technologies.
After looking at many different websites, we decided to go for a fully fluid 16-grid structure, that adapts to browser size. And make search function central to the webshop.
Below are some links that inspired us...
Fluid "full width" design:
http://www.rga.com/about/featured/our-model
Drag'n'drop (of products in our case):
http://business.meebo.com
Bottom "pop-up" navigation- and toolbar:
http://moma.org/
Big search input:
http://soundcloud.com/search?q%5Bfulltext%5D=axwell
Day2: Research'n Design'n Development in one go
After yesterday Rasmus had, in a fever dream, realized that the first wild search interface would be too difficult to use. So instead of staying with what was initially decided upon we quickly changed horses and revised the search interface to make it more intuitive and follow common user interface standards just a bit more.
Research collecting
We're using a shared Google Doc as continous specification of functions, to share proposals, snippets and inspirational material. Alongside design & development we're still massively researching for additional inspiration - and simply just trying stuff out.
Today we looked at HTML5 video in the background:
http://s3.envato.com/files/235878/index.html
+ the canvas element, new CSS3 and javascript stuff and lots of different non-flash interface experiments (among many, here are a few good ones):
http://methoddesignlab.com/
http://www.samdallyn.com/
http://us.playstation.com/psp/features/ps_psp_connectivity.html
everytimezone.com
Using time to output CSS, not PSD files!
We've also used a lot of CSS3 generators letting our designer chunk out CSS and HTML for buttons, backgrounds gradients etc. instead of the normal process of working out the aesthetics in Photoshop.
Iterating, iterating and iterating
We're deliberately not specifying everything in advance but trying things out and seeing what works, what's doesn't - and what's missing for an optimal user experience. It's a lot fun building things like this!
CSS3 and HTML5
While iteratively implementing the desires of Rasmus wicked deisgnmind, we dived into one of the goals of the project: To learn more about CSS3 and HTML5, we decided to go with a central radial gradient on the fontpage, and CSS3 gradients and drop-shadows on all input elements (especially the searchbar). We were a little disapointed to learn that webkit and mozilla does not share the same featureset and the endresult looks a little different depending on which browser you use. Especially we could not find any nive way to make the radial gradient elliptical, and were unable to specify the radius in percentage, rather than fixed pixels, which results in a less smooth experience when resizing the browserwindow in Chrome and other webkit browsers.
For now IE is not among the tested browser, but we have good reason to believe that the site with a little effort should degrade gracefully. We look forward to testing the brand new IE9 though!
Below is a little CSS snippet of the CSS for the frontpage, notice especially th use of radial-gradients, and SASS variables ($color-end-center-gradient etc.)
body {
background: -webkit-gradient(radial, 50% 50%, 350, 50% 50%, 550, from($color-white), to($color-end-center-gradient));
background: -moz-radial-gradient(50% 50% 90deg,ellipse closest-side, $color-white 60%, $color-end-center-gradient 100%);
height: 100%;
color: $color-std-text;
text-decoration: none;
word-spacing: normal;
text-align: left;
letter-spacing: 0;
font-size: 1em;
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
}
Canvas
For the search autocompletion (actually more a seach-while-you type google kind og thingie) we needed a loader icon, and off course decided to try out the new Canvas element. Although we would have loved to implement our own canvas loader icon, we decided to go for a preprogrammed canvas element, rendring an apple-style loadericon while we fetch the search-result.
Day 3-5: Progress and finalizing the shop
Good intentions are always best in the beginning, and this blogpost is no difference. I really did intend to write a little bit every day, but no such luck. So here is a wrapup of the last days.
Wednesday was a rather short day, personal issued meant that we were unable to put in the hours intended. But a lot of progress was made on the genereal design and CSS of the site. One big thing we did, was to refactor CSS and JavaScript into smaller components so we could work more easily on the same project sourcecode. We dvelved a little deeper into Sass and its @include directive, allwing us to split the CSS into different files, and still keeping a central scss file with color- and mixin-definitions.
Adding drag-n-drop
Thursday morning was really productive. We started implementing the drag'n'drop features of the shop. Using JqueryUI drag'n,drop proved really easy, great tool!. Take a look the JS snippet code below used for the drag'n'drop feature. Simple, right?
self.initDraggables = function() {
var dragConf = {
scope: 'products',
helper: 'clone',
appendTo: 'body',
start: function(event, ui) {
self.openDropZone();
},
stop: function(event, ui) {
if(!self.isOverDropZone) {
self.closeDropZone();
}
}
};
$('.product-dragable').draggable(dragConf);
};
self.initDropZone = function() {
self.origDropZoneHtml = self.dropZoneHandle.html();
var dropConf = {
scope: 'products',
hoverClass: 'hover-product',
over: function(event,ui) {
self.dropZoneHandle.html('Great, you can drop it now');
self.isOverDropZone = true;
},
out: function(event, ui) {
self.dropZoneHandle.html(self.origDropZoneHtml);
self.isOverDropZone = false;
},
drop: function(event,ui) {
var temp = ui.draggable.attr('id').split('_');
if(temp[1]) {
MOC_SHOP.Manager.addProduct(temp[1],1);
}
self.dropZoneHandle.addClass('finished').html('Good choice!<br />Shop or checkout');
self.open();
self.tabs.tabs[0].close();
self.tabs.tabs[1].open();
setTimeout(function() {
self.closeDropZone(100);
} ,2000);
}
};
self.dropZoneHandle.droppable(dropConf);
self.dropZoneHandle.droppable('disable');
};
As the day progressed, we reached the point where we had to kill features in order to actually end up with a working product. So some time was spent on debugging code, and working on perfecting the experience and the design.
Finalizing the end-product
The last bugs was killed, minor designchanges was implemented, and the last feature was implemented just 5 minutes before deadline and presentation friday. As always this part of a project take much longer times than one should think when planning the project. There are always bugs to kill, and things that needs change. As a final task, we used the YUI compressor to minimize JavaScript, merged all into one file. Actually, we decided to leave jQuery in its own file, included in the header, and have all other js merged into on minimized file and included in the bottom. To help this task we wrote up a small Phing buildfile to minimize css and JS and merge it. The buildlfile is given below for reference.
<?xml version="1.0" encoding="UTF-8" ?>
<project name="MOCTypo3PackageManager" default="all" basedir="build/">
<property name="jspath" value="../templates/scripts/" override="true" />
<property name="csspath" value="../templates/css/" override="true" />
<property name="mergedjspath" value ="${jspath}alljs-min.js" override="true" />
<property name="jsListFile" value="${jspath}scriptsToMerge.txt" override="true" />
<property name="mergedcsspath" value ="${csspath}allcss-min.js" override="true" />
<property name="cssListFile" value="${csspath}scriptsToMerge.txt" override="true" />
<taskdef name="compress" classname="tasks.YUI.CompressorTask" />
<taskdef name="merge" classname="tasks.MOC.MergeTask" />
<!-- ============================================ -->
<!-- Target: clean -->
<!-- ============================================ -->
<target name="clean">
<delete includeemptydirs="false" dir="${jspath}min/" />
<delete includeemptydirs="false" dir="${csspath}min/" />
<delete file="${mergedjspath}" />
<delete file="${mergedcsspath}" />
</target>
<!-- ============================================ -->
<!-- Target: all -->
<!-- ============================================ -->
<target name="all">
<echo msg="Makeing all" />
</target>
<!-- ============================================ -->
<!-- Target: minify-js -->
<!-- ============================================ -->
<target name="minify-js">
<echo>--------------------------------</echo>
<echo>| Minify javascript to release |</echo>
<echo>--------------------------------</echo>
<compress targetDir="${jspath}min/"
yuiPath="tools/yuicompressor-2.4.2.jar">
<fileset dir="${jspath}">
<include name="*.js"/>
</fileset>
</compress>
</target>
<!-- ============================================ -->
<!-- Target: merge-js -->
<!-- ============================================ -->
<target name="merge-js" depends="minify-js">
<echo>---------------------------------</echo>
<echo>| Merging javascript to release |</echo>
<echo>---------------------------------</echo>
<append destFile="${mergedjspath}" >
<filelist dir="${jspath}min/" listfile="${jsListFile}" />
</append>
</target>
<!-- ============================================ -->
<!-- Target: minify-css -->
<!-- ============================================ -->
<target name="minify-css">
<echo>--------------------------------</echo>
<echo>| Minify CSS |</echo>
<echo>--------------------------------</echo>
<compress targetDir="${csspath}min"
yuiPath="tools/yuicompressor-2.4.2.jar">
<fileset dir="${csspath}">
<include name="*.css"/>
</fileset>
</compress>
</target>
<!-- ============================================ -->
<!-- Target: merge-css -->
<!-- ============================================ -->
<target name="merge-css" depends="minify-css">
<echo>---------------------------------</echo>
<echo>| Merging CSS |</echo>
<echo>---------------------------------</echo>
<append destFile="${mergedcsspath}" >
<filelist dir="${csspath}min/" listfile="${cssListFile}" />
</append>
</target>
</project>
Varnish
We put the site behind out Varnish cache, instructed TYPO3 to send Cache-control headers, and configured Varnish to send one-hour Cache header to the client, but keep a local cache for images, css and JS for 1 week. Std. MOC Highperforrmance Operating procedure.
Conclusions
To sum up, we actually did implement a webshop in one week. There was a lot of things we wanted to make but did'nt have the time for, including a much more advanced search feature, and a one-step checkout-procedure (actually the demoshop has no checkout procedure at the momment).
But with only one week, we still ended up with a - in our own huble oppinions - very cool webshop. And we learned a lot during the development. Both technical (CSS3, HTML5, SASS, JQuery, Extbase), but also about working desinger and developers together. The process was both very inspiring, productive and very, very fun to implement! The possibility for the designer to provide instant feedback during the development gives a very dynamic end-product and a hyper-productive development process.
However, to have this process work its full potential, the team needs to be able to take decisions very fast, and as such require the end-customer or product-owner to be close to the team.
Or, the product-owner could just trust the designer and developer to produce a cool product (which they surely will).
Check it out!
So now you probalby want to take a look at the end-product? Sure, click here
and youre there!
One last thing: You would not think of using a inferior not-standard-compliant browser would you?
Thanks for following our work!
The MOColorshop team AKA Aske Ertmann, Rasmus Skjoldan and Jan-Erik Revsbech
Checkout it out!
Checkout the result, the MO Colorshop at
Oh, one more thing. Youre running a std. compliant browser right? We recomend Chrome.








