2013-12-03
My Little Machines Part 4

To make the customization of a machine even more friendly to in-page parameterization, we’ll add additional callbacks to be specified on the <machine> declaration.


Here is the source code for the above:

<machine ptr="MA" ng-init="customStateA = ''"
	reset-fn="customStateA='-'"
	step-fn="(MA.getMachineTime() == 5) ? MA.pauseMachine() : (customStateA = customStateA + '+')"
	pause-fn="customStateA = customStateA + 'P'"
	resume-fn="customStateA = customStateA + 'R'"
	halt-fn="customStateA = customStateA + 'H'"
	class="mlm background">

<div>

<button class="btn btn-default btn-xs py-0" title="Reset" ng-click="MA.resetMachine()"><span class="fa fa-power-off"></span></button>
<button class="btn btn-default btn-xs py-0" title="Step" ng-click="MA.stepMachine()" ng-disabled="!MA.isRunning()"><span class="fa fa-forward"></span></button>
<button class="btn btn-default btn-xs py-0" title="Resume" ng-click="MA.resumeMachine()" ng-disabled="!MA.isRunning() || MA.isPaused()"><span class="fa fa-play"></span></button>
<button class="btn btn-default btn-xs py-0" title="Pause" ng-click="MA.pauseMachine()" ng-disabled="!MA.isRunning() || !MA.isPaused()"><span class="fa fa-pause"></span></button>

<h6 class="status left">{{ MA.getMachineTime() }}</h6>
<h6 class="status right">{{ MA.getMachineState() }}</h6>
</div>

<hr class="mlm-timebar" ng-class="MA.isRunning() ? 'running' : 'halted'" style="width:{{ 20 * (MA.getMachineTime() + 1) }}px;"/>

</machine>

<h4>Custom State: <span style="color:purple;font-size:150%;">{{customStateA}}</span></h4>

Clearly, the step-fn is getting unwieldy and hard to read and edit. So let’s see if we can move it into an inline JavaScript function and have the AngularJS bindings still hold up:


Amazing! That worked out fine. I had to create an inline controller to host the stepFn function, but that function is able to refer to the same parent context as the stuff that was inline in the <machine>’s stepFn attribute. I just have to use $scope.MB instead of MB to refer to the machine.

Here is the source code:

<div ng-controller="MachineBController">

<script>

function MachineBController($scope) {
  $scope.myStepFn = function() {
	($scope.MB.getMachineTime() == 5) ?
		($scope.MB.pauseMachine()) :
		(($scope.MB.getMachineTime() > 10) ?
			($scope.MB.haltMachine()) : ($scope.customStateB = $scope.customStateB + '+'));
	return '1234';
  };
}

angular
  .module('BlogApp')
  .controller('MachineBController', MachineBController);

</script>


<machine ptr="MB" ng-init="customStateB = ''"
	reset-fn="customStateB='-'"
	step-fn="myStepFn()"
	pause-fn="customStateB = customStateB + 'P'"
	resume-fn="customStateB = customStateB + 'R'"
	halt-fn="customStateB = customStateB + 'H'"
	class="mlm background">


<div>

<button class="btn btn-default btn-xs py-0" title="Reset" ng-click="MB.resetMachine()"><span class="fa fa-power-off"></span></button>
<button class="btn btn-default btn-xs py-0" title="Step" ng-click="MB.stepMachine()" ng-disabled="!MB.isRunning()"><span class="fa fa-forward"></span></button>
<button class="btn btn-default btn-xs py-0" title="Resume" ng-click="MB.resumeMachine()" ng-disabled="!MB.isRunning() || MB.isPaused()"><span class="fa fa-play"></span></button>
<button class="btn btn-default btn-xs py-0" title="Pause" ng-click="MB.pauseMachine()" ng-disabled="!MB.isRunning() || !MB.isPaused()"><span class="fa fa-pause"></span></button>

<h6 class="status left">{{ MB.getMachineTime() }}</h6>
<h6 class="status right">{{ MB.getMachineState() }}</h6>
</div>

<hr class="mlm-timebar" ng-class="MB.isRunning() ? 'running' : 'halted'" style="width:{{ 20 * (MB.getMachineTime() + 1) }}px;"/>

</machine>

<h4>Custom State: <span style="color:purple;font-size:150%;">{{customStateB}}</span></h4>

</div>