Click here to Skip to main content
Click here to Skip to main content
Technical Blog

Recreating the Windows 8 SkyDrive App

, 25 Oct 2012 CPOL
Rate this:
Please Sign up or sign in to vote.
The SkyDrive Windows 8 application allows a user to manage their SkyDrive account. In this post I am going to show how to recreate the Folder/File User Interface in a WinJS (HTML & Javascript) project. In a future post I will look at other areas of functionality such as fetching the SkyDrive content

The SkyDrive Windows 8 application allows a user to manage their SkyDrive account. In this post I am going to show how to recreate the Folder/File User Interface in a WinJS (HTML & Javascript) project. In a future post I will look at other areas of functionality such as fetching the SkyDrive contents from the server.


The Goal

 

The UI of the SkyDrive app consists of the users folders displayed first in a multiple column list and the users files also in a multiple column list. For example see the following screenshot. The folders are displayed as wide blue rectangles and the files are display afterwards as tall rectangles with some known file types having a specific icon and colour. This is how we want our app to display.

screenshot_10232012_154846

 

What not to do

 

WinJS has a ListView control that is one of the main building blocks for WinJS applications and supports layout as a grid view. My first thought was that this should be 2 ListView controls, one after the other. This did not work. Thinking the ListView was really just some styled HTML my thought was that if I could force the 2 ListViews onto the same row then the first ListView would increase as its size increase and push the second ListView over.

I tried vanilla CSS (floats, inline display, etc), the –ms-grid properties, the -ms-flex properties but none gave the desired result. The grids would have individual scroll bars or be displayed underneath each other or not at all. I realized I was going down the wrong path and tried a different way. (If you look at the ListView in the DOM Explorer is seems to add elements to create its own viewport so getting it to work may have involved targeting this).

 

The Solution

 

The answer is to use one ListView to display both the folders and the files. We will use the ability of the ListView control to group items and to span multiple cells to accomplish the goal.

Grouping items works by grouping items in the ListView into separate sections e.g. to display address book contacts under alphabetical headers. This gives us the two separate sections for folders and files. See this screenshot for any example of grouping and this tutorial for more information.

grouping

The ListView control uses the –ms-grid display properties to display its item in a grid layout. For this reason the items must be the same size. However items can span multiple cells so we sill use this (with data binding of the CSS class name) to give us the different styles for folders and files. The following screenshot shows this and is taked from this sample.

spanning

 

The Setup

 

First create a new Javascript Windows Store application in Visual Studio using the “Navigation App” template. I’ve named mine SkyDrive. This project creates a default home page so we’ll just use that as our main page.

Now we’ll add the ListView control to the page. Place the contents of the section element with the following HTML.

<div class="itemslist" aria-label="List of items" data-win-control="WinJS.UI.ListView" data-win-options="{ selectionMode: 'none' }"></div>

 

Also let’s change the theme from dark to light to match SkyDrive. Change

<link href="//Microsoft.WinJS.1.0/css/ui-dark.css" rel="stylesheet" />

to

<link href="//Microsoft.WinJS.1.0/css/ui-light.css" rel="stylesheet" />

Also add the following CSS to the #contenthost style in default.css

background-color: #F4F4F4;

 

The app should now look like this:

screenshot_10232012_170437

 

Add Some Data

 

Binding to live data is a future exercise so for now we’ll just create some dummy data and bind to that.

Open up the home.js page and add the following code in the ready function to create our dummy data.

var items = [];
// Add some folders
for (var i = 1; i <= 6; i++) {
    items.push({
        Type: 'Folder',
        CssClass: 'Folder',
        Name: 'Folder ' + i
    });
}
// Add some files
items.push({
    Type: 'File',
    CssClass: 'File ExcelFile',
    Name: 'Book1'
});
for (var i = 1; i <= 3; i++) {
    items.push({
        Type: 'File',
        CssClass: 'File TextFile',
        Name: 'File' + i
    });
}

Next we need to bind this data to the ListView. We use the WinJS.Binding.List object to wrap our data array and assign it to the ListView.

var data = new WinJS.Binding.List(items);

var listView = element.querySelector(".itemslist").winControl;
listView.itemDataSource = data.dataSource;

This ListView should now display each of our items. It’s just going to display plain text representing the JSON objects so the next step is to use a template to style the items.

 

Styling the Items

 

We can use templates to style the ListView items. A template is a fragment of HTML that is hidden in the actual page but cloned and used to render each item. This allows us to use HTML to define each item. In addition we can use data binding to declaratively set the attributes of the HTML elements to the values for the current data item.

Insert the following HTML template into the home.html page anywhere under the body element.

    <div class="itemtemplate" data-win-control="WinJS.Binding.Template">
        <div data-win-bind="className: Type">
            <h2 class="item-title" data-win-bind="textContent: Name"></h2>
        </div>
    </div>

 

This template uses data binding to set the className of the wrapping div element and the inner HTML of the h2 element. (The div element with the itemtemplate class is not used in the item, it is just used to define the HTML as a template and to grab a reference to it).

Next we will assign the template to the ListView in the home.js file. Include the following line after the listView variable has been assigned.

listView.itemTemplate = element.querySelector(".itemtemplate");

 

Lastly add the following CSS to the home.css stylesheet to provide some initial styling for the items.

.itemslist
{
    height: 100%;
}

.Folder, .File
{
    height: 200px;
    width: 200px;
}

The app now displays each item as a square with the name of the folder/file.

screenshot_10232012_172426

 

Grouping Folders and Files

 

The next step is to group the folders and files to give us the 2 distinct sections for folders and files.

To group the items in a ListView we need to create a grouped projection. We can do this using the createGrouped method on the WinJS.Binding.List object. This method takes 3 parameters (each are functions): the first returns the key for the group given the item, the second returns the data for the group given the item, and the last is a comparer used to order the groups. Insert the following code after the binding list is created. This code will split the items into ‘Folder’ and ‘File’ groups and ensure the ‘Folder’ group comes first.

var groupedData = data.createGrouped(
    function getGroupKey(dataItem) {
        return dataItem.Type;
    },
    function getGroupData(dataItem) {
        return {
            Type: dataItem.Type
        };
    },
    function compareGroups(leftKey, rightKey) {
        if (leftKey === rightKey) return 0;
        if (leftKey === "Item") return -1;
        return 1;
    }
);

Next we need to bind the ListView using the grouped projection rather than the original binding list so remove the previous assignment of itemDataSource and insert the following code in it’s place.

listView.itemDataSource = groupedData.dataSource;
listView.groupDataSource = groupedData.groups.dataSource;

Lastly we don’t actually want to display the group headers so insert the following CSS into the home.css stylesheet to hide the group headers.

    .itemslist .win-groupheader
    {
        display: none;
    }

 

Great, we should now have a application that displays the folders first in one group and the files next in a second group.

screenshot_10232012_173422

 

Applying Different Styles to the Items

 

Now we need to display the individual items differently. We have already bound the className property of the template to the data items CssClass property so we can go ahead and start creating different CSS rules for each. However you would soon notice that each item is forced to be the same size. This is because each item is rendered using the grid layout. However we can use cell spanning to show each item as different sizes. If you look closely at the SkyDrive app you will notice that the folder elements are double the width of the file elements and the file elements are double the height of the folder elements. So we can see in both cases that cell spanning has been used.

To enable cell spanning we first need to setup the groupInfo property on the ListViews layout. We can use this to define the height and width of the cells. Insert the following javascript into the home.js file.

listView.layout.groupInfo = WinJS.Utilities.markSupportedForProcessing(function groupInfo() {
    return {
        enableCellSpanning: true,
        cellWidth: 185,
        cellHeight: 100
    };
});

Now we can assign different heights and width to the items. Replace the .Folder, .File CSS rule with this CSS.

.Folder
{
    height: 100px;
    width: 370px;
}

.File
{
    height: 200px;
    width: 185px;
}

 

Our app should now look like this.

screenshot_10232012_174431

Almost there! We now have the layout we were after and are ready to style the items.

 

Polishing it Off

 

We’ll make some changes to the template HTML to allow us to style it better.  We’ll add different elements for folders and files and only show the element we want. We’’ll also add a icon for files. So the template HTML looks like this.

<div class="itemtemplate" data-win-control="WinJS.Binding.Template">
    <div data-win-bind="className: CssClass">
         <div class="folder-overlay">
            <h3 class="folder-title" data-win-bind="textContent: Name"></h3>
        </div>

        <div class="file-image">
            <img src="#" data-win-bind="src: Image; alt: Name" />
        </div>
        <div class="file-overlay">
            <h3 class="file-title" data-win-bind="textContent: Name"></h3>
        </div>
    </div>
</div>

Next we’’ll modify the CSS stylesheet to attain a look similar to SkyDrive so our CSS now looks like this. We are making use of the grid and the flexible box layouts here. 

 

.itemslist
{
    height: 100%;
}

.itemslist .win-groupheader
{
    display: none;
}

h3
{
    font-family: Segoe UI Semibold;
    font-size: 11pt;
    color: white;
}

.Folder
{
    height: 100px;
    width: 370px;
	background: rgba(9,74,178,1);
    display: -ms-grid;
    -ms-grid-rows: 1fr 35px;
}
.Folder .folder-overlay
{
    -ms-grid-row: 2;
    margin: 10px;
}
.Folder .file-image
{
    display: none;
}
.Folder .file-overlay
{
    display: none;
}

.File
{
    height: 200px;
    width: 185px;
    background: rgba(147,149,152,1);
    display: -ms-grid;
    -ms-grid-rows: 1fr 50px;
    -ms-grid-columns: 1fr;
}
.File .file-image
{
    -ms-grid-row: 1;

    display: -ms-flexbox;
    -ms-flex-align: center;
    -ms-flex-pack: center;
}
.File .file-image img
{
    -ms-flex: 0 auto;
}
.ExcelFile
{
    background: rgba(67,148,103,1);
}
.File .file-overlay
{
    -ms-grid-row: 2;
    background: rgba(117,117,117,1);
    padding: 10px;
}
.File .folder-overlay
{
    display: none;
}

 

Lastly we need to set the icon for each file so the javascript code to create the dummy file now also assigns an Image property for each item.

// Add some files
items.push({
    Type: 'File',
    CssClass: 'File ExcelFile',
    Name: 'Book1',
    Image: 'images/excel.png'
});
for (var i = 1; i <= 3; i++) {
    items.push({
        Type: 'File',
        CssClass: 'File TextFile',
        Name: 'File' + i,
        Image: 'images/file.png'
    });
}

Voila, our app now closely resembles the SkyDrive app.

screenshot_10242012_111043

 

To Do

 

There are still some UI functionality to add such as the current location drop down on the header, the tooltips on hover and the number of items in the current and child folders. We’ll leave the implementation of these for a future post as well as the functionality to retrieve the data from a users actual SkyDrive account and opening of the files.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Chris P Herring
Software Developer (Senior) Intellimax Solutions
Australia Australia
I've been building software for 10 years after graduating from Griffith University with Honors. While I'm comfortable in any development environment I'm more focused on the Microsoft stack and Web technologies. I also do occasional Business Intelligence consulting and development.

Comments and Discussions

 
-- There are no messages in this forum --
| Advertise | Privacy | Mobile
Web04 | 2.8.141015.1 | Last Updated 25 Oct 2012
Article Copyright 2012 by Chris P Herring
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid