44 msdn magazine WinJS on Windows 8.1
Figure 3 shows the code for SearchLOCControl.js. Again, remem-
ber to link to this new JavaScript fi le from default.html.
Note that I use jQuery to build my custom control, which I add
to my solution using the NuGet Package Manager. Once you’ve
downloaded the NuGet package to your solution, you’ll need to
manually add a reference to the jQuery library in default.html.
The SearchLOCControl relies on some styling I’ve added to
default.css (/css/default.css), which is shown in Figure 4.
Now I add a new page control named dispose.html (/pages/
dispose/dispose.html) to the solution and add the following
HTML markup inside the
custom control:
<button id="dispose">Dispose</button><br/><br/>
<div id="searchControl" data-win-control="SearchLOCControl.Control"></div>
Finally, I add code to the PageControl.ready event handler in the
dispose.js fi le (/pages/dispose/dispose.js) that naively destroys the
control and creates a memory leak by setting the innerHTML of
the control’s host
Now I can test the control’s memory usage. The Performance
and Diagnostics window provides several tools for measuring the
performance of a Windows Store app, including CPU sampling, app
energy consumption, UI responsiveness and JavaScript function
timing. (You can read more about these tools on the Visual Studio
team’s blog at bit.ly/1bESdOH.) If it’s not already visible, you’ll need to
open the Performance and Diagnostics pane, either through the
Debug menu (Visual Studio Express 2013 for Windows) or through
the Analyze menu (Visual Studio Professional 2013 and Visual
Studio Ultimate 2013).
For this test, I use the JavaScript memory monitoring tool. Here
are the steps for performing the test:
- In the Performance and Diagnostics window, select
JavaScript Memory and then click Start. Th e project
then runs in debugging mode. If prompted by a User
Account Control dialog box, click Yes.
.searchList {
height: 700px !important;
width: auto !important;
}
.searchResultsItem {
display: -ms-inline-grid;
-ms-grid-columns: 200px;
-ms-grid-rows: 150px 150px
}
.searchResultsItem img {
-ms-grid-row: 1;
max-height: 150px;
max-width: 150px;
}
.searchResultsItem .details {
-ms-grid-row: 2;
}
Figure 4 Styling Added to Default.css
(function () {
"use strict";
WinJS.UI.Pages.define("/pages/dispose/dispose.html", {
ready: function (element, options) {
WinJS.UI.processAll();
$("#dispose").click(function () {
var searchControl = $("#searchControl")[0];
searchControl.innerHTML = "";
});
}
// Other page control code.
});
})();
Figure 5 Code in Dispose.js to ”Destroy” the Custom Control
Figure 3 Custom SearchLOCControl
(function () {
"use strict";
WinJS.Namespace.define("SearchLOCControl", {
Control: WinJS.Class.define(function (element) {
this.element = element;
this.element.winControl = this;
var htmlString = "<h3>Library of Congress Picture Search</h3>" +
"<div id='searchQuery' data-win-control='WinJS.UI.SearchBox'" +
"data-win-options='{ placeholderText: \"Browse pictures\" }'></div>" +
"<br/><br/>" +
"<div id='searchResults' class='searchList'></div>" +
"<div id='searchResultsTemplate'" +
"data-win-control='WinJS.Binding.Template'>" +
"<div class='searchResultsItem'>" +
"<img src='#' data-win-bind='src: pictureThumb' />" +
"<div class='details'>" +
"<p data-win-bind='textContent: title'></p>" +
"<p data-win-bind='textContent: date'></p>" +
"</div>" +
"</div>"+
"</div>";
// NOTE: This is an unusual technique for accomplishing this
// task. The code here is written for extreme brevity.
MSApp.execUnsafeLocalFunction(function () {
$(element).append(htmlString);
WinJS.UI.processAll();
});
this.searchQuery = $("#searchQuery")[0];
searchQuery.winControl.addEventListener("querysubmitted", this.submitQuery);
}, {
submitQuery: function (evt) {
var queryString = evt.target.winControl.queryText;
var searchResultsList = $("#searchResults")[0];
$(searchResultsList).append("<progress class='win-ring'></progress>");
if (queryString != "") {
var searchResults = LOCPictures.searchPictures(queryString).
then(function (response) {
var searchList = new WinJS.Binding.List(response),
searchListView;
if (searchResultsList.winControl) {
searchListView = searchResultsList.winControl;
searchListView.itemDataSource = searchList.dataSource;
}
else {
searchListView = new WinJS.UI.ListView(searchResultsList, {
itemDataSource: searchList.dataSource,
itemTemplate: $("#searchResultsTemplate")[0],
layout: { type: WinJS.UI.CellSpanningLayout}
});
}
WinJS.UI.process(searchListView);
});
}
}
})
})
})();