Identifying if a map moveend event was user initiated - openlayers-3

I registered a 'moveend' event listener on my ol.Map. It's firing when the map is moved around by user input, but also when I call ol.View.setCenter and ol.View.setResolution.
Is it possible to check the 'moveend' ol.MapEvent to determine if the event was triggered by user input or from manually changing the map view's properties?

I ended up doing the following.
map.on('moveend', function(event) {
var mapView = map.getView(),
moveInitiatedProgrammatically = mapView.get('moveInitiatedProgrammatically') || false;
mapView.unset('moveInitiatedProgrammatically');
// evaluate moveInitiatedProgrammatically's value and behave accordingly...
});
map.getView().set('moveInitiatedProgrammatically', true);
map.getView().setCenter(coord);
It's not ideal for the following reasons:
Introduces additional state information in the map's view.
Carelessly replacing the map view will lose that state information.
Requires setting a property before changing the view state and may be too easily forgotten.
However, it adresses my issue in the meantime.

Related

Open Layers 3: How to create listener for a modify interaction

I have managed to set up a modify interaction.
The docs for ol.interaction.Modify (http://ol3js.org/en/master/apidoc/ol.interaction.Modify.html) don't metion a single event that is fired when a feature is modified.
Unlike for instance for ol.interaction.Draw (http://ol3js.org/en/master/apidoc/ol.interaction.Draw.html) which works nicely.
I need to update the coordinates in the database when a feature has been modified.
How can I set up a listener?
I found a solution.
The high-level-explanation is here: http://boundlessgeo.com/2014/06/openlayers-editing-wfs-t/
Basically you don't listen to changes in the modify-interaction (like you do in the draw-interaction). Instead, you listen to changes in the selected features themselves.
Here's a short extract:
// get the features from the select interaction
var selected_features = select_interaction.getFeatures();
// when a feature is selected...
selected_features.on('add', function(event) {
// get the feature
var feature = event.element;
// ...listen for changes on it
feature.on('change', function(event) {
// got it!
});
});
Here is a complete working example: http://codepen.io/barbalex/pen/fBpyb
for this, you have to use like following :
feature.once('change', function(bool) {if (bool) {document.getElementById('my_input_text').value='feature changed'}})
you have to use 'once' instead of 'on' to avoid multiple check and use boolean variable to check if feature is changed or not.
Hope this help

How do you return a Future based off a Stream you don't control in Dart?

I have a situation where I'm expecting a single value from a Stream, but because it's one provided by the browser I can't rely on simply calling streamSub.single. Currently, I'm creating an explicit StreamController so that I can easily generate a Future from it while guaranteeing that it will only get a single response. However, that ends up being a lot more overhead than I was expecting to have to set up, making me think I'm missing something. The current code follows:
StreamController<String> streamCtrlr = new StreamController<String>();
var popup = window.open(targetUrl, "Auth Window");
//The popup above will call window.opener.postMessage, so listen for messages
StreamSubscription sub = window.onMessage.listen(null);
sub.onData((Event){
/* Logic goes here */
sub.cancel();
popup.close();
streamCtrlr.add(Event.data);
streamCtrlr.close();
});
return streamCtrlr.stream.single;
How can this be re-written so that the intermediary StreamController isn't required?
Why can't you rely on calling streamSub.single? Is it because there might be more than one message?
Your example code picks the first event in all cases, so to get the same behavior, you can use window.onMessage.first instead of window.onMessage.single.
It will still cause an error if there is no first event (but I don't think that can happen with DOM event handlers - they never send a done event), and otherwise it will give a future that is completed with the first event.
You also want to extract the event data, so you will probably want:
return window.onMessage.first.then((event) {
/* Logic goes here */
popup.close();
return event.data;
});

How to register map move / map pan events in OpenLayers 3

I'm looking for OpenLayer 3 map event for map move/map pan, something like:
map.on('move', function(){
...
}
Does anyone know how to implement?
The moveend event might be the one you search for - it detects any move made, even those not invoked by dragging.
map.on('moveend', function (e) {
console.log("moved");
});
See http://openlayers.org/en/latest/apidoc/module-ol_Map-Map.html
UPDATE:
These events are no longer present in recent versions. Please refer to the more recent answer for an up-to-date information.
Names of the events you're looking for are drag and/or dragend (it's probably a better idea to depend on properties names, though: ol.MapBrowserEvent.EventType.DRAG but it didn't work on the demo page):
map.on('drag', function() {
console.log('Dragging...');
});
map.on('dragend', function() {
console.log('Dragging ended.');
});
Reverse-engineered by looking inside mapbrowserevent.js, the documentation explicitly mentions events are not documented yet.
MoveEnd trigger if u move the map with a script.
I have use that in OpenLayers 6:
map.on('pointerdrag', function (event) {
is_map_center = false;
})
hf gl!
I believe this functionality exists in 2 functions within the View of a map, not the map itself. You can monitor the center property of the View by listening for change:center events. There is also a getInteracting() method in ol.View that will return a boolean if an interaction (zooming or panning) is occurring.
https://openlayers.org/en/v4.6.5/apidoc/ol.View.html#getInteracting

Dart web-ui not updated when data received from network

I have the following fragment in a web component:
<div id="mycodes">
<template iterate='code in codeList'>
{{code}}
</template>
</div>
And in a Dart file, codeList is populated when the user clicks on a button:
void onMyButtonClick(Event event) {
HttpRequest.getString('http://getData').then((response) {
mylist = json.parse(response);
for(var code in mylist){
codeList.add(code['c']);
}
}
The problem is that I don't see data on first click. I need to click the button twice to see data.
But if I fill codeList manually (not from network data) as shown below, then I see the data on first click:
void onMyButtonClick(Event event) {
codeList.add("data 1");
codeList.add("data 2");
}
}
I need the template to iterate after the network data is available. It appears that event loop has already done its job of painting a page before the network data becomes available through future object.
Is there a way to refresh the page after model is updated in dart?
The reason your codeList currently populates if you add it with the on-click event is because the current web_ui has 'watchers' which automatically are called when an event happens. You then populate the list synchronously. However one of the downfalls of watchers is exactly your use case, when the data is updated asynchronously then the watchers don't reflect changes in time.
As a result the watchers are being phased out and replaced with observables. Observables allow us to flag a variable to be watched for reassignment and when that happens it will cause the view to change. For example:
#observable int x = 0;
// ...
x = 1;
When the x = 1 is called later in the code it automatically triggers the views to update. This leaves us with one problem however. When you are adding to a list, you are not reassigning the value itself. As such, observables also offer a function to convert a list to an observable list (this also works for maps).
For instance if you changed your declaration of codeList to something like the following, then when you add to the list later it will update accordingly.
var codeList = toObservable([]); // Assuming it starts with an empty list
// or
var codeList = toObservable(_startCodeList); // if you already have a list
Also see the Dart Tutorial: Target 7 for more information on using #observable and toObservable.
For more in-depth information, check out the article on Observables and Data Binding
You need to mark the fields you want WebUi to monitor with the #observable annotation. Otherwise you only get the initial value not any subsequent updates.
You can do this either directly on the object declaration or you can make the entire class as observable and all its fields will then be observed.
For an example see http://www.dartlang.org/docs/tutorials/custom-elements/#using-two-way-data-binding

Why isn't the keydown event firing?

I'm trying to attach an event handler to the keyDown event in a canvas element. Here is a simplified version of my code.
class CanvasFun{
CanvasElement canvas;
CanvasFun(this.canvas){
print("Game is loading!");
this.canvas.onKeyDown.listen(handleInput);
}
void handleInput(e)
{
//breakpoint is never hit
print(e.keyCode);
}
}
I've removed some of the drawing code. In my main function I simply query the canvas element and pass it to my CanvasFun constructor.
I've also tried doing it this way:
void main() {
var canvas = query("#Game");
canvas.onKeyDown.listen(handleInput);
var canvasFun = new CanvasFun(canvas);
}
void handleInput(e)
{
print(e.keyCode);
}
The reason why the event is not firing is because the focus is on the document (or some other element like an input, for example). And in fact, canvas element even when focused does not fire an event. Some elements do, like input elements.
The solution is to listen to key down events from the document or window:
window.onKeyDown.listen(handleInput);
document.onKeyDown.listen(handleInput); // You already noticed this worked.
John McCutchan has written a nice Dart package to help handle keyboard input. You can read more about it here: http://dartgamedevs.org/blog/2012/12/11/keyboard-input/
Note that this library helps you handle input "correctly". You do not want to do any "work" in the input handling, instead you simply want to register that a key was pressed. You can check the state of any key presses inside of your requestAnimationFrame callback.
Hope that helps!
There exists a workaround to get the canvas-element accept KeyboardEvents:
Problems handling KeyboardEvents on DartFlash
Once you add the tabindex-attribute to your canvas-element, it can get the focus and then it will receive KeyboardEvents.
It looks like I can get it to work if I register the event on the document rather than the canvas element.
document.onKeyDown.listen(handleInput);

Resources