I have a code that is working with a canvas and I'd like to convert it into a layer.
The problem is that I do not want to use the build mechanism of OL3, I just want to use plain javascript.
At the moment, the problem I have is that my handleRender_ function is never called.
Here is my JS code :
ol.layer.MyLayerProperty = {
};
ol.layer.My = function (opt_options) {
var options = opt_options || {};
ol.layer.Layer.call(this, options);
this.on('render', this.handleRender_.bind(this)); //I suspect this is not working
};
ol.inherits(ol.layer.My, ol.layer.Layer);
ol.layer.My.prototype.handleRender_ = function (event) {
console.log('render process'); //never called
};
In fact, to display a canvas "above" openlayers, you simply have to use ImageCanvas.
see http://www.acuriousanimal.com/thebookofopenlayers3/chapter03_04_imagecanvas.html for example
Related
I am developing an app which uses WKWebView to show an html document. I want to inject content from my Swift code to this document. This is what I tried:
var myString: String
// ... Code which assigns some value to myString
targetView.evaluateJavaScript("injector.injectSnippet(\(myString);", completionHandler: nil)
This works exactly as I expect so long as the argument in the JavaScript function call is hardcoded:
targetView.evaluateJavaScript("injector.injectSnippet(\"Hello World\");", completionHandler: nil)
The injector object is in a JavaScript file which I have already added to the web view's user controller:
var injector = (function () {
"use strict"
var msgBox;
var injectSnippet = function (test) {
msgBox.innerHTML = "Received value: " + test;
}
var init = function () {
// Create msgBox div element and insert it into the document
}
return {
init: init,
injectSnippet: injectSnippet
};
} ());
injector.init();
How do I get content into the WKWebView?
I went through the Apple docs WebKit Objective-C Programming Guide and WebKit DOM Programming Topics but I don't understand what sort of WebView class they are using there. Both WKWebView and UIWebView don't have all the API they use in these documents.
Is there some way to manipulate the DOM directly in Swift? I get the sense that WebScriptObject might be what I'm looking for but can I use this with WKWebView?
If you want to continue using evaluateJavaScript, you need to inject the value into the javascript string.
Something like
var jsTemplate = "injector.injectSnippet(\"%#\");"
var js = String(format:jsTemplate , myString)
The earlier solution for programmatic custom element creation in polymer 0.8.5 seems to be broken in polymer 0.9.5.
If we modify the standard click-counter example to use programmatic element creation, like so:
main() {
Logger.root.level = Level.ALL;
Logger.root.onRecord.listen((LogRecord rec) {
print('${rec.loggerName}: ${rec.level.name}: ${rec.time}: ${rec.message}');
});
initPolymer();
var clickCounter = new Element.tag('click-counter');
document.body.children.add(clickCounter);
}
the on-click events are correctly invoking the {{increment}} method, but the {{count}} value is not updated in the HTML.
Polymer code should be run from
import "package:polymer/polymer.dart";
main() {
initPolymer().run(() {
// code here works most of the time
Polymer.onReady.then((value) {
// some things must wait until onReady callback is called
// for an example look at the discussion linked below
});
});
}
simple tooltip working in dartium, not as javascript
I'm trying to write a function on a MovieClip, and call it from the root clip. What works fine in ActionScript 3 doesn't seem to be working properly in ActionScript 2.
Frame 1 of the _root MovieClip:
var newMovieClip:MovieClip = _root.attachMovie('Notification', id, 0);
newMovieClip.SetNotificationText("Test text");
Frame 1 of the Notification MovieClip:
function SetNotificationText(inputText : String){
notificationText.text = inputText;
}
The result is that the MovieClip is created but the text is not changed.
Am I doing this wrong?
To add functions to a MovieClip in AS2, you need to use one of these methods:
Add the method to the prototype of MovieClip:
MovieClip.prototype.SetNotificationText = function(inputText:String):Void
{
if(this["notificationText"] !== undefined)
{
// If we're going to use the prototype, at least do some checks
// to make sure the caller MovieClip has the text field we expect.
this.notificationText.text = inputText;
}
}
newMovieClip.SetNotificationText("Test text");
Make the MovieClip and argument of the function:
function SetNotificationText(mc:MovieClip, inputText:String):Void
{
mc.notificationText.text = inputText;
}
SetNotificationText(newMovieClip, "Test text");
Add the method directly to the newly created MovieClip:
var newMovieClip:MovieClip = _root.attachMovie('Notification', id, 0);
newMovieClip.SetNotificationText(inputText:String):Void
{
notificationText.text = inputText;
}
newMovieClip.SetNotificationText("Test text");
Option 2 is best overall - it's the cleanest and avoids overhead of creating a new function for every new MovieClip. It also avoids messing around with the prototype, which at best should be used to add generic methods, like a removeItem() method on Array.
Iv been trying to pass arguments through an addEventListener event in actionscript such as...
target.addEventListener("pComp", rakeSoil(target));
but i get errors.
Iv tried to google but no luck :/
Thanks for replying if you do :)
The target is already passed as part of the event, either event.currentTarget or event.target will be what you want.
If you want something else passed, create a custom event. Add the property to the custom event.
Try adding an additional method as your event listener:
target.addEventListener ("pComp", targetListener);
...
private function targetListener (event:Event):void {
rakeSoil (event.currentTarget);
}
How this is what you want:
{
var target:EventDispatcher = ...;
Function rakeSoil = function (e:Event):void
{
// handle target
}
target.addEventListener("pComp", rakeSoil);
}
rakeSoil is a first class function(or closure), when event is dispatched, it will be invoked, and you can access 'target' in it.
EDIT:
Have a look at Closure (computer science)
I have always found anonymous functions to be more trouble than they are worth. I would simply follow the standard event handler code layout. It's more formal and takes a little more effort up front, but there is no ambiguity and it is far more readable when you return to it a year from now (reduces head-scratching duration):
// Target extends EventDispatcher
private var target:Target;
public function listenToTarget();
{
target = new Target();
target.addEventListener("pComp", pCompHandler);
}
private function pCompHandler(event:Event):void
{
target.rakeSoil();
}
Although, now that I look at it more closely, why are you having this object do something that Target should be capable of handling internally on its own?
So I have an Application Sandbox HTMLLoader object which I create in AIR and simply want to call ActionScript methods from JavaScript. In Flash, this is accomplished through our trusty ExternalInterface.addCallback() function. However in AIR, things are quite a bit different, and I just can't seem to get it to work.
Here is a simplified overview of my project:
My AIR (ActionScript) main:
public class Main extends Sprite {
public var _as3Var:String = "testing";
public function as3Function():void
{
trace("as3Function called from Javascript");
}
public function Main() {
NativeApplication.nativeApplication.addEventListener(InvokeEvent.INVOKE, onInvoke);
}
protected function onInvoke(e:InvokeEvent):void {
NativeApplication.nativeApplication.removeEventListener(InvokeEvent.INVOKE, onInvoke );
var app = new App();
addChild(app);
app.init(new ExternalContainer(), e.currentDirectory, e.arguments);
}
}
And this is how I create my HTMLLoader object:
{
_html = new HTMLLoader();
_html.useCache = false;
_html.runtimeApplicationDomain = ApplicationDomain.currentDomain;
_html.load(new URLRequest("sandbox/AirRoot.html"));
_html.width = 800;
_html.height = 600;
App.ref.addChild(_html);
}
And at last, here is my snippet of JavaScript in my AirRoot.html file which is trying to call the public method as3Function() declared in my Main class:
Exposed.testAs3 = function()
{
air.trace("Exposed.testAs3 called"); /* This works fine. */
air.trace("runtimeVersion:"); /* This works fine. */
air.trace(air.NativeApplication.nativeApplication.runtimeVersion); /* This works fine. */
air.trace("seeing if I can get to AS3 params..."); /* This works fine. */
/* This doesn't work - get the following error: TypeError: Value undefined does not allow function calls. */
air.NativeApplication.nativeApplication.as3Function();
}
What am I missing?
OK, I am going to answer my own question. I promise this was not a ploy to gain more reputation points, but I was seriously confused today but have now found the appropriate answers and documentation - which is usually the main problem to many an engineer's question...
Anyway, the answer:
The AIR HTMLLoader object contains a magical property, HTMLLoader.window, which is a proxy to the JavaScript window object. So setting HTMLLoader.window = AS3Function; is one way - or in relation to my previously included example (assuming I setup a static property called Main which pointed to the Main class):
_html.window.as3Function = Main.as3Function;
And now in JavaScript I can just call as3Function as:
<script>
window.as3Function();
</script>
Another interesting property is the JavaScript "window.htmlLoader" object. It is a proxy to the AS3 HTMLLoader parent object, in my case, the _html object. From this you can access things in relation to the _html object from JavaScript.
I'm not sure if this is a change in the new version of AIR, but you no longer need to reference the window in the javascript call, you can just do this:
<script>
as3Function();
</script>