implemented longclick functionality + ui rearrangement + geo loc conversion functions
[outofuni/glowingpatrol.git] / app / www / js / index.js
1 /*
2  *
3  * glowingpatrol: simple app to report and locate meter maids
4  * author: hackbrd@hackdaworld.org
5  *
6  */
7
8 /*
9  * Licensed to the Apache Software Foundation (ASF) under one
10  * or more contributor license agreements.  See the NOTICE file
11  * distributed with this work for additional information
12  * regarding copyright ownership.  The ASF licenses this file
13  * to you under the Apache License, Version 2.0 (the
14  * "License"); you may not use this file except in compliance
15  * with the License.  You may obtain a copy of the License at
16  *
17  * http://www.apache.org/licenses/LICENSE-2.0
18  *
19  * Unless required by applicable law or agreed to in writing,
20  * software distributed under the License is distributed on an
21  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
22  * KIND, either express or implied.  See the License for the
23  * specific language governing permissions and limitations
24  * under the License.
25  */
26
27 var ui = {
28         width: 0,
29         height: 0,
30         fb: {},
31         winwidth: 0,
32         winheight: 0,
33         touchtimer: null,
34         longtouch: false,
35         init: function(event_cb) {
36                 // width and height auf io and map window
37                 var bw=1;
38                 ui.height=$(window).height();
39                 ui.width=$(window).width();
40                 cl("init: width="+ui.width+", height="+ui.height);
41                 ui.winwidth=(ui.width-1)/2;
42                 ui.winheight=ui.height;
43                 if(ui.height>ui.width) {
44                         ui.winwidth=ui.width;
45                         ui.winheight=(ui.height-1)/2;
46                 }
47                 cl("init: winwidth="+ui.winwidth+", winheight="+ui.winheight);
48                 $('#io').css('width',ui.winwidth-2*bw);
49                 $('#io').css('height',ui.winheight-2*bw);
50                 $('#io').css('border',bw+"px solid black");
51                 $('#map').css('width',ui.winwidth-2*bw);
52                 $('#map').css('height',ui.winheight-2*bw);
53                 $('#map').css('border',bw+"px solid black");
54                 // io events (navigation)
55                 $('.ionavbtn').click(function(event) {
56                         ui.nav_event(event);
57                 });
58                 // io events (ctrl, info and settings windows)
59                 $('.fwbtn').click(function(event) {
60                         event_cb(event,'click');
61                 });
62                 $('.hwbtn').click(function(event) {
63                         event_cb(event,'click');
64                 });
65                 $('.twbtn').click(function(event) {
66                         event_cb(event,'click');
67                 });
68                 // click and long click events
69                 $('.longclickbtn').mouseup(function(event) {
70                         clearTimeout(ui.touchtimer);
71                         if(!ui.longtouch) {
72                                 event_cb(event,'click');
73                                 ui.longclick($(this).attr('data-id'),false);
74                         }
75                         return false;
76                 });
77                 $('.longclickbtn').mousedown(function(event) {
78                         ui.longtouch=false;
79                         ui.touchtimer=setTimeout(function() {
80                                 ui.longtouch=true;
81                                 var did=$(event.target).attr('data-id');
82                                 ui.longclick(Number(did),true);
83                                 event_cb(event,'longclick');
84                         },500);
85                         return false;
86                 });
87         },
88         longclick: function(did,long) {
89                 var str="click event: "+did;
90                 if(long)
91                         str="long"+str;
92                 cl(str);
93         },
94         draw: function() {
95                 ui.draw_io();
96                 ui.draw_map();
97         },
98         draw_io: function() {
99         },
100         draw_map: function() {
101         },
102         nav_event: function(event) {
103                 $('.ionavbtn').each(function() {
104                         var s="#"+this.id;
105                         if(event.target.id==this.id) {
106                                 $(s).css('background-color',ionav_col_active);
107                         }
108                         else {
109                                 $(s).css('background-color',ionav_col_default);
110                         }
111                 });
112                 var trgwin=event.target.id+"win";
113                 ui.main_show(trgwin);
114         },
115         main_show: function(win) {
116                 $('.iomainwin').each(function() {
117                         var s="#"+this.id;
118                         if(this.id==win) {
119                                 $(s).css('display','block');
120                         }
121                         else {
122                                 $(s).css('display','none');
123                         }
124                 });
125         },
126         vert_align_text: function(trg) {
127                 /* code snippet to vertically align text inside trg divs */
128                 $(trg).each(function() {
129                         var lh=$(this).parent().height();
130                         $(this).css('line-height',lh+'px');
131                         $(this).css('vertical-align','middle');
132                 });
133         },
134         draw_content: function(id,content) {
135                 var s='#'+id;
136                 $(s).html(content);
137         },
138         set_switch: function(id,active,txt) {
139                 var col=ionav_col_default;
140                 var trg='#'+id;
141                 if(active) {
142                         col=ionav_col_active;
143                 }
144                 if(txt!==undefined) {
145                         $(id).html(txt);
146                 }
147                 $(trg).css('background-color',col);
148         },
149         
150 }
151
152 var geo = {
153         loc: geo_default_loc,
154         locupd: null,
155         init: function(cb) {
156                 cl("geo: init");
157                 geo.getpos(cb);
158                 geo.locupd=setInterval(function() {
159                         geo.getpos(cb);
160                 },10000);
161         },
162         getpos: function(cb) {
163                 if(navigator.geolocation) {
164                         navigator.geolocation.getCurrentPosition(function(pos) {
165                                 geo.loc=pos;
166                                 cb(geo.loc,'success');
167                         }, function(err) {
168                                 cl("geo: error="+err.code);
169                                 cb(geo.loc,'error',err.code);
170                         });
171                 }
172                 else {
173                         cb(geo.loc,'unsupported');
174                 }
175         },
176         loc2ll: function(loc) {
177                 var ll={};
178                 if('coords' in loc) {
179                         ll[0]=loc.coords.latitude;
180                         ll[1]=loc.coords.longitue;
181                 }
182                 else if('latitude' in loc) {
183                         ll[0]=loc.latitude;
184                         ll[0]=loc.longitude;
185                 }
186                 else {
187                         return loc;
188                 }
189                 return ll;
190         }
191 };
192
193 var map = {
194         markc: {},
195         marks: {},
196         marko: {},
197         mobj: {},
198         tile: {},
199         center: map_default_center,
200         zoom: map_default_zoom,
201         init: function(mapdiv,loc,zoom) {
202                 var tpobj={
203                         'attribution': map_tp_attr,
204                         'maxZoom': map_tp_mzoom
205                 };
206                 var lobj={
207                         'center': loc,
208                         'zoom': zoom
209                 };
210                 map.tile=L.tileLayer(map_tp_url,tpobj);
211                 map.mobj=L.map(mapdiv,lobj);
212                 map.tile.addTo(map.mobj);
213         },
214         ll: function(loc) {
215                 var ll={};
216                 if('coords' in loc) {
217                         ll=L.latLng(loc.coords.latitude,loc.coords.longitude);
218                 }
219                 else if('latitude' in loc) {
220                         ll=L.latLng(loc.latitude,loc.longitude);
221                 }
222                 else {
223                         ll=L.latLng(loc[0],loc[1]);
224                 }
225                 return ll;
226         },
227         showpos: function(loc) {
228                 var zoom=15;
229                 map.mobj.setView(map.ll(loc),zoom);
230         },
231         set_mark: function(coord,type) {
232                 var prop= {};
233                 var ll=map.ll(coord);
234                 if(type=='current') {
235                         prop.color='green';
236                         prop.fillColor='green';
237                         prop.fillOpacity=1.0;
238                         map.mobj.removeLayer(map.markc);
239                         map.markc=L.circle(ll,20,prop).addTo(map.mobj);
240                 }
241                 if(type=='stored') {
242                         mark=map.marks;
243                         prop.color='blue';
244                         prop.fillColor='blue';
245                         prop.fillOpacity=1.0;
246                         map.mobj.removeLayer(map.marks);
247                         map.marks=L.circle(ll,20,prop).addTo(map.mobj);
248                 }
249         },
250         remove_mark: function(type) {
251                 switch(type) {
252                 case 'current':
253                         map.mobj.removeLayer(map.markc);
254                         break;
255                 case 'stored':
256                         map.mobj.removeLayer(map.marks);
257                         break;
258                 }
259         }
260 };
261
262 var gp = {
263         init: function() {
264                 document.addEventListener('deviceready',this.startup,false);
265                 window.addEventListener('orientationchange',function() {
266                         alert("change in orientation detected, rotating ...");
267                         ui.init();
268                         ui.draw();
269                 });
270         },
271         startup: function() {
272                 // ui
273                 ui.init(gp.event_action);
274                 ui.draw();
275                 ui.main_show("ctrlwin");
276
277                 // map
278                 mapdiv=document.getElementById('map');
279                 map.init(mapdiv,geo.loc,map_default_zoom);
280
281                 // db
282                 //idb.name='gp';
283                 //idb.del();
284                 var stores={
285                         'geo': db_geo_config,
286                         'map': db_map_config
287                 };
288                 idb.init('gp',gp.dbcallback,1,stores);
289
290                 // geo
291                 geo.init(gp.geocallback);
292         },
293         dbcallback: function() {
294                 // stored location
295                 idb.get_store_items('geo',function(item) {
296                         var str="Update locion";
297                         if(!item[1].update) {
298                                 var ll=geo.loc2ll(geo.loc);
299                                 str="Stored location<br>"+
300                                      ll[0].toFixed(3)+","+ll[1].toFixed(3)+")";
301                         }
302                         ui.draw_content('ioctrlstore',str);
303                         ui.set_switch('ioctrlstore',item[1].update);
304                         gp.status.geo.coords=item[1].coords;
305                 },0,-1);
306                 // map settings
307                 idb.get_store_items('map',function(item) {
308                         ui.set_switch('ioctrlcurrent',item[1].recenter)
309                         ui.set_switch('ioctrlstored',!(item[1].recenter))
310                         gp.status.map.recenter=item[1].recenter;
311                         if(item[1].current) {
312                                 idb.get_store_items('geo',function(item) {
313                                         map.set_mark(item[1].coords,'current');
314                                 },0,-1);
315                         }
316                         ui.set_switch('ioctrldisc',item[1].current);
317                         gp.status.map.current=item[1].current;
318                         idb.get_store_items('geo',function(it) {
319                                 if(item[1].stored)
320                                         map.set_mark(item[1].coords,'stored');
321                         },0,-1);
322                         ui.set_switch('ioctrldiss',item[1].stored);
323                         gp.status.map.stored=item[1].stored;
324                         ui.set_switch('ctrldissobj',item[1].objects);
325                         gp.status.map.objects=item[1].objects;
326                 },0,-1);
327         },
328         geocallback: function(loc,msg,code) {
329                 if(msg!='success') {
330                         var str='geocallback error: ';
331                         switch(code) {
332                         case 0:
333                                 str+="unknown error";
334                                 break;
335                         case 1:
336                                 str+="permission denied";
337                                 break;
338                         case 2:
339                                 str+="position unavailable";
340                                 break;
341                         case 3:
342                                 str+="timed out";
343                                 break;
344                         }
345                 }
346                 else {
347                         if(gp.status.map.current)
348                                 map.set_mark(loc,'current');
349                         if(gp.status.map.recenter)
350                                 map.showpos(loc);
351                 }
352         },
353         event_action: function(event,type) {
354                 if(type=="click") {
355                         switch(event.target.id) {
356                         case 'whatsoever':
357                                 gp.button_event(event.target.id);
358                                 break;
359                         default:
360                                 gp.switch_event(event.target.id);
361                                 break;
362                         }
363                 }
364                 if(type=="longclick") {
365                         cl("going to do some longclick action ...");
366                 }
367         },
368         switch_event: function(id) {
369                 cl("event from id "+id);
370                 var nstat=true;
371                 switch(id) {
372                 case 'ioctrlstore':
373                         idb.get_store_items('geo',function(item) {
374                                 var str="Update location";
375                                 if(item[1].update) {
376                                         nstat=false;
377                                         item[1].coords=geo.loc;
378                                         var ll=geo.loc2ll(geo.loc);
379                                         str="Stored location<br>("+
380                                             ll[0].toFixed(3)+","+
381                                             ll[1].toFixed(3)+")";
382                                 }
383                                 item[1].update=nstat;
384                                 idb.update_store_item('geo',1,item[1],
385                                                       function() {
386                                         gp.status.geo.coords=item[1].coords;
387                                         ui.draw_content(id,str);
388                                         ui.set_switch(id,nstat);
389                                         var loc=geo.loc
390                                         if(!gp.status.map.recenter)
391                                                 loc=item[1].coords;
392                                         map.showpos(loc);
393                                 },0,-1);
394                         },0,-1);
395                         break;
396                 case 'ioctrlcurrent':
397                         idb.get_store_items('map',function(item) {
398                                 item[1].recenter=true;
399                                 ui.set_switch(id,true)
400                                 ui.set_switch('ioctrlstored',false)
401                                 gp.status.map.recenter=true;
402                                 map.showpos(geo.loc);
403                                 idb.update_store_item('map',1,item[1]);
404                         },0,-1);
405                         break;
406                 case 'ioctrlstored':
407                         idb.get_store_items('map',function(item) {
408                                 item[1].recenter=false;
409                                 ui.set_switch('ioctrlcurrent',false)
410                                 ui.set_switch(id,true)
411                                 gp.status.map.recenter=false;
412                                 map.showpos(gp.status.geo.coords);
413                                 idb.update_store_item('map',1,item[1]);
414                         },0,-1);
415                         break;
416                 case 'ioctrldisc':
417                         idb.get_store_items('map',function(item) {
418                                 nstat=true;
419                                 if(item[1].current)
420                                         nstat=false;
421                                 ui.set_switch(id,nstat);
422                                 gp.status.map.current=nstat;
423                                 item[1].current=nstat;
424                                 idb.update_store_item('map',1,item[1]);
425                                 if(nstat)
426                                         map.set_mark(geo.loc,'current');
427                                 else
428                                         map.mobj.removeLayer(map.markc)
429                                 
430                         },0,-1);
431                         break;
432                 case 'ioctrldiss':
433                         idb.get_store_items('map',function(item) {
434                                 nstat=true;
435                                 if(item[1].stored)
436                                         nstat=false;
437                                 ui.set_switch(id,nstat)
438                                 gp.status.map.stored=nstat;
439                                 item[1].stored=nstat;
440                                 idb.update_store_item('map',1,item[1]);
441                                 if(nstat)
442                                         map.set_mark(
443                                                 gp.status.geo.coords,'stored'
444                                         );
445                                 else
446                                         map.mobj.removeLayer(map.marks)
447                         },0,-1);
448                         break;
449                 case 'ioctrldiso':
450                         idb.get_store_items('map',function(item) {
451                                 nstat=true;
452                                 if(item[1].objects)
453                                         nstat=false;
454                                 ui.set_switch(id,nstat)
455                                 gp.status.map.objects=nstat;
456                                 item[1].objects=nstat;
457                                 idb.update_store_item('map',1,item[1]);
458                         },0,-1);
459                         break;
460                 }
461         },
462         button_event: function(id) {
463                 var txt='Reporting ';
464                 var s="#"+id;
465                 var obj=$(s);
466                 txt=txt+id+"!";
467                 cl(txt);
468                 alert(txt);
469         },
470         status: {
471                 geo: {
472                         coords: [0,0],
473                         update: true
474                 },
475                 map: {
476                         recenter: true,
477                         current: true,
478                         stored: true,
479                         objects: true
480                 }
481         }
482 };
483
484 $(document).ready(function() {
485         if('cordova' in window) {
486                 gp.init();
487         }
488         else {
489                 gp.startup();
490         }
491 });
492