Click here to Skip to main content
13,054,329 members (132,588 online)
Click here to Skip to main content
Add your own
alternative version

Stats

6K views
7 bookmarked
Posted 25 Oct 2012

Recreating the Windows 8 SkyDrive App

, 25 Oct 2012
Rate this:
Please Sign up or sign in to vote.
How to recreate the Windows 8 SkyDrive app

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 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, it 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 still 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 taken 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 its 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 an 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 is 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.

You may also be interested in...

Comments and Discussions

 
-- There are no messages in this forum --
Permalink | Advertise | Privacy | Terms of Use | Mobile
Web02 | 2.8.170713.1 | Last Updated 25 Oct 2012
Article Copyright 2012 by Chris P Herring
Everything else Copyright © CodeProject, 1999-2017
Layout: fixed | fluid