Monthly Archives: February 2015

Typescript Headers and Browser Quirks.

It’s been a pretty good week. The WebGl graphics in the directive are connected to the user functionality in the controller, I have tooltips running, and even have raycasting working, so the 2D items appear in the overlay plane above the 3D object:

AngularJSWebGl

 

The big problem that I needed to chase down was circular references in the typescript files. TypeScript uses reference path comments to tell the compiler where to look for type and structure information. Below is the information that I need for the angular module that creates the above application

/// <reference path="../../definitelytyped/angularjs/angular.d.ts" />
/// <reference path="../controllers/WGLA1_controller.d.ts" />
/// <reference path="../directives/WGLA2_directives.d.ts" />

In this case note that there is a path for controller and directive code. In this case, pointing directly to the code file is fine, but I have a case where my WebGLCanvas has to know about WebGLComponents and vice versa. The typescript compiler (tsc) doesn’t like that, and barfs a ‘duplicate definition’ error. At this point, I was wondering why TypeScript doesn’t have a #pragma once directive that would prevent this sort of thing, or even an #ifndef capability. It’s a preprocessor after all, and it should be able to do this. Easily.

But TypeScript does have interfaces. So in this case, I put interfaces for both modules in a single file, which I could then refer to in the downstream files and avoid the circular dependency issue.

The other issue was browsers not playing well together. I kind of thought that we had gotten beyond that, but no.

I develop with IntelliJ, and their debugger plays the best with Chrome, so that’s my default browser. At the end of the day, I’ll check to see that everything runs in IE and FF. And today FF was not playing well, and the tooltips I worked so hard on were not showing. WTF, I say.

If you look at the screenshot above, you’ll see the white text at the upper left. That’s my real-time logging (it’s pointless to write to the console at 30hz). And I could see that the unit mouse values were NaN. Again, WTF.

Now FF has my favorite debugger, and it even works (generally) with typescript, as long as you have all the .ts and .map files alongside your .js files. So I stepped into the code at the handleMouseEvents() method in WebGlCanvasClasses and started looking.

I’ve been getting the mouse coordinate from MouseEvent.offsetX. That turns out be used by IE and Chrome, but not FF. so I changed

var sx:number = ev.offsetX; to var sx:number = ev.offsetX | ev.layerX;

All fixed, I thought. But wait! There’s more! It turns out that IE has both of these values, and they don’t mean the same thing. so in the end I wind up with the following monkeypatch:

handleMouseEvents = (ev:MouseEvent):void => {
    var sx = ev.layerX;
    var sy = ev.layerY;

    if(ev.offsetX < sx){
        sx = ev.offsetX;
        sy = ev.offsetY;
    }
}

This works because the smaller value has to be the coordinate of the mouse on the div I’m interested, since all screen coordinates increase from 0. So it’s quick, but jeez.

Text Overlay for ThreeJS with Angular and TypeScript

This is not my first foray into WebGL. The last time I was working on a 3D charting API using the YUI framework, which could do things like this:

Personally, I can’t do any debugging at 30fps without having a live list of debugging text that I can watch. So almost immediately after the ‘hello world’ spinning cube, I set that up. And now I’m in the middle of moving my framework over to Angular and TypeScript. For the most part, I like how things are working out, but when it comes to lining up a transparent text plane over a threeJS element, YUI gives a lot more support than Angular. The following is so brute-force that I feel like I must be doing it wrong (And there may be a jquery-lite pattern, but after trying a few StackOverflow suggestions that didn’t work), I went with the following.

First, this all happens in the directive. I try to keep that pretty clean:

// The webGL directive. Instantiates a webGlBase-derived class for each scope
export class ngWebgl {
   private myDirective:ng.IDirective;

   constructor() {
      this.myDirective = null;
   }

   private linkFn = (scope:any, element:any, attrs:any) => {
      //var rb:WebGLBaseClasses.RootBase = new WebGLBaseClasses.RootBase(scope, element, attrs);
      var rb:WebGlRoot = new WebGlRoot(scope, element, attrs);
      scope.webGlBase = rb;
      var initObj:any = {
         showStage: true
      };
      rb.initializer(initObj);
      rb.animate();
   };

   public ctor = ():ng.IDirective => {
      if (!this.myDirective) {
         this.myDirective = {
            restrict: 'AE',
            scope: {
               'width': '=',
               'height': '=',
            },
            link: this.linkFn
         }
      }
      return this.myDirective;
   }
}

The interface with all the webGL code happens in the linkFn() method. Note that the WebGLRoot class gets assigned to the scope. This allows for multiple canvases.

WebGLRoot is a class that inherits from WebGLBaseClasses.CanvasBase, which is one of the two big classes I’m currently working on. It’s mostly there to make sure that everything inherits correctly and I don’t break that without noticing:-)

Within WebGLBaseClasses.CanvasBase is the initializer() method. That in turn calls the methods that set up the WebGL and the ‘stage’ that I want to interact with. The part we’re interested for our overlay plane is the overlay canvas’ context. You’ll needthat  to draw into later:

overlayContext:CanvasRenderingContext2D;

This is set up along with the renderer. Interesting bits are in bold:

this.renderer = new THREE.WebGLRenderer({antialias: true});
this.renderer.setClearColor(this.blackColor, 1);
this.renderer.setSize(this.contW, this.contH);

// element is provided by the angular directive
this.renderer.domElement.setAttribute("class", "glContainer");
this.myElements[0].appendChild(this.renderer.domElement);

var overlayElement:HTMLCanvasElement = document.createElement("canvas");
overlayElement.setAttribute("class", "overlayContainer");
this.myElements[0].appendChild(overlayElement);
this.overlayContext = this.overlayElement.getContext("2d");

The first thing to notice is that I have to add CSS classes to the elements. These are pretty simple, just setting absolute and Z-index:

.glContainer {
    position: absolute;
    z-index: 0;
}

.overlayContainer {
    position: absolute;
    z-index: 1;
}

That forces everything to have the same upper left corner. And once that problem was solved, drawing is pretty straightforward. The way I have things set up is with an animate method that uses requestAnimationFrame() wich then calls the render() method. That draws the 3D, and then hands the 2D context off to the draw2D() method:

draw2D = (ctx:CanvasRenderingContext2D):void =>{
   var canvas:HTMLCanvasElement = ctx.canvas;
   canvas.width = this.contW;
   canvas.height = this.contH;
   ctx.clearRect(0, 0, canvas.width, canvas.height);
   ctx.font = '12px "Times New Roman"';
   ctx.fillStyle = 'rgba( 255, 255, 255, 1)'; // Set the letter color
   ctx.fillText("Hello, framecount: "+this.frameCount, 10, 20);
};

render = ():void => {
   // do the 3D rendering
   this.camera.lookAt(this.scene.position);
   this.renderer.render(this.scene, this.camera);
   this.frameCount++;

   this.draw2D(this.overlayContext);
};

I’m supplying links to to the running code and directives, but please bear in mind that this is in-process development and not an minimal application for clarity.

Lexical Scoping and a revisit of AngularJS + Typescript

In the process of putting together my first ‘real’ Angular/TypeScript application, I ran into a frustrating problem: the callback functions that I was using in my $http calls were unable to reach other functions (methods?) in my TypeScript objects.

It turned out that it has to do with the way that TypeScript has to deal with the self = this problem. To tell TS (and EcmaScript 6) to use the ‘this’ from the calling function, functions are created using ‘fat arrow’ notation (=>), something that I had seen, but not really paid attention to.

The Mozilla Developer Network discusses fat arrows in JavaScript here. The part about ‘lexical this is worth paraphrasing here:

Until arrow functions, every new function defined its own this value (a new object in case of a constructor, undefined in strict mode function calls, the context object if the function is called as an “object method”, etc.). This proved to be annoying with an object-oriented style of programming. In ECMAScript 3/5, this issue was fixed by assigning the value in this (e.g. self) to a variable that could be closed over. Arrow functions capture the this value of the enclosing context, so the following code works as expected.

function Person(){
  this.age = 0;

  setInterval(() => {
    this.age++; // |this| properly refers to the person object
  }, 1000);
}

var p = new Person();

So TypeScript works the same way, but it has to compile to current JavaScript. I had several areas in my code where I needed access to ‘this’, for example in lambda functions. In TypeScript, the way you keep lexical scoping looks like this:

this.querySpeech.onend = (event:Event) => {
   this.queryService.submit(this.query, this.goodUserQuery, this.errorResponse);
};

And the generated Javascript looks like this:

this.querySpeech.onend = function (event) {
    _this.queryService.submit(_this.query, _this.goodUserQuery, _this.errorResponse);
};

Note that rather than ‘self’ TypesScript has defined ‘_this’. It’s declared as you would expect it – var _this = this;.

With respect to methods, the pattern in similar. Rather than declaring a method in the ‘default manner:

public runQuery(query:string){
   this.query = query;
   this.submit();
};

A ‘scoped’ method should be declared as follows:

public runQuery = (query:string) => {
   this.query = query;
   this.submit();
};

These result in very different JavaScript. The former generates a prototype:

QueryController.prototype.runQuery = function (query) {
    this.query = query;
    this.submit();
};

While the latter generates a function that is within the ‘constructor’:

this.runQuery = function (query) {
    _this.query = query;
    _this.submit();
};

To me, it’s clearer how things will work out with a callback in the second function. Because we’re using _this via closure, we know that we’ll get only members of our class. With the other JavaScript, things are much less obvious– ‘this’ could be global, or what apply() would pass in. Scary.

So now we have TypeScript classes that behave the way that (I think) a proper OO class should behave. Which makes me think about the pattern of using static methods for building Factories and Directives that I described a few posts ago. Maybe there’s a better way.

Factories and directives want a function that returns an object that contains what they need to work with. In the case of a directive, angular is pretty particular, and will need to look something like:

public ctor = (gService:ITestService):ng.IDirective => {
   var myDirective:ng.IDirective = {
      template: '<p>Directive (Ctor) = ' + gService.getHello() + ', linkFn = {{name}}</p>',
      restrict: 'AE',
      link: this.linkFn
   };
   myDirective;
};

Factories, on the other hand pretty much just want references to the functions that will be accessed.

public ctor = () => {
   var retval = {
      getHello: this.getHello
   };
   return retval;
};

The neat thing is that now that the functions have lexical scope, we can instance them and then just pass the reference to the ctor() method to angular, and it’s happy. Below is how I like to initialize my Angular apps. Note that the Factory and Directive classes are instanced with new before being passed in:

module AngularApp {
// define how this application assembles.
   class AngularMain {
      serviceModule:ng.IModule;
      appModule:ng.IModule;

      public doCreate(angular:ng.IAngularStatic, tcontroller:Function, tservice:Function, tfactory:Function, tdirective:Function) {
         this.serviceModule = angular.module('globalsApp', [])
            .factory('GlobalsFactory', [tfactory])
            .service('GlobalsService', [tservice]);

         this.appModule = angular.module('simpleApp', ['globalsApp'])
            .controller('MainCtrl', ['GlobalsFactory', 'GlobalsService', tcontroller])
            .directive('testWidget', ['GlobalsService', tdirective]);
      }
   }
// instantiate Angular with the components defined above.
   new AngularMain().doCreate(angular,
      InheritApp.TestController2,
      InheritApp.TestService,
      new InheritApp.TestFactory().ctor,
      new InheritApp.TestDirective().ctor);
}

So now we have a much cleaner way of dealing with angular components that supports OO patterns and inheritance without having to write parasitic inheritance functions. And we get typing! I am a happy web developer.

The full code that demonstrates all of the above is in the following links:

Hopefully, this is the last of my general purpose struggles with getting Angular and JavaScript to be reasonably well behave OOP objects. Next posts should be about getting this all working with threejs, and maybe a little gpu programming

TypeScript and AngularJS part 2; the Good, the Bad and the Ugly.

As will become clear, this is the takehome message:

  • Directives and Factories, because they are used without new(), must be created as static TypeScript objects.
  • Controllers and Services can be plain old typescript objects (potsos?)

Naturally, there are ramifications.

Let’s start at the end, where everything is combined and delivered to Angular:

module AngularApp {
   // define how this application assembles.
   class AngularMain {
      serviceModule:ng.IModule;
      appModule:ng.IModule;

      public doCreate(angular:ng.IAngularStatic, tcontroller:Function, tservice:Function, tfactory:Function, tdirective:Function) {
         this.serviceModule = angular.module('globalsApp', [])
            .factory('GlobalsFactory', [tfactory])
            .service('GlobalsService', [tservice]);

         this.appModule = angular.module('simpleApp', ['globalsApp'])
            .controller('MainCtrl', ['GlobalsFactory', 'GlobalsService', tcontroller])
            .directive('testWidget', ['GlobalsService', tdirective]);
      }
   }
   // instantiate Angular with the components defined above.
   new AngularMain().doCreate(angular, InheritApp.TestController2, InheritApp.TestService, InheritApp.TestFactory.ctor, InheritApp.TestDirective2.ctor);
}

This structure isn’t needed, but as with the last post, I kind of like the way it looks. The first thing to notice is that the angular-specific code is wrapped in its own module and class within that module. Since this isn’t going to get called outside of the module (this would be custom for each application), I didn’t bother with an interface. Once the class is built, I call it with the arguments that will be used by Angular to build the application. There are two things to note: the arguments with the ctor member are static. The items with a ‘2’ in their names are child classes, built with typescript-defined inheritance.

Let’s take a look at the controller and the service that gets passed in.

Controllers and Services, since they are instances, require virtually no contortions to use. A controller is declared pretty much just the way you’d want to. (I have the classes for this example wrapped in a module that I can then export from – full code here) . The following controller has an interface, a class that implements that interface, and a constructor that takes angular injections.

export interface ITestController {
   myString:string;
   serviceString:string;
   factoryString:string;
}
export class TestController implements ITestController {
   myString:string;
   serviceString:string;
   factoryString:string;

   constructor(gFactory:ITestService, gService:ITestService) {
      this.myString = "Hello, TypeScript4";
      this.serviceString = gService.getHello();
      this.factoryString = gFactory.getHello();
   }
}

The child class is built as follows. I added a new variable, and modified a parent variable in the constructor::

// example on an inherited interface and controller
export interface ITestController2 extends ITestController {
   myInheritedString: string;
}
// the associated controller.
export class TestController2 extends TestController implements ITestController2 {
   myInheritedString:string;

   constructor(gFactory:ITestService, gService:ITestService) {
      super(gFactory, gService);
      this.myInheritedString = "Hello, inheritance";
      this.myString += " from your child"
   }
}

In case you were wondering (you can look at the generated code here), typescript uses parasitic inheritance.

The service in this example is constructed essentially identically to the controller:

// example service with interface
export interface ITestService {
   helloStr:string;
   getHello():string;
}
export class TestService implements ITestService {
   helloStr:string;

   constructor() {
      this.helloStr = "TestService String";
   }

   public getHello():string {
      return "Hello from TestService";
   }
}

Now let’s compare the service to a factory. Factories are set up by angular to be singletons, while services can breed like bacteria and clog all your memory. Typescript uses a static** property to define singletons, so a factory in typescript looks like this:

// Factory. Like the directive, factories are called without new, 
// so no this, and all references to the factory are references 
// to the same object. 
export class TestFactory {
   static helloStr:string = "TestFactory String";

   public static ctor() {
      var retval = {
         getHello: TestFactory.getHello
      };
      return retval;
   }

   public static getHello():string {
      return TestFactory.helloStr;
   }
}

This is a little more clunky, but it does make what’s going on clearer, at least for me. Note how you can’t have any items attached to the ‘this’ object. They have to be explicitly attached to the ‘class definition’. As such the static/singleton status is hard to overlook.

Inheritance will work on static classes, but with some odd considerations. This is the parent and child directives:

// directives have to be static, as they are called without the 
// 'new' operator, which means they have no 'this' They also 
// don't get interfaces, since all the functions are static 

export class TestDirective implements ng.IDirective {

   public static  linkFn(scope:any, element:any, attr:ng.IAttributes) {
      function sayIt(str:string):string{
         return str;
      }
      scope.name = "Hello from linkFn";
      scope.sayIt = sayIt;
      alert (sayIt("alert me!"));
   }

   public static ctor(gService:ITestService):ng.IDirective {

      var directive:ng.IDirective = {};
      directive.template = '<p>Directive (Ctor) = ' + gService.getHello() + ', linkFn = {{name}}</p>';
      directive.restrict = 'AE';
      directive.link = TestDirective.linkFn; // silly, but necessary.
      return directive;
   }
}

export class TestDirective2 extends TestDirective {
   public static ctor(gService:ITestService):ng.IDirective {

      var directive:ng.IDirective = {};
      directive.template = '<p>Inherited Directive (Ctor) = ' + gService.getHello() + ', linkFn = {{name}}</p>';
      directive.restrict = 'AE';
      directive.link = TestDirective2.linkFn; // silly, but necessary.
      return directive;
   }
}

There are a couple of things to note in the code above. First, the directive as it is built in the ctor() method is created as an empty object and then populated. This is how I found it being done in examples on the web, and I believe it helps determine typing. I’m not convinced though – I’ll have to check by putting something mis-typed inside the object definition. By the way, note that services or factories can be passed to the directive as arguments to the ctor() method.

The second odd thing is the directive.link function. I would have thought that this could have been done a variety of ways, but this is how Angular likes it. And because everything is static, I wound up using functions inside the linkFn class since you can’t nest typescript-style methods in a clear way.

With respect to inheritance, directives are going to be a pain.  You can’t easily overload parts of the parent class to add capability to the child class. It may actually be easier to use inheritance on just the link function. I’m still not sure what the best way to go on that is. It will probably only become clear when I try to write some sophisticated directives (and, boy do I have one to work on…).

So there is good, not-so-bad and ugly. I’d be curious if anyone has a better pattern, particularly for directives.

—————————-

** It turns out that there is a non-static way to treat directives and factories, which is instancing them and then passing a function reference to angular. I think this works much better. For more detail, check out this post.