lib.js 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404
  1. /*
  2. Copyright (c) 2013 Mapo developers and contributors <mapo.tizen@gmail.com>
  3. This file is part of Mapo.
  4. This program is free software: you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation, either version 3 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program. If not, see <http://www.gnu.org/licenses/>.
  14. */
  15. /*
  16. * Application Global variables
  17. */
  18. // The map of the application
  19. var map = null;
  20. // The boolean which provide the connection state of the application
  21. var isReady = true;
  22. var isOnline = navigator.onLine;
  23. var isLoaded = false;
  24. var isDownloaded = false;
  25. /*
  26. * Recording Global Variable
  27. */
  28. // Directory where the recording document is placed
  29. var docDir;
  30. // Name of the recording document
  31. var doc;
  32. // The file where the records are placed
  33. var file;
  34. // Boolean which provide the information if a file has been recorded
  35. var fileRecorded = false;
  36. var url_openlayers = "http://openlayers.org/api/OpenLayers.js";
  37. var url_gmaps = "http://maps.google.com/maps/api/js?v=3.2&sensor=false";
  38. var url_gmaps = 'http://maps.googleapis.com/maps/api/js?v=3.2&signed_in=true&callback=handleLoadedGmaps';
  39. /*
  40. * General Manager
  41. */
  42. /**
  43. * Quit the application
  44. */
  45. function exit() {
  46. tizen.application.getCurrentApplication().exit();
  47. }
  48. /**
  49. * Show a message
  50. *
  51. * @param message
  52. */
  53. function log(message) {
  54. if (!false) {
  55. console.log("# " + message);
  56. var log = document.getElementById("console");
  57. log.innerHTML += "<pre>" + message + "</pre>";
  58. }
  59. }
  60. // upstream: https://gist.github.com/kamranzafar/3136584#comment-1244934
  61. function toast(message) {
  62. var $toast = $('<div class="ui-loader ui-overlay-shadow ui-body-e ui-corner-all"><h3>'
  63. + message + '</h3></div>');
  64. $toast.css({
  65. display : 'block',
  66. background : '#fff',
  67. opacity : 0.90,
  68. position : 'fixed',
  69. padding : '7px',
  70. 'text-align' : 'center',
  71. width : '270px',
  72. left : ($(window).width() - 284) / 2,
  73. top : $(window).height() / 2 - 20
  74. });
  75. var removeToast = function() {
  76. $(this).remove();
  77. };
  78. $toast.click(removeToast);
  79. $toast.appendTo($.mobile.pageContainer).delay(2000);
  80. $toast.fadeOut(400, removeToast);
  81. }
  82. function handleError(message) {
  83. log(message);
  84. toast(message);
  85. }
  86. /*
  87. * Storage Manager
  88. */
  89. /**
  90. * Store the coordinates values in the local storage
  91. */
  92. function storeData() {
  93. localStorage.setItem('lat', $('#lat').val());
  94. localStorage.setItem('lon', $('#lon').val());
  95. localStorage.setItem('dms', $('#dms').val());
  96. }
  97. /**
  98. * Store the settings values in the local storage
  99. */
  100. function storeSettings() {
  101. log("#{ storeSettings: " + isOnline);
  102. localStorage.setItem('connection', $('#switchOnline').val());
  103. localStorage.setItem('energySaving', $('#switchEnergy').val());
  104. localStorage.setItem('timeout', $('#selectorTimeout').val());
  105. localStorage.setItem('downloaded', isDownloaded);
  106. log("#} storeSettings: " + isOnline);
  107. }
  108. function store() {
  109. var i = 0;
  110. var r = $.Deferred();
  111. storeData();
  112. storeSettings();
  113. for (i = 0; i < localStorage.length; i++) {
  114. log(i + " -- " + localStorage.key(i) + " : "
  115. + localStorage.getItem(localStorage.key(i)));
  116. }
  117. r.resolve();
  118. return r;
  119. }
  120. /**
  121. * Store the data before quitting the application
  122. */
  123. function quit() {
  124. log("#{ exit");
  125. store().done(exit);
  126. log("#} exit");
  127. }
  128. /*
  129. * Set Manager
  130. */
  131. /**
  132. * Modify the latitude value
  133. *
  134. * @param lat :
  135. * new latitude value
  136. */
  137. function setLat(lat) {
  138. if (document.getElementById("lat").value !== lat) {
  139. document.getElementById("lat").value = lat;
  140. }
  141. }
  142. /**
  143. * Modify the longitude value
  144. *
  145. * @param lon :
  146. * new longitude value
  147. */
  148. function setLon(lon) {
  149. if (document.getElementById("lon").value !== lon) {
  150. document.getElementById("lon").value = lon;
  151. }
  152. }
  153. /*
  154. * Link Manager
  155. */
  156. /**
  157. * Get the OpenStreetMap link with the corresponding latitude and longitude
  158. *
  159. * @returns url
  160. */
  161. function getLink(provider) {
  162. var lat = $("#lat").val();
  163. var lon = $("#lon").val();
  164. var url;
  165. switch (provider) {
  166. case 'OSM':
  167. url = "http://www.openstreetmap.org/?&zoom=10&layers=mapnik&lat=${lat}&lon=${lon}";
  168. break;
  169. case 'GM':
  170. url = "http://maps.google.com/maps?&z=10&ll=${lat},${lon}";
  171. break;
  172. case 'HERE':
  173. url = "http://maps.nokia.com/${lat},${lon},16,0,0,normal.day";
  174. break;
  175. default:
  176. url = "http://www.openstreetmap.org/?&zoom=10&layers=mapnik&lat=${lat}&lon=${lon}";
  177. break;
  178. }
  179. url = url.replace("${lon}", lon);
  180. url = url.replace("${lat}", lat);
  181. return url;
  182. }
  183. /**
  184. * Use the Internet Application Control to go to OSM link with the browser
  185. */
  186. function goToURL(provider) {
  187. var i = 0;
  188. var j = 0;
  189. if (isOnline) {
  190. var appControl = new tizen.ApplicationControl(
  191. "http://tizen.org/appcontrol/operation/view",
  192. getLink(provider), null);
  193. var appControlReplyCallback = {
  194. onsuccess : function(data) {
  195. for (i = 0; i < data.length; i++) {
  196. log("#" + i + " key:" + data[i].key);
  197. for (j = 0; j < data[i].value.length; j++) {
  198. log(" value#" + j + ":" + data[i].value[j]);
  199. }
  200. }
  201. },
  202. onfailure : function() {
  203. log('The launch application control failed');
  204. }
  205. }
  206. tizen.application.launchAppControl(appControl, null, function() {
  207. log("launch internet application control succeed");
  208. }, function(e) {
  209. log("launch internet application control failed. reason: "
  210. + e.message);
  211. }, appControlReplyCallback);
  212. } else {
  213. handleError("Please connect your application online in the settings"
  214. + " if you want to open a browser")
  215. }
  216. }
  217. /**
  218. * update links
  219. * TODO: check if needed ?
  220. */
  221. // function updateLinks() {
  222. // $('#OSMLink').attr('href', getOSMLink());
  223. // }
  224. /*
  225. * Map Manager
  226. */
  227. /**
  228. * get the size of the map (width, height) according to the dimension of the
  229. * screen
  230. *
  231. * @returns [ width, height ]
  232. */
  233. function getMapSize() {
  234. var viewHeight = $(window).height();
  235. var viewWidth = $(window).width();
  236. var header = $("div[data-role='header']:visible:visible");
  237. var footer = $("div[data-role='footer']:visible:visible");
  238. var navbar = $("div[data-role='navbar']:visible:visible");
  239. var content = $("div[data-role='content']:visible:visible");
  240. var contentHeight = viewHeight - header.outerHeight()
  241. - navbar.outerHeight() - footer.outerHeight();
  242. var contentWidth = viewWidth - 30;
  243. return [ contentWidth, contentHeight ];
  244. }
  245. /**
  246. * Modify the dimension of the map according to getMapSize()
  247. */
  248. function setMapSize(size) {
  249. size = getMapSize();
  250. $('#myMap').css("width", size[0]);
  251. $('#myMap').css("height", size[1]);
  252. }
  253. function initIcon() {
  254. var size = new OpenLayers.Size(21, 25);
  255. var offset = new OpenLayers.Pixel(-(size.w / 2), -size.h);
  256. return new OpenLayers.Icon('http://www.openlayers.org/dev/img/marker.png',
  257. size, offset);
  258. }
  259. function loadTrace(data) {
  260. var i = 0;
  261. log("loadTrace data : " + data['dates'][0]);
  262. var icon = initIcon();
  263. log("tab lons = " + data['lons']);
  264. log("tab lats = " + data['lats']);
  265. log("tab dates = " + data['dates']);
  266. for (i = 0; i < data['dates'].length; i++) {
  267. var lon = parseFloat(data['lons'][i]);
  268. var lat = parseFloat(data['lats'][i]);
  269. var date = data['dates'][i];
  270. log("data['dates'][" + i + "] = " + date);
  271. log("data['lons'][" + i + "] = " + lon);
  272. log("data['lat'][" + i + "] = " + lat);
  273. log("lat before : " + lat);
  274. log("lon before : " + lon);
  275. var lonlat = new OpenLayers.LonLat(lon, lat).transform('EPSG:4326',
  276. 'EPSG:3857');
  277. var mark = new OpenLayers.Marker(lonlat, icon);
  278. trace.addMarker(mark);
  279. }
  280. map.addLayer(trace);
  281. }
  282. /**
  283. * Load the OpenLayers map with different OpenStreetMap and Google maps'
  284. * layers
  285. * TODO: check if needed ?
  286. */
  287. function loadMap() {
  288. log("#{ loadMap: " + OpenLayers);
  289. if (OpenLayers === null) {
  290. log("error: OpenLayers " + isDownloaded);
  291. return;
  292. }
  293. var latCenter = $("#lat").val();
  294. var lonCenter = $("#lon").val();
  295. var zoom = $("#zoom").val();
  296. var layers = [ new OpenLayers.Layer.OSM("OpenStreetMap") ];
  297. log("# is gmaps available ?" + gmaps + "/" + gmaps);
  298. if (gmaps !== null) {
  299. var array = [ new OpenLayers.Layer.Google("Google Satellite", {
  300. type : google.maps.MapTypeId.SATELLITE,
  301. numZoomLevels : 22,
  302. })
  303. , new OpenLayers.Layer.Google("Google Physical", {
  304. type : google.maps.MapTypeId.TERRAIN
  305. }), new OpenLayers.Layer.Google("Google Hybrid", {
  306. type : google.maps.MapTypeId.HYBRID,
  307. numZoomLevels : 20
  308. }),
  309. new OpenLayers.Layer.Google("Google Streets", {
  310. numZoomLevels : 20
  311. }) ];
  312. // layers = array.concat(layers);
  313. layers = layers.concat(array);
  314. }
  315. log("# add ui " + layers);
  316. map = new OpenLayers.Map('myMap', {
  317. projection : 'EPSG:3857',
  318. layers : layers,
  319. center : new OpenLayers.LonLat(lonCenter, latCenter).transform(
  320. 'EPSG:4326', 'EPSG:3857'),
  321. zoom : zoom,
  322. });
  323. map.addControl(new OpenLayers.Control.LayerSwitcher());
  324. if (fileRecorded) { // TODO : Data vide : data([0])?.length!=0 or
  325. // fileRecorded
  326. // var trace = new OpenLayers.Layer.Markers( "Latest recorded trace"
  327. // );
  328. // map.removeLayer(trace);
  329. var markers = map.getLayersByName("Last recorded trace");
  330. if (markers.length != 0) {
  331. var previousTrace = markers[0];
  332. log("trace = " + previousTrace.name);
  333. previousTrace.destroy();
  334. }
  335. trace = new OpenLayers.Layer.Markers("Last recorded trace");
  336. // readFile().done(loadTrace);
  337. readFile();
  338. // setTimeout(
  339. // // log("result 0 : "+result[0]);
  340. // // log("result 1 : "+result[1]);
  341. // loadTrace
  342. // , 5000);
  343. }
  344. log("#} loadMap: " + OpenLayers);
  345. }
  346. /*
  347. * Refresh Manager
  348. */
  349. /**
  350. * Refresh all the application according to the coordinates and the settings
  351. */
  352. function refresh() {
  353. log("#{ refresh: " + OpenLayers);
  354. if (isOnline) {
  355. isReady = (OpenLayers !== null);
  356. } else {
  357. isReady = false;
  358. }
  359. log("isReady=" + isReady);
  360. if (isReady) {
  361. $('#myMap').empty();
  362. setMapSize();
  363. loadMap();
  364. } else {
  365. // isOnline = navigator.onLine;
  366. // $('#switchOnline').val(isOnline ? 'online' : 'offline');
  367. $('#myMap').empty();
  368. $('#myMap')
  369. .html(
  370. "<p align='center'>"
  371. + "Please connect your application online in the settings"
  372. + " if you want to load the map</p>");
  373. }
  374. // isOffline $('#switchOffline').val() // TODO
  375. log("#} refresh: " + isReady);
  376. }
  377. /*
  378. * Initialization Manager
  379. */
  380. /**
  381. * Recover in the local storage the coordinates values from the preceding use
  382. */
  383. function initData() {
  384. log("#{ initData");
  385. if (localStorage.getItem('lat') !== null) {
  386. $('#lat').val(localStorage.getItem('lat'));
  387. }
  388. if (localStorage.getItem('lon') !== null) {
  389. $('#lon').val(localStorage.getItem('lon'));
  390. }
  391. if (localStorage.getItem('dms') !== null) {
  392. $('#dms').val(localStorage.getItem('dms'));
  393. }
  394. storeData();
  395. log("#} initData");
  396. }
  397. /**
  398. * Recover in the local storage the setting values from the preceding use
  399. */
  400. function initSettings() {
  401. log("#{ initSettings: " + isOnline);
  402. if (null !== localStorage.getItem('connection')) {
  403. isOnline = (localStorage.getItem('connection') == 'online');
  404. }
  405. $('#switchOnline').val(isOnline ? 'online' : 'offline');
  406. if (localStorage.getItem('energySaving') !== null) {
  407. $('#switchEnergy').val(localStorage.getItem('energySaving'));
  408. }
  409. if (localStorage.getItem('timeout') !== null) {
  410. $('#selectorTimeout').attr('value', localStorage.getItem('timeout'));
  411. }
  412. if (localStorage.getItem('downloaded') !== null) {
  413. isDownloaded = localStorage.getItem('downloaded');
  414. }
  415. storeSettings();
  416. log("#} initSettings: " + isReady);
  417. }
  418. /*
  419. * Coordinates transformation Manager
  420. */
  421. /**
  422. * Transform the latitude/longitude into DMS coordinate
  423. *
  424. * @param lat :
  425. * latitude
  426. * @param lon :
  427. * longitude
  428. * @returns dms : DMS coordinate
  429. */
  430. function fromLatLonToDMS(lat, lon) {
  431. var latitude = lat;
  432. var longitude = lon;
  433. var dms = "";
  434. var NS = "";
  435. if (latitude >= 0) {
  436. NS += "N";
  437. } else {
  438. latitude = -latitude;
  439. NS += "S";
  440. }
  441. var dLat = parseInt(latitude, 10);
  442. var mLat = parseInt((latitude - dLat) * 60, 10);
  443. var sLat = parseInt((latitude - dLat) * 60 * 60 - 60 * mLat, 10);
  444. dms += NS + " " + dLat + "° " + mLat + "' " + sLat + "\" ";
  445. var EW = "";
  446. if (longitude >= 0) {
  447. EW += "E";
  448. } else {
  449. EW += "W";
  450. longitude = -longitude;
  451. }
  452. var dLon = parseInt(longitude, 10);
  453. var mLon = parseInt((longitude - dLon) * 60, 10);
  454. var sLon = parseInt((longitude - dLon) * 60 * 60 - 60 * mLon, 10);
  455. dms += EW + " " + dLon + "° " + mLon + "' " + sLon + "\"";
  456. // text = NS+" "+d+"° "+m+"' "+s+"\" "+EW+" "+d+"° "+m+"' "+s+"\"";
  457. return dms;
  458. }
  459. /**
  460. * Transform the DMS into latitude/longitude coordinates
  461. *
  462. * @param dms :
  463. * DMS coordinate
  464. * @returns [ lat, lon ] : latitude and longitude coordinates
  465. */
  466. function fromDMSToLatLon(dms) {
  467. var re = /^([NS])\s*([0-9.\-]+)\s*°\s*([0-9.\-]+)\s*\'\s*([0-9.\-]+)\s*\"\s*([EW])\s*([0-9.\-]+)\s*°\s*([0-9.\-]+)\s*\'\s*([0-9.\-]+)\s*\"\s*$/;
  468. if (re.test(dms)) {
  469. var lat = (parseFloat(RegExp.$2) + parseFloat(RegExp.$3) / 60 + parseFloat(RegExp.$4)
  470. / (60 * 60)).toFixed(6);
  471. if (RegExp.$1 == 'S') {
  472. lat = -lat;
  473. }
  474. lat = lat.toString();
  475. setLat(lat);
  476. var lon = (parseFloat(RegExp.$6) + parseFloat(RegExp.$7) / 60 + parseFloat(RegExp.$8)
  477. / (60 * 60)).toFixed(6);
  478. if (RegExp.$5 == 'W') {
  479. lon = -lon;
  480. }
  481. lon = lon.toString();
  482. setLon(lon);
  483. }
  484. }
  485. /*
  486. * Coordinates Manager
  487. */
  488. /**
  489. * Modify the DMS value using the transformation's function fromLatLonToDMS
  490. */
  491. function setDMS() {
  492. $('#dms').val(fromLatLonToDMS($("#lat").val(), $("#lon").val()));
  493. }
  494. /**
  495. * Modify the latitude and longitude values using the transformation's function
  496. * fromDMSToLatLon
  497. */
  498. function setLatLon() {
  499. var coordinates = fromDMSToLatLon($('#dms').val());
  500. }
  501. /**
  502. * Validate or not the DMS coordinate according to the form of the regular
  503. * expression
  504. *
  505. * @param dms :
  506. * DMS coordinates
  507. * @returns Validation
  508. */
  509. function validateDMS(dms) {
  510. var re = /^([NS])\s*([0-9.\-]+)\s*°\s*([0-9.\-]+)\s*\'\s*([0-9.\-]+)\s*\"\s*([EW])\s*([0-9.\-]+)\s*°\s*([0-9.\-]+)\s*\'\s*([0-9.\-]+)\s*\"\s*$/;
  511. if (re.test(dms)) {
  512. return true;
  513. } else {
  514. return false;
  515. }
  516. }
  517. /**
  518. * Validate or not the latitudes and longitudes coordinates according to the
  519. * form of the regular expression
  520. *
  521. * @param latOrLon
  522. * @returns Validation
  523. */
  524. function validateLatOrLon(latOrLon) {
  525. if (/^[0-9.\-]+$/.test(latOrLon)) {
  526. return true;
  527. } else {
  528. return false;
  529. }
  530. }
  531. /**
  532. * Function called when the latitude value changes Calculate the new DMS
  533. * coordinate
  534. */
  535. function changeLat() {
  536. var lat = $('#lat').val();
  537. if (validateLatOrLon(lat)) {
  538. $('#lat').val(parseFloat($('#lat').val()).toFixed(6).toString());
  539. setDMS();
  540. storeData();
  541. } else {
  542. handleError("Latitude coordinate invalid : " + lat);
  543. initData();
  544. }
  545. }
  546. /**
  547. * Function called when the longitude value changes Calculate the new DMS
  548. * coordinate
  549. */
  550. function changeLon() {
  551. var lon = $('#lon').val();
  552. if (validateLatOrLon(lon)) {
  553. $('#lon').val(parseFloat($('#lon').val()).toFixed(6).toString());
  554. setDMS();
  555. storeData();
  556. } else {
  557. handleError("Lontitude coordinate invalid : " + lon);
  558. initData();
  559. }
  560. }
  561. /**
  562. * Function called when the DMS value changes Calculate the new latitude and
  563. * longitude coordinates
  564. */
  565. function changeDMS() {
  566. var dms = $('#dms').val();
  567. if (validateDMS(dms)) {
  568. setLatLon();
  569. storeData();
  570. } else {
  571. alert("DMS coordinate invalid : " + dms);
  572. initData();
  573. }
  574. }
  575. /*
  576. * Location Manager
  577. */
  578. /**
  579. * Function called when the getCurrentPosition succeded Refresh the application
  580. */
  581. function handleShowLocation(position) {
  582. var lat = position.coords.latitude.toFixed(6).toString();
  583. var lon = position.coords.longitude.toFixed(6).toString();
  584. setLat(lat);
  585. setLon(lon);
  586. refresh();
  587. }
  588. /**
  589. * Function called when the getCurrentPosition failed Show the error
  590. *
  591. * @param error
  592. */
  593. function handleErrorLocation(error) {
  594. var errorInfo = document.getElementById("locationInfo");
  595. switch (error.code) {
  596. case error.PERMISSION_DENIED:
  597. errorInfo.innerHTML = "User denied the request for Geolocation.";
  598. break;
  599. case error.POSITION_UNAVAILABLE:
  600. errorInfo.innerHTML = "Location information is unavailable.";
  601. break;
  602. case error.TIMEOUT:
  603. errorInfo.innerHTML = "The request to get user location timed out.";
  604. break;
  605. case error.UNKNOWN_ERROR:
  606. errorInfo.innerHTML = "An unknown error occurred.";
  607. break;
  608. }
  609. }
  610. /**
  611. * Get the current position according to the GPS' device
  612. */
  613. function getLocation() {
  614. if (navigator.geolocation) {
  615. navigator.geolocation.getCurrentPosition(handleShowLocation,
  616. handleErrorLocation, {
  617. enableHighAccuracy : $('#switchEnergy').val() == 'off'
  618. });
  619. } else {
  620. document.getElementById("locationInfo").innerHTML = "Geolocation is not supported by this browser.";
  621. }
  622. }
  623. /*
  624. * Recording manager
  625. */
  626. /**
  627. * Function called when the file resolution succeded Create the recording file
  628. * in the corresponding directory
  629. *
  630. * @param dir :
  631. * directory where the file is placed
  632. */
  633. function handleResolveSuccess(dir) {
  634. docDir = dir;
  635. var date = new Date();
  636. var dateFile = "" + date.getFullYear().toString() + "-"
  637. + date.getMonth().toString() + "-" + date.getDate().toString()
  638. + "-" + date.getHours().toString() + "-"
  639. + date.getMinutes().toString() + "-" + date.getSeconds().toString();
  640. dateFile = (new Date).getTime();
  641. // log(dateFile);
  642. doc = 'mapo-' + dateFile + ".csv.txt";
  643. docDir.createFile(doc);
  644. $('#locationInfo').html("Track recording in file:<br/>" + doc);
  645. }
  646. /**
  647. * Function called when the file resolution failed Show the error
  648. *
  649. * @param e :
  650. * error
  651. */
  652. function handleResolveError(e) {
  653. handleError('resolve: ' + e.message);
  654. }
  655. /**
  656. * Resolve the file
  657. */
  658. function resolveFile() {
  659. try {
  660. file = docDir.resolve(doc);
  661. } catch (exc) {
  662. log('Could not resolve file: ' + exc.message);
  663. // Stop in case of any errors
  664. return;
  665. }
  666. }
  667. /**
  668. * Function called when the record failed, writing or reading Show the error
  669. *
  670. * @param e :
  671. * error
  672. */
  673. function handleRecordError(e) {
  674. var msg = '';
  675. switch (e.code) {
  676. case FileError.QUOTA_EXCEEDED_ERR:
  677. msg = 'QUOTA_EXCEEDED_ERR';
  678. break;
  679. case FileError.NOT_FOUND_ERR:
  680. msg = 'NOT_FOUND_ERR';
  681. break;
  682. case FileError.SECURITY_ERR:
  683. msg = 'SECURITY_ERR';
  684. break;
  685. case FileError.INVALID_MODIFICATION_ERR:
  686. msg = 'INVALID_MODIFICATION_ERR';
  687. break;
  688. case FileError.INVALID_STATE_ERR:
  689. msg = 'INVALID_STATE_ERR';
  690. break;
  691. default:
  692. msg = 'Unknown Error';
  693. break;
  694. }
  695. handleError(msg);
  696. }
  697. /**
  698. * Function called when the writing succeeded Add the position at the end of the
  699. * file
  700. *
  701. * @param fileStream :
  702. * Stream to write
  703. */
  704. function writeToStream(fileStream) {
  705. try {
  706. var date = (new Date).getTime();
  707. var lat = $("#lat").val();
  708. var lon = $("#lon").val();
  709. var line = "" + date + ";" + lat + ";" + lon + "\n";
  710. fileStream.write(line);
  711. fileStream.close();
  712. } catch (exc) {
  713. handleError('io: could not write to file: ' + exc.message);
  714. }
  715. }
  716. /**
  717. * Try to write the record into the file
  718. */
  719. function writeRecord() {
  720. try {
  721. file.openStream(
  722. // open for appending
  723. 'a',
  724. // success callback - add textarea's contents
  725. writeToStream,
  726. // error callback
  727. handleRecordError);
  728. } catch (exc) {
  729. handleError('io: could not write to file: ' + exc.message);
  730. }
  731. }
  732. /**
  733. * Function called when the reading succeded
  734. *
  735. * @param fileStream :
  736. * Stream to read
  737. */
  738. function readFromStream(fileStream) {
  739. try {
  740. log('File size: ' + file.fileSize);
  741. var contents = fileStream.read(fileStream.bytesAvailable);
  742. fileStream.close();
  743. log('file contents: ' + contents);
  744. } catch (exc) {
  745. handleError('io: Could not read from file: ' + exc.message);
  746. }
  747. }
  748. /**
  749. * Try to read the file
  750. */
  751. function readRecord() {
  752. try {
  753. file.openStream(
  754. // open for reading
  755. 'r',
  756. // success callback - add textarea's contents
  757. readFromStream,
  758. // error callback
  759. handleRecordError);
  760. } catch (exc) {
  761. handleError('io: Could not write to file: ' + exc.message);
  762. }
  763. }
  764. /**
  765. * Function called when getPosition got successfully the position Resolve the
  766. * file, write and read the records
  767. *
  768. * @param position
  769. */
  770. function handleRecordPosition(position) {
  771. if ($('#switchRecord').val() == "start") {
  772. handleShowLocation(position);
  773. resolveFile();
  774. writeRecord();
  775. readRecord();
  776. }
  777. }
  778. /**
  779. * Function called when getPosition failed to get the position Show the error
  780. *
  781. * @param error
  782. */
  783. function handleErrorPosition(error) {
  784. $('#switchRecord').val('stop').slider('refresh');
  785. var errorInfo = document.getElementById("locationInfo");
  786. switch (error.code) {
  787. case error.PERMISSION_DENIED:
  788. errorInfo.innerHTML = "User denied the request for Geolocation.";
  789. break;
  790. case error.POSITION_UNAVAILABLE:
  791. errorInfo.innerHTML = "Location information is unavailable.";
  792. break;
  793. case error.TIMEOUT:
  794. errorInfo.innerHTML = "The request to get user location timed out.";
  795. break;
  796. case error.UNKNOWN_ERROR:
  797. errorInfo.innerHTML = "An unknown error occurred.";
  798. break;
  799. }
  800. }
  801. /**
  802. * Get the recording position
  803. */
  804. function getPosition() {
  805. navigator.geolocation.getCurrentPosition(handleRecordPosition,
  806. handleErrorPosition, {
  807. enableHighAccuracy : $('#switchEnergy').val() == 'off'
  808. });
  809. }
  810. /**
  811. * Function called when the record of a trace has been launched Record the
  812. * position whith a timeout predefined in the settings
  813. */
  814. function record() {
  815. if (navigator.geolocation) {
  816. var intervalID;
  817. if ($('#switchRecord').val() == "start") {
  818. tizen.filesystem.resolve('documents', handleResolveSuccess,
  819. handleResolveError, 'rw');
  820. getPosition();
  821. intervalID = setInterval(getPosition,
  822. $('#selectorTimeout').val() * 1000);
  823. } else {
  824. clearInterval(intervalID);
  825. $('#locationInfo').html("Trace recorded in the file:<br/>" + doc);
  826. fileRecorded = true;
  827. }
  828. } else {
  829. document.getElementById("locationInfo").innerHTML = "Geolocation is not supported.";
  830. }
  831. }
  832. /**
  833. * Extract from a file composed by the last recorded trace all the dates,
  834. * latitudes and lontitudes and place its in data
  835. * TODO: test if parse CSV as "date,la,lo\n"
  836. */
  837. function readFile() {
  838. // var deferred = $.Deferred();
  839. try {
  840. file = docDir.resolve(doc);
  841. log('File size: ' + file.fileSize);
  842. } catch (exceptionResolve) {
  843. log('error: Could not resolve file: ' + exceptionResolve.message);
  844. // Stop in case of any errors
  845. return;
  846. }
  847. try {
  848. file.readAsText(
  849. // success callback - display the contents of the file
  850. function(contents) {
  851. // log('File contents:' + contents);
  852. var lines = contents.split("\n");
  853. var re = /^([0-9.:\-]+),([0-9.\-]+),([0-9.\-]+)$/;
  854. var data = [];
  855. var dates = [];
  856. var lats = [];
  857. var lons = [];
  858. var iData = 0;
  859. for (var iLines = 0; iLines < lines.length; iLines++) {
  860. if (re.test(lines[iLines])) {
  861. log("line " + iLines + ": " + lines[iLines]);
  862. var parts = lines[iLines].split(";");
  863. for (var iParts = 0; iParts < parts.length; iParts++) {
  864. log(" part " + iParts + ": " + parts[iParts]);
  865. if ((iParts % 3) == 0) {
  866. dates[iData] = parts[iParts];
  867. log(" date " + iData + ": " + dates[iData]);
  868. } else if ((iParts % 3) == 1) {
  869. lats[iData] = parts[iParts];
  870. log(" lat " + iData + ": " + lats[iData]);
  871. } else {
  872. lons[iData] = parts[iParts];
  873. log(" lon " + iData + ": " + lons[iData]);
  874. }
  875. }
  876. iData++;
  877. }
  878. }
  879. data['dates'] = dates;
  880. data['lats'] = lats;
  881. data['lons'] = lons;
  882. log("readfile data" + data['dates'][0]);
  883. loadTrace(data);
  884. },
  885. // error callback
  886. handleRecordError);
  887. } catch (exceptionRead) {
  888. handleError("io: readAsText() exception:" + exceptionRead.message);
  889. }
  890. // deferred.resolve();
  891. // return deferred; // [data, referred]
  892. }
  893. /*
  894. * Social Manager
  895. */
  896. /**
  897. * Use the Email Application Control to share a position by Email
  898. */
  899. function sendEmail() {
  900. if (isOnline) {
  901. var message = "This is the position I want to show you from Mapo:"
  902. + "\nLatitude=" + $("#lat").val() + "\nLongitude = "
  903. + $("#lon").val() + "\nIf you prefer in DMS, here it is: "
  904. + $('#dms').val()
  905. + "\nYou can see this position on OpenStreetMap: "
  906. + getLink('OSM') + "\nConnect you on Mapo for more details!";
  907. var appControl = new tizen.ApplicationControl(
  908. "http://tizen.org/appcontrol/operation/compose", null, null,
  909. null, [
  910. new tizen.ApplicationControlData(
  911. "http://tizen.org/appcontrol/data/subject",
  912. [ "Mapo" ]),
  913. new tizen.ApplicationControlData(
  914. "http://tizen.org/appcontrol/data/text",
  915. [ "mapo.tizen@gmail.com" ]),
  916. new tizen.ApplicationControlData(
  917. "http://tizen.org/appcontrol/data/text",
  918. [ message ]) ]);
  919. tizen.application.launchAppControl(appControl, "tizen.email",
  920. function() {
  921. log("launch service succeeded");
  922. }, function(e) {
  923. handleError("launch service failed. Reason: " + e.name);
  924. })
  925. } else {
  926. alert("Please connect your application online in the settings"
  927. + " if you want to send an email");
  928. }
  929. }
  930. // TODO: check
  931. // var appControl = new tizen.ApplicationControl(
  932. // "http://tizen.org/appcontrol/operation/send", // compose or send
  933. // "mailto:", null, null,
  934. // [
  935. // new tizen.ApplicationControlData(
  936. // "http://tizen.org/appcontrol/data/subject", [ "Mapo" ]),
  937. // new tizen.ApplicationControlData(
  938. // "http://tizen.org/appcontrol/data/text", [ message ]),
  939. // new tizen.ApplicationControlData(
  940. // "http://tizen.org/appcontrol/data/to",
  941. // [ "mapo.tizen@gmail.com" ])
  942. //
  943. // // TODO tizen.mapo@spamgourmet.com
  944. // // new tizen.ApplicationControlData(
  945. // // "http://tizen.org/appcontrol/data/path",
  946. // // ["images/image1.jpg"])
  947. // ]);
  948. // tizen.application.launchAppControl(appControl, null,
  949. // function() {log("launch service succeeded");},
  950. // function(e) {
  951. // log("launch service failed. Reason: " + e.name);});
  952. // TODO: check
  953. function sendBluetooth() {
  954. var appControl = new tizen.ApplicationControl(
  955. "http://tizen.org/appcontrol/operation/bluetooth/pick", null,
  956. "image/jpeg", // "image/jpeg"
  957. null, []);
  958. tizen.application.launchAppControl(appControl, "tizen.bluetooth",
  959. function() {
  960. log("launch service succeeded");
  961. }, function(e) {
  962. handleError("launch service failed. Reason: " + e.name);
  963. });
  964. // var appControlReplyCallback = {
  965. // // callee sent a reply
  966. // onsuccess: function(data) {
  967. // for (var i = 0; i < data.length; i++) {
  968. // if (data[i].key == "http://tizen.org/appcontrol/data/selected") {
  969. // log('Selected image is ' + data[i].value[0]);
  970. // }
  971. // }
  972. // },
  973. // // callee returned failure
  974. // onfailure: function() {
  975. // log('The launch application control failed');
  976. // }
  977. // }
  978. //
  979. // tizen.application.launchAppControl(
  980. // appControl,
  981. // null,
  982. // function() {log("launch application control succeed"); },
  983. // function(e) {log("launch application control failed. reason:
  984. // "+e.message); },
  985. // appControlReplyCallback );
  986. // tizen.application.launch("tizen.bluetooth",
  987. // function(){log("launch service succeeded");},
  988. // function(e){log("launch service failed. Reason: " + e.name);});
  989. // var appControl = new
  990. // tizen.ApplicationControl("http://tizen.org/appcontrol/operation/bluetooth/pick",
  991. // "Phone/Images/image16.jpg");
  992. // tizen.application.launchAppControl(appControl, null,
  993. // function(){log("launch service succeeded");},
  994. // function(e){log("launch service failed. Reason: " + e.name);});
  995. }
  996. function sendMessage() {
  997. var message = "This is the position I want to show you from Mapo:"
  998. + "\nLatitude=" + $("#lat").val() + "\nLongitude = "
  999. + $("#lon").val() + "\nIf you prefer in DMS, here it is: "
  1000. + $('#dms').val()
  1001. + "\nYou can see this position on OpenStreetMap: " + getLink('OSM')
  1002. + "\nConnect you on Mapo for more details!";
  1003. var appControl = new tizen.ApplicationControl(
  1004. "http://tizen.org/appcontrol/operation/compose", null, null, null,
  1005. [
  1006. new tizen.ApplicationControlData(
  1007. "http://tizen.org/appcontrol/data/messagetype",
  1008. [ "sms" ]),
  1009. new tizen.ApplicationControlData(
  1010. "http://tizen.org/appcontrol/data/text",
  1011. [ message ]) ]);
  1012. tizen.application.launchAppControl(appControl, "tizen.messages",
  1013. function() {
  1014. log("launch service succeeded");
  1015. }, function(e) {
  1016. handleError("launch service failed. Reason: " + e);
  1017. });
  1018. }
  1019. /*
  1020. * Settings Manager
  1021. */
  1022. function settings() {
  1023. var url = "http://tizen.org/appcontrol/operation/configure/location";
  1024. var appControl = new tizen.ApplicationControl(url, null, null);
  1025. tizen.application.launchAppControl(appControl, "tizen.settings",
  1026. function() {
  1027. log("launch appControl succeeded");
  1028. }, function(e) {
  1029. handleError("launch appControl failed. Reason: " + e.name);
  1030. }, null);
  1031. }
  1032. /*
  1033. * Caller Manager : may not be needed
  1034. */
  1035. function call() {
  1036. var appControl = new tizen.ApplicationControl(
  1037. "http://tizen.org/appcontrol/operation/dial", null, null);
  1038. tizen.application.launchAppControl(appControl, "tizen.phone", function() {
  1039. log("launch appControl succeeded");
  1040. }, function(e) {
  1041. log("error: launch appControl failed. Reason: " + e.name);
  1042. }, null);
  1043. }
  1044. // TODO:
  1045. // function caller(){
  1046. // var appControl = new tizen.ApplicationControl(
  1047. // "http://tizen.org/appcontrol/operation/call",
  1048. // null,
  1049. // null,
  1050. // null,
  1051. // [
  1052. // new
  1053. // tizen.ApplicationControlData("http://tizen.org/appcontrol/data/call/type",[
  1054. // "voice" ])
  1055. // ]
  1056. // );
  1057. // tizen.application.launchAppControl(appControl,"tizen.call",
  1058. // function(){log("launch appControl succeeded");},
  1059. // function(e){log("launch appControl failed. Reason: " + e.name);},
  1060. // null);
  1061. // }
  1062. /*
  1063. * Contact Manager
  1064. */
  1065. /**
  1066. * Use the Contact Application Control to add a contact with the corresponding
  1067. * position
  1068. */
  1069. function createContact() {
  1070. log("#{ createContact");
  1071. var addressbook = tizen.contact.getDefaultAddressBook();
  1072. var groups = addressbook.getGroups();
  1073. var idMapo = "-1";
  1074. for (var i = 0; i < groups.length; i++) {
  1075. log(groups[i].name);
  1076. if (groups[i].name == 'Mapo') {
  1077. idMapo = groups[i].id;
  1078. }
  1079. }
  1080. var group;
  1081. if (idMapo != "-1") {
  1082. group = addressbook.getGroup(idMapo);
  1083. log('Group already exists ' + group.id);
  1084. } else {
  1085. group = new tizen.ContactGroup('Mapo');
  1086. addressbook.addGroup(group);
  1087. log('Group added with id ' + group.id);
  1088. }
  1089. //TODO: edit contact is present
  1090. var contact = new tizen.Contact({
  1091. emails : [ new tizen.ContactEmailAddress("mapo.tizen@gmail.com") ],
  1092. urls : [ new tizen.ContactWebSite(getLink('OSM'), 'HOMEPAGE') ],
  1093. notes : [ 'Position: lat=' + $("#lat").val() + ' lon='
  1094. + $("#lon").val() ],
  1095. organizations : [ new tizen.ContactOrganization({
  1096. name : "Mapo"
  1097. }) ],
  1098. groupIds : [ group.id ]
  1099. });
  1100. addressbook.add(contact);
  1101. var appControl = new tizen.ApplicationControl(
  1102. "http://tizen.org/appcontrol/operation/social/edit",
  1103. null,
  1104. "vnd.tizen.item.type/vnd.tizen.contact",
  1105. null,
  1106. [
  1107. new tizen.ApplicationControlData(
  1108. "http://tizen.org/appcontrol/data/social/item_type",
  1109. [ "person" ]),
  1110. new tizen.ApplicationControlData(
  1111. "http://tizen.org/appcontrol/data/social/item_id",
  1112. [ contact.personId ]) ]);
  1113. tizen.application.launchAppControl(appControl, null, function() {
  1114. log("contact: launch service succeeded");
  1115. }, function(e) {
  1116. handleError("contact: launch service failed. Reason: " + e);
  1117. });
  1118. log("#} createContact");
  1119. }
  1120. /*
  1121. * Calendar Manager
  1122. */
  1123. /**
  1124. * Use the Contact Application Control to add an event in the calendar with the
  1125. * corresponding date
  1126. */
  1127. function createCalendarEvent() {
  1128. var calendar = tizen.calendar.getDefaultCalendar("EVENT");
  1129. var date = new Date();
  1130. var event = new tizen.CalendarEvent({
  1131. description : "Mapo Event",
  1132. summary : "Mapo",
  1133. startDate : new tizen.TZDate(date.getFullYear().toString(), date
  1134. .getMonth().toString(), date.getDate().toString(), date
  1135. .getHours().toString(), date.getSeconds().toString()),
  1136. duration : new tizen.TimeDuration(1, "HOURS"),
  1137. location : 'Position: lat=' + $("#lat").val() + ' lon='
  1138. + $("#lon").val()
  1139. });
  1140. calendar.add(event);
  1141. var url = "http://tizen.org/appcontrol/operation/social/edit";
  1142. var appControl = new tizen.ApplicationControl(url, null, null, null, [
  1143. new tizen.ApplicationControlData(
  1144. "http://tizen.org/appcontrol/data/social/item_type",
  1145. [ "event" ]),
  1146. new tizen.ApplicationControlData(
  1147. "http://tizen.org/appcontrol/data/social/item_id",
  1148. [ event.id.uid ]) ]);
  1149. tizen.application.launchAppControl(appControl, "tizen.calendar",
  1150. function() {
  1151. log("success: " + url);
  1152. }, function(e) {
  1153. handleError("launch service failed. Reason: " + e);
  1154. });
  1155. }
  1156. /*
  1157. * Settings Manager
  1158. */
  1159. /**
  1160. * Function called when the online swith is activated or desactived Verify if
  1161. * the the device has a connection before connecting the application
  1162. */
  1163. function switchOnline() {
  1164. log("#{ switchOnline: " + isOnline);
  1165. log($('#switchOnline').val());
  1166. isOnline = ("online" === $('#switchOnline').val());
  1167. if (isOnline && !navigator.onLine)
  1168. log("connect system's wifi before");
  1169. if (isOnline) {
  1170. isReady = (null === OpenLayers);
  1171. if (!isReady || (null === gmaps)) {
  1172. download();
  1173. }
  1174. } else {
  1175. isReady = false;
  1176. }
  1177. refresh();
  1178. log("#} switchOnline: " + isOnline);
  1179. }
  1180. /**
  1181. * Use the tactil swipe to change between every pages
  1182. * TODO : blink ?
  1183. */
  1184. function swipePage() {
  1185. $('div.ui-page').live("swipeleft", function() {
  1186. var nextpage = $(this).next('div[data-role="page"]');
  1187. // swipe using id of next page if exists
  1188. if (nextpage.length > 0) {
  1189. $.mobile.changePage(nextpage, {
  1190. transition : "slide",
  1191. reverse : false
  1192. });
  1193. }
  1194. });
  1195. $('div.ui-page').live("swiperight", function() {
  1196. var prevpage = $(this).prev('div[data-role="page"]');
  1197. // swipe using id of next page if exists
  1198. if (prevpage.length > 0) {
  1199. $.mobile.changePage(prevpage, {
  1200. transition : "slide",
  1201. reverse : true
  1202. });
  1203. }
  1204. });
  1205. }
  1206. function handleLoadedGmaps() {
  1207. log("#{ handleLoadedGmaps: + " + google);
  1208. gmaps = google;
  1209. isDownloaded = true;
  1210. refresh();
  1211. log("#} handleLoadedGmaps: + " + isDownloaded);
  1212. }
  1213. function downloadScriptsBody() {
  1214. log("#{ downloadScriptsBody: " + OpenLayers);
  1215. {
  1216. var element = document.createElement("script");
  1217. element.type = 'text/javascript';
  1218. element.src = url_openlayers;
  1219. document.body.appendChild(element);
  1220. }
  1221. {
  1222. var element = document.createElement("script");
  1223. element.type = 'text/javascript';
  1224. element.src = url_gmaps;
  1225. document.body.appendChild(element);
  1226. }
  1227. log("#} downloadScriptsBody: " + OpenLayers);
  1228. }
  1229. function download() {
  1230. log("#{ download: " + OpenLayers);
  1231. if (null == OpenLayers) {
  1232. $.getScript(url_openlayers, function() {
  1233. log("download:" + OpenLayers);
  1234. refresh();
  1235. $.getScript(url_gmaps, function() {
  1236. handleLoadedGmaps();
  1237. });
  1238. });
  1239. } else if (null == google) {
  1240. $.getScript(url_gmaps, function() {
  1241. handleLoadedGmaps();
  1242. });
  1243. } else {
  1244. handleLoadedGmaps();
  1245. }
  1246. // isLoaded = true; // TODO?
  1247. log("#} download: " + OpenLayers);
  1248. }
  1249. function initScripts() {
  1250. log("#{ initScripts: " + OpenLayers);
  1251. log("# isDownloaded=" + isDownloaded);
  1252. if (false === isDownloaded) {
  1253. download();
  1254. } else {
  1255. download();
  1256. refresh();
  1257. }
  1258. log("#} initScripts: " + OpenLayers);
  1259. }
  1260. /**
  1261. * Initialize the data from the preceding use
  1262. */
  1263. function start() {
  1264. log("#{ start: " + OpenLayers);
  1265. initData();
  1266. initSettings();
  1267. initScripts();
  1268. // refresh();
  1269. if (false) { // TODO: buggy flash screen
  1270. swipePage();
  1271. }
  1272. // refresh();
  1273. log("#} start: " + OpenLayers);
  1274. }