Current location in sencha touch - google-maps

I am using the following code to display my current location on Sencha Touch 2. Its showing the correct latitude in console.log() but not showing the map. Please help.
Ext.define('restApp.view.GreetingView', {
extend: 'Ext.Map',
alias: 'widget.mymap',
config: {
fullscreen: true,
//tpl: '<p>The ID is {uuid}</p><p>The content is {display}</p>',
layout: {
type: 'fit'
}
},
initialize:function(){
Ext.Viewport.add({
xtype: 'map',
id:'geomap',
itemId:'ma'
});
var geo = Ext.create('Ext.util.Geolocation', {
autoUpdate: true,
frequency: '10000',
listeners: {
locationupdate: function (geo) {
var center = new google.maps.LatLng(geo.getLatitude(), geo.getLongitude());
Ext.getCmp('geomap').setData(center);
//restApp.view.GreetingView.getComponent('ma').update(center);
var marker = new google.maps.Marker({
position: center,
map: Ext.getCmp('geomap').map
});
console.log('New latitude: '+ geo.getLatitude());
},
locationerror: function (geo, bTimeout, bPermissionDenied, bLocationUnavailable, message) {
if (bTimeout) {
alert('Timeout occurred.');
}
else {
alert('Error occurred.');
}
}
}
});
}
});

OLD ANSWER
Comparing it to a snippet I use for the same purpose (shown below), I realised the issue is a simple one. "center" is a reserved word. Try using a different variable name.
PART OF EDIT: removal of code snippets.
NEW ANSWER
I looked around and noticed your "project" is but a piecemeal collection of demo code.
Here's a complete code solution, with all excess pieces removed for simplicity, as well as over use of variables, also expanded to a longwinded format to be obvious.
/*
The application, including a simple launcher.
*/
Ext.application({
requires : ['Ext.device.Geolocation'],
views : ['MainView'],
controllers : ['Maps'],
name : 'Geo',
launch: function() {
Ext.create('Geo.view.MainView', {fullscreen: true});
}
});
/*
The View to display the map, as well as how to include the navigation bar
and include a "you are here" button.
*/
Ext.define('Geo.view.MainView', {
extend: 'Ext.navigation.View',
alias: 'widget.mainview',
requires: [
'Ext.Panel',
'Ext.Map',
'Ext.navigation.Bar',
'Ext.Button'
],
config: {
items: [
{
xtype : 'panel',
title : 'Map',
itemId : 'mapPanel',
items : [
{
xtype: 'map',
height: '100%',
itemId: 'map'
}
]
}
],
navigationBar: {
docked: 'top',
items: [
{
xtype: 'button',
itemId: 'youAreHereButton',
text: 'You Are Here'
}
]
}
}
});
/*
The Controller with functionality for the "you are here" button tap
*/
Ext.define('Geo.controller.Maps', {
extend: 'Ext.app.Controller',
config: {
refs: {
mapView: {
selector: 'mainview #map',
xtype: 'Ext.Map'
},
mainView: {
selector: 'mainview',
xtype: 'Ext.navigation.View'
}
},
control: {
"mainview #youAreHereButton": {
tap: 'onYouAreHereTap'
}
}
},
onYouAreHereTap: function(button, e, eOpts) {
// set 'mapView' as the parent view displaying the map
var mapView = this.getMapView();
// control measure for old browsers or denied permission for location detection.
if (Ext.feature.has.Geolocation) {
/*
Ext.device.Geolocation uses native (phone) Geolocation capabilities if available,
and falls back to Ext.util.Geolocation if only browser support detected.
*/
Ext.device.Geolocation.getCurrentPosition({
allowHighAccuracy : true,
maximumAge : 0,
timeout : 20000,
success : function(position) {
var latitude = position.coords.latitude,
longitude = position.coords.longitude,
location = new google.maps.LatLng(latitude, longitude),
marker = new google.maps.Marker({
position : location,
map : mapView.getMap(),
animation : google.maps.Animation.DROP
});
mapView.setMapOptions({ // Move to the center
center: location
});
},
failure: function() {
console.log('something went wrong!');
}
});
}
}
});
Yes, I could have simplified it further down to a single view, containing also the controller's handler for the "you are here" tap. I have chosen to present it this way to assist you with understanding the MVC pattern and how it applies in Sencha Touch.
For this to work, it'll require the Sencha Touch library, as well as this following line:
<script src="http://maps.google.com/maps/api/js?sensor=true"></script>
This is the script which includes Google Maps in your page and is essential for displaying.
Learn more:
https://www.sencha.com/learn/hello-world/ - getting started
http://docs.sencha.com/touch/2.3.1/#!/guide - complete documentation for how to do anything in Sencha Touch, starting with the Guides page.

Related

Adding geometries to data layer - how to set feature styles during add?

I'm building a school layer. For each school, I will assign a different icon depending on its properties.
This is my current solution. I first insert all the schools into a data layer, and then run a forEach function to change each point's icon. This is not optimal, because I am adding the schools, then immediately editing the schools.
// Current solution. It is WORKING but it is not optimal
schools = (a list of google.maps.Data.Point objects)
for (school in schools) {
schoolLayer.add({
geometry: school,
});
}
schoolLayer.forEach(function(feature) {
schoolLayer.overrideStyle(feature, {
if (some condition) {
icon: ...
} else {
icon: ...
}
}
}
The optimal solution would be to add styles to the school while it is added, so that no editing is required afterwards. Something like this:
// The solution I am trying to achieve. The `StyleOptions` property is made up to represent what I am trying to achieve. I want to add styles to the school as it is being inserted into the data layer
for (school in schools) {
schoolLayer.add({
geometry: school,
StyleOptions: {
if (some condition) {
icon: ...
} else {
icon: ...
}
}
});
}
The above code does not work. Is there something I'm missing from the documentation that allows me to achieve that?
I would suggest creating a list of google.maps.Data.Feature objects instead of the google.maps.Data.Point objects. Data.Feature can include geometry that is an instance of google.maps.Data.Point in your case, id that can be string or number and properties where you can put name-value pairs.
https://developers.google.com/maps/documentation/javascript/reference/3/data#Data.Feature
The presence of properties in a feature makes a trick. You can apply a styling function for your data layer that reads property of the feature (icon in your case) and returns corresponding style. The styling function will be applied when you add a feature to the data layer.
Have a look at the following code sample, the schoolLayer.setStyle() is the most relevant part
var map;
function initMap() {
var schools = [
new google.maps.Data.Feature({
geometry: new google.maps.Data.Point({lat: 41.384301, lng: 2.173792}),
id: 1,
properties: {
"icon": "http://maps.google.com/mapfiles/kml/paddle/blu-blank.png"
}
}),
new google.maps.Data.Feature({
geometry: new google.maps.Data.Point({lat: 41.384897, lng: 2.176656}),
id: 2,
properties: {
"icon": "http://maps.google.com/mapfiles/kml/paddle/pink-blank.png"
}
}),
new google.maps.Data.Feature({
geometry: new google.maps.Data.Point({lat: 41.386756, lng: 2.175268}),
id: 3,
properties: {
"icon": "https://maps.gstatic.com/mapfiles/place_api/icons/geocode-71.png"
}
})
];
map = new google.maps.Map(document.getElementById('map'), {
zoom: 17,
center: {lat: 41.385064, lng: 2.173403}
});
var schoolLayer = map.data;
schoolLayer.setStyle(function(feature){
return {
icon: feature.getProperty("icon"),
title: "" + feature.getId()
};
});
for (school of schools) {
schoolLayer.add(school);
}
}
#map {
height: 100%;
}
html, body {
height: 100%;
margin: 0;
padding: 0;
}
<div id="map"></div>
<script async defer
src="https://maps.googleapis.com/maps/api/js?key=AIzaSyDztlrk_3CnzGHo7CFvLFqE_2bUKEq1JEU&callback=initMap">
You can also find this example on jsfiddle: https://jsfiddle.net/xomena/tLsjkowp/
I hope this helps!
#xonema - Great answer.
Just adding that I set the properties locally in this manner:
new google.maps.Data.Feature({
geometry: new google.maps.Data.Point(gaugeLatLng),
properties: {
title: gaugeDetail.gaugeId,
icon: {
path: google.maps.SymbolPath.CIRCLE,
scale: 6,
},
}
})

Highcharts with angularjs drilled down does not work

I am developing a drilled down chart using HichartJS, the chart is getting generated but drill down is not functioning properly.
I need the back button as well so that user can go back to the previous data.
Here is my code,
HTML:
<div ng-controller="myctrl">
<highchart id="chart1" config="highchartsNG"></highchart>
</div>
JS:
var myapp = angular.module('myapp', ["highcharts-ng"]);
myapp.controller('myctrl', function ($scope) {
$scope.highchartsNG = {
options: {
chart: {
type: 'column'
}
},
title: {
text: 'Basic drilldown'
},
xAxis: {
type: 'category'
},
legend: {
enabled: false
},
plotOptions: {
series: {
borderWidth: 0,
dataLabels: {
enabled: true,
}
}
},
series: [{"data":[{"name":"Hiring","y":390309.25,"drilldown":"PRIME MOVER"},{"name":"Private","y":406746.97,"drilldown":"PRIME MOVER"}],"name":"series1","color":"","type":"area"}],
drilldown: {
series: [{"id":"Hiring","data":[["MOTOR CAR",97610],["VAN",129750],["THREE WHEELER",62949.25],["PRIME MOVER",100000]]},{"id":"Private","data":[["MOTOR CAR",488356.97],["VAN",129750],["THREE WHEELER",78949.25],["PRIME MOVER",100000]]}]
}
}
});
Here is the Plunker
Update2 I have made changes for your data , The problem was in formatting of json and the second problem was you were not calling proper id in drillDown. Check the fiddle updated Here with your data
Update1 I have made changes and now its working on fiddle Here . I have added changes to highcharts-ng in script tag in html section of fiddle. Also I changed the data, because your data was not formatted for me.
I just realize that drillDown feature isn't supported by highcharts-ng .see the link Highcharts-ng with drilldown
Following edit was done at source code to make it work.
if(config.drilldown) {
mergedOptions.drilldown = config.drilldown;
};

Sencha touch selectfield works fine in chrome, but it fails in android 2.1 emulator and Android 2.2 phone

I am learning Sencha Touch. I am having a strange issue. A view using select field is not showing it on Android emulator, but it does in Google Chrome. It worked fine before, I cannot guess what changed to "break" it.
In the emulator logcat I can see these three messages:
E/ActivityThread(243): Failed to find provider info for android.server.checkin
W/Checkin(243): Can't update stat BROWSER_SNAP_CENTER: java.lang.IllegalArgumentException: Unknown URL content://android.server.checkin/stats
D/CordovaLog(243): undefined: Line 1 : TypeError: Result of expression 'c' [null] is not a constructor.
Sometimes only the third is shown.
Hereafter the view code:
(function() {
var setSettingValue = function(component, query, value) {
var c = component.query(query);
if (c && value && (c.length > 0)) {
c[0].setValue(value);
}
};
var createToolbar = function () {
return Ext.create('Ext.Toolbar', {
xtype: 'toolbar',
docked: 'bottom',
layout: { pack: 'center' },
items: [
{
iconMask: true, ui: 'normal', iconCls: 'info',
itemId: 'infoButton'
},
{ xtype: 'spacer' },
{
iconMask: true, ui: 'normal', iconCls: 'reply',
itemId: 'backButton'
}
]
})};
Ext.define('MyWF.view.Settings', {
extend: 'Ext.Container',
initialize: function ()
{
this.setItems([createToolbar()]);
this.callParent();
},
config : {
layout : 'vbox',
padding : '0 10',
scrollable: {
direction: 'vertical'
},
onBackAction: function () { console.log('back'); },
onInfoAction: function () { console.log('info'); },
listeners: [{
delegate: "#backButton",
event: 'tap',
fn: 'onBackAction'
},
{
delegate: "#infoButton",
event: 'tap',
fn: 'onInfoAction'
},
{
event: 'show',
fn: function(component, eOpts) {
setSettingValue(component, 'selectfield[name=windMU]','kmh');
setSettingValue(component,'selectfield[name=temperatureMU]','C');
}
}],
items : [{
xtype : 'fieldset',
title : 'Measure units',
items : [{
xtype : 'selectfield',
name : 'temperatureMU',
label : 'Temperature',
labelAlign: 'top',
listeners : {
change : function(selectField, newData, oldData, eOpts) {
alert('Your choice is: ' + newData);
}
},
options : [{
text : 'Celsius',
value : 'C'
}, {
text : 'Farenheit',
value : 'F'
},]
}, {
xtype : 'selectfield',
name : 'windMU',
label : 'Wind speed',
labelAlign : 'top',
listeners : {
change : function(selectField, newData, oldData, eOpts) {
alert('Your choice is: ' + newData);
}
},
options : [{
text : 'Kilometers per hour',
value : 'km/h'
}, {
text : 'Meters per second',
value : 'm/s'
}, {
text : 'Miles per hour',
value : 'MPH'
}, {
text : 'Knots',
value : 'kn'
}]
}]
},]
}
});
})();
Thanks for any suggestion
Well I got some time to fix the issue.
First of all I add a lacking information to the question: I was running the app with a custom build of the Sencha Touch library, the library version is 2.0.1.1.
On Google Chrome the select field (Ext.field.Select) creates by default an Ext.dataview.List instance for the list of choiches, while on a phone an Ext.picker.Picker is created.
But Ext.picker.Picker also creates an Ext.TitleBar, that was lacking in my custom build of sencha library, while the Ext.dataview.List class is in.
So the application can show the select field in Chrome, but it cannot in the emulator, and it gives the unclear message, because the libary build is compressed and obfuscated.
There are two solutions:
you can force the use of a list also in the emulator or phone. The class Ext.picker.Picker has a creation option for this: "usePicker: false", by default set to "auto".
or, better, add an explicit reference to the title bar component in the app file: "Ext.require('Ext.TitleBar');" to include it in the library build.
I saw the problem forcing the use of the picker in Chrome, by setting the picker configuration "usePicker: true", and running the app with the debug library build "sencha-touch-debug.js", see http://docs.sencha.com/touch/2-0/#!/api/Ext.Loader, and http://docs.sencha.com/touch/2-0/#!/guide/building .
Then in the Chrome console, as well in the Android emulator logcat, I saw the clear message:
[WARN][Anonymous] [Ext.Loader] Synchronously loading 'Ext.TitleBar';
consider adding 'Ext.TitleBar' explicitly as a require of the corresponding class
A suggestion: in the logcat is better to filter the many messages, for example writing "Ext.Loader" in the filter mask.

Sencha Touch not firing beforeshow event listener

Im new to sencha touch and going through the obligatory hair pulling and head2desk pounding.
Im trying to display a List but Im having a problem.
Im using a beforeshow event to load my json store before the list is displayed. But it's not firing the event. If any can help it is MOST appreciated.
My code is as follows: *note- this code is AS/400 centric so the /%...%/ is for that
function doList() {
var List1 = new Ext.List ({
id : List1,
renderTo : 'panel',
fullscreen: true,
showAnimation: {
type: 'slide',
duration: 250
},
cls: 'demo-list',
width: Ext.is.Phone ? undefined : 300,
height: 500,
store: ListStore,
itemTpl: '<strong>{SCEQPT}</strong>',
grouped: true,
indexBar: true,
onItemDisclosure: function(record, btn, index) {
doPopUp(record);
},
listeners: {
'beforeshow': function () {
alert('beforeshow');
var StoreList = Ext.StoreMgr.get('ListStore'
StoreList.load({
params: {
screfr: Ext.getCmp('SCREFR').getValue(),
scptyp: scptyp,
user : '/%SCUSER%/'
}
});
}
}
});
}
beforeshow listener is triggered only when you are displaying an item with show() method.
Try using the listeners
'render','beforerender' and 'afterrender'. instead.

Sencha Touch - Add Markers to Map after Maprender

I want to load markers to my map, in sencha touch, after I load some json data from ajax request. The thing is I don't know how to achieve this after the maprender event is fired.
I've got this:
my map view:
app.views.MapTab = Ext.extend(Ext.Panel, {
iconCls: 'map',
id: 'map',
items: [{
xtype: 'map',
id: 'mapa',
mapOptions : {
center : new google.maps.LatLng(50.077721, 14.448585),
zoom : 12,
mapTypeId : google.maps.MapTypeId.ROADMAP,
navigationControl: true,
navigationControlOptions: {
style: google.maps.NavigationControlStyle.DEFAULT
}
},
listeners : {
'maprender' : function(comp, map){
Ext.dispatch({
controller: app.controllers.map,
action: 'map_rendered',
map: map
});
}
}
}],
initComponent: function() {
app.views.MapTab.superclass.initComponent.apply(this, arguments);
}
});
store to load json:
app.stores.results = new Ext.data.Store({
model: "app.models.Results",
proxy: {
type: 'ajax',
url: 'http://app.cz/json_list2.php?a=l&zp=1&u=vinohrady-praha&c0=500000&c1=6000000&p0=10&p1=120&cm20=1000&cm21=120000&pg=0&s=Datumu&t=byt&age=30&pod=0&lat=50.075401&lng=14.458344&pp=prodej&tp0=0&tp1=12',
reader: {
type: 'json',
root: 'markers'
}
},
listeners: {
'load': function (t, r, s) {
Ext.dispatch({
controller: app.controllers.map,
action: 'loaded',
records: r
});
}
}
});
controller
app.controllers.map = new Ext.Controller({
loaded: function(options) {
for(var i = 0; i < options.records.length; i++){
var marker = new google.maps.Marker({
position: new google.maps.LatLng(options.records[i].get('lat'), options.records[i].get('lng')),
map: app.views.mapTab.getComponent('mapa')
});
}
// need to rerender/refresh the map here
},
map_rendered: function(options) {
console.log("map rendered");
}
});
Your code should work but you are attaching the markers to the Sencha Touch Map component rather than the underlying Google Maps map, which can be accessed with the 'map' property.
...
var marker = new google.maps.Marker({
position: new google.maps.LatLng(options.records[i].get('lat'), options.records[i].get('lng')),
**map: app.views.mapTab.getComponent('mapa').map**
});
...
The map shouldn't need manually re-rendered and should just add them in when you bind them with the map config.