共用方式為


如何自訂 Visual Studio 範本資料 (HTML)

[ 本文的目標對象是撰寫 Windows 執行階段 App 的 Windows 8.x 和 Windows Phone 8.x 開發人員。如果您正在開發適用於 Windows 10 的 App,請參閱 最新文件 ]

在「中樞/樞紐」、「中樞」、「樞紐」、「格線」及「分割」範本中,取得應用程式所需資料的程式碼位於 data.js 檔案中。 這個檔案代表應用程式的範例資料來源。data.js 檔案包含通常需以動態資料取代的靜態資料。例如,如果您的應用程式發出一個 xhr 要求來取得 RSS 或 JSON 資料,您可能想在 data.js 中包含這個程式碼。在該處包含程式碼可讓您易於使用自己的資料,而不用變更範本中的資料模型。

秘訣  「中樞/樞紐」、「中樞」及「樞紐」範本也可以從支援全球化的 .resjson 檔案擷取靜態資料。如需詳細資訊,請參閱將資料繫結至中樞/樞紐、中樞及樞紐範本 UI 的範例。

 

將您自己的資料新增至應用程式時,您需要注意幾件事情:

  • 群組與項目在本質上是連結的。應用程式的項目資料必須組織為群組。您可以在自己的實作取消兩者的連結,但是需要修改程式碼才能讓實作運作。本主題顯示範本資料模型中群組的用法。
  • 當您在 data.js 中實作應用程式的自訂資料時,需要確定自訂資料的固有屬性名稱對應到範本使用的屬性名稱。您可以變更範本使用的名稱,但是需要修改更多程式碼。本主題將說明做法範例。

項目和群組

範本資料是儲存在 WinJS.Binding.List 中。這個程式碼顯示 data.js 檔案中的清單宣告。

var list = new WinJS.Binding.List();

項目資料陣列 (此範例中為 sampleItems) 是透過 push 函式傳送至 WinJS.Binding.List,如這裡所示:

generateSampleData.forEach(function (item) {
    list.push(item);
});

WinJS.Binding.List 包含用來處理資料群組的內部邏輯。sampleItems 陣列包含 group 屬性,用來識別項目所屬的群組 (在範例資料中,群組指定於 sampleGroups 陣列中)。這裡是 generateSampleData 函式中的項目資料陣列:

function generateSampleData() {
    // . . .
    var sampleGroups = [
        { key: "group1", title: "Group Title: 1", // . . .
        // . . .
    ];

    var sampleItems = [
        { group: sampleGroups[0], title: "Item Title: 1", // . . .
        // . . .
    ];

    return sampleItems;
}

當您為自訂資料修改應用程式時,可能需要按照資料群組的相同模式。若為較小的資料集,建議您為 ListView 使用 WinJS.Binding.List。如果您沒有將項目群組,仍然可以使用 WinJS.Binding.List,但是如果範本需要尋找以群組為基礎的資料時,還是需要修改範本的程式碼。

秘訣  WinJS.Binding.List 是使用 JavaScript 陣列的同步資料來源。若為非常龐大的資料集 (可能包含數千個項目),則需要使用非同步資料來源。如需詳細資訊,請參閱使用 ListView

 

WinJS.Binding.ListcreateGrouped 函式指定如何使用群組機碼和項目群組值來群組項目。此函式是在 data.js 中呼叫。keygroup 都是在範例資料陣列中指定的屬性名稱。

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

當範本應用程式需要項目清單時,它會呼叫 getItemsFromGroup,而這會傳回 WinJS.Binding.List,其中僅包含屬於指定群組的項目。

function getItemsFromGroup(group) {
    return list.createFiltered(function (item) {
        return item.group.key === group.key;
    });
}

秘訣  getItemsFromGroup 這類函式 (會呼叫 createFiltered) 會建立新的 WinJS.Binding.List 投影,如果您離開頁面,可能就需要處置傳回的物件。若要處置物件,請呼叫 WinJS.Binding.List.dispose 方法。

 

適用於 JavaScript 的 Windows Library define 函式會透過指定名為 Data 的命名空間搭配一組公開成員函式,公開要在應用程式中使用的資料。

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

如果您要針對應用程式的每個頁面定義不同的資料來源,或不同的資料模型,就必須在 JavaScript 程式碼中取代對這些成員的所有呼叫。

將群組和項目繫結至 UI

下列程式碼顯示 ListView 控制項的標記範例。ListView 的資料來源是在 itemDataSource 屬性指定,如下所示。這個範例來自「分割」範本中的 split.html。


<div class="itemlist win-selectionstylefilled" aria-label="List of this group's items" data-win-control="WinJS.UI.ListView" data-win-options="{
    layout: {type: WinJS.UI.ListLayout},
    currentItem: {type: WinJS.UI.ObjectType.item, index: 0, hasFocus: true},
    selectionMode: 'single',
    swipeBehavior: 'none',
    tapBehavior: 'toggleSelect',
    itemDataSource: select('.pagecontrol').winControl.itemDataSource,
    itemTemplate: select('.itemtemplate'),
    onselectionchanged: select('.pagecontrol').winControl.selectionChanged
    }">
</div>

在上述程式碼中,與頁面關聯的 itemDataSource 屬性會指派給 ListView 控制項的 itemDataSource 屬性。

在範本中,資料通常是繫結至 init 函式或 ready 函式 (定義於和每個 HTML 網頁相關聯的 .js 檔案) 中的 UI。下列程式碼包含在 split.html 的 init 函式中。在這段程式碼中,應用程式會取得群組參考,然後呼叫在 data.js 中實作的 getItemsFromGroup。如前所述,getItemsFromGroup 會傳回 WinJS.Binding.List,其中只包含指定群組中的項目。

this._group = Data.resolveGroupReference(options.groupKey);
this._items = Data.getItemsFromGroup(this._group);

我們接著將 getItemsFromGroup 傳回的清單繫結至頁面的 itemDataSource 屬性,這會將資料繫結至 ListView,我們還會指定項目選取的處理常式 (_selectionChanged)。


this.itemDataSource = this._items.dataSource;
this.selectionChanged = ui.eventHandler(this._selectionChanged.bind(this));

為了在 ListView 中顯示每個項目,應用程式會讓範本與 ListView 產生關聯,如下所示。這段程式碼會顯示在 ListView 控制項的標記中,並使用 itemTemplate 屬性指定類別名稱為 itemtemplate 的 DIV 元素。

itemTemplate: select('.itemtemplate')

WinJS.Binding.Template 為基礎的 WinJS 範本會用來格式化和顯示資料的多個例項。「格線」和「分割」範本中最常使用的範本,是用來顯示 ListView 中項目的項目範本。就像每個 WinJS 範本物件,您透過新增 data-win-control 屬性並將該屬性設定為 WinJS.Binding.Template 來宣告它。這是 split.html 中 itemtemplate 的 HTML 程式碼:

<div class="itemtemplate" data-win-control="WinJS.Binding.Template">
    <div class="item">
        <img class="item-image" src="#" data-win-bind="src: backgroundImage; alt: title" />
        <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>

itemtemplate 是用於一個任意 ListView 項目。視內容而定,ListView 項目可能是群組或個別資料項目。例如,在 items.html 中,ListView 項目是群組。

重要  您使用 WinJS.Binding.Template 建立的範本與 Visual Studio 專案和項目範本沒有關係,例如「格線」和「分割」範本。

 

專案範本在資料中必須出現特定屬性,而且 HTML 中要明確命名這些屬性。在 itemtemplate 的上述 HTML 程式碼中,您會找到 titlesubtitle 之類的屬性。如果您的自訂應用程式資料不使用這些屬性名稱,則需要執行下列其中一項工作:

  • 將您的資料對應至這些屬性名稱 (通常在 data.js 中);或者
  • 在範本程式碼中修正這些屬性的所有 HTML 和 .js 程式碼參考,讓它們符合您資料中使用的屬性名稱。範本中使用的屬性包含:
    • titlesubtitledescription 以及 backgroundImage (群組和項目屬性)
    • groupcontent (項目屬性)
    • key (群組屬性)

按照相同的 WinJS 範本模式,「格線」應用程式範本也會在它的部分 HTML 網頁中使用 headerTemplate

將資料繫結至「中樞/樞紐」、「中樞」及「樞紐」範本 UI 的範例

Visual Studio 的「中樞/樞紐」、「中樞」及「樞紐」專案範本示範如何實作兩種不同的資料來源:

  • 儲存在 .resjson 資源檔中的全球化靜態資料。這個資料會用在一些應用程式區段 (PivotItemHubSection 控制項) 中。
  • data.js 中的範例資料 (代表資料模型)。這個檔案與「格線」和「分割」範本中的相同。這個範例資料會用在其中一個應用程式區段的 ListView 控制項中。

HTML 中的宣告式函式最初是用來取得範例資料,資料模型預設是同步的。自訂範本以便在所有區段中使用動態資料,需要對 hub.html、hub.js 及其他檔案進行一些變更。下列範例應用程式示範如何自訂「中樞/樞紐」和「樞紐」範本以支援非同步資料:

因為 .resjson 檔案中的全球化資料很容易被取代,所以範例應用程式不會修改這個資源檔。在範例應用程式中,會以非同步方式擷取 <img> 元素資料和「中樞/樞紐」區段中的 ListView 控制項。

如需在 .resjson 檔案中提供全球化資料的詳細資訊,請參閱快速入門:翻譯 UI 資源

若要支援將非同步資料繫結至「中樞/樞紐」的 ListView 控制項,請先取代 hub.js 中這些呼叫資料模型的全域變數。

var section3Group = Data.resolveGroupReference("group4");
var section3Items = Data.getItemsFromGroup(section3Group);

取代為這些變數宣告:


var section3Group = "group2";
var section3Items;

您還必須修改 hub.js 中宣告式函式的實作。在預設範本實作中,這些函式取決於已可使用的資料 (例如對於 section3Items.dataSource 的呼叫)。請將這個程式碼:

section3DataSource: section3Items.dataSource,

section3HeaderNavigate: util.markSupportedForProcessing(function (args) {
    nav.navigate("/pages/section/section.html", { title: args.detail.section.header, 
        groupKey: section3Group.key });
}),

section3ItemNavigate: util.markSupportedForProcessing(function (args) {
    var item = Data.getItemReference(section3Items.getAt(args.detail.itemIndex));
    nav.navigate("/pages/item/item.html", { item: item });
}),

取代為:


section3DataSource: null,

section3HeaderNavigate: util.markSupportedForProcessing(function (args) {
    nav.navigate("/pages/section/section.html", { title: args.detail.section.header,
        groupKey: section3Group });
}),

section3ItemNavigate: util.markSupportedForProcessing(function (args) {
    var itemSet = section3Items;
    var itemObj = itemSet.getAt(args.detail.itemIndex);
    var item = [itemObj.group.key, itemObj.title, itemObj.backgroundImage];

    nav.navigate("/pages/item/item.html", { item: item });
}),

這個程式碼會將 section3DataSource 函式設定為 null,以避免嘗試繫結尚未就緒的資料。我們稍後會在資料繫結函式 (_bindDatabindListView,取決於範例應用程式而定) 中設定資料來源。

資料可用時,就會呼叫資料繫結函式。為了啟用此功能,我們為資料模型的 dataReady 事件新增了接聽程式 (在 data.js 中的範例應用程式定義)。


this._observer = Data.getObservable();
this._observer.addEventListener('dataReady', this.onDataCompleted.bind(this));

應用程式會從 onDataCompleted 事件處理常式 (未顯示) 呼叫資料繫結函式。「中樞」範本範例 _bindData 函式的程式碼如下所示。在這段程式碼中,我們設定 ListViewitemDataSource 屬性。


_bindData: function (context, grp1Items, grp2Items) {

    var self = context;

    // . . .

    self._items = grp2Items;
    section3Items = self._items;
    self._section3lv.itemDataSource = self._items.dataSource;

    // . . .   

},

如果使用 [上一步] 按鈕瀏覽頁面,因為不需要等候新資料,所以會直接從頁面的初始化函式呼叫資料繫結函式。

秘訣  在「中樞」範本程式碼中,為了查詢 ListView 元素的 DOM (儲存於 _section3lv),應用程式會從 Hub 控制項的 loadingstatechanged 事件處理常式呼叫 _hubReady 函式。只在中樞頁面載入完成時,才會啟動這個事件。使用這個事件處理常式,我們就能夠查詢 DOM,以取得與 ListView 關聯的巢狀 DIV 元素。

 

如需讓非同步資料能夠在「中樞/樞紐」和「中樞」範本中運作的完整程式碼,請參閱使用中樞/樞紐範本的 JSON Web 讀取程式使用中樞範本的 JSON Web 讀取程式。除了此處所述的自訂之外,我們還對範例應用程式進行了下列變更:

  • 在資料模型 (data.js) 中加入程式碼,以使用 xhr 要求擷取資料並剖析 JSON 資料 (來自 Flickr)。
  • 在資料模型中加入程式碼,以處理多重資料要求並在資料傳回時啟動 dataReady 事件。
  • 在 UI 中加入輸入方塊,以要求新資料。
  • 加入進度列,以顯示資料要求的狀態。
  • 在輸入方塊與進度列新增 CSS 樣式。
  • 加入函式,在 Hub 控制項完全載入之後初始化頁面 (如 _hubReady_hubReadyPhone)。
  • 修改「中樞/樞紐」或「中樞」的 <img> 元素,以支援 Click 事件 (修改的檔案專用於這個範本)。
  • 修改檔案,將非同步資料繫結至「中樞/樞紐」或「中樞」的 <img> 元素 (修改的檔案專用於這個範本)。
  • 修改 hub.js,支援從「中樞」的 <img> 元素瀏覽至影像 (修改的檔案專用於這個範本)。
  • 修改了 item.html 與 item.js,以支援檢視單一影像。

將資料繫結至 UI 的範例 (格線與分割)

本節說明如何在「格線」與「分割」專案範本中實作您自己的資料來源。這裡的程式碼範例使用 xhr 要求來產生 RSS 資料。

重要  若要在「中樞」範本中實作非同步資料,請參閱將資料繫結至中樞範本中的 UI。

 

更新 data.js

  1. 在 Visual Studio 中建立新專案。使用分割應用程式或格線應用程式專案範本。

  2. 在 data.js 中,將下列變數新增到檔案開頭附近的 use strict 陳述式之後:

    var lightGray = "data:image/png;base64,
        iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXY7h4+cp/AAhpA3h+ANDKAAAAAElFTkSuQmCC";
    var mediumGray = "data:image/png;base64,
        iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXY5g8dcZ/AAY/AsAlWFQ+AAAAAElFTkSuQmCC";
    
  3. 在 data.js 中,移除包含下列陣列的 generateSampleData 函式:sampleGroupssampleItems

    我們將以 RSS 資料取代此資料。我們不會使用大多數的預留位置變數 (例如 groupDescription),但是會重複使用預留位置影像 (lightGraymediumGray),以讓新的程式碼運作。

  4. 在移除 generateSampleData 的同一個位置,將下列程式碼新增到 data.js:

    
    function getFeeds() {
        // Create an object for each feed.
        blogs = [
            {
                key: "blog1", url: 
           'https://windowsteamblog.com/windows/b/developers/atom.aspx',
                title: 'tbd', subtitle: 'subtitle', updated: 'tbd',
                backgroundImage: lightGray,
                acquireSyndication: acquireSyndication, dataPromise: null
            },
            {
                key: "blog2", url: 
           'https://windowsteamblog.com/windows/b/windowsexperience/atom.aspx',
                title: 'tbd', subtitle: 'subtitle', updated: 'tbd',
                backgroundImage: lightGray,
                acquireSyndication: acquireSyndication, dataPromise: null
            }]
        // Get the content for each feed in the blog's 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) {
        return WinJS.xhr(
        {
            url: url,
            headers: { "If-Modified-Since": "Mon, 27 Mar 1972 00:00:00 GMT" }               
        });
    }
    
    function getBlogPosts() {
        getFeeds().then(function () {
            // Process each blog.
            blogs.forEach(function (feed) {
                feed.dataPromise.then(function (articlesResponse) {
                    var articleSyndication = articlesResponse.responseXML;
    
                    // Get the blog title and last updated date.
                    if (articleSyndication) {
                        // Get the blog title and last updated date.
                        feed.title = articleSyndication.querySelector(
                            "feed > title").textContent;
                        var ds = articleSyndication.querySelector(
                            "feed > updated").textContent;
                        var date = ds.substring(5, 7) + "-" +
                            ds.substring(8, 10) + "-" + ds.substring(0, 4);
                        feed.updated = "Last updated " + date;
                        // Process 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, blogPosts, feed) {
        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 pds = post.querySelector("published").textContent;
            var postDate = pds.substring(5, 7) + "-" + pds.substring(8, 10)
                + "-" + pds.substring(0, 4);
            // Process the content so that it displays nicely.
            var staticContent = toStaticHTML(post.querySelector(
                "content").textContent);
            // Store the post info we care about in the array.
            blogPosts.push({
                group: feed, key: feed.title, title: postTitle, 
                author: postAuthor, pubDate: postDate, 
                backgroundImage: mediumGray, content: staticContent
            });
        }
    }
    
  5. 在 data.js 中,取代這個程式碼:

    var list = new WinJS.Binding.List();
    var groupedItems = list.createGrouped(
        function groupKeySelector(item) { return item.group.key; },
        function groupDataSelector(item) { return item.group; }
    );
    
    // TODO: Replace the data with your real data.
    // You can add data from asynchronous sources whenever it becomes available.
    generateSampleData.forEach(function (item) {
        list.push(item);
    });
    

    取代為:

    var dataPromises = [];
    var blogs;
    
    var blogPosts = new WinJS.Binding.List();
    
    var list = getBlogPosts();
    var groupedItems = list.createGrouped(
        function groupKeySelector(item) { return item.group.key; },
        function groupDataSelector(item) { return item.group; }
    );
    

    我們將重複使用 createGrouped 中可指定群組的程式碼—groupKeySelectorgroupDataSelector 函式。

    因為我們已經變更範本所使用的某些屬性名稱,所以將需要更新 HTML 網頁。特別是對於參考從 subtitle 變更為 author 的項目 (非群組) 的任何 subtitle 屬性。對於參考項目的任何 description 屬性,需要將 description 變更為 pubDate

    若要在 UI 中實作這些變更,請參閱下列其中一個小節:

    • 將範例資料繫結至分割範本中的 UI
    • 將範例資料繫結至格線範本中的 UI

將範例資料繫結至分割範本中的 UI

  1. 若要在分割範本中使用範例程式碼,請開啟 split.html。

  2. 在 split.html 中,我們需要變更 DIV 元素中的幾行程式碼,這個元素具有 itemtemplate 的類別名稱。將這行:

    
    <h6 class="item-subtitle win-type-ellipsis" data-win-bind="textContent: subtitle"></h6>
    

    變更為:

    <h6 class="item-subtitle win-type-ellipsis" data-win-bind="textContent: author"></h6>
    
  3. 此外在 split.html 中,文章區段 (articlesection) 有我們需要更新的標頭資訊。將這行:

    <h4 class="article-subtitle" data-win-bind="textContent: subtitle"></h4>
    

    變更為:

    <h4 class="article-subtitle" data-win-bind="textContent: author"></h4>
    
  4. 開啟 items.html。

    HTML 程式碼中定義的 WinJS 項目範本包含任意 ListView 項目。在 items.html 中,範本是用來顯示群組 (部落格)。我們在這裡唯一需要變更的群組屬性是 subtitle

    <h6 class="item-subtitle win-type-ellipsis" 
        data-win-bind="textContent: subtitle"></h6>
    
  5. subtitle 屬性變更為 updated,如這裡所示:

    <h6 class="item-subtitle win-type-ellipsis"
        data-win-bind="textContent: updated"></h6>
    
  6. 儲存專案,然後按 F5 來偵錯應用程式。

    您會立刻看到網頁標題,但是在抓取摘要資料時會有短暫延遲。完成所有應完成的事項之後,您會在首頁中看到每個部落格。按一下其中一個部落格,在主控制項/詳細資料控制項檢視中查看部落格文章。

將範例資料繫結至格線範本中的 UI

進行這些步驟之前,請更新 data.js 專案檔,如將資料繫結至 UI 的範例所述。

  1. 若要在格線範本中使用 RSS 範例程式碼,請開啟 groupDetail.html。

    此頁面顯示單一群組 (一個部落格) 以及該群組中的個別項目 (部落格文章)。

  2. 在 groupDetail.html 中,我們需要變更 DIV 元素中的幾行程式碼,這個元素具有 item-info 的類別名稱。將這幾行:

    
    <h6 class="item-subtitle win-type-ellipsis"
        data-win-bind="textContent: subtitle"></h6>
    <h4 class="item-description" 
        data-win-bind="textContent: description"></h4>
    

    變更為:

    <h6 class="item-subtitle win-type-ellipsis" 
        data-win-bind="textContent: author"></h6>
    <h4 class="item-description" 
        data-win-bind="textContent: pubDate"></h4>
    

    在 groupDetail.html 中,標頭範本描述群組資訊,而不是個別項目。因此我們不需要變更 subtitle 屬性。這裡是標頭範本:

    
    <div class="headertemplate" data-win-control="WinJS.Binding.Template">
        <h2 class="group-subtitle" data-win-bind="textContent: subtitle"></h2>
        <img class="group-image" src="#" 
            data-win-bind="src: backgroundImage; alt: title" />
        <h4 class="group-description" data-win-bind="innerHTML: description"></h4>
    </div>
    
  3. 不過,並非每個群組都有 description 屬性 (項目才有這個屬性),因此我們必須在上述程式碼中,將該屬性變更為 updated,如下所示。

    <h4 class="group-description" data-win-bind="innerHTML: updated"></h4>
    
  4. 開啟 groupedItems.html,它會顯示所有群組及其中個別的部落格文章。

  5. 在這個網頁上,一般 WinJS 項目範本會顯示個別項目 (部落格文章),所以我們需要更新 subtitle 屬性。將這個:

    <h6 class="item-subtitle win-type-ellipsis" 
        data-win-bind="textContent: subtitle"></h6>
    

    變更為:

    <h6 class="item-subtitle win-type-ellipsis" 
        data-win-bind="textContent: author"></h6>
    
  6. 儲存專案,然後按 F5 來偵錯應用程式。

    您會立刻看到網頁標題,但是在抓取摘要資料時會有短暫延遲。傳回資料即表示已完成應完成的事項,您會在首頁看到每個部落格中的項目。按一下群組標題來檢視群組頁面,或是按一下項目來檢視個別部落格文章。

data.js 的程式碼清單

以下是 data.js 的完整程式碼清單。相同的 data.js 檔案會使用於先前顯示的格線與分割範本範例。如需中樞/樞紐範本的 data.js 檔案,請參閱使用中樞/樞紐範本的 JSON Web 讀取程式。如需中樞範本的 data.js 檔案,請參閱使用中樞範本的 JSON Web 讀取程式


(function () {
    "use strict";

    
    var lightGray = "data:image/png;base64, iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXY7h4+cp/AAhpA3h+ANDKAAAAAElFTkSuQmCC";
    var mediumGray = "data:image/png;base64, iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXY5g8dcZ/AAY/AsAlWFQ+AAAAAElFTkSuQmCC";


    var dataPromises = [];
    var blogs;

    var blogPosts = new WinJS.Binding.List();

    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) {
        return groupedItems.groups.getItemFromKey(key).data;
    }

    // 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;
            }
        }
    }



    function getFeeds() {
        // Create an object for each feed.
        blogs = [
            {
                key: "blog1", url:
           'https://windowsteamblog.com/windows/b/developers/atom.aspx',
                title: 'tbd', subtitle: 'subtitle', updated: 'tbd',
                backgroundImage: lightGray,
                acquireSyndication: acquireSyndication, dataPromise: null
            },
            {
                key: "blog2", url:
           'https://windowsteamblog.com/windows/b/windowsexperience/atom.aspx',
                title: 'tbd', subtitle: 'subtitle', updated: 'tbd',
                backgroundImage: lightGray,
                acquireSyndication: acquireSyndication, dataPromise: null
            }]
        // Get the content for each feed in the blog's 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) {
        return WinJS.xhr({
            url: url,
            headers: { "If-Modified-Since": "Mon, 27 Mar 1972 00:00:00 GMT" }
        });
    }

    function getBlogPosts() {
        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 and last updated date.
                        feed.title = articleSyndication.querySelector(
                            "feed > title").textContent;
                        var ds = articleSyndication.querySelector(
                            "feed > updated").textContent;
                        var date = ds.substring(5, 7) + "-" +
                            ds.substring(8, 10) + "-" + ds.substring(0, 4);
                        feed.updated = "Last updated " + date;
                        // Process 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, blogPosts, feed) {
        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 pds = post.querySelector("published").textContent;
            var postDate = pds.substring(5, 7) + "-" + pds.substring(8, 10)
                + "-" + pds.substring(0, 4);
            // Process the content so that it displays nicely.
            var staticContent = toStaticHTML(post.querySelector(
                "content").textContent);
            // Store the post info we care about in the array.
            blogPosts.push({
                group: feed, key: feed.title, title: postTitle,
                author: postAuthor, pubDate: postDate,
                backgroundImage: mediumGray, content: staticContent
            });
        }
    }

})();

相關主題

JavaScript 專案範本

JavaScript 項目範本

新增資料至專案範本 (使用 C#、VB 和 C++)