AngularJS and Interactives Create Awesome Workouts

By Jason Shah | November 26, 2013

Mediafly Interactives lets our customers create rich and engaging custom apps using Mediafly SalesKit and ProReview. Interactives are zip files consisting of HTML, CSS, JavaScript, and resources that can work entirely offline. You can learn more about Interactives in the API documentation.

Angular.JS (or, Angular for short) is an open-source JavaScript framework that makes building MVC-like web applications simple, testable, and fun. Many Angular apps run as single-page JavaScript applications, and the framework is ideal for offline web apps.

When you combine the two, very interesting things can happen. In this post, we will explore how AngularJS and Interactives create awesome workouts.  Specifically, Mediafly Workouts, which is a cross-device, fully responsive Interactive meant to help you improve your core through a structured workout. You can find the source code on BitBucket.

This post assumes you have a working knowledge of Angular.

How It Works

In the Mediafly Airship content management system, create a folder with all of your workouts as separate images, named with each exercise. I suggest building your workout using one of the many core workouts you can find online. We didn’t include any images in the source, so as to avoid any copyright issues that might exist.

a core workout as seen in Airship

A core workout as seen in Airship

Package and drop the Interactive as the first item in the folder*. Open and go!

On launch, the Interactive will

Angular Interactive - core workout dialogAngular Interactive - core workout dialog on iPhone
Angular Interactive - core workoutAngular Interactive - core workout dialog on iPhone

Interesting Areas

mflyDataInit, mflyInit and mflyResume

Mediafly apps tell Interactives information by calling JavaScript functions in those Interactives, as described in the documentation. For example, mflyDataInit is called by the app to tell the Interactive of the various features and capabilities of the device, OS, app, and Interactive itself. Interactives simply have to implement the function to catch and make use of this information.

However, implementing functions in JavaScript is not the AngularJS way of doing things. Handling Angular events is. To ease the transition, we built a simple file called mflyAngular.js that implements each relevant function and then broadcasts the event into the Angular root scope. Interactives developers simply need to include the following file (after including angular.js):

[code language=”html”]<script type=”text/javascript” src=”js/mflyAngular.js”></script>[/code]

Then, catch the events in their controllers:

[code language=”javascript”]
$scope.$on(‘Mediafly.mflyDataInit’, function(event, obj) {
// Do stuff
});
[/code]

Using Timer

Workouts make use of Angular Timer, a simple timer directive. While basic operation of timer was very smooth, there were some unclean areas of integration. Notably, the events it generates operate outside of Angular for some reason. As a result, we had to wrap the body within a $scope.$apply. For example:

[code language=”javascript”]
/**
* When the timer stops, change state and restart timer
* Note: operating from outside AngularJS
**/
$scope.$on(‘timer-stopped’, function (event, data) {
$scope.$apply(function () {
$scope.moveToNextState();
});
$scope.startTimer();
});
[/code]

Models and Views

We maintain the two states for exercises with a JSON object:

[code language=”javascript”]
$scope.STATE = {
REST: { display: ‘rest and prepare’, color: ‘#A00000’, timer: 10 },
DO: { display: ‘workout’, color: ‘#00AA00’, timer: 60 }
};
[/code]

With Angular, we can let the user change what value they want for each timer:

[code language=”html”]
<label for=”restTime”>Rest time (seconds):</label>
<input class=”form-control” id=”restTime” type=”text” />

<label for=”workoutTime”>Workout time (seconds):</label>
<input class=”form-control” id=”workoutTime” type=”text” />
[/code]

And then, the app can save the state into a key it defines.

Saving and Getting Key/Value Data

The latest version of Mediafly’s iOS apps (and soon, Android and Windows 8) allows Interactives to store generalized key/value data. Interactives simply need to:

1. Include mflyAngular.js in index.html, as was done earlier:

[code language=”html”]<script type=”text/javascript” src=”js/mflyAngular.js”></script>[/code]

2. Load the Mediafly.services module:

[code language=”javascript”]
angular.module(‘myApp’, [‘myApp.controllers’, ‘Mediafly.services’, ‘timer’, ‘ngSanitize’]);
[/code]

3. Pass the MflyDataService factory into your controller:

[code language=”javascript”]
angular.module(‘myApp.controllers’, []).
controller(‘WorkoutCtrl’, [‘$scope’, ‘MflyDataService’, function ($scope, MflyDataService) {

}]);
[/code]

4a. Save values to keys with MflyDataService.saveState. This function utilizes the Promises pattern to handle callbacks; simply implement one of the common functions (e.g. success, error, then) to take action on save completion:

[code language=”javascript”]
MflyDataService.saveState(‘state’, JSON.stringify($scope.STATE))
.success(function (result, status, xhr) {
// Save successful
}).error(function (result, status, xhr) {
// Error while saving
});
[/code]

4b. Retrieve values from keys with MflyDataService.getState, the corollary to saveState:

[code language=”javascript”]
$scope.$on(‘Mediafly.mflyResume’, function(event) {
MflyDataService.getState(‘state’)
.success(function (result, status, xhr) {
$scope.STATE = result;
})
.error(function (result, status, xhr) {
// Error while retrieving
});
});
[/code]

Next Steps

This was a great start. However, there is a lot of work do.

In the meantime, happy workout!

* There are some configuration steps that need to take place. Take a look at README.md within the source.


Subscribe to Mediafly’s Blog!

Get all the latest Mediafly News and Updates! Just enter your email below:

Comments are closed.