0.6.15 • Published 8 years ago

winjsrocks v0.6.15

Weekly downloads
6
License
MIT
Repository
github
Last release
8 years ago

logo

An ES6 MVVM framework optimized for WinJS

Dependency Status Build Status Download Status Build Status devDependency Status

Built to support amazing app developers targetting:

  • Windows 10
  • Windows 8/8.1
  • XboxOne
  • Windows Phone 10
  • Android
  • iOS
  • FireTV
  • Playstation 3/4/tv
  • Web

Featuring the Commandments of great code:

  • View, ViewModel, Model coordination
  • Message based Communication
  • Navigation Framework
  • Command Pattern
  • Event/Dispatch Pattern
  • Providers
  • Services
  • Plugins
  • Domain model indexing with Lokijs

See Technical Documentation for APIs


Why WinJS?

WinJS is a visual framwork that really considers a few important factors that other frameworks fall short on:

  • Input Modalities - Given a world of accelerating device fragmentation, people interact with UI's from a variety of input patterns. WinJS is built with the exectation that elements should automatically support Mouse, Keyboard, Gesture, Remote and Controller interaction patterns seamlessly. This support is not a weak accessibility-focused implementation, but one that actually attempts to provide core persona support for each input type.
  • Command/Property Binding - WinJS supports a variety of markup-driven binding styles that allows developers to avoid common pitfalls with Javascript memory management. This allows clear seperation of concerns when diagnosing memory performant creative View development. Many frameworks don't do this and seem to encourage Views, Models and Controllers to all be directly bound to the DOM, leaving the advanced topic of Javascript Memory Profiling
  • Dynamic View Resolve - Views can be either packaged in the app, fetched from a CDN or remotely generated via Web API. This allows application developers to use the tools that work for creative View development while still offering the advantages of dynamic server-side generation of artifacts.
  • Localization - Views can use localized strings to bind declaratively and developers can support a wide range of localization sets

WinJS is a future-facing UI Framework that really is designed to allow your Information Architecture to adapt to Desktop, Console, Mobile and Web without having to frankenstein your development architecture.

Sample Apps

Project Setup

Install Packages

Install the framework and the current WinJS bits:

npm install winjs --save
npm install winjsrocks --save

Note: Though WinJSRocks is tested against a specific version (latest verified) of the WinJS library, the distribution does not package these bits. So, "Bring your own WinJS" and "Millage may vary" if not the same version tested with WinJSRocks.

Optionally, install the maintained pluglin library WinJSRocks-Extras. This project includes cool plugins like IndexDB Storage, JQuery Adapters and shows really good examples of how to write your own application plugins.

npm install winsrocks-extras --save

Load WinJS

Application developers are required to pre-load WinJS before attempting run of the library.

var WinJS = require('winjs');
var WinJSRocks = require('winjsrocks');

Create Application Instance

Create a version of the Application object:

var WinJSRocks = require('winjsrocks');
var app = new WinJSRocks.Application();

Once the application is instatiated, access is available as a singleton:

var app = WinJSRocks.Application.Instance;

The Application Object

The Application object has three important phases that need to be implemented for an application:

  • configure - Allows plugin registration and generally is the best place to build up the container with Services and Providers.
var app = new WinJSRocks.Application();
var CustomProvider = require('providers/customProvider');
var CustomService = require('services/customService');
var CustomPlugin = require('plugins/customPlugin');
app.configure({
    plugins: [
      CustomPlugin
    ]
  }, function(err){
    if(err)
      console.error(err);
    // Load up the container with goodies
    app.container.registerProvider("customProvider", CustomProvider);
    app.container.registerService("customService", CustomService);
  });
app.load({},
  function(err){
    if(err)
      console.error(err);

    // Application has loaded and ready for use

    // Suggestion: Inject the Message Service and navigate to a view
    // see [Building Views](#building-views)
    var MessageService = app.container.getService('message');
    MessageService.send("navigateToMessage", {
      viewKey: "landing"
    });
  });
  • unload - Stops Services and unloads all known components.
app.unload({},
  function(err){
    if(err)
      console.error(err);

    // All components have been notified of the shutdown
  });

Building Views

The WinJSRocks MVVM framework provides the View/ViewModel sequencing to enable the fastest possible asynchronous load behavior for application developers.

This is achieved by using a NavigationService to instantiate ViewModels at the same time as their respective View, kicking off the ViewModel's load life-cycle before WinJS starts up the native page life-cycle.

Then, the View is allowed to render while the native WinJS Page ready method is suspended until the ViewModel has fully loaded initially.

In result, application developers can rely on the native WinJS Page ready method to fire after the View Template is fully rendered, the ViewModel has loaded up principle Models and the initial *.processAll() phases have completed on the visual tree.

sequence-navigation

ViewKey Registration

The framework provides the WinJSRocks.Application.Instance.builder API to aid in view/item registrations around a single ViewKey.

Example of registering views:

var app = new WinJSRocks.Application();
var viewKeys = ['splash', 'landing', 'items', 'article', 'contributor'];
viewKeys.forEach(function(viewKey) {
  app.builder.registerView(
    viewKey, // framework ViewKey
    require('./views/' + viewKey + '/view'),
    require('./views/' + viewKey + '/view-model'),
    'views/' + viewKey + '/view.html');
});

Note: View registration should occur before calling load on the Application object

View

Building a view is a combination of a Template, Component and ViewKey. The Template/Component will be associated with a ViewKey and will be joined together at runtime upon navigation to a view.

Template

Templates are expected to be compliant HTML mark-up files and their defintion is based on the WinJS navigation framework's formal definition of an WinJS.UI.Pages.PageControl

Generally, anything goes here and this is where most teams will match the UI creative pattern to each target User-Experience.

<!DOCTYPE html>
<html>

<head>
  <meta charset="utf-8" />
  <title>Landing Screen</title>
</head>

<body>
  <h1>Landing Screen</h1>
  <!-- Bind directly to the ViewModel using ES6 property compatible Binding Helpers  -->
  <div data-win-bind="innerHTML: sampleData WinJSRocks.Binding.Mode.Property"></div>

  <!-- Execute ViewModel Commands directly from markup -->
  <button data-win-bind="onclick: navigateToListPageCommand WinJSRocks.Binding.Mode.Command">Navigate To List Page</button>

  <div id="landingPivot" data-win-control="WinJS.UI.Pivot">
    <div data-win-control="WinJS.UI.PivotItem" data-win-options="{'header': 'PivotItem1'}">
      PivotItem1 Content
    </div>
    <div data-win-control="WinJS.UI.PivotItem" data-win-options="{'header': 'PivotItem2'}">
      PivotItem2 Content
    </div>
  </div>
</body>

</html>

Component

import WinJSRocks from "winjsrocks";

export default class extends WinJSRocks.View.Page {
  // Polymorphic constructor that already integrates into the WinJS.Page base structure
  constructor(element, viewModel) {
    super(element, viewModel);
  }

  // Ready is supsensed until both:
  //  - View element (this.element) has been loaded into the DOM
  //  - ViewModel loading state has fired
  ready(element, options) {

    // Managed events automatically get disconnected when the view unloads
    // The binding context is managed too!
    this.addManagedEventListener(landingPivot.winControl, "selectionchanged",
      this._onPivotSelectionChanged);

    return super.ready(element, options);
  }

  _onPivotSelectionChanged() {
    // ViewModel is already bound to the View and can be used to monitor events
    // and send commands
    this.viewModel.onPivotSelectedCommand.execute();
  }
}

ViewModel

import WinJSRocks from "winjsrocks";

export default class extends WinJSRocks.ViewModel.Base {
  constructor(application) {
    super(application);
  }

  // All ViewModel classes have a Data property that is
  // posted during navigation events
  onDataSet(callback) {
    var that = this;
    super.onDataSet(function() {
      return callback();
    });
  }

  // Encapsulate your data with Getters/Setters for view binding
  get sampleData(){
    return this._sampleData;
  }

  // Dispatch events when properties are set
  set sampleData(val){
    this._sampleData = val;
    this.notify("sampleData");
  }

  // Expose commands for execution
  get navigateToListPageCommand() {
    return new WinJSRocks.Command.Base(function() {
      console.log("navigateToListPageCommand command called!");
    });
  }
}

#Working with Plugins Plugins are the recommended way of bolting on features into the WinJSRocks application life-cycle.

These types of components are loaded after the core framework has loaded and enables access to all of the goodies (Services/Providers) without any load order mishaps. They are loaded in series, so make sure you provide them in the order of dependence.

To activate, register the class plugin class definition in the WinJSRocks.Application.Instance.configure options as a plugins array:

var WinJSRocks = require('winjsrocks');
var app = new WinJSRocks.Application();
app.configure({
    plugins:[
      MyAwesomePlugin // Provide the Class Definition of the Plugin
    ]
  },
  function(err){
  });

Building Providers

Providers are an elegant design pattern for decoupling application behavior into implementation strategies that might vary in different situations.

As an example, a common use-case is selecting a provider type to fullfill a need within a service Service at runtime based on measured conditions within application state.

In the WinJSRocks framework, providers have the following expecations:

  • remain Stateless (don't expect the same instance to be used in all places)
  • Use a self reference to application to manage their stateful needs
  • Does all build-up in the Constructor (no load/unload cycle)

To build a provider, inherit from the WinJSRocks.Provider.Base class:

import WinJSRocks from "winjsrocks";

export default class KeyboardCatProvider extends WinJSRocks.Provider.Base {
  constructor(application) {
    super(application);
  }

  methodA: function(args){
    return this.methodB(args);
  }

  methodB: function(args){
    return "Keyboard cat";
  }
};

To activate a provider, register using the WinJSRocks.Application.Instance.builder before calling configure:

var WinJSRocks = require('winjsrocks');
var app = new WinJSRocks.Application();
app.builder.registerProvider("localStorage", KeyboardCatProvider);

Providers are registered in the WinJSRocks.Application.Instance.container before the load method is called on the application instance to assure custom Services and Providers are first-class citizens during application start-up.

0.6.15

8 years ago

0.6.13

8 years ago

0.6.12

8 years ago

0.6.11

8 years ago

0.6.10

8 years ago

0.6.9

8 years ago

0.6.7

8 years ago

0.6.6

8 years ago

0.6.5

8 years ago

0.6.4

8 years ago

0.6.3

8 years ago

0.6.2

8 years ago

0.6.0

8 years ago

0.5.35

8 years ago

0.5.34

8 years ago

0.5.32

8 years ago

0.5.31

8 years ago

0.5.28

8 years ago

0.5.27

8 years ago

0.5.25

8 years ago

0.5.23

8 years ago

0.5.21

8 years ago

0.5.20

8 years ago

0.5.19

8 years ago

0.5.18

8 years ago

0.5.17

8 years ago

0.5.16

8 years ago

0.5.15

8 years ago

0.5.14

8 years ago

0.5.13

8 years ago

0.5.12

8 years ago

0.5.11

8 years ago

0.5.10

8 years ago

0.5.9

8 years ago

0.5.8

8 years ago

0.5.7

8 years ago

0.5.5

8 years ago

0.5.4

8 years ago

0.5.3

8 years ago

0.5.2

8 years ago

0.5.1

8 years ago

0.5.0

8 years ago

0.4.7

8 years ago

0.4.6

8 years ago

0.4.5

8 years ago

0.4.4

8 years ago

0.4.3

8 years ago

0.4.2

8 years ago

0.4.1

9 years ago

0.4.0

9 years ago

0.3.15

9 years ago

0.3.14

9 years ago

0.3.13

9 years ago

0.3.12

9 years ago

0.3.11

9 years ago

0.3.10

9 years ago

0.3.9

9 years ago

0.3.8

9 years ago

0.3.7

9 years ago

0.3.6

9 years ago

0.3.5

9 years ago

0.3.4

9 years ago

0.3.3

9 years ago

0.3.2

9 years ago

0.3.1

9 years ago

0.3.0

9 years ago

0.2.2

9 years ago

0.2.1

9 years ago

0.2.0

9 years ago

0.1.112

9 years ago

0.1.111

9 years ago

0.1.110

9 years ago

0.1.109

9 years ago

0.1.108

9 years ago

0.1.107

9 years ago

0.1.106

9 years ago

0.1.105

9 years ago

0.1.104

9 years ago

0.1.103

9 years ago

0.1.102

9 years ago

0.1.101

9 years ago

0.1.100

9 years ago

0.1.99

9 years ago

0.1.98

9 years ago

0.1.97

9 years ago

0.1.96

9 years ago

0.1.95

9 years ago

0.1.94

9 years ago

0.1.93

9 years ago

0.1.92

9 years ago

0.1.91

9 years ago

0.1.90

9 years ago

0.1.89

9 years ago

0.1.88

9 years ago

0.1.87

9 years ago

0.1.86

9 years ago

0.1.85

9 years ago

0.1.84

9 years ago

0.1.83

9 years ago

0.1.82

9 years ago

0.1.81

9 years ago

0.1.80

9 years ago

0.1.79

9 years ago

0.1.78

9 years ago

0.1.77

9 years ago

0.1.76

9 years ago

0.1.75

9 years ago

0.1.74

9 years ago

0.1.73

9 years ago

0.1.72

9 years ago

0.1.71

9 years ago

0.1.70

9 years ago

0.1.69

9 years ago

0.1.68

9 years ago

0.1.67

9 years ago

0.1.66

9 years ago

0.1.65

9 years ago

0.1.62

9 years ago

0.1.61

9 years ago