Haxe – External classes

The time will come you have to communicate with an third party JavaScript file. This can be Google Maps, Facebook, TweenMax, Webtrekk, Youtube and so on. To use this third party objects correctly Haxe need to know a few things:

  • How is this object called in native JavaScript?
  • The properties do the object.
  • The methods names, the proper parameters and what will be returned.

With this informations Haxe will support you using these third party objects.

Make yourself library

I’ll show you in the example of Youtube how I write my own external class.
First we will set up our external library folder where we store all our external classes in.
Start FDT,make a new Haxe Project and name it as you like. I will name mine „ExtLib“. Rename the MainClass to “MainExtLib“ and finish the project wizard. Because we will use the MainExtLib.hx class you go to the src folder and delete the Main.hx.

Name spacing

Let’s use the power of name spacing create a new Haxe class. To do so mae a right click on the scr folder and select New > Haxe Class. In this dialog you can set the package (name spacing) and the name of this new class. The package would be „lib.externals.youtube“ and the name will be „Youtube API“. Click on finish to confirm. What happened? FDT creates 3 new folders and a Haxe class named Youtube API. You can check that in the src folder.
Let’s take a deeper look at the Youtube API class.

The Structure

Open this class and you will find something like this

package lib.externals.youtube;

class YoutubeAPI {

}

To make this class an external class we need to add the keyword „extern“.

package lib.externals.youtube;

extern class YoutubeAPI {

}

Now where at the point where we need to know all the required informations from the youtube API. Do you remember them?

  • How is this object called in native JavaScript?
  • The properties do the object.
  • The methods names, the proper parameters and what will be returned.

Right now we will write this informations down in this class. The first information is the native we will set is the native object name. So we update the class to this.

package lib.externals.youtube;

@:native("YT")
extern class YoutubeAPI {
	
				
}

Now we need to know the properties and write them down. In this case there are no properties for the YT object so we can go on to the Methods.

package lib.externals.youtube;

@:native("YT")
extern class YoutubeAPI {
	
	public static function get():Dynamic;
	
	public static function loaded():Dynamic;
	
	public static function loading():Dynamic;
	
	public static function ready():Dynamic;
	
	public static function scan():Dynamic;
	
	public static function setConfig():Dynamic;
	
	public static function subscribe():Dynamic;

	public static function unsubscribe():Dynamic;
			
}

For using the Youtube API we need the additional class „YoutubePlayer“. Create this class the same way like you created the YoutubeAPI class. This class will be a property of the native object „YT“, so we will set @:native to „YT.Player“.

package lib.externals.youtube;

@:native("YT.Player")
extern class Player {
		
}

The package will tell you that both classes are located in the same folder.

Also for this class we have to write down the properties and methods from the Youtube API.

package lib.externals.youtube;

@:native("YT.Player")
extern class YoutubePlayer {
	public var a:Dynamic;
	
	public function new(id:String, obj:Dynamic):Void;
	
	public function playVideo():Void;
	
	public function stopVideo():Void;
	
	public function pauseVideo():Void;
	
	public function getDuration():Int;
	
	public function getVideoUrl():String;
	
	public function getVideoEmbedCode():String;
	
	public function getAvailableQualityLevels():Array<String>;
	
	public function setPlaybackQuality(suggestedQuality:String):Void;
	
	public function getPlaybackQuality():String;
	
	public function getCurrentTime():Int;
	
	public function mute():Void;
	
	public function unMute():Void;
			
	public function isMuted():Bool;
	
	public function setVolume(volume:Int):Void;
	
	public function getVolume():Int;
	
	public function seekTo(seconds:Int, allowSeekAhead:Bool):Void;	
}

We’re done!

Using/Testing

To test our classes we will first open up the index.html located in the bin folder in the project.
The Youtube API will call the function „onYouTubePlayerAPIReady“ when the API is loaded and ready, so lets add this function to the header of this site. Also we need to include the API itself but you will have to make sure that the API is included after our JavaScript file. The order is important when you would use the Youtube API. We also need an Iframe Player and two buttons. Make sure that the player parameter „enablejsapi=1“.

<!DOCTYPE html>
<html lang="en">
	<head>
		<title>ExtLib</title>
		<script type="text/javascript">
			function onYouTubePlayerAPIReady(){}
		</script>
		
	</head>
	<body>
		<div id="content">
			<div id="head"></div>
			<div id="body">
				<iframe src="https://www.youtube.com/embed/ngElkyQ6Rhs?enablejsapi=1" id="youtube-0" frameborder="0" width="500" height="350"  allowfullscreen class="yt_video"></iframe>
				<button id="play-btn">Play</button><button id="pause-btn">Pause</button>
			</div>
			<div id="footer"></div> 
		</div>	
		
		<script type="text/javascript" src="js/App.js"></script>	
		<script type="text/javascript" src="https://www.youtube.com/iframe_api"></script>
	</body>
</html>

Now let’s go back to the coding part.

import lib.externals.youtube.YoutubePlayer;

import js.Browser.window;
import js.html.ButtonElement;
import js.html.Event;

class MainExtLib {
	
	public static var player:YoutubePlayer;
	
	public static function main() {
		var base:Dynamic = window;
		base.onYouTubePlayerAPIReady = onYouTubePlayerAPIReady;
	}
	
	public static function onYouTubePlayerAPIReady():Void{
		trace("Haxe onYouTubePlayerAPIReady");
		player = new YoutubePlayer("youtube-0", {
        	events: {
        		'onReady' 		: onplayerReady,
        		'onStateChange'	: onPlayerStateChange,
        		'onError'		: onErrorHandler
        	}
        });
		
		var playBtn:ButtonElement = cast(window.document.querySelector("#play-btn"));
		playBtn.addEventListener("click", playHandler, true);
		var pauseBtn:ButtonElement = cast(window.document.querySelector("#pause-btn"));
		pauseBtn.addEventListener("click", pauseHandler, true);
	}
	
	public static function playHandler(ev:Event):Void{
		player.playVideo();
	}
	
	public static function pauseHandler(ev:Event):Void{
		player.pauseVideo();
	}
	
	public static function onplayerReady():Void{
		trace("Ready");
	}
	
	public static function onPlayerStateChange(event:Dynamic):Void{
		switch(event.data){
			case -1: 
				trace('unstarted');
			
			case 0: 
				trace('completed');
			case 1: 
				trace('playing');
				
			case 2: 
				trace('pausing');
			
			case 3: 
				trace('buffering');
				
			case 5: 
				trace('cued');
		}
	}
	
	public static function onErrorHandler():Void{
		trace("Error");
	}
}

We have to import quite a few things:

  • Our external „YoutubePlayer“ class.
  • The window object (BOM).
  • The button element (DOM).
  • The event object (DOM).

To make the player variable access able in the hole class we will define it as property. The main constructor will only overwrite the „onYouTubePlayerAPIReady“ function defined in the index.html with our own method „onYouTubePlayerAPIReady“. As I mention it before, the Youtube API will call this function when ready. In this function we can now make an instance of our external class. We have to provide 2 parameters:

  • The id of the Youtube iframe we ant to talk to.
  • An anonymous object with events and listener methods.

Then we will register the two buttons an add event listeners to them. In these event listeners we can access the player instance and call it’s methods.
That’s it!
Let’s say you have to start a new project and want to use these external classes? No problem. Just open up the compile.hxml and copy the path of your ExtLib underneath the „-cp src“ line.

-js bin/js/App.js
-main MainExtLib
-cp src

// Path of the project you will include
-cp c:/Users/…/ExtLib/src

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>