Create a blog reader complete code

This topic provides the complete code sample used in the tutorial Create a blog reader.

This topic contains these sections:

  • Technologies
  • Requirements
  • View the code (JavaScript)

Download location

This sample is not available for download.

Technologies

Programming languages HTML, JavaScript
Programming models Windows Runtime

Requirements

Minimum supported client Windows 8
Minimum supported server Windows Server 2012
Minimum required SDK Microsoft Visual Studio Express 2012 for Windows 8

View the code (JavaScript)

data.js

(function () {
    "use strict";

    // Set up array variables
    var dataPromises = [];
    var blogs;

    // Create a data binding for our ListView
    var blogPosts = new WinJS.Binding.List();

    // Process the blog feeds
    function getFeeds() {
        // Create an object for each feed in the blogs array
        // Get the content for each feed in the blogs array
        // Return when all asynchronous operations are complete

        // Create an object for each feed in the blogs array
        blogs = [
        {
            key: "blog1",
            url: 'https://blogs.windows.com/windows/b/windowsexperience/atom.aspx',
            title: 'tbd', updated: 'tbd',
            acquireSyndication: acquireSyndication, dataPromise: null
        },
        {
            key: "blog2",
            url: 'https://blogs.windows.com/windows/b/extremewindows/atom.aspx',
            title: 'tbd', updated: 'tbd',
            acquireSyndication: acquireSyndication, dataPromise: null
        },
        {
            key: "blog3",
            url: 'https://blogs.windows.com/windows/b/business/atom.aspx',
            title: 'tbd', updated: 'tbd',
            acquireSyndication: acquireSyndication, dataPromise: null
        },
        {
            key: "blog4",
            url: 'https://blogs.windows.com/windows/b/bloggingwindows/atom.aspx',
            title: 'tbd', updated: 'tbd',
            acquireSyndication: acquireSyndication, dataPromise: null
        },
        {
            key: "blog5",
            url: 'https://blogs.windows.com/windows/b/windowssecurity/atom.aspx',
            title: 'tbd', updated: 'tbd',
            acquireSyndication: acquireSyndication, dataPromise: null
        },
        {
            key: "blog6",
            url: 'https://blogs.windows.com/windows/b/springboard/atom.aspx',
            title: 'tbd', updated: 'tbd',
            acquireSyndication: acquireSyndication, dataPromise: null
        },
        {
            key: "blog7",
            url: 'https://blogs.windows.com/windows/b/windowshomeserver/atom.aspx',
            title: 'tbd', updated: 'tbd',
            acquireSyndication: acquireSyndication, dataPromise: null
        },
        {
            key: "blog8",
            url: 'https://blogs.windows.com/windows_live/b/developer/atom.aspx',
            title: 'tbd', updated: 'tbd',
            acquireSyndication: acquireSyndication, dataPromise: null
        },
        {
            key: "blog9",
            url: 'https://blogs.windows.com/ie/b/ie/atom.aspx',
            title: 'tbd', updated: 'tbd',
            acquireSyndication: acquireSyndication, dataPromise: null
        },
        {
            key: "blog10",
            url: 'https://blogs.windows.com/windows_phone/b/wpdev/atom.aspx',
            title: 'tbd', updated: 'tbd',
            acquireSyndication: acquireSyndication, dataPromise: null
        },
        {
            key: "blog11",
            url: 'https://blogs.windows.com/windows_phone/b/wmdev/atom.aspx',
            title: 'tbd', updated: 'tbd',
            acquireSyndication: acquireSyndication, dataPromise: null
        }];

        // Get the content for each feed in the blogs array
        blogs.forEach(function (feed) {
            feed.dataPromise = feed.acquireSyndication(feed.url);
            dataPromises.push(feed.dataPromise);
        });

        // Return when all asynchronous operations are complete
        return WinJS.Promise.join(dataPromises).then(function () {
            return blogs;
        });


    }

    function acquireSyndication(url) {

        // Call xhr for the URL to get results asynchronously
        return WinJS.xhr(
            {
                url: url,
                headers: { "If-Modified-Since": "Mon, 27 Mar 1972 00:00:00 GMT" }

            });

    }

    function getBlogPosts() {
        // Walk the results to retrieve the blog posts
        getFeeds().then(function () {
            // Process each blog
            blogs.forEach(function (feed) {
                feed.dataPromise.then(function (articlesResponse) {

                    var articleSyndication = articlesResponse.responseXML;

                    if (articleSyndication) {
                        // Get the blog title 
                        feed.title = articleSyndication.querySelector("feed > title").textContent;

                        // Use the date of the latest post as the last updated date
                        var published = articleSyndication.querySelector("feed > entry > published").textContent;

                        // Convert the date for display
                        var date = new Date(published);
                        var dateFmt = new Windows.Globalization.DateTimeFormatting.DateTimeFormatter(
                           "month.abbreviated day year.full");
                        var blogDate = dateFmt.format(date);
                        feed.updated = "Last updated " + blogDate;

                        // Get the blog posts
                        getItemsFromXml(articleSyndication, blogPosts, feed);
                    }
                    else {
                        
                        // There was an error loading the blog. 
                        feed.title = "Error loading blog";
                        feed.updated = "Error"; 
                        blogPosts.push({
                            group: feed,
                            key: "Error loading blog",
                            title: feed.url,
                            author: "Unknown",
                            month: "?",
                            day: "?",
                            year: "?",
                            content: "Unable to load the blog at " + feed.url
                        });

                    }
                });
            });
        });

        return blogPosts;

    }

    function getItemsFromXml(articleSyndication, bPosts, feed) {

        // Get the info for each blog post
        var posts = articleSyndication.querySelectorAll("entry");

        // Process each blog post
        for (var postIndex = 0; postIndex < posts.length; postIndex++) {
            var post = posts[postIndex];

            // Get the title, author, and date published
            var postTitle = post.querySelector("title").textContent;
            var postAuthor = post.querySelector("author > name").textContent;
            var postPublished = post.querySelector("published").textContent;

            // Convert the date for display
            var postDate = new Date(postPublished);
            var monthFmt = new Windows.Globalization.DateTimeFormatting.DateTimeFormatter(
                "month.abbreviated");
            var dayFmt = new Windows.Globalization.DateTimeFormatting.DateTimeFormatter(
                "day");
            var yearFmt = new Windows.Globalization.DateTimeFormatting.DateTimeFormatter(
                "year.full");
            var blogPostMonth = monthFmt.format(postDate);
            var blogPostDay = dayFmt.format(postDate);
            var blogPostYear = yearFmt.format(postDate);

            // Process the content so it displays nicely
            var staticContent = toStaticHTML(post.querySelector("content").textContent);

            // Store the post info we care about in the array
            bPosts.push({
                group: feed,
                key: feed.title,
                title: postTitle,
                author: postAuthor,
                month: blogPostMonth.toUpperCase(),
                day: blogPostDay,
                year: blogPostYear,
                content: staticContent
            });
        }

    }


    var list = getBlogPosts();

    var groupedItems = list.createGrouped(
        function groupKeySelector(item) { return item.group.key; },
        function groupDataSelector(item) { return item.group; }
    );



    WinJS.Namespace.define("Data", {
        items: groupedItems,
        groups: groupedItems.groups,
        getItemReference: getItemReference,
        getItemsFromGroup: getItemsFromGroup,
        resolveGroupReference: resolveGroupReference,
        resolveItemReference: resolveItemReference
    });

    // Get a reference for an item, using the group key and item title as a
    // unique reference to the item that can be easily serialized.
    function getItemReference(item) {
        return [item.group.key, item.title];
    }

    // This function returns a WinJS.Binding.List containing only the items
    // that belong to the provided group.
    function getItemsFromGroup(group) {
        return list.createFiltered(function (item) { return item.group.key === group.key; });
    }

    // Get the unique group corresponding to the provided group key.
    function resolveGroupReference(key) {
        for (var i = 0; i < groupedItems.groups.length; i++) {
            if (groupedItems.groups.getAt(i).key === key) {
                return groupedItems.groups.getAt(i);
            }
        }
    }

    // Get a unique item from the provided string array, which should contain a
    // group key and an item title.
    function resolveItemReference(reference) {
        for (var i = 0; i < groupedItems.length; i++) {
            var item = groupedItems.getAt(i);
            if (item.group.key === reference[0] && item.title === reference[1]) {
                return item;
            }
        }
    }


})();

default.css

#contenthost {
    height: 100%;
    width: 100%;    
    background-color: #0A2562;
}

.fragment {
    /* Define a grid with rows for a banner and a body */
    -ms-grid-columns: 1fr;
    -ms-grid-rows: 128px 1fr;
    display: -ms-grid;
    height: 100%;
    width: 100%;
}

    .fragment header[role=banner] {
        /* Define a grid with columns for the back button and page title. */
        -ms-grid-columns: 120px 1fr;
        -ms-grid-rows: 1fr;
        display: -ms-grid;
    }

        .fragment header[role=banner] .win-backbutton {
            margin-left: 39px;
            margin-top: 59px;
        }

        .fragment header[role=banner] .titlearea {
            -ms-grid-column: 2;
            margin-top: 37px;
        }

            .fragment header[role=banner] .titlearea .pagetitle {
                width: calc(100% - 20px);
            }

    .fragment section[role=main] {
        -ms-grid-row: 2;
        height: 100%;
        width: 100%;
    }

@media screen and (-ms-view-state: snapped) {
    .fragment header[role=banner] {
        -ms-grid-columns: auto 1fr;
        margin-left: 20px;
    }

        .fragment header[role=banner] .win-backbutton {
            margin: 0;
            margin-right: 10px;
            margin-top: 76px;
        }

            .fragment header[role=banner] .win-backbutton:disabled {
                display: none;
            }

        .fragment header[role=banner] .titlearea {
            -ms-grid-column: 2;
            margin-left: 0;
            margin-top: 68px;
        }
}

@media screen and (-ms-view-state: fullscreen-portrait) {
    .fragment header[role=banner] {
        -ms-grid-columns: 100px 1fr;
    }

        .fragment header[role=banner] .win-backbutton {
            margin-left: 29px;
        }
}

default.html

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>WindowsBlogReader</title>

    <!-- WinJS references -->
    <link href="//Microsoft.WinJS.2.0/css/ui-dark.css" rel="stylesheet" />
    <script src="//Microsoft.WinJS.2.0/js/base.js"></script>
    <script src="//Microsoft.WinJS.2.0/js/ui.js"></script>

    <!-- WindowsBlogReader references -->
    <link href="/css/default.css" rel="stylesheet" />
    <script src="/js/data.js"></script>
    <script src="/js/default.js"></script>
    <script src="/js/navigator.js"></script>
</head>
<body>
    <div id="contenthost" data-win-control="Application.PageControlNavigator" data-win-options="{home: '/pages/items/items.html'}"></div>
<div id="appbar" data-win-control="WinJS.UI.AppBar">
    <button data-win-control="WinJS.UI.AppBarCommand" 
        data-win-options="{id:'view', label:'Full View', icon:'add'}" type="button">
    </button>
</div> 

</body>
</html>

default.js

// For an introduction to the Split template, see the following documentation:
// https://go.microsoft.com/fwlink/p/?LinkID=232447
(function () {
    "use strict";

    WinJS.Binding.optimizeBindingReferences = true;

    var app = WinJS.Application;
    var activation = Windows.ApplicationModel.Activation;
    var nav = WinJS.Navigation;

    app.addEventListener("activated", function (args) {
        if (args.detail.kind === activation.ActivationKind.launch) {
            if (args.detail.previousExecutionState !== activation.ApplicationExecutionState.terminated) {
                // TODO: This application has been newly launched. Initialize
                // your application here.
            } else {
                // TODO: This application has been reactivated from suspension.
                // Restore application state here.
            }

            if (app.sessionState.history) {
                nav.history = app.sessionState.history;
            }
            args.setPromise(WinJS.UI.processAll().then(function () {
                if (nav.location) {
                    nav.history.current.initialPlaceholder = true;
                    return nav.navigate(nav.location, nav.state);
                } else {
                    return nav.navigate(Application.navigator.home);
                }
            }));
        }
    });

    app.oncheckpoint = function (args) {
        // TODO: This application is about to be suspended. Save any state
        // that needs to persist across suspensions here. If you need to 
        // complete an asynchronous operation before your application is 
        // suspended, call args.setPromise().
        app.sessionState.history = nav.history;
    };

    app.start();
})();

itemDetail.css

.itemDetail section[role=main] {
    -ms-grid-row: 2;
    display: block;
    height: 100%;
    overflow-x: auto;
    position: relative;
    width: 100%;
    z-index: 0;
}

    .itemDetail section[role=main] article {
        /* Define a multi-column, horizontally scrolling article by default. */
        column-fill: auto;
        column-gap: 80px;
        column-width: 480px;
        height: calc(100% - 50px);
        margin-left: 120px;
        width: 480px;
    }

        .itemDetail section[role=main] article .item-content p {
            margin-bottom: 20px;
            margin-right: 20px;
            vertical-align: baseline;
        }

@media screen and (-ms-view-state: snapped) {
    .itemDetail section[role=main] article {
        /* Define a single column, vertically scrolling article in snapped mode. */
        -ms-grid-columns: 300px 1fr;
        -ms-grid-row: 2;
        -ms-grid-rows: auto 60px;
        display: -ms-grid;
        height: 100%;
        margin-left: 20px;
        overflow-x: hidden;
        overflow-y: auto;
        width: 300px;
    }

        .itemDetail section[role=main] article .item-content {
            padding-bottom: 60px;
        }
}

@media screen and (-ms-view-state: fullscreen-portrait) {
    .itemDetail section[role=main] article {
        margin-left: 100px;
    }
}

itemDetail.html

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>itemDetail</title>

    <!-- WinJS references -->
    <link href="//Microsoft.WinJS.2.0/css/ui-dark.css" rel="stylesheet" />
    <script src="//Microsoft.WinJS.2.0/js/base.js"></script>
    <script src="//Microsoft.WinJS.2.0/js/ui.js"></script>

    <link href="itemDetail.css" rel="stylesheet" />
    <script src="itemDetail.js"></script>
</head>
<body>
    <div class="itemDetail fragment">
        <header aria-label="Header content" role="banner">
            <button class="win-backbutton" aria-label="Back" disabled type="button"></button>
            <h1 class="titlearea win-type-ellipsis">
                <span class="pagetitle">Welcome to itemDetail</span>
            </h1>
        </header>
<section aria-label="Main content" role="main">
    <article>
        <div class="item-content"></div>
    </article>
</section>

    </div>
</body>
</html>

itemDetail.js

// For an introduction to the Page Control template, see the following documentation:
// https://go.microsoft.com/fwlink/p/?LinkID=232511
(function () {
    "use strict";

    WinJS.UI.Pages.define("/pages/itemDetail/itemDetail.html", {
        // This function is called whenever a user navigates to this page. It
        // populates the page elements with the app's data.
        ready: function (element, options) {
            // TODO: Initialize the page here.
            // Display the appbar but hide the Full View button
            var appbar = document.getElementById('appbar');
            var appbarCtrl = appbar.winControl;
            appbarCtrl.hideCommands(["view"], false);

            var item = options && options.item ? options.item : Data.items.getAt(0);
            element.querySelector(".titlearea .pagetitle").textContent = item.title;
            element.querySelector("article .item-content").innerHTML = item.content;

        },

        unload: function () {
            // TODO: Respond to navigations away from this page.
        },

        updateLayout: function (element, viewState, lastViewState) {
            /// <param name="element" domElement="true" />

            // TODO: Respond to changes in viewState.
        }
    });
})();

items.css

.itemspage section[role=main] {
    -ms-grid-row: 1;
    -ms-grid-row-span: 2;
}

/* This selector is used to prevent ui-dark/light.css from overwriting changes
   to .win-surface. */
.itemspage .itemslist .win-horizontal.win-viewport .win-surface {
    margin-bottom: 60px;
    margin-left: 115px;
    margin-right: 115px;
    margin-top: 155px;
}

.itemspage .itemslist {
    height: 100%;
    position: relative;
    width: 100%;
    z-index: 0;
}

.itemspage .itemslist .item {
    -ms-grid-columns: 1fr;
    -ms-grid-rows: 1fr 60px;
    display: -ms-grid;
    height: 250px;
    width: 250px;
    background-color: #557EB9;
}
.itemspage .itemslist .win-item .item-title {
    -ms-grid-row: 1;
    overflow: hidden;
    width: 220px;
    font-size:  24px;
    margin-top: 12px;
    margin-left: 15px;
}


        .itemspage .itemslist .item .item-image {
            -ms-grid-row-span: 2;
        }

        .itemspage .itemslist .item .item-overlay {
            -ms-grid-row: 2;
            -ms-grid-rows: 1fr 21px;
            display: -ms-grid;
            padding: 6px 15px 2px 15px;
        }

            .itemspage .itemslist .item .item-overlay .item-title {
                -ms-grid-row: 1;
                overflow: hidden;
                width: 220px;
            }

            .itemspage .itemslist .item .item-overlay .item-subtitle {
                -ms-grid-row: 2;
                width: 220px;
            }

@media screen and (-ms-view-state: fullscreen-landscape), screen and (-ms-view-state: fullscreen-portrait), screen and (-ms-view-state: filled) {
    .itemspage .itemslist .item .item-overlay {
        background: rgba(0,0,0,0.65);
    }

        .itemspage .itemslist .item .item-overlay .item-title {
            color: rgba(255,255,255,0.87);
        }

        .itemspage .itemslist .item .item-overlay .item-subtitle {
            color: rgba(255,255,255,0.6);
        }
}

@media screen and (-ms-view-state: fullscreen-landscape) and (-ms-high-contrast), screen and (-ms-view-state: fullscreen-portrait) and (-ms-high-contrast), screen and (-ms-view-state: filled) and (-ms-high-contrast) {
    .itemspage .itemslist .item .item-overlay {
        color: WindowText;
    }
}

@media screen and (-ms-view-state: snapped) {
    .itemspage section[role=main] {
        -ms-grid-row: 2;
        -ms-grid-row-span: 1;
    }

    .itemspage .itemslist {
        margin-top: 0;
    }

        .itemspage .itemslist .win-vertical.win-viewport .win-surface {
            margin-bottom: 30px;
        }

        .itemspage .itemslist .win-container {
            margin-bottom: 15px;
            margin-left: 13px;
            margin-right: 35px;
            padding: 7px;
        }

        .itemspage .itemslist .item {
            -ms-grid-columns: 60px 1fr;
            -ms-grid-rows: 1fr;
            display: -ms-grid;
            height: 60px;
            width: 272px;
        }

            .itemspage .itemslist .item .item-image, .itemspage .itemslist .item:hover .item-image {
                -ms-grid-column: 1;
                -ms-grid-row-span: 1;
                height: 60px;
                width: 60px;
            }

            .itemspage .itemslist .item .item-overlay {
                -ms-grid-column: 2;
                -ms-grid-row: 1;
                -ms-grid-row-align: stretch;
                background: transparent;
                display: inline-block;
                margin-left: 10px;
                padding: 0;
            }

                .itemspage .itemslist .item .item-overlay .item-title {
                    margin-top: 4px;
                    max-height: 40px;
                    width: 202px;
                }

                .itemspage .itemslist .item .item-overlay .item-subtitle {
                    opacity: 0.6;
                    width: 202px;
                }
}

@media screen and (-ms-view-state: fullscreen-portrait) {
    .itemspage .itemslist .win-horizontal.win-viewport .win-surface {
        margin-left: 100px;
    }
}

items.html

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>itemsPage</title>

    <!-- WinJS references -->
    <link href="//Microsoft.WinJS.2.0/css/ui-dark.css" rel="stylesheet" />
    <script src="//Microsoft.WinJS.2.0/js/base.js"></script>
    <script src="//Microsoft.WinJS.2.0/js/ui.js"></script>

    <link href="/css/default.css" rel="stylesheet" />
    <link href="/pages/items/items.css" rel="stylesheet" />
    <script src="/js/data.js"></script>
    <script src="/pages/items/items.js"></script>
</head>
<body>
<div class="itemtemplate" data-win-control="WinJS.Binding.Template">
    <div class="item">
        <h4 class="item-title" data-win-bind="textContent: title"></h4>
        <div class="item-overlay">           
            <h6 class="item-subtitle win-type-ellipsis" data-win-bind="textContent: updated"></h6>
        </div>
    </div>
</div>


    <!-- The content that will be loaded and displayed. -->
    <div class="itemspage fragment">
        <header aria-label="Header content" role="banner">
            <button class="win-backbutton" aria-label="Back" disabled type="button"></button>
            <h1 class="titlearea win-type-ellipsis">
    <span class="pagetitle">Windows Team Blogs</span>
</h1>

        </header>
        <section aria-label="Main content" role="main">
            <div class="itemslist win-selectionstylefilled" aria-label="List of groups" data-win-control="WinJS.UI.ListView" data-win-options="{ selectionMode: 'none' }"></div>
        </section>
    </div>
</body>
</html>

items.js

(function () {
    "use strict";

    var appViewState = Windows.UI.ViewManagement.ApplicationViewState;
    var ui = WinJS.UI;

    ui.Pages.define("/pages/items/items.html", {
        // This function is called whenever a user navigates to this page. It
        // populates the page elements with the app's data.
        ready: function (element, options) {
            var listView = element.querySelector(".itemslist").winControl;
            listView.itemDataSource = Data.groups.dataSource;
            listView.itemTemplate = element.querySelector(".itemtemplate");
            listView.oniteminvoked = this._itemInvoked.bind(this);

            this._initializeLayout(listView, Windows.UI.ViewManagement.ApplicationView.value);
            listView.element.focus();

            // Display the appbar but hide the Full View button
            var appbar = document.getElementById('appbar');
            var appbarCtrl = appbar.winControl;
            appbarCtrl.hideCommands(["view"], false);

        },

        // This function updates the page layout in response to viewState changes.
        updateLayout: function (element, viewState, lastViewState) {
            /// <param name="element" domElement="true" />

            var listView = element.querySelector(".itemslist").winControl;
            if (lastViewState !== viewState) {
                if (lastViewState === appViewState.snapped || viewState === appViewState.snapped) {
                    var handler = function (e) {
                        listView.removeEventListener("contentanimating", handler, false);
                        e.preventDefault();
                    }
                    listView.addEventListener("contentanimating", handler, false);
                    var firstVisible = listView.indexOfFirstVisible;
                    this._initializeLayout(listView, viewState);
                    if (firstVisible >= 0 && listView.itemDataSource.list.length > 0) {
                        listView.indexOfFirstVisible = firstVisible;
                    }
                }
            }
        },

        // This function updates the ListView with new layouts
        _initializeLayout: function (listView, viewState) {
            /// <param name="listView" value="WinJS.UI.ListView.prototype" />

            if (viewState === appViewState.snapped) {
                listView.layout = new ui.ListLayout();
            } else {
                listView.layout = new ui.GridLayout();
            }
        },

        _itemInvoked: function (args) {
            var groupKey = Data.groups.getAt(args.detail.itemIndex).key;
            WinJS.Navigation.navigate("/pages/split/split.html", { groupKey: groupKey });
        }
    });
})();

navigator.js contains only generated code.

split.css

.splitpage {
    -ms-grid-columns: 640px 1fr;
    display: -ms-grid;
    height: 100%;
    width: 100%;
}

.splitpage .itemlistsection .itemlist .item .item-date {
    -ms-grid-column:  1;
    background-color: #557EB9;
}

    .splitpage .itemlistsection .itemlist .item .item-date .item-month{
        margin-top: 12px;
        margin-left: 12px;
        margin-bottom: 4px;
        font-weight: bold;
        font-size: 28px;
    }

    .splitpage .itemlistsection .itemlist .item .item-date .item-day{
        margin-left: 12px;
        font-size: 28px;
    }


    .splitpage header[role=banner] .pagetitle {
        -ms-grid-column: 2;
        overflow: hidden;
        width: calc(100% - 20px);
    }

    .splitpage .itemlistsection {
        -ms-grid-row: 2;
        margin-left: 106px;
    }

        .splitpage .itemlistsection .itemlist {
            height: 100%;
            position: relative;
            width: 100%;
            z-index: 0;
        }

            .splitpage .itemlistsection .itemlist .win-vertical.win-viewport .win-surface {
                margin-bottom: 60px;
            }

            .splitpage .itemlistsection .itemlist .win-container {
                margin-bottom: 15px;
                margin-right: 35px;
                padding: 7px;
            }

                .splitpage .itemlistsection .itemlist .win-container .win-selectioncheckmark, .splitpage .itemlistsection .itemlist .win-container .win-selectioncheckmarkbackground {
                    display: none;
                }

            .splitpage .itemlistsection .itemlist .item {
                -ms-grid-columns: 110px 1fr;
                -ms-grid-rows: 1fr;
                display: -ms-grid;
                height: 110px;
                width: 500px;
            }

                .splitpage .itemlistsection .itemlist .item .item-info {
                    -ms-grid-column: 2;
                    margin-left: 10px;
                    margin-right: 10px;
                    overflow: hidden;
                }

                    .splitpage .itemlistsection .itemlist .item .item-info .item-title {
                        margin-top: 4px;
                    }

                    .splitpage .itemlistsection .itemlist .item .item-info .item-subtitle {
                        opacity: 0.6;
                    }

                    .splitpage .itemlistsection .itemlist .item .item-info .item-description {
                        max-height: 60px;
                        overflow: hidden;
                    }

    .splitpage .articlesection {
        -ms-grid-column: 2;
        -ms-grid-row: 2;
        -ms-grid-row-span: 2;
        margin-left: 50px;
        overflow-y: auto;
        padding-right: 120px;
        position: relative;
        z-index: 0;
    }

        .splitpage .articlesection header {
            -ms-grid-columns: 180px 20px 1fr;
            -ms-grid-rows: 180px;
            display: -ms-grid;
            margin-bottom: 5px;
            margin-top: 60px;
        }

            .splitpage .articlesection header .text {
                -ms-grid-column: 3;
            }

                .splitpage .articlesection header .text .article-subtitle {
                    margin-top: 4px;
                }

            .splitpage .articlesection header .article-image {
                height: 180px;
                width: 180px;
            }

        .splitpage .articlesection .article-content {
            overflow-y: auto;
        }

            .splitpage .articlesection .article-content p {
                margin-bottom: 16pt;
            }

@media screen and (-ms-view-state: filled) {
    .splitpage {
        -ms-grid-columns: 420px 1fr;
    }

        .splitpage .itemlistsection .itemlist .item {
            -ms-grid-columns: 60px 1fr;
            height: 60px;
            margin-bottom: 0;
            width: 282px;
        }

            .splitpage .itemlistsection .itemlist .item .item-image {
                height: 60px;
                width: 60px;
            }

            .splitpage .itemlistsection .itemlist .item .item-info .item-title {
                margin-top: 4px;
                max-height: 40px;
                overflow: hidden;
            }

            .splitpage .itemlistsection .itemlist .item .item-info .item-description {
                display: none;
            }

        .splitpage .articlesection {
            margin-left: 60px;
            padding-right: 66px;
        }
}

@media screen and (-ms-view-state: snapped) {
    .splitpage {
        -ms-grid-columns: 320px 0px;
    }

        .splitpage .itemlistsection {
            margin-left: 6px;
        }

            .splitpage .itemlistsection .itemlist .item {
                -ms-grid-columns: 60px 1fr;
                height: 60px;
                width: 282px;
            }

                .splitpage .itemlistsection .itemlist .item .item-image {
                    height: 60px;
                    width: 60px;
                }

                .splitpage .itemlistsection .itemlist .item .item-info .item-title {
                    margin-top: 4px;
                    max-height: 30pt;
                    overflow: hidden;
                }

                .splitpage .itemlistsection .itemlist .item .item-info .item-description {
                    visibility: hidden;
                }

        .splitpage .articlesection {
            -ms-grid-row-span: 1;
            -ms-grid-row: 2;
            margin-left: 20px;
            padding-right: 36px;
        }

            .splitpage .articlesection header {
                display: block;
                margin-top: 0;
            }

                .splitpage .articlesection header .text {
                    -ms-grid-column: 1;
                    margin-top: 6px;
                }

                    .splitpage .articlesection header .text .article-subtitle {
                        margin-bottom: 16px;
                        margin-top: 10px;
                        overflow: hidden;
                    }

                .splitpage .articlesection header .article-image {
                    height: 160px;
                    width: 242px;
                }

        .splitpage .itemlistsection, .splitpage .articlesection {
            -ms-grid-column: 2;
            visibility: hidden;
        }

        .splitpage .primarycolumn {
            -ms-grid-column: 1;
            visibility: visible;
        }
}

@media screen and (-ms-view-state: fullscreen-portrait) {
    .splitpage {
        -ms-grid-columns: 1fr 0px;
    }

        .splitpage .itemlistsection {
            margin-left: 86px;
        }

            .splitpage .itemlistsection .itemlist .win-vertical.win-viewport .win-container {
                margin-right: calc(100% - 510px);
            }

        .splitpage .articlesection {
            -ms-grid-row: 2;
            -ms-grid-row-span: 1;
            margin-left: 100px;
            padding-right: 100px;
        }

            .splitpage .articlesection .header {
                margin-top: 0;
            }

        .splitpage .itemlistsection, .splitpage .articlesection {
            -ms-grid-column: 2;
            visibility: hidden;
        }

        .splitpage .primarycolumn {
            -ms-grid-column: 1;
            visibility: visible;
        }
}

split.html

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>splitPage</title>

    <!-- WinJS references -->
    <link href="//Microsoft.WinJS.2.0/css/ui-dark.css" rel="stylesheet" />
    <script src="//Microsoft.WinJS.2.0/js/base.js"></script>
    <script src="//Microsoft.WinJS.2.0/js/ui.js"></script>

    <link href="/css/default.css" rel="stylesheet" />
    <link href="/pages/split/split.css" rel="stylesheet" />
    <script src="/js/data.js"></script>
    <script src="/pages/split/split.js"></script>
</head>
<body>
    <!-- This template is used to display each item in the ListView declared below. -->
<div class="itemtemplate" data-win-control="WinJS.Binding.Template">
    <div class="item">
       <div class="item-date">
          <p class="item-month" data-win-bind="innerHTML: month"></p>
          <span class="item-day" data-win-bind="innerHTML: day"></span> | 
          <span class="item-year" data-win-bind="innerHTML: year"></span>
       </div>
        <div class="item-info">
            <h3 class="item-title win-type-ellipsis" data-win-bind="textContent: title"></h3>
            <h6 class="item-subtitle win-type-ellipsis" data-win-bind="textContent: author"></h6>
        </div>
    </div>
</div>


    <!-- The content that will be loaded and displayed. -->
    <div class="splitpage fragment">
        <header aria-label="Header content" role="banner">
            <button class="win-backbutton" aria-label="Back" disabled type="button"></button>
            <h1 class="titlearea win-type-ellipsis">
                <span class="pagetitle"></span>
            </h1>
        </header>
        <div class="itemlistsection" aria-label="List column">
            <div class="itemlist win-selectionstylefilled" aria-label="List of this group's items" data-win-control="WinJS.UI.ListView" data-win-options="{ selectionMode: 'single', swipeBehavior: 'none', tapBehavior: 'toggleSelect' }"></div>
        </div>
        <div class="articlesection" aria-atomic="true" aria-label="Item detail column" aria-live="assertive">
            <article>
                
                <div class="article-content" data-win-bind="innerHTML: content"></div>
            </article>
        </div>
    </div>
</body>
</html>

split.js

(function () {
    "use strict";

    var appViewState = Windows.UI.ViewManagement.ApplicationViewState;
    var binding = WinJS.Binding;
    var nav = WinJS.Navigation;
    var ui = WinJS.UI;
    var utils = WinJS.Utilities;
    // The selected item
    var post;

    function displayFullView() {
        // Display the selected item in the item detail page
        nav.navigate('/pages/itemDetail/itemDetail.html', { item: post });
    }


    ui.Pages.define("/pages/split/split.html", {

        /// <field type="WinJS.Binding.List" />
        _items: null,
        _group: null,
        _itemSelectionIndex: -1,

        // This function is called whenever a user navigates to this page. It
        // populates the page elements with the app's data.
        ready: function (element, options) {
            var listView = element.querySelector(".itemlist").winControl;

            // Store information about the group and selection that this page will
            // display.
            this._group = (options && options.groupKey) ? Data.resolveGroupReference(options.groupKey) : Data.groups.getAt(0);
            this._items = Data.getItemsFromGroup(this._group);
            this._itemSelectionIndex = (options && "selectedIndex" in options) ? options.selectedIndex : -1;

            // Get the first item, which is the default selection
            post = this._items.getAt(0);

            element.querySelector("header[role=banner] .pagetitle").textContent = this._group.title;

            // Set up the ListView.
            listView.itemDataSource = this._items.dataSource;
            listView.itemTemplate = element.querySelector(".itemtemplate");
            listView.onselectionchanged = this._selectionChanged.bind(this);
            listView.layout = new ui.ListLayout();

            this._updateVisibility();
            if (this._isSingleColumn()) {
                if (this._itemSelectionIndex >= 0) {
                    // For single-column detail view, load the article.
                    binding.processAll(element.querySelector(".articlesection"), this._items.getAt(this._itemSelectionIndex));
                }
            } else {
                if (nav.canGoBack && nav.history.backStack[nav.history.backStack.length - 1].location === "/pages/split/split.html") {
                    // Clean up the backstack to handle a user snapping, navigating
                    // away, unsnapping, and then returning to this page.
                    nav.history.backStack.pop();
                }
                // If this page has a selectionIndex, make that selection
                // appear in the ListView.
                listView.selection.set(Math.max(this._itemSelectionIndex, 0));
            }

            // Display the appbar and show the Full View button
            var appbar = document.getElementById('appbar');
            var appbarCtrl = appbar.winControl;
            appbarCtrl.showCommands(["view"], false);

            // Register the event handler for the Full View button
            document.getElementById('view').addEventListener("click", displayFullView, false);

        },

        unload: function () {
            this._items.dispose();
        },

        // This function updates the page layout in response to viewState changes.
        updateLayout: function (element, viewState, lastViewState) {
            /// <param name="element" domElement="true" />

            var listView = element.querySelector(".itemlist").winControl;
            var firstVisible = listView.indexOfFirstVisible;
            this._updateVisibility();

            var handler = function (e) {
                listView.removeEventListener("contentanimating", handler, false);
                e.preventDefault();
            }

            if (this._isSingleColumn()) {
                listView.selection.clear();
                if (this._itemSelectionIndex >= 0) {
                    // If the app has snapped into a single-column detail view,
                    // add the single-column list view to the backstack.
                    nav.history.current.state = {
                        groupKey: this._group.key,
                        selectedIndex: this._itemSelectionIndex
                    };
                    nav.history.backStack.push({
                        location: "/pages/split/split.html",
                        state: { groupKey: this._group.key }
                    });
                    element.querySelector(".articlesection").focus();
                } else {
                    listView.addEventListener("contentanimating", handler, false);
                    if (firstVisible >= 0 && listView.itemDataSource.list.length > 0) {
                        listView.indexOfFirstVisible = firstVisible;
                    }
                    listView.forceLayout();
                }
            } else {
                // If the app has unsnapped into the two-column view, remove any
                // splitPage instances that got added to the backstack.
                if (nav.canGoBack && nav.history.backStack[nav.history.backStack.length - 1].location === "/pages/split/split.html") {
                    nav.history.backStack.pop();
                }
                if (viewState !== lastViewState) {
                    listView.addEventListener("contentanimating", handler, false);
                    if (firstVisible >= 0 && listView.itemDataSource.list.length > 0) {
                        listView.indexOfFirstVisible = firstVisible;
                    }
                    listView.forceLayout();
                }

                listView.selection.set(this._itemSelectionIndex >= 0 ? this._itemSelectionIndex : Math.max(firstVisible, 0));
            }
        },

        // This function checks if the list and details columns should be displayed
        // on separate pages instead of side-by-side.
        _isSingleColumn: function () {
            var viewState = Windows.UI.ViewManagement.ApplicationView.value;
            return (viewState === appViewState.snapped || viewState === appViewState.fullScreenPortrait);
        },

        _selectionChanged: function (args) {
            var listView = document.body.querySelector(".itemlist").winControl;
            var details;
            // By default, the selection is restriced to a single item.
            listView.selection.getItems().done(function updateDetails(items) {
                if (items.length > 0) {
                    this._itemSelectionIndex = items[0].index;
                    // Get the item selected by the user
                    post = this._items.getAt(this._itemSelectionIndex);

                    if (this._isSingleColumn()) {
                        // If snapped or portrait, navigate to a new page containing the
                        // selected item's details.
                        nav.navigate("/pages/split/split.html", { groupKey: this._group.key, selectedIndex: this._itemSelectionIndex });
                    } else {
                        // If fullscreen or filled, update the details column with new data.
                        details = document.querySelector(".articlesection");
                        binding.processAll(details, items[0].data);
                        details.scrollTop = 0;
                    }
                }
            }.bind(this));
        },

        // This function toggles visibility of the two columns based on the current
        // view state and item selection.
        _updateVisibility: function () {
            var oldPrimary = document.querySelector(".primarycolumn");
            if (oldPrimary) {
                utils.removeClass(oldPrimary, "primarycolumn");
            }
            if (this._isSingleColumn()) {
                if (this._itemSelectionIndex >= 0) {
                    utils.addClass(document.querySelector(".articlesection"), "primarycolumn");
                    document.querySelector(".articlesection").focus();
                } else {
                    utils.addClass(document.querySelector(".itemlistsection"), "primarycolumn");
                    document.querySelector(".itemlist").focus();
                }
            } else {
                document.querySelector(".itemlist").focus();
            }
        }
    });
})();