How do I implement my own animation library in Aurelia? - aurelia

Let's say I want to use something like JQuery UI to write some animations when an element is added or removed from the DOM. I see in this article that I could use the animator interface to write my own animations using the enter and leave functions. This same article uses the example of view-slot.js to show how this interface is utilized. I can even see this dependency being injected here, like this
import {Animator} from './animator';
...
constructor(anchor: Node, anchorIsContainer: boolean, animator?: Animator = Animator.instance) {
How can I supply my own implementation of the Animator interface here? I used the Greensock aurelia plugin, which is another javascript animation library, as an example of how I might do this only to find that it's using its own version of animator.js with Greensock animations written into it. I was expecting to find something that would supply a custom implementation of the animator interface to the view-slot constructor but came up empty.
Any help is appreciated.

Found it. You need to run configureAnimator on the templating engine which resides inside Aurelia's DI container. Below example is taken from animator-css which is an implementation of the animator interface. This piece of code runs during the startup process as a plugin.
export function configure(config: Object, callback?:(animator:CssAnimator) => void): void {
let animator = config.container.get(CssAnimator);
config.container.get(TemplatingEngine).configureAnimator(animator);
if (typeof callback === 'function') { callback(animator); }
}
https://github.com/aurelia/animator-css/blob/master/src/index.js

Related

Exception when I change to other scene in KorGE

com.soywiz.korinject.AsyncInjector$NotMappedException: Class 'class ChooseCampaign (Kotlin reflection is not available)' doesn't have constructors RequestContext(initialClazz=class ChooseCampaign (Kotlin reflection is not available))
Above exception was threw when I compiled current code. And I dont know how fix it and what does it means.
My code:
textButton {
position(0, 128)
text = "Play"
onClick {
println("Play")
launchImmediately {
sceneContainer.changeTo<ChooseCampaign>()
}
}
}
How it fix?
When using Scenes in KorGE, you are using the korinject dependency injector indirectly.
And that injector requires manual mapping. If you are using Modules, you can configure those mappings at the Module.init method.
Check this sample: https://github.com/korlibs/korge-samples/blob/1771b7ca7f4440e1a368ff4b441e97bf62e08b8d/sample-scenes/src/commonMain/kotlin/main.kt#L15-L23
In your case, once you get the Injector instance, you can map a scene like this:
mapPrototype { ChooseCampaign(get()) }
You have to put as many get() as parameters your ChooseCampaign constructor has.
In the case you are not using modules, the place to put the mapping is different, and you need to get the Injector instance.
In your suspend fun main() = Korge { block, you have the Stage singleton injected. This is the root view that has a reference to the Views singleton.
So there you can just access the injector like this: this.views.injector
You can then map your scenes whenever you like, though I suggest you do to it at the beginning of the application.

How to best use global service classes in Aurelia

I have some services which are used by many classes in my application. As an example this could be a LoggerService which logs messages to an internal store and prints them to the console.
This service could look something like this:
export class LoggerService {
let _logs = [];
addLog(msg) {
this._logs.push(msg);
console.log(this._logs.length + ': ' + msg);
}
}
I guess the usual way in Aurelia would be to use this class with dependency injection which works just fine since it uses a singleton per default. An example usage could then look something like this:
import {autoinject, Aurelia} from 'aurelia-framework';
import {LoggerService} from 'LoggerService';
#autoinject
export class SomeViewModel {
let _loggerService;
constructor(loggerService) {
this._loggerService = loggerService
}
somethingChanged() {
this._loggerService.addLog('Something changed...');
}
}
Basically this approach works just fine but it feels a little "clumsy" at a larger scale and I hope that it could be simplified:
Using dependency injection requires a lot of boilerplate code in each "using class" which unnecessarily "bloats" them (import statement, a dedicated class member which needs to be assigned in the constructor etc.).
I'm used to having such classes inside a dedicated namespace which lives in the window object. This allows me convenient debugging since I can call code like MyNamespace.LoggerService.addLog('blahblah'); directly from the command line. How do I accomplish this best with Aurelia?
Is there an more straight forward way which would also give me a better debug experience from the command line?
Honest answer? If you follow ES6 modular code conventions, not really. You will always be importing modules if and when you require them. There are things that you can do, which I'll go over in this answer.
You don't actually need to use Aurelia's dependency injection if you don't want to. However, that means that you'll have to handle the lifecycle of the object yourself. Because your object is a class, you'll have to call "new" on it when you import it. However, you can write your logging module differently, and instead of exporting a class, you can export a function, like so:
let _logs = [];
export var LoggerService = {
addLog: function (msg) {
_logs.push(msg);
console.log(_logs.length + ': ' + msg);
}
}
That way, all you have to do is import LoggerService and call LoggerService.addLog inside of your Aurelia view without having to inject it. This is a more functional approach than the class instantiation approach, which can work very well.
import {LoggerService} from 'LoggerService';
export class SomeViewModel {
constructor() {
}
somethingChanged() {
LoggerService.addLog('Something changed...');
}
}
Another thing you can do (I wouldn't recommend this) is simply make this a window variable. This would mean that you wouldn't have to import modules. This violates module principles, though, and things get messy really quickly. Modules exist for a reason, and although import statements do add lines of code, the benefits are worth the extra space.
For your use case, I would use the function-based approach above, and I would check a "development" flag somewhere so that you can expose properties on the window object so that you can access them through the console. (You wouldn't want this available in a production environment, as people could easily mess up your application.) Something like
if (developmentFlag) { window.loggerService = LoggerService; }
This may be the best approach until we're able to run the import statement in the console REPL.

Add methods to an assigned closure with GroovyDSL

Geb uses a static field called content to define the contents of a page or module. The value of the content field is a closure.
class GebishOrgHomePage extends Page {
static content = {
manualsMenu {
module MenuModule, $("#header-content ul li", 0)
}
links { $('.link-list li a') }
}
}
Intellij already has support for this content dsl, however it does not support the module and moduleList methods. This causes limited auto-complete support when working with modules.
To fix this I'd like to write a GroovyDSL script that adds the missing method definitions to the content closure and its nested closures. However, I've no idea how to add methods to a closure that is not passed to a method, since enclosingCall requires a concrete method name.
And the other thing is that those methods must have a generic return type like this:
<T extends Module> T module(Class<T> m) {
// return an instance of T
}
If you use the latest snapshot then module() calls will be understood by your IDE. This is down to moving module() to Navigator exactly for what you are after - autocompletion and strong typing.
Have a look at the current version of section 6.4 of the Book of Geb. The moduleList() will be gone in a future release and that section explains what to use instead. The module() method taking a map argument to initialise module properties will also go, you now initialise the module yourself and pass the instance to module() and there is an example of doing this in 6.4. Thanks to all that you will get autocompletion around module defintions and usage in IntelliJ.

Using dojo.require() without dojo.declare()

I'm quite confused from Dojo's documentation. How can I use dojo.require() without actually using dojo.declare()? The reason I don't want to use dojo.declare() is that it exposes declared class as global variable.
Right now my code looks like this:
HTML file:
dojo.require('module.test');
Module/test.js:
dojo.provide('module.test');
function test() {
return 'found me';
}
I just can't get Dojo to return test() method anywhere. What's the correct pattern for using dojo.require() without declaring?
I think you are confusing dojo.provide/dojo.require with dojo.declare. They are completely different concepts.
Things that relate to modules
dojo.provide defines a module.
dojo.require requires that a module be defined before running any code later.
Things that relate to JavaScript classes
dojo.declare is something completely different. It declares a Dojo-style class.
You can have multiple classes in a module, or several modules making up one class. In general, modules !== classes and they are completely unrelated concepts.
dojo.provide defines the code module so that the loader will see it and creates an object from the global namespace by that name. From that point, you can anchor code directly to that global variable, e.g.
Module/test.js:
dojo.provide('module.test');
module.test.myFunc = function() {
return 'found me';
}
There are various patterns you can use, such as creating a closure and hiding "private" function implementations, exposing them via the global reference you created in dojo.provide:
dojo.provide('module.test');
function(){
// closure to keep top-level definitions out of the global scope
var myString = 'found me';
function privateHelper() {
return myString;
}
module.test.myFunc = function() {
return privateHelper();
}
}();
Note that the above simply puts methods directly on an object. Now, there's also dojo.declare, which is often used with dojo.provide to create an object with prototypes and mixins so that you can create instances with the 'new' keyword with some inheritance, even simulating multiple inheritance vai mixins. This sort of OO abstraction is often overused. It does approximate the patterns required by languages like Java, so some folks are used to declaring objects for everything.
Note that as of Dojo 1.5, dojo.declare returns an object and does not necessarily need to declare anything in the global scope.
Here's a pattern I sometimes use (this would be the contents of test.js):
(function() {
var thisModule = dojo.provide("module.test");
dojo.mixin(thisModule, {
test: function() {
return "found me";
}
});
})();
Now you can reference module.test.test() in your HTML page.

How do you hide a Gtk# window?

How can I hide a Gtk# window that I created in MonoDevelop? I tried the following but it doesn't work:
public MainWindow (): base (Gtk.WindowType.Toplevel)
{
Build();
this.HideAll();
this.Visible = false;
}
Solution
Calling HideAll() outside the constructor, as tomlog suggested, works. If you want to do some work before showing the window you can
Add an event handler to Window.Shown before calling Build()
Do the work before calling Build() (probably the better alternative in most cases)
I don't think you can call HideAll in the constructor, because the form is not fully initialized and therefore not visible yet.