Which event when HERE map is fully rendered? - here-api

How to be notified when all graphics are fully rendered on HERE maps, for instance when huge amount of icons are to be displayed ?

It is fairly straightforward to check when the map is rendered - there is a "render" event (https://developer.here.com/documentation/maps/topics_api/h-map-render-renderengine.html#h-map-render-renderengine__render-event) on the RenderEngine.
When target of the even is RenderEngine itself it means that the map was rendered. For example:
map.getEngine().addEventListener('render', (evt) => {
if (map.getEngine() === evt.target) {
console.log('rendered');
}
})

Related

Reacting to changes made outside of Angular2

I've got a non-angular page made with fairly basic JS, and thought it'd be a splendid idea to try and add learn some Angular2 and use it for some new functionality.
My plan was that I'd bind an Angular2 component to an object that is being updated by the old code, and I'd use Angular2 magic to update a chunk of UI.
The problem is I cant convince Angular2 to react to any changes made in the outside JS. What the trick to doing that? Attempts at googling the problem lead to in depth explanations of Angular2's change detection process, which hasn't been helpful so far. Is this just an awful idea?
I found a random Angular2 jsfiddle and hacked it up to show the problem. Strings are added to 'window.names', but you dont see them until one is added from the angular side: https://jsfiddle.net/byfo3jg3/ . The code follows:
var names = ['Joe'];
setTimeout(function() {
names.push("Frank");
}, 1000);
setTimeout(function() {
names.push("Sterve");
}, 2000);
setTimeout(function() {
names.push("Garfield");
}, 3000);
(function() {
var HelloApp,
ListThing;
ListThing = ng
.Component({
selector: 'list-thing',
template: '<ul><li *ng-for="#name of names">{{name}}</li></ul>',
directives: [ng.NgFor]
})
.Class({
constructor: function() {
this.names = window.names;
setTimeout(function() {
this.names.push("Oh hai");
}.bind(this), 10000);
}
});
HelloApp = ng
.Component({
selector: 'hello-app',
template: '<list-thing></list-thing>',
directives: [ListThing]
})
.Class({
constructor: function() {}
});
document.addEventListener('DOMContentLoaded', function() {
ng.bootstrap(HelloApp);
});
}());
You will need to set the NgZone to window object and then call run function of the zone.
Please refer to Angular 2 How to get Angular to detect changes made outside Angular? SO Question
names should be component property to work inside of template:
constructor(){this.names = window.names}
Changes to window.names will not be detected by angular, so you have few options: poll names using setInterval(()=>{this.names = window.names}, 1000) or expose global callback:
constructor(zone:NgZone)
{
window.notify = ()=> {
zone.run(()=> {
this.names = window.names;
});
}
}
and call it from plain js window.notify() or use other methods to invoke change detection.
Is this just an awful idea?
Yes.
Angular's automatic change detection system assumes that changes to data (that you want your components to display) are happening inside an event handler that is monkey-patched by Zone.js. Because then Angular's change detection will execute when such an event handler fires (well, technically, it will execute after the event handler finishes).
If you want a component view to automatically update, you have to change the bound data inside Angular – inside the Angular zone. As #Jigar answered, you can modify your code to call angularZone.run(_ => // make changes here), but if you have to do that, you might as well move the code that manages and manipulates the data into a service (or a component, if the logic is minimal).
See also Günter's alternative approach: set up an event listener inside Angular (hence inside the Angular zone). Then fire that event whenever you make changes outside the Angular zone.

How to check if Accounts UI widget loaded on client?

The default Accounts-UI widget takes a while to load. I want to check on the client when it is ready, so that I can perform some DOM manipulations on it afterwards. I am currently using a timer like so:
Template.sign_in_modal.onRendered(function (){
Tracker.afterFlush(function () {
Meteor.setTimeout(function () {
$('a#login-sign-in-link').click();
$('a#login-name-link').click();
$('a.login-close-text').remove();
}, 100);
});
});
The above hack works locally (probably because it loads faster) but not when I push to saturnapi.com. I just want it to be expanded by default as shown below. Is there a way to ensure the UI widget is fully loaded via a template helper or otherwise make it expanded by default?
I would suggest checking when the <a id="login-sigin-in-link"></a> is added to the DOM. This could be verified by checking $('a#login-sign-in-link').length. If the element is on the DOM do your manipulation.
However if it is not just check again in a few milliseconds. I would suggest using setInterval().
See below for the complete solution:
Template.sign_in_modal.onRendered(function (){
var setIntervalId = Meteor.setInterval(function() {
if($('a#login-sign-in-link').length) {
$('a#login-sign-in-link').click();
$('a.login-close-text').remove();
Meteor.clearInterval(setIntervalId);
}
}, 100);
});
Template.sign_in_modal.onDestroyed(function() {
$('.modal-backdrop.fade.in').remove();
});
Some may think that using loginButtons.onRendered(function(){}); is a good way to verify if the element has been added to the DOM, but it is not. If you try to do the same DOM manipulation in onRendered, it will throw an afterFlush error. The onRendered function has been extremely misleading.

Programmatically (not declaratively) render Meteor template

I'm trying to customize events added to FullCalendar, using eventRender. I'm aware that I can directly return HTML from my eventRender method, but I would prefer to programmatically merge event data with a predefined Meteor template (with associated events).
Previously I could have used Meteor.render() but that functionality is no longer available. I'm familiar with Template.dynamic, but that appear to only be available declaratively, and most of the questions I've seen here are quite old, so refer to deprecated functionality.
Here's what I would like to do:
Calendar - event population & rendering:
Template.dashboard.rendered = function(){
$('#calendar').fullCalendar({
events: function(start, end, timezone, callback) {
callback(Events.find().fetch());
},
eventRender: function(event, element) {
// PROGRAMMATICALLY RENDER TEMPLATE
// The following does not work - no data is attached
return Template.calendarEvent.renderFunction(event);
}
});
};
Event template HTML
<template name="calendarEvent">
{{title}}
<!-- full layout for rendering event here -->
</template>
Event template JS
Template.calendarEvent.events({
// define template event handlers
});
That function was not removed, it was renamed and quite a while ago it also changed behaviour (when spark was replaced by blaze).
What you are looking for is Blaze.renderWithData.
Note that it returns a Blaze.View and not a DOM object.
To make it a dom object you could provide it as a parent:
var renderedCalendarEvent = document.createElement("div");
Blaze.renderWithData(Template.calenderEvent, event, renderedCalendarEvent);
The DOM element renderedCalendarEvent will react to any reactive sources the template uses.
If you need HTML you can use Blaze.toHTMLWithData, but that html will remain static.
Blaze.toHTMLWithData(Template.calenderEvent, event);

Meteor - automatically updating canvas with subscribed data?

I might be missing something, but it seems that Meteor's "magic" revolves around binding data to DOM elements, and updating text and HTML fragments via handlebars: http://docs.meteor.com/#reactivity
This is great, however, when trying to write a meteor app that displays live data in a <canvas> element, I cannot figure out the "meteor way" to update my canvas when the live data changes, since the canvas is populated via JS code like:
var g = canvas.getContext('2d')
g.fillRect(x, y, w, h)
and not data-backed text in the HTML template.
I am trying to draw on the canvas using data from a Meteor.Collection.
My only thought was to embed canvas-drawing JS code in the HTML template in a script tag populated by handlebar vars, but this seems wrong since meteor's events and data-binding code is already client-side JS.
Is there some way listen for live data changes, which triggers drawing on the canvas via JS instead of HTML elements/text?
Please let me know if I can clarify the question in some way
Update:
Tom's answer below made me notice Meteor.deps, which look to allow executing arbitrary code in a reactive context:
http://docs.meteor.com/#on_invalidate
I will try this out and update here if it works.
Perhaps the answer to your question is to use Collection.observe (http://docs.meteor.com/#observe) and trigger the relevant redrawing code in the various callbacks.
For instance, something like:
Rectangles.observe({
added: function(rect) {
var g = canvas.getContext('2d');
g.fillRect(rect.x, rect.y, rect.w, rect.h);
},
// etc
})
This works:
var Shapes = new Meteor.Collection('shapes')
if (Meteor.is_client) {
// Function that redraws the entire canvas from shapes in Meteor.Collection
function drawShapes() {
var shapes = Shapes.find({})
shapes.forEach(function(shape) {
// draw each on canvas
})
}
var startUpdateListener = function() {
// Function called each time 'Shapes' is updated.
var redrawCanvas = function() {
var context = new Meteor.deps.Context()
context.on_invalidate(redrawCanvas) // Ensures this is recalled for each update
context.run(function() {
drawShapes()
})
}
redrawCanvas()
}
Meteor.startup(function() {
startUpdateListener()
})
}
I had some trouble with updating the canvas so I created this simple game demo:
https://github.com/randompast/Meteor-SimpleGame

how to properly bind jquery ui behaviors in meteor?

I am trying to create a group of draggable DOM objects using jQuery UI's .draggable() that are populated through Meteor subscriptions. The code I came up with looks like
Meteor.subscribe('those_absent', function() {
$( "li.ui-draggable" ).draggable( { revert: "invalid" } );
});
Meteor.subscribe('those_present', function() {
$( "li.ui-draggable" ).draggable( { revert: "invalid" } );
});
These correspond with some Meteor.publish() calls, so that any time the collection changes, the .draggable() behaviour will be attached. At least, that was my intention.
However, it only works once - once one of these <li>'s has been dragged and dropped, then they are no longer draggable at all.
When the objects are dropped, I'm firing a custom event that is attached to the Template for the item like so
$( "#c_absent .inner-drop" ).droppable({
drop: function( event, ui ) {
ui.draggable.trigger('inout.leave');
}
});
Template.loftie_detail.events = {
'inout.leave': function (e) {
Lofties.update({_id:this._id}, {$set: {present: 'N' }});
}
};
So, my thinking is that this change to the collection on drop should propagate through the pub/sub process and re-run the .draggable() line above. But it doesn't seem to.
The complete code for this can be seen here https://github.com/sbeam/in-out/blob/master/client/inout.js and the app is live at http://inout.meteor.com/ (there are some other probably unrelated issues with items randomly losing values or disappearing from the UI altogether)
So if my understanding of how pub/sub works in Meteor is off, it would be good to know. Or is there a more efficient way to achieve this UI behavior binding that works without it?
The way I have implemented this in my apps is with the method shown by #lashleigh.
I have a template event that listens using code like this :
Template.myDraggableItem.events({
'mouseover .workItem' : function() {
$(this._id).draggable();
}
});
Then I listen for the dragstop like this.
$('body').on('dragstop', '.myDraggableItem', function (e) {
// Update the collection with the new position
};
You can see the app that's using this code at aduno.meteor.com

Resources