Nokia OVI map autocomplete feature - javascript

I am using google API to autocomplete feature of user address. and its working fine.
But now I want to use Nokia OVI Map for address autocomplete feature.
Please help me how to implement the same.
I am using below code
<div id="customSearchBox" class="main-search">
<span class ="caption">Search For Places:</span>
<div module="SearchBox">
<input rel="searchbox-input" class="search-box-bckgrnd" type="text" />
<div rel="searchbox-list" class="search-list"></div>
</div>
</div>
<script>
var customSearchBox = new nokia.places.widgets.SearchBox({
targetNode: 'customSearchBox',
template: 'customSearchBox',
searchCenter: function () {
return {
latitude: 52.516274,
longitude: 13.377678
}
},
onResults: function (data) {
//here you have access to data
alert(data);
}
});
</script>
How to get lat, long in this code
Thanks
Shivam

I got answer of my question by reading document of OVI map.
<script>
var customSearchBox = new nokia.places.widgets.SearchBox({
targetNode: 'customSearchBox',
template: 'customSearchBox',
searchCenter: function () {
return {
latitude: 52.516274,
longitude: 13.377678
}
},
onResults: function (data) {
//here you have access to data
//var a=getData();
renderResults(data);
//alert(data.results[0]);
}
});
function renderResults (data) {
var previewList = document.getElementById ('results');
previewList.innerHTML = '';
var results = data.results;
for (var i = 0, l = results.length; i < l; i++) {
var result = results[i];
var resultLi = document.createElement ('li');
resultLi.innerHTML = result.place.name+" - Lat:"+result.place.location.position.latitude+" Long:"+result.place.location.position.longitude;
//alert(result.place.location.position.longitude);
previewList.appendChild (resultLi);
}
}
</script>
I hope this will help to someone.
Thanks
Shivam

for jQuery you can do it like this with a textfield, because i don't wanted to use the predefined "searchbox widget":
$('#location_address').autocomplete({
focus:function (event, ui) {
return false;
},
search:function () {
$(this).addClass('working');
},
open:function () {
$(this).removeClass('working');
},
select:function (event, ui) {
var position = ui.item.id.split(";");
var coord = new nokia.maps.geo.Coordinate(parseFloat(position[0]), parseFloat(position[1]))
$('#location_address').val(ui.item.label)
$('#location_longitude')[0].value = coord.longitude;
$('#location_latitude')[0].value = coord.latitude;
map.setCenter(coord, "default");
map.setZoomLevel(16);
},
source:function (request, response) {
var searchCenter = {
latitude:52.516274,
longitude:13.377678
};
nokia.places.search.manager.findPlaces({
searchTerm:request.term,
onComplete:function (data, status) {
var nData = data.results.map(function (val, i) {
return {
value:val.place.name,
id:val.place.location.position.latitude + ";" + val.place.location.position.longitude
};
})
response(nData);
},
searchCenter:searchCenter,
didYouMean:5
});
},
minLength:2
});

Related

Convert this LINQ code back to a Loop (or Why is this object sometimes null)

I have an Upload Button in an app that uploads a deliveries object, but sometimes the deliveries object is null when it gets to the web service.
Full code is below, but it is this bit that I am having trouble unpicking. I believe this is LINQ code, so can anyone help me convert this back into a loop so that I can begin to try and understand why the deliveries object might be null?
var deliveries = Enumerable.From(results).Select(function (r) {
r.transactionDate = r.transactionDate.format("YYYY-MM-DD HH:mm:ss");
return r;
}).ToArray();
Full code:
me.uploadClicked = function () {
playClicked();
coreViewModel.busyMessage("Processing delivery data...");
deliveryRepository.GetTodaysDeliveries(function (results) {
var deliveries = Enumerable.From(results).Select(function (r) {
r.transactionDate = r.transactionDate.format("YYYY-MM-DD HH:mm:ss");
return r;
}).ToArray();
window.setTimeout(function () {
coreViewModel.busyMessage("Uploading delivery data...");
var objUploadDeliveries = Object.create({
objStore: Object.create({
storeTypeID: coreViewModel.store.storeTypeID(),
storeID: coreViewModel.store.id()
}),
objDeliveries: deliveries
});
var comm = new URLHelper();
var xhr = $.ajax({
url: comm.hosturl() + "UploadDelivery",
type: 'POST',
beforeSend: function(xh) { xh.setRequestHeader("token", coreViewModel.token); },
data: objUploadDeliveries,
dataType: 'json',
success: function (result) {
if (!result) {
playError();
return;
}
playUploadComplete();
},
error: function (x, e) {
playError();
errorHandler(x, e);
},
timeout: 60000
});
}, 20000);
});
}
The GetTodaysDeliveries function is as follows:
GetTodaysDeliveries: function (callback) {
deliverysDatabase.GetDeliveries(function (results) {
$.each(results, function (index, result) {
result.transactionDate = moment(result.transactionDate).utc();
});
var todaysResults = Enumerable.From(results).Where(function (r) {
return moment().isSame(r.transactionDate, 'day');
}).ToArray();
return callback(todaysResults);
});
}
and the deliverydatabase.GetDeliveries function inside that is as follows:
GetDeliveries: function (callback) {
var me = this;
db.transaction(
function (context) {
context.executeSql("SELECT barcode, titleName, delivered, expected, isNews, supplier, supplierId, transactionDate FROM delivery ORDER BY titlename", [], function (context, result) {
if (result.rows.length > 0) {
var results = [];
for (var i = 0; i < result.rows.length; i++) {
results.push(result.rows.item(i));
}
return callback(results);
} else {
return callback([]);
}
}, me.ErrorHandler);
}
, me.ErrorHandler);
}
Your code snippet takes the array from results, formats the date, and then returns an array. So deliverables is the same as results but with date formatted. If delivarables is null, then results must be empty or null. You can check this by inserting a
console.log("test");
into the loop
This is the unlinqd code snippet
var deliveries = [];
results.forEach(function(item)
{
var item.transactionDate = item.transactionDate.format("YYYY-MM-DD HH:mm:ss");
deliveries.push(item);
};
I hope this clears it up.

Data not binding as it should be after calling ajax with knockoutjs

I have this grid that i am creating using knockoutjs, it works perfectly at first, now i am using a window.location.hash to run another query, it works too and query returns the correct amount of data however when i insert it within the observableArray (which gets inserted correctly as well), the grid doesn't update the data and shows the old data... I'm using removeAll() function on the observableArray as well before inserting new set of data but it wont update my grid, i suspect there is something wrong with the DOM?
I should mention when i reload the page (since the page's url keeps the hash for query) my grid shows the data and works perfectly. for some reason it needs to reload the page and doesn't work without,
Here is my JS:
if (!ilia) var ilia = {};
ilia.models = function () {
var self = this;
this.pageCount = ko.observable(0);
//this is the observableArray that i am talking about ++++++++
this.items = ko.observableArray();
var $pagination = null;
var paginationConfig = {
startPage: 1,
totalPages: 20,
onPageClick: function (evt, page) {
self.generateHash({ pageNum: page });
self.getData();
}
}
var hashDefault = {
pageNum: 1,
pageSize: 20,
catId: null,
search: ""
}
this.dataModel = function (_id, _name, _desc, _thumb, _ext) {
var that = this;
this.Id = ko.observable(_id);
this.Name = ko.observable(_name);
this.Desc = ko.observable(_desc);
this.Url = '/site/ModelDetail?id=' + _id;
var b64 = "data:image/" + _ext + ";base64, ";
this.thumb = ko.observable(b64 + _thumb);
}
this.generateHash = function (opt) {
//debugger;
var props = $.extend(hashDefault, opt);
var jso = JSON.stringify(props);
var hash = window.location.hash;
var newHash = window.location.href.replace(hash, "") + "#" + jso;
window.location.href = newHash;
return jso;
}
this.parseHash = function () {
var hash = window.location.hash.replace("#", "");
var data = JSON.parse(hash);
if (data)
data = $.extend(hashDefault, data);
else
data = hashDefault;
return data;
}
var _cntrl = function () {
var _hdnCatName = null;
this.hdnCatName = function () {
if (_hdnCatName == null)
_hdnCatName = $("hdnCatName");
return _hdnCatName();
};
var _grid = null;
this.grid = function () {
if (_grid == null || !_grid)
_grid = $("#grid");
return _grid;
}
this.rowTemplate = function () {
return $($("#rowTemplate").html());
}
}
this.createPagnation = function (pageCount, pageNum) {
$pagination = $('#pagination-models');
if ($pagination && $pagination.length > 0)
if (paginationConfig.totalPages == pageCount) return;
var currentPage = $pagination.twbsPagination('getCurrentPage');
var opts = $.extend(paginationConfig, {
startPage: pageNum > pageCount ? pageCount : pageNum,
totalPages: pageCount,
onPageClick: self.pageChange
});
$pagination.twbsPagination('destroy');
$pagination.twbsPagination(opts);
}
this.pageChange = function (evt, page) {
var hash = self.parseHash();
if (hash.pageNum != page) {
self.generateHash({ pageNum: page });
self.getData();
}
}
this.getData = function () {
var _hash = self.parseHash();
inputObj = {
pageNum: _hash.pageNum,
pageSize: _hash.pageSize,
categoryId: _hash.catId
}
//debugger;
//console.log(_hash);
if (inputObj.categoryId == null) {
ilia.business.models.getAll(inputObj, function (d) {
//debugger;
if (d && d.IsSuccessfull) {
self.pageCount(d.PageCount);
self.items.removeAll();
_.each(d.Result, function (item) {
self.items.push(new self.dataModel(item.ID, item.Name, item.Description, item.Thumb, item.Extention));
});
if (self.pageCount() > 0)
self.createPagnation(self.pageCount(), inputObj.pageNum);
}
});
}
else {
ilia.business.models.getAllByCatId(inputObj, function (d) {
if (d && d.IsSuccessfull) {
self.pageCount(d.PageCount);
self.items.removeAll();
console.log(self.items());
_.each(d.Result, function (item) {
self.items.push(new self.dataModel(item.ID, item.Name, item.Description, item.Thumb, item.Extention));
});
// initializing the paginator
if (self.pageCount() > 0)
self.createPagnation(self.pageCount(), inputObj.pageNum);
//console.log(d.Result);
}
});
}
}
this.cntrl = new _cntrl();
};
And Initialize:
ilia.models.inst = new ilia.models();
$(document).ready(function () {
if (!window.location.hash) {
ilia.models.inst.generateHash();
$(window).on('hashchange', function () {
ilia.models.inst.getData();
});
}
else {
var obj = ilia.models.inst.parseHash();
ilia.models.inst.generateHash(obj);
$(window).on('hashchange', function () {
ilia.models.inst.getData();
});
}
ko.applyBindings(ilia.models.inst, document.getElementById("grid_area"));
//ilia.models.inst.getData();
});
Would perhaps be useful to see the HTML binding here as well.
Are there any console errors? Are you sure the new data received isn't the old data, due to some server-side caching etc?
Anyhow, if not any of those:
Are you using deferred updates? If the array size doesn't change, I've seen KO not being able to track the properties of a nested viewmodel, meaning that if the array size haven't changed then it may very well be that it ignores notifying subscribers. You could solve that with
self.items.removeAll();
ko.tasks.runEarly();
//here's the loop
If the solution above doesn't work, could perhaps observable.valueHasMutated() be of use? https://forums.asp.net/t/2056128.aspx?What+is+the+use+of+valueHasMutated+in+Knockout+js

Google Maps AngularJS with multiple addresses

I have an application that uses an AngularJS service and using Angular-Google-Maps and I do get multiple markers on my map but I can't get the click on each marker to work. The only marker that allows a click is the last one which doesn't allow me to close it after opening the window or if I only have one address the marker works as expected. I think I'm close but can't figure out what I might be missing to have the click on the markers work for all of them. Any ideas on what I'm missing or need to do differently?
Here is the markup on my page.
<div ng-app="myMapApp" ng-controller="mapController">
<ui-gmap-google-map center='map.center' zoom='map.zoom' options="options">
<ui-gmap-markers models="directoryMarkers" coords="'self'" icon="'icon'" click="'onClick'">
<ui-gmap-windows show="show">
<div ng-non-bindable>{{organization}}</div>
</ui-gmap-window>
</ui-gmap-markers>
</ui-gmap-google-map>
</div>
The code in myMapApp.js
var app = angular.module("myMapApp", ['uiGmapgoogle-maps', 'ngStorage']);
The code in mapController.js
app.controller('mapController', function ($scope, Geocoder) {
$scope.map = { center: { latitude: 45, longitude: -73 }, zoom: 10 };
var hfValue = $("#ucDirectory_UcResults_hfResults");
$scope.directoryMarkers = [];
var createMarker = function (organization, address, latitude, longitude, i) {
var ret = {
latitude: latitude,
longitude: longitude,
address: address,
organization: organization,
show: false
};
ret.onClick = function () {
console.log("Clicked!");
ret.show = !ret.show;
};
ret["id"] = i;
return ret;
};
var json = jQuery.parseJSON(hfValue[0].value);
var markers = [];
var i = 0;
var org;
for (var key in json) {
if (json.hasOwnProperty(key)) {
org = json[key].organization;
if (json[key].address.length > 0) {
Geocoder.geocodeAddress(json[key].address).then(function (data) {
markers.push(createMarker(org, json[key].address, data.lat, data.lng, i))
$scope.map.center.latitude = data.lat;
$scope.map.center.longitude = data.lng;
});
i++;
}
}
}
$scope.directoryMarkers = markers;
});
The code in geocoder-service.js
* An AngularJS Service for intelligently geocoding addresses using Google's API. Makes use of
* localStorage (via the ngStorage package) to avoid unnecessary trips to the server. Queries
* Google's API synchronously to avoid `google.maps.GeocoderStatus.OVER_QUERY_LIMIT`.
*
* #author: benmj
* #author: amir.valiani
*
* Original source: https://gist.github.com/benmj/6380466
*/
/*global angular: true, google: true, _ : true */
'use strict';
//angular.module('geocoder', ['ngStorage']).factory('Geocoder', function ($localStorage, $q, $timeout, $rootScope) {
app.factory('Geocoder', function ($localStorage, $q, $timeout, $rootScope) {
var locations = $localStorage.locations ? JSON.parse($localStorage.locations) : {};
var queue = [];
// Amount of time (in milliseconds) to pause between each trip to the
// Geocoding API, which places limits on frequency.
var QUERY_PAUSE = 250;
/**
* executeNext() - execute the next function in the queue.
* If a result is returned, fulfill the promise.
* If we get an error, reject the promise (with message).
* If we receive OVER_QUERY_LIMIT, increase interval and try again.
*/
var executeNext = function () {
var task = queue[0],
geocoder = new google.maps.Geocoder();
geocoder.geocode({ address: task.address }, function (result, status) {
if (status === google.maps.GeocoderStatus.OK) {
var parsedResult = {
lat: result[0].geometry.location.lat(),
lng: result[0].geometry.location.lng(),
formattedAddress: result[0].formatted_address
};
locations[task.address] = parsedResult;
$localStorage.locations = JSON.stringify(locations);
queue.shift();
task.d.resolve(parsedResult);
} else if (status === google.maps.GeocoderStatus.ZERO_RESULTS) {
queue.shift();
task.d.reject({
type: 'zero',
message: 'Zero results for geocoding address ' + task.address
});
} else if (status === google.maps.GeocoderStatus.OVER_QUERY_LIMIT) {
if (task.executedAfterPause) {
queue.shift();
task.d.reject({
type: 'busy',
message: 'Geocoding server is busy can not process address ' + task.address
});
}
} else if (status === google.maps.GeocoderStatus.REQUEST_DENIED) {
queue.shift();
task.d.reject({
type: 'denied',
message: 'Request denied for geocoding address ' + task.address
});
} else {
queue.shift();
task.d.reject({
type: 'invalid',
message: 'Invalid request for geocoding: status=' + status + ', address=' + task.address
});
}
if (queue.length) {
if (status === google.maps.GeocoderStatus.OVER_QUERY_LIMIT) {
var nextTask = queue[0];
nextTask.executedAfterPause = true;
$timeout(executeNext, QUERY_PAUSE);
} else {
$timeout(executeNext, 0);
}
}
if (!$rootScope.$$phase) { $rootScope.$apply(); }
});
};
return {
geocodeAddress: function (address) {
var d = $q.defer();
if (_.has(locations, address)) {
d.resolve(locations[address]);
} else {
queue.push({
address: address,
d: d
});
if (queue.length === 1) {
executeNext();
}
}
return d.promise;
}
};
});
As an aside, if you don't have a lot of windows open at the same time, you shouldn't use the windows directive, instead use the window directive and define it as a sibling to your markers. As recommended by the documentation.
But to answer the original question, this plnkr uses your code, minus the geocoding, to produce markers with windows. It takes two clicks on a marker to get to where you want it to be because the click happens before the value is changed.
I think to get the behavior you want it would look more like the following:
html:
<ui-gmap-google-map center='map.center' zoom='map.zoom' options="options">
<ui-gmap-markers fit="true" models="directoryMarkers" coords="'self'" icon="'icon'" click="'onClick'">
</ui-gmap-markers>
<ui-gmap-window show="selected.show" coords="selected">
<div>{{selected.organization}}</div>
</ui-gmap-window>
controller:
$scope.map = {
center: {
latitude: 45,
longitude: -73
},
zoom: 10
};
$scope.directoryMarkers = [];
$scope.selected = null;
var createMarker = function(latitude, longitude, i) {
var ret = {
latitude: latitude,
longitude: longitude,
organization: "Foo",
show: false
};
ret.onClick = function() {
console.log("Clicked!");
$scope.selected = ret;
ret.show = !ret.show;
};
ret["id"] = i;
return ret;
};
var markers = [];
var org;
var coords = chance.coordinates().split(",");
$scope.map.center.latitude = coords[0];
$scope.map.center.longitude = coords[1];
for (var i = 0; i < 20; i++) {
coords = chance.coordinates().split(",");
markers.push(createMarker(coords[0], coords[1], i));
}
$scope.directoryMarkers = markers;
Which can be seen tied together in this plnkr: http://plnkr.co/edit/rT4EufIGcjplgd8orVWu?p=preview

How can I create chrome.notification real Time?

Using the google chrome Api extension, I have the following code that show notification from JSON. Once notification is show, and when I clicked on it opened multiple tabs url (It's an error). I need to solve that problem because this should open only one tab url, this is the only problem. look the code below:
var timeChange = 1000, jsons = ['JSON_URL'];
updateValue = function() {
var colorStatus = 0;
chrome.storage.local.get(function (dataStorage) {
$.getJSON(jsons+'?'+$.now(), function (data) {
var jLastPost = {'LastNotification':''}, sizePost = (data.results.length - 1), dataLastPost = data.results[0];
totalEntradas = data.totalEntradas ? data.totalEntradas : '';
$.each(data.results, function (k,v) {
if (($.inArray('post-'+v.id, dataStorage.IDs) !== -1) && (v.date_status > 0)) {
colorStatus = 1;
}
});
chrome.browserAction.setBadgeText({'text': totalEntradas.toString()});
if (dataStorage.LastNotification !== dataLastPost.id)
{
jLastPost.LastNotification = dataLastPost.id;
chrome.storage.local.set(jLastPost);
chrome.notifications.create(dataLastPost.id,{
type: 'basic',
title: dataLastPost.titulo,
message: 'Now for you!',
iconUrl: dataLastPost.image
}, function (id) {});
chrome.notifications.onClicked.addListener(function () {
chrome.tabs.create({url: dataLastPost.uri});
});
chrome.notifications.clear(dataLastPost.id, function() {});
return false;
}
});
});
setTimeout(updateValue, timeChange);
}
updateValue();
You are attaching a chrome.notifications.onClicked listener every second when you run updateValue. At a minimum you should move the listener outside of the method.
Something along these lines should work.
var timeChange = 1000, jsons = ['JSON_URL'];
var lastPostUri;
chrome.notifications.onClicked.addListener(function () {
if (lastPostUri) {
chrome.tabs.create({url: lastPostUri});
}
});
updateValue = function() {
var colorStatus = 0;
chrome.storage.local.get(function (dataStorage) {
$.getJSON(jsons+'?'+$.now(), function (data) {
var jLastPost = {'LastNotification':''}, sizePost = (data.results.length - 1), dataLastPost = data.results[0];
totalEntradas = data.totalEntradas ? data.totalEntradas : '';
$.each(data.results, function (k,v) {
if (($.inArray('post-'+v.id, dataStorage.IDs) !== -1) && (v.date_status > 0)) {
colorStatus = 1;
}
});
chrome.browserAction.setBadgeText({'text': totalEntradas.toString()});
if (dataStorage.LastNotification !== dataLastPost.id)
{
jLastPost.LastNotification = dataLastPost.id;
chrome.storage.local.set(jLastPost);
lastPostUri = dataLastPost.uri
chrome.notifications.create(dataLastPost.id,{
type: 'basic',
title: dataLastPost.titulo,
message: 'Now for you!',
iconUrl: dataLastPost.image
}, function (id) {});
chrome.notifications.clear(dataLastPost.id, function() {});
return false;
}
});
});
setTimeout(updateValue, timeChange);
}
updateValue();

scroll display pagination with knockout js

I would like to use knockout js to enable scroll pagination
Problem
I would like to pass in url and id into my `GetPage(controller, id#, page#))
Currently it is hard coded but i would like to change that.
Knockout js
$.views.Roster.GetPage = function (url, id, pageNumber) {
$.grain.Ajax.Get({
Url: url,
SectionID: {id:id},
DataToSubmit: { pageNumber: pageNumber, id: id },
DataType: "json",
OnSuccess: function (data, status, jqXHR) {
$.views.Roster.RosterViewModel.AddUsers(data);
}
});
};
Next = function () {
var _page = $.views.Roster.ViewModel.CurrentPage() + 1;
$.views.Roster.ViewModel.CurrentPage(_page);
$.views.Roster.GetPage("/api/Roster", 9, _page);
}
Scroll pagination
$(document).ready(function(){
$('#main').scroll(function () {
if ($('#main').scrollTop() >= $(document).height() - $('#main').height()) {
$('#status').text('Loading more items...' + $.views.Roster.ViewModel.TotalRoster());
if ($.views.Roster.ViewModel.RosterUsers() == null ) {
$('#status').hide();
$('#done').text('No more items...'),
$('#main').unbind('scroll');
}
setTimeout(updateStatus, 2500);
}
//updateStatus();
});
});
Change the data in getRoster function to what your server function is expecting for you to return the data. Also, remove the code $.views.Roster.GetRoster, it is not required anymore. Now when you do ko.applyBindings(new $.views.Roster.RosterViewModel()); you should get the first page of data, subsequently, when you scroll, the next() call on the view model will continue paging. That logic is all you.
$.views.Roster.RosterViewModel = function (data) {
var self = this;
self.RosterUsers = ko.observableArray([]);
_rosterUsers = self.RosterUsers;
self.currentPage = ko.observable(1);
self.toDisplay = ko.observable(10);
var filteredRoster = ko.computed(function(){
var init = (self.currentPage()-1)* self.toDisplay(),
filteredList = [],
rosterLength = self.RosterUsers().length,
displayLimit = self.toDisplay();
if(rosterLength == 0)
return[];
for(var i = init; i<(displayLimit + init) && i<rosterLength; i++)
{
filteredList.push(self.RosterUsers()[i]);
}
return filteredList;
}),
totalRoster = ko.computed(function () {
return self.RosterUsers().length;
}),
changePage = function (data) {
self.currentPage(data);
},
next = function () {
if ((self.currentPage() * self.toDisplay()) > self.RosterUsers().length)
return;
self.currentPage(self.currentPage() + 1);
},
prev = function () {
if (self.currentPage() === 1)
return;
self.currentPage(self.currentPage() - 1);
},
getRoster = ko.computed(function () {
var data = {
currentPage: self.currentPage(),
pageSize: self.toDisplay()
},
$promise = _makeRequest(data);
$promise.done(function (data) {
var localArray = [];
ko.utils.arrayForEach(data, function(d){
localArray.push(new $.views.Roster.UserViewModel(d));
});
self.RosterUsers.push.apply(self.RosterUsers,localArray);
});
}),
_makeRequest = function(data){
return $.getJSON('your url here', data);
};
};

Categories