Refresh ol.layer.heatmap KML every 2 Seconds and Update Layer - setinterval

I use OpenLayers Heatmap and I want to refresh the KML Vector every 2 seconds. So I thought it would be possible just to delete the Layer, refresh the Layer and then add the Layer in the map again. But nothing worked so far.
Here is my script:
var vector = new ol.layer.Heatmap({
source: new ol.source.Vector({
url: 'tweets.php',
format: new ol.format.KML({
extractStyles: false
})
}),
blur: parseInt(6, 10),
radius: parseInt(4, 10)
});
var raster = new ol.layer.Tile({
source: new ol.source.Stamen({
minZoom: 3,
maxZoom: 8,
layer: 'toner'
})
});
var koordinate = 5.9;
var map = new ol.Map({
target: 'map',
controls: [] ,
interactions: ol.interaction.defaults({
dragging: false,
dragPan: false
}),
view: new ol.View({
center: ol.proj.transform([10.5 , 51.0], 'EPSG:4326', 'EPSG:3857'),
minZoom: koordinate,
maxZoom: koordinate,
zoom: koordinate
})
});
map.addLayer(raster);
map.addLayer(vector);
blur.addEventListener('input', function() {
vector.setBlur(parseInt(blur.value, 10));
});
radius.addEventListener('input', function() {
vector.setRadius(parseInt(radius.value, 10));
});
Edit: This was my best solution for the problem but i don't worked.
setInterval(function() {
vector.loaded = false;
vector.setVisibility(true);
vector.redraw({ force: true });
}, 2000);
I've also tried everything with SetInterval, but everytime it was not correct or it was wrong.
I think the ol.layer.heatmap makes it difficult to solve the problem.

ol.layer.Heatmap doesn't provide a "redraw" method.
ol.Map does offer a render method though, which you should be using. consider the Dynamic data example for more insight: http://openlayers.org/en/v3.5.0/examples/dynamic-data.html

Related

Ext JS: TabPanel rendering Infinite Grid too quickly

Let's say I have a TabPanel that gets two components added to it. Each component contains an Infinite Grid. Each Infinite Grid loads its data from a service call, and each set of data contains 2,000 records. After the components are added to the TabPanel, we set each one to be the active tab, using setActiveTab. We first set the 2nd tab as the active tab and then set the first tab. When the page loads, the first tab is selected, as we expected.
When looking at the first tab, everything looks fine... we can infinitely scroll, sort, hide columns, etc. However, if we switch to the second tab, we see that it has partially loaded, and we can't scroll past the x records that have loaded, hide columns, sort, etc. It's almost as if using setActiveTab was a bit premature with rendering the grid... as if the store wasn't completely loaded, but the tab was rendered anyway. (this is what I'm assuming the issue is)
I do have code, but it takes a little work on your end to reproduce (because you need a service call). I'm using CompoundJS within a Node.js application, so it was very easy for me to create the test case. If you have access to a database, and can make a quick service call, just modify my Ext JS code, but if you want to use Node.js, you can try this:
Ext JS 4.2.1
Ext.onReady(function() {
var tabPanel = Ext.create('Ext.tab.Panel', {
width: 400,
height: 400,
renderTo: Ext.getBody()
});
Ext.define('myGrid', {
extend: 'Ext.grid.Panel',
constructor: function(config) {
this.columns = config.columns;
this.store = Ext.create('Ext.data.Store', {
fields: config.fields,
buffered: true,
leadingBufferZone: 20,
pageSize: 50,
proxy: {
type: 'ajax',
url: '/getData?id=' + config.id,
reader: {
totalProperty: 'totalCount',
type: 'json',
root: 'root'
}
},
autoLoad: true
});
this.id = config.id;
this.callParent();
}
});
var grid1 = Ext.create('myGrid', {
id: 'blah',
columns: [{
text: 'one',
dataIndex: 'one'
}, {
text: 'two',
dataIndex: 'two'
}, {
text: 'three',
dataIndex: 'three'
}],
fields: ['one', 'two', 'three'],
title: 'grid1'
});
var grid2 = Ext.create('myGrid', {
id: 'bleh',
columns: [{
text: 'one',
dataIndex: 'one'
}, {
text: 'two',
dataIndex: 'two'
}, {
text: 'three',
dataIndex: 'three'
}],
fields: ['one', 'two', 'three'],
title: 'grid2'
});
var c1 = [];
c1.items = [grid1];
c1.title = "BLAH";
c1.layout = 'fit';
var c2 = [];
c2.items = [grid2];
c2.title = "BLEH";
c2.layout = "fit";
tabPanel.add([c1, c2]);
tabPanel.setActiveTab(1);
tabPanel.setActiveTab(0);
});
Node.js code
compound init test && cd test
npm install
compound g s testcontroller
Replace app/controllers/testcontrollers_controller.js with:
load('application');
action('getData', function(data) {
var query = data.req.query;
var id = query.id;
var page = query.page;
var pushObj;
if (id === 'blah') {
pushObj = {
one: 'bye',
two: 'goodbye',
three: 'auf wiedersehen'
};
}
else {
pushObj = {
one: 'hi',
two: 'hello',
three: 'guten tag'
};
}
var obj = [];
for (var i = 0; i < 50; i++) {
obj.push(pushObj);
}
send({
totalCount: 2000,
root: obj,
page: page
});
});
In config/routes.js, remove testcontroller's map.resources line, and add this:
map.get('getData', 'testcontrollers#getData');
In public/index.html, make it a generic HTML file, and add in your links to Ext JS and my above Ext JS code.
Now, once you've done all of that, you should be able to reproduce my issue. The first tab will open and be just fine, but the second tab only loads the first x amount of records and doesn't function properly. I believe this is due to the store not loading completely when setActiveTab is fired, which makes the rendering load an impartial store.
What I want to know is, how do I get this to work properly? I've tried waiting for the store to load, and then adding it to the tab, but that still gives me inconsistent results, as well as tried waiting for the grid to stop rendering, but still, I get inconsistent results... inconsistent meaning, sometimes the grid loads all the way, and the tab is fine, but other times, I get a cannot read property 'length' of undefined in ext-all-dev.js:135,786... which makes it seem like the store hasn't completely loaded, as that line contains a reference to records.length.
If anyone has any ideas, I'd love to hear them! Cross-posted from the Sencha forums.
EDIT: Thanks to #rixo, I was able to reproduce the problem in this example. If you enable Firebug, you'll see the error about property length of undefined, as I stated above.
I tracked the issue down to the plugin caching incorrect size values when it is hidden.
Here's an override that would fix this behavior:
/**
* Prevents BufferedRenderer plugin to break when buffered views are
* rendered or refreshed while hidden, like in a card layout.
*
* Tested with Ext 4.2.1
*/
Ext.define('Ext.ux.Ext.grid.plugin.BufferedRenderer.HiddenRenderingSupport', {
override: 'Ext.grid.plugin.BufferedRenderer'
/**
* Refreshes the view and row size caches if they have a value of 0
* (meaning they have probably been cached when the view was not visible).
*/
,onViewResize: function() {
if (this.rowHeight === 0) {
if (this.view.body.getHeight() > 0) {
this.view.refresh();
}
} else {
this.callParent(arguments);
}
}
});
That being said, I advice against using this and unnecessarily bloating your code base.
You should rather organise your code in a way that avoid this situation. The problem is created by the fact that you're calling setActiveTab multiple time in the same execution frame. If you avoid that, Ext will handle the situation correctly all by itself.
As a general principle, you should try to make your Ext code more declarative... Ext architecture rather expects you to build big configuration objects to create your component at once (allowing for atomic DOM updates, etc.), and use methods that will update the state only later, to drive the components behaviour.
In your precise case, you should use the activeTab option to set the initial tab, and only call setActiveTab later, when you actually need to change the tab. That will save some unnecessary processing at initialization, and will also resolve your rendering issue...
Here's how your code should look like:
Ext.create('Ext.tab.Panel', {
renderTo: Ext.getBody(),
width: 400,
height: 400,
// Use this option to set the initial tab.
activeTab: 2,
// You don't need to overnest your grids into another Panel, you can add
// them directly as children of the tab panel.
items: [
// Ideally, you should give an xtype to your class, and add this to
// avoid instantiating the object yourself... Thus giving Ext more
// control on the rendering process, etc.
Ext.create('myGrid', {
id: 'blah',
title: 'Bleh',
columns: [{
text: 'one',
dataIndex: 'one'
}, {
text: 'two',
dataIndex: 'two'
}, {
text: 'three',
dataIndex: 'three'
}],
fields: ['one', 'two', 'three'],
title: 'grid1'
}),
Ext.create('myGrid', {
id: 'bleh',
title: 'Bleh',
columns: [{
text: 'one',
dataIndex: 'one'
}, {
text: 'two',
dataIndex: 'two'
}, {
text: 'three',
dataIndex: 'three'
}],
fields: ['one', 'two', 'three'],
title: 'grid2'
})
]
});
As you can see, the tab panel child items are set at creation time, avoiding useless processing with the add method. Likewise, the activeTab option avoid to initialize the panel in a given state and change it right away... Later (in another execution frame, for example in a button handler), you can use setActiveTab without triggering the bug demonstrated in your original example.

How can I add markers to Google Maps using Node.js/Express/MongoDB?

I decided this week that I'd like to learn Node.js (I'm not a programmer). I've been having a lot of fun with it so far but I'm stuck at the moment.
I've created a basic app using Express. Let's say I have a route /locations. I set my get request to render the related view and to find (using Mongoose's .find method) all docs in my location model. I know I can pass the docs to the view like this:
app.get('/locations', function(req, res) {
Location.find({}, function(err, docs) {
res.render('locations/index', {
title: 'Locations',
user: req.user,
docs: docs
});
});
});
I can then, for example, access the results in the (Jade) view and list them by doing something like:
if(docs.length)
each location in docs
p #{location.name} is at #{location.coordinates}
I want to add all these locations (using coordinates stored with each 'location') to a Google Map. I have an example map displaying on the view using the following script in the head, taken from the Google Maps API documentation.
function initialize() {
var myLatlng = new google.maps.LatLng(-25.363882,131.044922);
var mapOptions = {
zoom: 4,
center: myLatlng,
mapTypeId: google.maps.MapTypeId.ROADMAP,
}
var map = new google.maps.Map(document.getElementById("map-canvas"), mapOptions);
var marker = new google.maps.Marker({
position: myLatlng,
title: "Hello World!"
});
marker.setMap(map);
}
google.maps.event.addDomListener(window, 'load', initialize);
I figured where the marker variable is created then set I could loop through my 'docs' and create and set a marker for each location stored in my database. That said, I'm too new to this and I can't seem to figure out how to do it as the script in the head can't access the 'docs' that I've passed to the view.
Any advice? Thanks in advance, it's much appreciated.
I JSON.stringify() any objects that my client scripts need and insert it as HTML5 data-whatever attributes.
For example:
//app.js
app.get('/map', function(req, res){
var data = {
id: '1234',
LL: {
lat: 42.1,
lng: 80.8,
};
res.locals.docsJSON = JSON.stringify([data]);
res.render('locations/index');
});
//jade
!!!
html
body(data-locations=locals.docsJSON)
script
var docs = JSON.parse($('body').attr('data-locations'));
console.log(docs[0].LL);

Extjs Grid - Click next page button with search condition

I have a gridpanel and i create store in initComponet function like
,initComponent: function() {
var store = Ext.create('Ext.data.Store', {
model: 'MyObject',
autoLoad: false,
pageSize:22,
remoteSort:true,
proxy: {
type: 'ajax',
url: 'example.php',
reader: {
type: 'json',
totalProperty: 'total',
root: 'results'
}
}
});
this.store = store;
this.dockedItems = [{
xtype: 'pagingtoolbar',
store: this.store,
displayMsg: '{0} - {1} / {2}',
emptyMsg: 'empty',
dock: 'bottom',
displayInfo: true,
pageSize: 22
}];
this.callParent(arguments);
this.store.load({params:{start:0, limit:22}});
}
I make a form search with some value and when i press search button i will do below code
grid.store.load({
params:{
start:0,
limit:22,
signalSearch: 1,
search1: myValue1,
search2: myValue2,
}
});
In my php file will catch that to know that's search
if ( have $_REQUEST["signalSearch"]) {
// print json with condition search
}else {
// print json with all data
}
And results return with 2 page (it well). But when i press Next page button to see some results on page 2 But my store load fail (i think they call store.load({params:{start:0, limit:22}}); when i press next page button and in my php file that will run with else case).
That's not call
grid.store.load({
params:{
start:0,
limit:22,
search1: myValue1,
search2: myValue2,
}
});
My idea to make search is not good? How can i fix that thank
If you use params in the "load" function of the store, those are referred to the single request only so if you click next page of the toolbar you won't post the signalSearch param.
You should register a custom listener on the before load event and add your params:
initComponent: function(){
....
this.callParent(arguments);
this.store.addListener('beforeload', function(store, operation){
Ext.apply(operation.params, {
signalSearch: 1 // Or you could make conditions if apply this search param
});
return true;
}, this);
}

extjs4 MVC Scope Issue

I am trying to call resetCombo method once i click on link from tooltip which is rendered on combo
But i am not able to access it because of scope issue not sure what i am missing. Please help me on this.
Ext.define('test.BasicForm', {
extend: 'Ext.form.Panel',
renderTo:Ext.getBody(),
initComponent :function(){
this.items=[
{
fieldLabel: 'Test',
xtype: 'combo',
displayField: 'name',
width: 320,
labelWidth: 130,
store: [
[1, 'Value 1'],
[2, 'Value 2'],
[3, 'Value 3'],
[4, 'Value 4']
],
listeners:{
afterrender: function(combo) {
Ext.create('Ext.tip.ToolTip', {
target: combo.getEl(),
autoHide: false,
name:'tool-tip',
scope:this,
html: 'Old value was '+ combo.getValue()+ ' test',
listeners: {
beforeshow: function() {
return combo.isDirty();
}
}
});
}
},
value:'1'
}];
this.callParent(arguments);
},
resetCombo:function(){
alert('called');
}
});
First this has nothing to do with ExtJS4's MVC features which are generally associated with a controller's control method:
http://docs.sencha.com/ext-js/4-1/#!/api/Ext.app.Controller-method-control
Second, you may be able to instead get the effect you want by switching to the following, fully qualified path to reset combo:
onclick="javascript:test.BasicForm.resetCombo();" //etcetera
Lastly, though you may get the above to work, it is far from best practice. I don't have time to give the complete answer, but essentially what you want to do consists of:
Adding a click event handler to the tooltip's underlying Element
Then inside the element use the arguments to Ext.dom.Element.click (see http://docs.sencha.com/ext-js/4-1/#!/api/Ext.dom.Element-event-click) to ensure it was an <A> tag that got clicked
Then invoke the desired function without having to use Javascript pseudo-URL's and a fully qualified path to the function
Here is my working re-write of the afterrender listener following the above guidelines, with some tweaks to scope, in particular storing a reference to the form in a variable of the same name.
listeners:{
afterrender: function(combo) {
var form = this;
var tooltip = Ext.create('Ext.tip.ToolTip', {
target: combo.getEl(),
autoHide: false,
name:'tool-tip',
html: 'Old value was '+ combo.getValue()+ ' <a class="tooltipHref" href="#">test</a>',
listeners: {
beforeshow: function() {
return combo.isDirty();
},
afterrender: function() {
tooltip.el.on('click', function(event, element) {
if (element.className == 'tooltipHref') {
form.resetCombo();
}
});
}
}
});
},
scope: this
}
test
this code is attempting to call a function named resetCombo which is stored inside the top-level object (the window object).

Ext Js : add nested panels dynamically

I have several records of the same type that I want to show on the screen. I thought about creating several panels that will print the data of each record. I chose this solution because data structure is too complex to be printed in a simple grid. Here is a simplified example of that structure :
{
label: 'myLabel',
{
attr1: 'value1',
attr2: 'value2'
}
startValidityDate: oneDay,
endValidityDate: anotherDay
}
I try to add dynamically nested panels in my current panel :
var myStore = new Ext.data.Store({
id: 'myStore',
restful: true,
idProperty: 'OID',
root: 'tbas',
proxy: myProxy,
reader: myReader,
autoLoad: false,
listeners: {
'load': function(data){
var records = data.getRange();
var currStore = null;
for(var i=0; i<records.length; i++) {
currStore = new Ext.Panel({
layout:'vBox',
items: [{
xtype: 'textfield',
fieldLabel: I18nManager.get('label_ttbaUI_label'),
name: 'tbaLabel',
value: records[i].data.tbaLabel
},{
xtype: 'textfield',
fieldLabel: I18nManager.get('label_ttbaUI_label'),
name: 'tbaOid',
value: records[i].data.tbaoid
}]
});
recordList.add(currStore);
console.log("------------------------------");
console.log(currStore);
}
recordList.doLayout();
}
}
});
var recordList = new Ext.Panel({
id: 'recordList',
renderTo: 'recordPart',
layout:'vBox',
title: I18nManager.get('label_ttbaUI_selected_tariffs')
});
recordList.doLayout();
In the firebug console, the UI objects seems to be ok.
My problem is that the recordList elements are not visible
I can see that they exist in the FB console, but they are not well printed on the screen.
Did I forgot something that make the elements hidden ? or bad printed ?
I'm sure that it is a CSS problem, some trouble with ext-all.css : when I remove the content of that CSS, I can see my fields
There must be something wrong in the way I wrote the code so that it causes the render problem WDYT ???

Resources