Continuing from part 2 of this series, we’ll finish off the last few obscure methods of WinJS.Utilities. First, the empty method removes all child nodes from a specified element. This is basically a simple iteration over the element’s childNodes property, calling removeNode for each in turn (actually in reverse order). A simple bit of code, but one that you don’t need to write yourself.

Next is eventWithinElement. To this you provide an element and an eventArgs object as you received from some event. The method then checks to see if the eventArgs.relatedTarget element is contained within the element you provide. This basically says that an event occurred somewhere within that element, even if it’s not directly on that element. This is clearly useful for working with events on controls that contain some number of child elements.

Finally there’s getMember, to which you pass a string name of a “member” and a root object (defaults to global). The documentation says that this “Gets the leaf-level type or namespace specified by the name parameter.” What this means is that if you give it a name like “navigate” it will look within the namespace of the root you give for that member and return it. In the case of passing “WinJS” and “navigate” it will find WinJS.Navigation.navigate.

This is particularly useful with WinJS binding initializers that are given source and target property names as arrays of separate identifiers. For example, if I have a data-win-bind attribute with a property like title.style.color, the initializer will get an array with [“title”, “style”, “color”]. To either get or set that property for real, I need to turn it into the actual reference to the title.style.color property of the source of target object.

If I want to get that value from the source object, and the array of names is called “sourceProp,” I can do this: var value = WinJS.Utilities.getMember(sourceProp.join(“.”), source);

If I need to set a value in a target object with the array of named called targetProp, I need to pop the last name from the array, use getMember (if I have other names left), then reference the property with [], as in:

var lastProp = targetProp.pop();
var dest = targetProp.length ? WinJS.Utilities.getMember(targetProp,join(“.”), target) : target;
target[lastProp] = newValue;


Continuing from part 1 of this series, the next few methods in WinJS to look at are WinJS.Utilities.data and WinJS.Utilities.convertToPixels.

WinJS.Utilities.data is documented as “gets a data value associated with the specific element.” The data value is always an object and is attached to the element using a property name of _msDataKey. So WinJS.Utilities.data(<element>) always just gives you back that object, or creates one if one doesn’t yet exist. You can then add properties to that object, or retrieve them. Basically this is a tidy way to attach extra data to an arbitrary element knowing that you won’t interfere with the element otherwise. WinJS uses this internally in various places.

WinJS.Utilities.convertToPixels sounds fancier than it is. It’s just a helper to convert a CSS positioning string for an element to a real number. That is, in CSS you often use values suffixes like “px” and “em” and so on that, of course, aren’t values that are meaningful in any computations. This function converts those values to a meaningful number of pixels. With “px” values, or something without suffixes, it’s easy–just pass it to parseInt which will strip “px” automatically if it’s there. For other CSS values–basically anything that starts with a numerical value, what this function does it just assign the value to the elements left property (saving the prior value so nothing gets altered), then reads back the elements pixelLeft property. In other words, it lets the DOM engine handle the conversion which will produce 0 if the value isn’t convertible.

Along these same lines are the following WinJS.Utilities methods:

  • getRelativeLeft: gets the left coordinate of an element relative to a specified parent. Note that the parent doesn’t have to be the immediate parent, but can be any other node in the element’s tree. This function then basically takes the offsetLeft property of the element and keeps subtracting off the offsetLeft of the next element up until the designated ancestor is reached.
  • getRelativeTop: does the same thing as getRelativeLeft except with offsetTop.
  • getContentWidth: returns the offsetWIdth of an element minus the values of borderLeftWidth, borderRightWidth, paddingLeft, and paddingRight, which results in the actual width of the area where content is shown.
  • getTotalWidth: returns the offsetWIdth of the element plus the marginLeft and marginRight values.
  • getContentHeight: returns the offsetHeight of an element minus the values of borderTopWidth, borderBottomWidth, paddingTop, and paddingBottom, which results in the actual height of the area where content is shown.
  • getTotalHeight: returns the offsetHeight of the element plus the marginTop and marginBottom values.
  • getPosition: returns an object with properties of left, top, width, and height properties of an element relative to the topmost element in the tree (up to document or body), taking scroll postions into account.

Again, it’s helpful to take a look in base.js for the implementation of these functions so you can see what they’re doing, and appreciate the work they’ll save you!


In this and the next few posts I want to bring up a few of the more obscure features of APIs of WinJS and give a little more explanation about them, or at least just make you aware that they exist!

The first ones in these posts are simple wrappers around a few common DOM operations.

WinJS.Utilities.QueryCollection is a class that wraps an element.querySelectorAll or document.querySelectorAll with a number of useful methods. An instance of this class is created by calling WinJS.Utilities.query(<query>[, ]) where <query> is a usual DOM query string and the optional <element> scopes the query. That is, if you provide <element>, the instance wraps element.querySelectorAll(<query>); if you omit <element>, the instance uses document.querySelectorAll(<query>). Similarly, WinJS.Utilities.id(<id>) does a document.getElementById(<id>), then passes the result to new WinJS.Utilities.QueryCollection. WinJS.Utilities.children creates a QueryCollection that contains children of a specified element.

Anyway, once you have a QueryCollection instance, it provides methods to work with its collection, that is, with the results of the DOM query that in and of itself is just an array. As such, you’d normally be writing plenty of loops and iterators to work with the items in the array, and that’s exactly what QueryCollection provides as a convenience. It follows along with other parts of WinJS, which are utilities that most developers end up writing anyway, so it might as well be in a library!

We can see this in what the individual methods do:

  • forEach: calls Array.prototype.forEach.apply on the collection using the given callback function and this argument.
  • get: returns [] from the array
  • setAttribute: iterates the collection and calls setAttribute for each item.
  • getAttribute: gets an attribute for the first item in the collection.
  • addClass, hasClass, removeClass, toggleClass: iterates the collection and calls WinJS.Utilities.addClass, hasClass, removeClass, or toggleClass for each item, respectively.
  • listen, removeEventListener: iterates the collection calling addEventListener or removeEventListener for each item
  • setStyle, clearStyle: iterates the collection setting a given style to a value or “”, respectively.
  • include: adds other items to this collection. The items can be in an array, a document fragment (DOM node), or a single item.
  • query: executes a querySelectorAll on each item in the collection and calls include for each set of results. This could be used, for instance, to extract specific children of the items in the collection and add them to the collection.
  • control: given the name of a control constructor (a function) and an options object (as WinJS controls typically use), creates an instance of that control and attaches it to each item in the collection. It’s allowable to call this method with just an options object as the first argument, in which case the method calls WinJS.UI.process on each item in the collection followed by WinJS.UI.setOptions for each control therein. This allows the collection to basically contain elements that have WinJS control declarations (data-win-control attributes) that have not yet been instantiated.
  • template: renders a template element that is bound to the given data and parented to the elements included in the collection. If the collection contains multiple elements, the template is rendered multiple times, once at each element per item of data passed.

As for WinJS.Utilities.addClass, WinJS.Utilities.removeClass, WinJS.Utilities.hasClass, and WinJS.Utilities.toggleClass, as used above, these are helper functions that simply add one or more classes (space delimited) to an element, removes a single class from an element, checks if an element has a class, and adds or removes a class from an element depending on whether it’s already applied. While these operations sound simple, the implementation is actually quite non-trivial. Take a look at the WinJS source code (in base.js) to see what I mean! Good code that you don’t have to write.

 


When using WinJS page controls to implement pages and navigation in an app, it's important to understand that any and all CSS that is loaded on behalf of those pages is cumulative. Because page controls are just performing DOM replacement within the context of the app's root page, you get the benefit of preserving the global JavaScript context but at the same time get the sometimes-frustrating behavior of preserving all the CSS styles as well.

For example, let's say the app's root page is default.html and its global styles are in css/default.css. It then has several page controls defined in pages/page1 (page1.html. page1.js, page1.css), pages/page2 (page2.html. page2.js, page2.css), and pages/page1 (page3.html. page3.js, page3.css). Let's say that page1 is the 'home' page and is loaded into default.html at startup. This means that the styles in default.css and page1.css have been loaded.

Now the user navigates to page2. This causes page1.html to be dumped from the DOM, but its styles remain in the stylesheet. So when page2 is loaded, page2.css gets added to the overall stylesheet as well. This means that any styles in page2.css that have identical selectors to page1.css will overwrite the latter's. The same thing happens also when the user navigates to page3–the styles in page3.css get loaded and overwrite those that already exist.

The tricky part is what then happens if the user navigates back to page1. Because the apphost's rendering engine has already loaded page1.css into the stylesheet, page1.css won't be loaded again. This means that any styles that were overwritten by other pages' stylesheets will not be reset to those in page1.css–basically you get whichever ones were loaded most recently.

The same thing happens with .js files, by the way, as those are not reloaded if they've been loaded already. The lesson here is to not duplicate variable names between those files.

On that thought, there are two ways to get around the CSS issue. One is to just use a global stylesheet (i.e. default.css) and not do much in the individual page .css files unless you're certain it's local. The second way is to make sure that each page has a top-level div with a page-name class, e.g. <div class="page1">, which allows you to then scope all style rules in page1.css with the page name, e.g.

.page1 p {
    font-weight: bold;
}

This will prevent collision between all the page<n>.css files.

Another place where this can arise is if you try to use the ui-light.css and ui-dark.css WinJS stylesheets in different pages of the same app. Because there are only two files here, whichever one is used first will be overwritten by the second, with the effect that subsequent pages that refer to ui-light.css will still appear with the dark styles.

The solution to this particular problem comes from the fact that where the styles differ, those in ui-light.css are scoped with a CSS class win-ui-light and those in ui-dark.css are scoped with win-ui-dark. This means you can just refer to whichever stylesheet you use most often in your .html files, then add either win-ui-light or win-ui-dark to individual elements that you need to style differently. (Thanks to Scott Salam for this one.)

The other way of avoiding collisions is to specifically unload and reload CSS files by modifying <link> tags in the page header. You can either remove one <link> tag and add a different one, toggle the disabled attribute for a tag between true and false, or change the href attribute of an existing link. These methods are demonstrated for styling an iframe in the CSS styling and branding your app sample, which swaps out and enables/disables both WinJS and app-specific stylesheets. Another demonstration for switching between the WinJS stylesheets is in scenario 1 of the HTML NavBar control sample  (js/1-CreateNavBar.js):

function switchStyle() {
    var linkEl = document.querySelector('link');
    if (linkEl.getAttribute('href') === "//Microsoft.WinJS.2.0 /css/ui-light.css") {
        linkEl.setAttribute('href', "//Microsoft.WinJS.2.0 /css/ui-dark.css");
    } else {
        linkEl.setAttribute('href', "//Microsoft.WinJS.2.0 /css/ui-light.css"); 
    }
}

The downside of this approach is that every switch means reloading and reparsing the CSS files and a corresponding re-rendering of the page. This isn’t much of an issue during page navigation, but given the size of the WinJS files I recommend using it only for your own page-specific stylesheets and using the win-ui-light and win-ui-dark classes to toggle the WinJS styles.


Background tasks, though they are essentially extensions of a app, only have limited capabilities where using the WinRT APIs are concerned. They can access the app’s appdata folders and settings, for example, and perform file I/O with Windows.Storage APIs. No problem there. Background tasks cannot, however, generate UI with the exception of issuing toast notifications and tile update.

Background tasks are also able to perform string lookups in resource files using the Windows.ApplicationModel.Resources.ResourceLoader class or Windows.ApplicationModel.Resources.Core.ResourceManager.current, meaning that they do have access to the app’s localized content.

One issue that comes up with background tasks written in JavaScript is that the task itself, which runs as a web worker, cannot employ the WinJS library. As a result, a JavaScript background task cannot access resources through WinJS.Resources.getString, and occasionally this leads developers to think that background tasks cannot access resources at all. But because this particular WinJS API is implemented with the WinRT APIs, you can just use the latter directly.


Using a <form> element in a Windows Store app is allowable, but has a few caveats to be aware of. The most important part to understand is that generally speaking, <form> really isn’t a necessary construct in an app. On a website, <form> is often used to collect information within a group of other controls (children of the <form>). So far so good. The tricky part is what happens with the contents of those controls when some kind of button is clicked or tapped, where the behavior is specifically defined by the method and action attributes of <form>.

The method attribute, either “get” or “post,” defines the HTTP method used to interact with whatever URI is given in the action attribute. On the web, if you want to take the contents of the form’s controls and post them to another URI–presumably to store that info in a database or such–you’d use method=”post” with that URI. In this case the form contents are transmitted within the body of the HTTP request. With method=”get”, the contents of those controls are appended to the action URI as name-value pairs, such that the URI can do whatever it wants with that data.

The main caveat, then, for Store apps is that typical form submission implies navigation to a new URI, meaning that you lose your script context. If this is what you want to do, that’s perfectly fine, but typically you want to stay in the same page context as apps normally do.

The navigation behavior can be hidden if the <form> element has no explicit action, for instance:

<form method=”post”>
<input type=”text” name=”login_username” />
<input type=”password” name=”login_password” />
<input type=”submit” id=”login_submit” name=”login_submit” />
</form>

In this case, action defaults to the same URI as the current page (a web page can post form data to itself, as when doing validation). As a result, using this kind of markup in an app will cause you to lose the script context. What could happen with the above code, then, is that if you’d assigned a handler for the login_submit button’s click event in the app’s activated handler, it would work the first time but not the second time. That is, the URI navigation that happens with a submit button like this doesn’t restart the app, so the activated handler isn’t called again, even though the HTML and JavaScript for that page is reloaded.

Let me be clear on this point. When you start a Store app written in JavaScript, what gets launched is an instance of wwahost.exe that will load up whatever HTML page you identify in the app’s manifest as the start page. This, as always, means it will load and execute whatever JavaScript exists in that page (directly or via <script>). The code in such a page typically subscribes to the app’s activated event (Windows.UI.WebUI.WebUIApplication.onactivated, for which many apps use the WinJS.Application.onactivated wrapper). And this is exactly what happens if the page is reloaded through a <form> submit.

However, even though the code in the reloaded page listens for the activated event, it won’t be fired again because the app is already running. That is, the activated event is fired from within WinRT only when the app is launched or activated from some other system event (like various contracts), An internal URI navigation within an app does not “activate” the app and therefore the event is not fired.

So if the activated code for the app wired up a click handler for the submit button, it will work only the first time and not after the page is reloaded.

A second issue is that even if you did reload the page properly, an app doesn’t have access to the HTTP request body, so the form data is loast anyway.

In the code above, you can just remove the <form> element completely, then in the submit button’s click handler just extract the data you need and act on it–typically using WinJS page controls to “navigate” via DOM replacement.

Alternately, if you use type=”button” instead of type=”submit” then you remove the reposting behavior of <form> and can handle the button click in the same way. That is, a button in this case doesn’t trigger the form’s navigation behavior, so the page won’t be reloaded.

The bottom line is really that <form> isn’t particularly useful in an app (the local context, anyway), so you need to disable it’s navigation behavior one way or another. If you want to use the element for semantic markup purposes to delineate a group of input controls, that’s fine–just use type=”button” for the submit, or just use a <button> to begin with. Otherwise you can use a <div> to group the controls.

 


A recent MSDN forum post asked a good question, one that I realized isn’t often adequately answered for developers new to the concept of data binding. It’s simply then question, “When do I use data binding at all?”

Here’s how I answered the question, and I’d enjoy hearing your thoughts on the matter.

Data binding is typically used to set up an automatic relationship between a data source and one or more UI elements. This is so you can

  1. Simplify the initialization of UI element contents from a data source (one-time binding)
  2. Have the UI elements update whenever the data source changes (one-way binding, which effectively includes one-time)
  3. Have changes in the UI element also be reflected back to the data source (two-data binding, which includes one-way)

When small bits of UI are involved, you can just as easily do all this manually, just by setting innerText/innerHTML values (or other attributes) within the appropriate event handler. However, when the UI gets more involved, e.g. you’re using collections or you’re starting to set up relationships to multiple properties of multiple elements, then having a more formalized structure to handle the data-to-UI wiring starts to make a lot of sense. This is really what data-binding is meant for (and really shines when you’re dealing with database sources and other large data sets.)

“Formalized structure” is what you often see referred to in the context of “view models” (e.g. model-view-controller (MVC), model-view-viewmodel (MVVM), and so forth). Those patterns are ones that have developed from data-binding capabilities; they encapsulate a structure wherein data (the model) is managed independently of how it’s shaped (view), how it’s presented (viewmodel), and how it’s manipulated procedurally (controller). These patterns achieve a ‘separation of concerns’ between data and UI, which is an adjunct to a similar but different separation between markup (HTML), styling (CSS), and code (JS).

[Here I inserted this note as the question was related to WinJS: Note that WinJS provides mechanisms for one-time and one-way data-binding, but not two-way; the latter, however, is not too hard to wire up on your own. I talk about all this in Chapter 4 of my book.]

The bottom line is that data binding is really a best practice, but not a requirement, especially in simple cases.


This flag exists to answer the question: “Is there a way with WinJS.Navigation.navigate to navigate to a new page without adding an entry in the history?” If you look in WinJS’s base.js, you’ll find that when this flag is true, WinJS skips the step of adding whatever page you’re navigating to to the nav stack. That flag itself exists in WinJS to apparently prevent the initial page in an app from being entered into the history, but as it’s implemented you can use it also for this more general purpose. Just be sure to set it to false when you want pages to be added to the history again.

 


As you’ve probably heard many times, the use of asynchronous APIs is a key theme in Windows Store apps to help them be “fast and fluid,” and to remain responsive to touch input and so forth. Simply said, async operations run on non-UI threads, so they don’t block the UI thread (and therefore input) while their processing is going on.

However, at some point the results from those async operations (as most of those APIs produce) do have to make their way back to the UI thread. That is, some completed handler that runs on the UI thread will be called with those results, wherein that handler processes them in some way.

For small numbers of parallel async operations, this isn’t typically a problem. Problems can arise, however, if an app kicks off many simultaneous operations within a short amount of time, such that the completed handler will at some point get pounded with each individual result. For example, let’s say you have a StorageFolder for some part of the user’s pictures library, and you call its getFilesAsync method. This is a single operation that produces a vector of StorageFile objects, so no problem there.

Now let’s say you use forEach to iterate that vector and call StorageFile.getThumbnailAsync on each one. If that folder contains 1000 files, you’ll quickly kick off 1000 background threads. This might cause the CPU usage to spike, but it’s all in the background so the UI is still responsive.

Then those thumbnail results start to come into the completed handler, where you might be extracting more information from each thumbnail or calling URL.createObjectURL to turn it into a displayable image, like so (where listItemImage is, say, some img element in a ListView):

file.getThumbnailAsync(Windows.Storage.FileProperties.ThumbnailMode.picturesView).done(function (thumb) {
    var stream = MSApp.createStreamFromInputStream(thumb.contentType, thumb.getInputStreamAt(0));
    listItemImage.src = URL.createObjectURL(stream);
});

thumb.getInputStreamAt, MSApp.createStreamFromInputStream, and URL.createObjectURL are all synchronous APIs, however, and assinging an image source can trigger rerendering as well once you return from that handler. So with every callback you might be blocking the UI thread for some time as well as triggering additional UI work as a consequence. In the end, even though you’re using async APIs to do some of the work, the UI can sluggish nonetheless.

So beware of situations where you’re creating a many async operations in a short span of time, you’ll want to implement a kind of batching strategy to stretch the work out in the time domain somewhat. I don’t have any specific numbers to offer here, but in the example above, you’d want to prioritize items that are actually visible and do those first, then continue doing the work for non-visible items within some setTimeout delays.

 


It’s a common need to have some commands on an app’s settings panel that are web links (and thus open in a browser, often used for one’s privacy policy) and others that are flyouts (and thus open in a WinJS.UI.Flyout control). However, it’s a little tricky to mix the two, as the method is specifically designed to work with settings panes defined in separate .html files, and not with links. I hinted at how to do this in Chapter 8 of my book, but didn’t spell it out. Let me remedy that in this post.

First, the event that comes form WinRT when the settings charm is invoked is Windows.UI.ApplicationSettings.commandrequested, which you listen to as follows:

var as = Windows.UI.ApplicationSettings;
var settingsPane = as.SettingsPane.getForCurrentView();
settingsPane.addEventListener(“commandsrequested”, onCommandsRequested);

To create a link command in the settings pane, you do the following:

function onCommandsRequested(e) {
    var commandHelp = new as.SettingsCommand(“privacy”, “Privacy Policy”, privacyCommandInvoked);
    e.request.applicationCommands.append(commandHelp);
}

function privacyCommandInvoked(e) {
    var uri = new Windows.Foundation.Uri(http://www.kraigbrockschmidt.com/src/HereMyAm_PrivacyStatement.html);
    Windows.System.Launcher.launchUriAsync(uri).done();
}

(The URI here is the privacy policy for the Here My Am! app in the book.)

To create WinJS flyout commands, you instead use WinJS.Application.onsettings, typically with WinJS.UI.SettingsFlyout.populateSettings to create settings commands that open flyouts,  as shown in the App settings sample, scenario 2:

WinJS.Application.onsettings = function (e) {
    e.detail.applicationcommands = { “help”: { title: “Help”, href: “/html/2-SettingsFlyout-Help.html” } };
    WinJS.UI.SettingsFlyout.populateSettings(e);
};

However, it doesn’t work to insert a link command in this way (e.g. putting a URI in the href field), because populateSettings assumes that the href points to a local file, which it will attempt to load when that command is invoked. If you put http:// URI in the href, you’ll get an exception.

So how do you mix the two?

There are two key things to know:

  1. Within WinJS.Application.onsettings, the e.detail.e is the same as the event args that come into the WinRT oncommandsrequested event.
  2. WinJS.UI.SettingsFlyout.populateCommands simply goes through whatever is in e.detail.applicationcommands (an object) and creates settings commands that open the flyout pane. It does this with e.detail.e.request.applicationCommands.append(). (Take a look at the source code in ui.js of WinJS to see all it does.)

What this means is that within WinJS.Application.onsettings you can also just create Windows.UI.ApplicationSettings.SettingsCommand objects directly, and pass them to the append method or insertAt. So if I wanted to add a Privacy Policy link after the WinJS flyout Help setting, I can do this (making a modification to scenario 2 of the sample):

function scenario2AddSettingsFlyout() {
    WinJS.Application.onsettings = function (e) { 
        e.detail.applicationcommands = { “help”: { title: “Help”, href: “/html/2-SettingsFlyout-Help.html” }, };
        WinJS.UI.SettingsFlyout.populateSettings(e);

        var as = Windows.UI.ApplicationSettings;
        var command = new as.SettingsCommand(“privacy”, “Privacy Policy”, privacyCommandInvoked); 
        e.detail.e.request.applicationCommands.append(command);
    };

    function privacyCommandInvoked(e) {
        var uri = new Windows.Foundation.Uri(“http://www.kraigbrockschmidt.com/src/HereMyAm_PrivacyStatement.html”);
        Windows.System.Launcher.launchUriAsync(uri).done();
    }

    // …
}
You can, of course, create the link settings first, then create the flyouts. Ultimately everything resolves to call to append so you can do it in either order. You can use insertAt to place commands directly if you want.

UPDATE: my previous statement about interspersing flyouts and commands by calling populateSettings multiple times with different contents in e.detail.applicationcommands doesn’t actually work. The problem is that the call to populateSettings stores the applicationCommands object you pass in another variable, and it uses this variable in its handler for the command to check if the command is valid. So although command from earlier calls to populateSettings appear in the Settings pane, they won’t do anything because WinJS won’t find that command.

To correct this, you basically need to create your own simple handler to call WinJS.UI.SettingsFlyout.showSettings, which is all that populateSettings does. As an example, here’s an update to the code above that borrows a flyout from scenario 3 of the sample (I’ve added two lines to the end of the onsettings function and the legalNoticesCommandInvoked function):

    WinJS.Application.onsettings = function (e) { 
        e.detail.applicationcommands = { “help”: { title: “Help”, href: “/html/2-SettingsFlyout-Help.html” },
};
        WinJS.UI.SettingsFlyout.populateSettings(e);

        var as = Windows.UI.ApplicationSettings;
        var command = new as.SettingsCommand(“privacy”, “Privacy Policy”
, privacyCommandInvoked); 
        e.detail.e.request.applicationCommands.append(command);

        var command = new as.SettingsCommand(“legalNotices”, “Legal Notices”, legalNoticesCommandInvoked); 
        e.detail.e.request.applicationCommands.append(command);

    };
    function legalNoticesCommandInvoked(e) {
        WinJS.UI.SettingsFlyout.showSettings(“legalNotices”, “/html/3-SettingsFlyout-Legal.html”);
    }

So with this, use populateSettings for the largest group of flyouts that you have, then append or insert individual commands with your own handlers for additional flyouts. Alternately, just go to WinJS’s ui.js file, copy the populateSettings code, and make your own version that keeps a full list of commands that your own generic handler uses for lookup. It’s all helper code, so it’s perfectly allowable to do something like this.