연습: 블로그 뷰어 만들기(JavaScript 및 HTML)

이 연습에서는 분할 앱 Visual Studio 템플릿을 사용하여 블로그 읽기 앱을 만드는 방법을 보여 줍니다. 블로그 뷰어 앱은 RSS 피드의 데이터를 요청하고, 피드에서 반환된 XML을 구문 분석하고, ListView 컨트롤을 채우고, 상황에 맞는 AppBar 컨트롤을 만듭니다.

중요  이 연습에서는 Windows 8.1에 도입된 API를 사용합니다. Microsoft Visual Studio 2012 및 Windows 8에서는 이 자습서의 일부가 제대로 작동하지 않습니다.

WindowsBlogReader

이 연습에서는 일부 Windows 팀 블로그에 대한 기본 뷰어를 만듭니다. 완성된 앱은 다음과 같습니다.

Windows 블로그 뷰어 앱의 홈페이지, 분할 페이지 및 세부 정보 페이지

항목 페이지의 제목은 "Windows Team Blogs"이며 블로그당 한 항목씩 ListView 컨트롤이 있습니다. ListView에서 항목을 클릭하여 선택한 블로그에 대한 분할 페이지로 이동합니다. 분할 페이지에는 블로그 게시물당 한 항목씩 ListView 컨트롤이 있으며 현재 선택한 블로그 게시물의 콘텐츠를 세로로 표시하는 컨트롤이 있습니다. 분할 페이지에서는 블로그 게시물의 제목을 맨 위에 표시하고 현재 선택한 블로그 게시물의 콘텐츠를 가로로 표시하는 항목 세부 정보 페이지로 이동할 수 있습니다.

Visual Studio에서 새 프로젝트 만들기

앱에 대해 WindowsBlogReader라는 새 프로젝트를 만들어 보겠습니다. 방법은 다음과 같습니다.

  1. Visual Studio를 시작합니다.

  2. 시작 페이지 탭에서 새 프로젝트를 클릭합니다. 새 프로젝트 대화 상자가 열립니다.

  3. 설치됨 창에서 JavaScript를 확장하고 Windows 스토어 앱 템플릿 유형을 선택합니다. JavaScript에 사용할 수 있는 프로젝트 템플릿이 대화 상자의 가운데 창에 표시됩니다.

  4. 가운데 창에서 분할 앱 프로젝트 템플릿을 선택합니다.

  5. 이름 텍스트 상자에 "WindowsBlogReader"를 입력합니다.

  6. 확인을 클릭하여 프로젝트를 만듭니다. 이 작업에는 약간 시간이 걸릴 수 있습니다.

다음은 솔루션 탐색기에 표시되는 프로젝트의 구조입니다. 페이지 폴더에는 두 개의 파일 그룹이 있습니다. 하나는 항목 페이지용이고 하나는 분할 페이지용입니다. 각 그룹은 앱이 이동하거나 사용자 지정 컨트롤로 사용할 수 있는 페이지를 정의하는 HTML, CSS 및 JavaScript 파일 그룹인 PageControl입니다.

새 프로젝트에는 항목 PageControl 및 분할 PageControl을 만드는 데 필요한 HTML, CSS 및 JavaScript 파일이 포함되어 있습니다. 나중에 항목 세부 정보 PageControl에 대한 파일을 추가하게 됩니다.

솔루션 탐색기의 WindowsBlogReader 프로젝트에 대한 스크린샷

여러 가지 템플릿에 대한 자세한 내용은 Windows 스토어 앱용 JavaScript 프로젝트 템플릿을 참조하세요.

새 Windows 스토어 앱 시작

기본 분할 앱의 모양이 궁금한 경우 F5 키를 눌러 앱을 빌드, 배포 및 실행합니다. 앱은 "WindowsBlogReader"라는 제목과 샘플 항목 목록이 그리드로 표시된 전체 화면 페이지로 나타납니다. 각 항목은 데이터 그룹을 나타냅니다. 목록에서 항목을 탭하거나 클릭하여 분할 페이지로 이동합니다. 분할 페이지에는 두 개의 핵심 콘텐츠 영역이 있습니다. 왼쪽에는 선택한 그룹과 연관된 항목 목록이 표시됩니다. 오른쪽에는 선택한 항목에 대한 콘텐츠가 표시됩니다. 페이지의 뒤로 단추를 탭하거나 클릭하여 항목 페이지로 돌아갈 수 있습니다.

앱은 실행되면 items.html에서 HTML, CSS 및 JavaScript를 가져와 앱의 시작 페이지인 default.html 페이지에 삽입합니다. 앱 컨테이너에서 실행되는 코드가 기본적으로 수행할 수 있는 기능에는 몇 가지 제한이 있습니다. 예를 들어 앱에서 인터넷이나 웹캠에 액세스할 수 있으려면 이러한 액세스가 앱에 필요함을 선언하고 앱을 설치할 때 사용자가 액세스 권한을 부여해야 합니다. 자세한 내용을 보려면 package.appxmanifest를 열고 기능 탭으로 이동하세요.

제목 및 배경색 변경

앱을 사용자 지정하는 두 가지 간단한 작업을 수행해 보겠습니다.

앱의 제목을 변경하려면 items.html을 열고 다음과 같이 itemspageh1 요소에 대한 텍스트를 "Windows Team Blogs"로 바꿉니다.


<h1 class="titlearea win-type-ellipsis">
    <span class="pagetitle">Windows Team Blogs</span>
</h1>

앱의 배경색을 설정하려면 default.css를 열고 이 background-color 특성을 #contenthost에 추가합니다.


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

F5 키를 눌러 앱을 빌드, 배포 및 실행합니다. 항목 페이지의 제목이 변경되고 항목 페이지와 분할 페이지의 배경색이 파란색입니다.

참고  프로젝트의 images 폴더에는 앱이 실행될 때 시스템에서 앱의 타일 및 시작 화면에 사용하는 기본 파일이 포함되어 있습니다. 이 자습서에서는 이러한 파일을 변경하지 않지만 원하는 경우 다른 이미지를 사용할 수 있습니다. 사용할 이미지 파일을 images 폴더에 추가하면 됩니다. package.appxmanifest를 열고 응용 프로그램 UI 탭에서 로고, 작은 로고시작 화면의 내용을 이미지 파일 경로로 바꿉니다.

예제 데이터 바꾸기

프로젝트 템플릿에는 앱을 실행하면 표시되는 예제 데이터가 있습니다. 다음 단계를 사용하여 예제 데이터를 Windows 팀 블로그에 대한 ATOM 피드의 데이터로 바꿉니다.

예제 데이터 삭제

앱에 대한 예제 데이터가 포함되어 있는 data.js를 엽니다.

generateSampleData 함수는 필요하지 않으므로 삭제할 수 있습니다.


// Returns an array of sample data that can be added to the application's
// data list. 
function generateSampleData() {
    // Omitted code.

        
}

다음 코드는 필요하지 않으므로 삭제할 수 있습니다.


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

변수 및 함수 설정

data.js 파일의 앞부분, var list = new WinJS.Binding.List(); 문 바로 앞에 이 코드를 추가합니다. 이 코드는 필요한 변수와 이를 채우는 함수를 설정합니다. 이 자습서의 단계를 수행할 때 포함된 설명을 사용하면 각 단계에 대한 코드를 삽입할 위치를 확인하는 데 도움이 됩니다.


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

// Declare an HttpClient object to send and receive
// RSS feed data.
var httpClient = new Windows.Web.Http.HttpClient();

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

function acquireSyndication(url) {
    // Call xhr for the URL to get results asynchronously
}

function getBlogPosts() {
    // Walk the results to retrieve the blog posts
}

function getItemsFromXml(articleSyndication, bPosts, feed) {
    // Get the info for each blog post
}

블로그 목록 정의

이 예제를 간단하게 유지하기 위해 하드 코드된 URL 목록을 blogs 배열에 포함해 보겠습니다.

이 코드를 getFeeds 함수에 추가합니다. 코드는 URL 배열을 문자열로 받아서 Array.map 함수를 사용하여 JavaScript 개체 배열로 변환합니다. blogs 변수의 각 개체는 RSS 피드의 콘텐츠를 저장합니다.


// Create an object for each feed in the blogs array.
var urls = [
    'http://blogs.windows.com/windows/b/windowsexperience/atom.aspx',
    'http://blogs.windows.com/windows/b/extremewindows/atom.aspx',
    'http://blogs.windows.com/windows/b/business/atom.aspx',
    'http://blogs.windows.com/windows/b/bloggingwindows/atom.aspx',
    'http://blogs.windows.com/windows/b/windowssecurity/atom.aspx',
    'http://blogs.windows.com/windows/b/springboard/atom.aspx',
    'http://blogs.windows.com/windows/b/windowshomeserver/atom.aspx',
    'http://blogs.windows.com/windows_live/b/developer/atom.aspx',
    'http://blogs.windows.com/ie/b/ie/atom.aspx',
    'http://blogs.windows.com/windows_phone/b/wpdev/atom.aspx',
    'http://blogs.windows.com/windows_phone/b/wmdev/atom.aspx'
];

var counter = 0;
blogs = urls.map(function (item) {
    return {
        key: "blog" + counter++,
        url: item,
        title: 'tbd',
        updated: 'tbd',
        acquireSyndication: acquireSyndication,
        dataPromise: null
    };
});

피드 데이터 검색

이 섹션의 단계에서는 Windows.Web.Http.HttpClient 클래스를 사용하여 RSS 피드를 요청합니다. HttpClient 클래스는 쿠키 관리, 필터링 및 유연한 전송 허용을 포함하여 HTTP 요청을 보내고 받기 위한 강력한 API를 제공합니다.

이 코드를 acquireSyndication 함수에 추가합니다. 비동기 HttpClient.getStringAsync 함수를 호출하여 피드 콘텐츠를 검색합니다. 다행히 비동기 호출을 사용할 때 예상되는 복잡성 중 대부분은 해결되었습니다. 서버로부터 응답이 수신될 때 결과 약속을 받고 호출자에게 반환합니다.


// Call HttpClient.getStringAsync passing in the URL to get results asynchronously.
return return httpClient.getStringAsync(new Windows.Foundation.Uri(url)););

이제 getFeeds 함수에 코드를 추가하여 blogs 배열의 각 블로그에 대해 acquireSyndication 함수를 호출하고 반환된 약속을 약속 배열 dataPromises에 추가합니다. WinJS.Promise.join 함수를 호출하여 모든 약속이 이행될 때까지 기다린 후 getFeeds에서 돌아옵니다. 이렇게 하면 ListView 컨트롤을 표시하기 전에 필요한 모든 정보를 얻을 수 있습니다.


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

그런 다음, 이 코드를 getBlogPosts 함수에 추가합니다. blogs 배열의 각 블로그에 대해 XML 피드 데이터를 구문 분석하여 필요한 정보를 가져옵니다. 먼저 DOMParser 개체를 사용하여 문자열을 XML 문서로 변환한 다음 필요한 선택기와 함께 querySelector 메서드를 사용하여 블로그의 제목과 마지막 업데이트 날짜를 가져옵니다. Windows.Globalization.DateTimeFormatting.DateTimeFormatter를 사용하여 표시할 마지막 업데이트 날짜를 변환합니다.

articlesResponsenull인 경우 블로그를 로드하는 중 오류가 발생한 것이므로 블로그에 나타나는 오류 메시지를 표시합니다.


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

            var parser = new window.DOMParser();
            var articleSyndication = parser.parseFromString(articlesResponse, 'text/xml');

            if (articlesResponse) {
                // 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;

그런 다음, 이 코드를 getItemsFromXml 함수에 추가합니다. 먼저 querySelectorAll를 사용하여 블로그 게시물 집합 및 각 블로그 게시물에 대한 정보를 가져옵니다. 그런 다음 querySelector를 사용하여 각 블로그 게시물에 대한 정보를 가져옵니다. Windows.Globalization.DateTimeFormatting.DateTimeFormatter를 사용하여 표시할 마지막 업데이트 날짜를 변환합니다. 마지막으로 bPosts 메서드를 사용하여 각 블로그 게시물에 대한 정보를 push 배열의 항목으로 저장합니다.


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

데이터를 사용 가능하도록 설정

피드 데이터를 배열에 저장하는 코드를 완성했으므로 ListView 컨트롤에 필요한 피드 데이터를 그룹화해야 합니다. 또한 피드 데이터를 ListView 컨트롤에 바인딩해야 합니다.

getItemsFromGroup 함수는 createFiltered 메서드를 호출하고 지정한 블로그에 대한 블로그 게시물을 반환합니다. getItemsFromGroup 함수는 list 변수를 사용합니다.


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

이 정의를 blogPosts 변수를 반환하는 getBlogPosts 함수에 대한 호출로 바꿉니다. 이는 WinJS.Binding.List 개체입니다.



var list = getBlogPosts();

createGrouped 메서드를 호출하면 블로그 게시물이 지정한 키(이 경우 각 게시물이 속하는 블로그)에 따라 정렬됩니다.


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

항목 PageControl 업데이트

항목 PageControl의 주요 기능은 WinJS.UI.ListView를 사용하여 구현된 ListView 컨트롤입니다. 각 블로그에는 이 목록의 항목이 있습니다. 템플릿에 제공된 ListView 항목을 블로그 제목과 블로그가 마지막으로 업데이트된 날짜를 포함하도록 수정해 보겠습니다.

items.html를 엽니다. blogs 배열의 내용을 반영하도록 이 div 태그에서 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-overlay">
            <h4 class="item-title" data-win-bind="textContent: title"></h4>
            <h6 class="item-subtitle win-type-ellipsis" data-win-bind="textContent: subtitle"></h6>
        </div>
    </div>
</div>

다음 업데이트를 만듭니다.

  1. 각 블로그에 대한 이미지가 없으므로 img 태그를 제거합니다.
  2. h6 태그에서 textContent: subtitletextContent: updated로 업데이트합니다. 그러면 마지막 업데이트 날짜가 ListView 항목의 오버레이 부분에 배치됩니다.
  3. h4 태그를 item-overlay 클래스의 div 앞으로 이동합니다. 그러면 블로그 제목이 ListView 항목의 주요 부분에 배치됩니다.

결과는 다음과 같습니다.


<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>

목록 항목의 색을 연한 파랑으로 설정하려면 items.css를 열고 다음에 표시된 background-color 특성을 추가합니다. 또한 오버레이에 마지막 업데이트 날짜만 표시하므로 두 번째 행의 크기를 다음 -ms-grid-rows 특성에 표시된 90px에서 60px로 줄입니다.


.itemspage .itemslist .item {
    -ms-grid-columns: 1fr;
    -ms-grid-rows: 1fr 60px;
    display: -ms-grid;
    height: 250px;
    width: 250px;
    background-color: #557EB9;
}

블로그 제목의 글꼴 크기와 여백을 설정하려면 items.css에 다음 코드를 추가합니다.


.itemspage .itemslist .win-item .item-title {
    -ms-grid-row: 1;
    overflow: hidden;
    width: 220px;
    font-size:  24px;
    margin-top: 12px;
    margin-left: 15px;
}

분할 PageControl 업데이트

split.html를 엽니다. 템플릿의 분할 페이지에 대한 HTML에서는 샘플 데이터와 동일한 이름을 사용합니다. blogPosts 배열의 이름을 반영하도록 이 div 태그에서 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: subtitle"></h6>
            <h4 class="item-description" data-win-bind="textContent: description"></h4>
        </div>
    </div>
</div>

다음 업데이트를 만듭니다.

  1. img 태그를 새 <div class="item-date">...</div> 노드로 바꿉니다.
  2. h6 태그에서 textContent: subtitletextContent: author로 변경합니다.
  3. h4 태그를 삭제합니다.

결과는 다음과 같습니다.


<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>

HTML에는 세로선을 그리는 태그가 포함되어 있지 않으므로 파이프 문자를 구분 기호로 사용합니다.

샘플 데이터에 포함된 모든 정보를 사용하는 것이 아니므로 articleSection에서 이 코드를 삭제하여 페이지를 간단하게 합니다.


<header class="header">
    <div class="text">
        <h2 class="article-title win-type-ellipsis" data-win-bind="textContent: title"></h2>
        <h4 class="article-subtitle" data-win-bind="textContent: subtitle"></h4>
    </div>
    <img class="article-image" src="#" data-win-bind="src: backgroundImage; alt: title" />
</header>

항목 날짜가 포함된 텍스트 블록의 색과 텍스트의 글꼴 및 여백을 설정하려면 split.css를 열고 다음 코드를 추가합니다.


.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: 1.2em;
    }

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

    .splitpage .itemlistsection .itemlist .item .item-date .item-year{
        font-size: 0.8em;
    }

원하는 페이지 레이아웃을 표시하려면 이 -ms-grid-row 특성을 "1"에서 "2"로 변경합니다. 그러면 페이지 제목이 첫 번째 행 전체를 채우고 ListView 및 기사가 두 번째 행에 배치됩니다.


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

이제 앱을 다시 실행해 보는 것이 좋습니다. F5 키를 눌러 앱을 빌드, 배포 및 실행합니다. 페이지 제목이 바로 표시되지만 앱에서 피드 데이터를 검색하는 동안 약간의 지연이 있습니다. 모든 약속이 이행되면 블로그당 하나의 항목이 ListView에 표시됩니다. 이 코드는 이러한 항목을 약속이 이행되는 순서로 ListView에 추가합니다. ListView에서 항목을 탭하거나 클릭하면 선택한 블로그에 대한 블로그 게시물 목록과 선택한 블로그 게시물의 콘텐츠가 있는 분할 페이지로 이동합니다. 기본적으로 첫 번째 블로그 게시물이 선택되어 있습니다.

뒤로 화살표를 클릭하여 항목 페이지로 돌아갑니다. 타일이 전환 애니메이션이 있는 화면으로 돌아갑니다. 이는 컨트롤 및 기타 사용자 인터페이스 요소를 Windows 스토어 앱에 대한 UX 지침에 따라 이동하도록 하는 JavaScript용 Windows 라이브러리의 기능입니다.

가로 방향 홈페이지의 스크린샷

항목 세부 정보 PageControl 추가

항목 세부 정보 PageControl에는 블로그 게시물의 제목이 해당 제목으로 표시되고 블로그 게시물의 콘텐츠에 대한 영역이 있습니다.

항목 세부 정보 PageControl을 추가하려면

  1. 솔루션 탐색기에서 pages 폴더를 마우스 오른쪽 단추로 클릭하고 추가 > 새 폴더를 선택합니다.
  2. 폴더 이름을 itemDetail로 지정합니다.
  3. 솔루션 탐색기에서 itemDetail 폴더를 마우스 오른쪽 단추로 클릭하고 추가 > 새 항목을 선택합니다.
  4. JavaScript > Windows 스토어 > 페이지 컨트롤을 선택하고 파일 이름으로 itemDetail.html을 사용합니다.
  5. 추가를 클릭하여 pages/itemDetail 폴더에 itemDetail.css, itemDetail.html 및 itemDetail.js 파일을 만듭니다.

itemDetail.html을 열고 다음과 같이 <section> 태그를 업데이트합니다. 이 코드는 페이지 레이아웃을 정의합니다. 이 코드는 그리드 앱 템플릿에 포함된 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">
            <p>Content goes here.</p>
        </section>
    </div>
</body>
</html>

Main content 섹션을 다음으로 교체합니다.


<section aria-label="Main content" role="main">
    <article>
        <div class="item-content"></div>
    </article>
</section>

itemDetail.js를 열고 다음과 같이 ready 함수의 코드를 업데이트합니다. 이 코드는 사용자가 페이지로 이동할 때 제목 및 콘텐츠를 표시합니다. 이 코드는 그리드 앱 템플릿에 포함된 itemDetail.js 페이지에 있는 코드의 단순화된 버전입니다.


ready: function (element, options) {
   // 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;
},

이제 항목 세부 정보 페이지의 스타일을 정의합니다. 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;
        }



항목 세부 정보 페이지를 표시하는 명령이 있는 앱 바 추가

항목 세부 정보 페이지로 이동하는 데 사용할 수 있는 단추가 있는 앱 바를 추가해 보겠습니다. 이 앱 바는 분할 페이지에 있는 경우에만 나타납니다.

split.html을 열고 닫는 <body> 태그 바로 앞에 이 코드를 추가합니다.


<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> 

사용자가 앱 바에서 전체 보기 단추를 클릭하면 앱이 항목 세부 정보 PageControl로 이동하고 선택한 블로그 게시물의 제목 및 콘텐츠를 표시합니다.

split.js를 엽니다. 이 변수 선언을 utils 변수 선언 뒤에 추가합니다.


// The selected item
var post;

두 번째 querySelector 호출 바로 전에 ready 함수에 이 문을 추가하여 this.items를 먼저 설정합니다. 이 코드는 사용자가 페이지로 이동할 때마다 첫 번째 블로그 게시물의 색인으로 post 변수를 설정합니다.


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

이 문을 _selectionChanged 함수에서 this._itemSelectionIndex를 설정하는 문 뒤에 추가합니다. 이 코드는 사용자가 선택하는 블로그 게시물의 색인으로 post 변수를 설정합니다.


// Get the item selected by the user
post = this._items.getAt(this._itemSelectionIndex);

_selectionChanged 함수 외부에서 이 이벤트 처리기 함수를 post 변수 선언 뒤에 추가합니다. 이 처리기는 사용자가 전체 보기 단추를 클릭할 때 호출됩니다. WinJS.Navigation.navigate 함수는 항목 세부 정보 페이지를 로드하고 선택한 블로그 게시물을 항목으로 전달합니다.


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

split.js의 ready 함수에 이 코드를 추가합니다. 이 코드는 displayFullView 함수를 전체 보기 단추에 대한 click 이벤트의 이벤트 처리기로 등록합니다.


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

F5 키를 눌러 앱을 실행합니다. 항목 페이지에서 항목을 클릭하면 블로그 게시물 목록과 선택한 블로그 게시물의 콘텐츠가 있는 분할 페이지로 이동합니다. 탭 또는 클릭하면 블로그 게시물 및 해당 콘텐츠가 오른쪽 열에 표시됩니다. 앱 바를 표시하려면 아래쪽 또는 위쪽에서 살짝 밀거나 시스템에서 터치를 지원하지 않는 경우 마우스 오른쪽 단추를 클릭합니다.

가로 방향 분할 페이지의 스크린샷

전체 보기 단추를 탭하거나 클릭하면 앱에서 선택한 블로그 게시물의 콘텐츠를 항목 세부 정보 페이지에 표시합니다.

가로 방향 세부 정보 페이지의 스크린샷

뒤로 단추를 탭하거나 클릭하면 분할 페이지로 돌아갑니다. ListView의 첫 번째 항목이 선택되며 이 항목은 항목 세부 정보 페이지에 표시하도록 선택한 항목이 아닐 수 있습니다. 원하는 경우 선택한 항목을 저장하고 복원하는 코드를 추가할 수 있습니다.

앱에서 사용하는 템플릿 코드에서는 가로 방향과 세로 방향을 모두 사용합니다. PC를 회전하거나 Microsoft Visual Studio Express 2012 for Windows 8의 시뮬레이터에서 앱을 실행하고 디스플레이를 회전하세요. 항목 페이지는 다음과 같습니다.

세로 방향 홈페이지의 스크린샷

분할 페이지는 다음과 같습니다. 항목을 선택할 때까지는 ListView 컨트롤만 표시됩니다. 그런 다음 블로그 게시물이 세로로 표시됩니다. Full View 단추를 클릭하면 블로그 게시물이 가로로 표시됩니다.

세로 방향 분할 페이지의 스크린샷

요약

앱에 대한 코드 작업을 완료했습니다. 기본 제공 페이지 템플릿으로 빌드하는 방법, 데이터를 ListView에 바인딩하는 방법, 새 페이지로 이동하는 방법 및 단추가 있는 앱 바를 추가하는 방법을 살펴보았습니다.

앱에 추가할 수 있는 다른 기능에 대한 자세한 내용은 JavaScript를 사용하는 Windows 스토어 앱용 로드맵을 참조하세요.

관련 항목

JavaScript를 사용하는 Windows 스토어 앱용 로드맵
Visual Studio를 사용하여 Windows 스토어 앱 개발

 

 

표시:
© 2015 Microsoft