forked from bferster/VisualEyes-5
-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.htm
854 lines (799 loc) · 40.7 KB
/
index.htm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<link REL="SHORTCUT ICON" HREF="img/shanti.ico">
<title>VisualEyes</title>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<link rel="stylesheet" href="//ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/themes/smoothness/jquery-ui.css" />
<script src="//ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/jquery-ui.min.js"></script>
<script src="jquery.ui.touch-punch.min.js"></script>
<link rel="stylesheet" href="http://openlayers.org/en/v3.5.0/css/ol.css" type="text/css">
<script src="http://openlayers.org/en/v3.5.0/build/ol-debug.js" type="text/javascript"></script>
<script type="text/javascript" src='//www.google.com/jsapi?autoload={"modules":[{"name":"visualization","version":"1"}]}'></script>
<script src="//www.qmediaplayer.com/qfile.js"></script>
<script src="space.js" type="text/javascript"></script>
<script src="time.js" type="text/javascript"></script>
<script src="popup.js" type="text/javascript"></script>
<script src="data.js" type="text/javascript"></script>
<script src="story.js" type="text/javascript"></script>
<style type="text/css">
body { font-family:Verdana,Geneva,sans-serif; font-size:9px;
padding:0px;margin:0px;
}
.popup-main { position:absolute;padding:12px;border-radius:6px;display:none;
border:1px solid #999;background-color:#fff;font-size:11px;
overflow-x:hidden;max-height:100px;max-width:300px;
}
.popup-webpage { position:absolute;padding:12px;border-radius:6px;display:none;
border:1px solid #999;background-color:#fff;font-size:11px;
}
.popup-pic { margin-right:8px;vertical-align:top;cursor:zoom-in;
border:1px solid #999;max-width:80px;max-height:60px;overflow:hidden;
}
.popup-desc { vertical-align:top;color:#555;cursor:zoom-in;
}
.popup-title { margin-bottom:8px;color:#555;
}
.popup-date { color:#999;font-size:9px;
}
.popup-cite { text-align:right;font-size:8px;color:#999;display:none;
}
.time-timebar { position:absolute;color:#999;
}
.time-seg { position:absolute;height:14px;text-align:center;padding-top:2px;
white-space:nowrap;overflow:hidden;cursor:pointer;
}
.time-startend { font-size:11px;font-weight:bold;color:#666;
}
.time-timeslider { background:#ccc;height:6px;border:none;display:inline-block;
}
.time-timeslider.ui-slider .ui-slider-handle {
height:30px;width:8px;margin-top:-8px;
background:#009900;border:none;cursor:pointer;
}
.time-slidertime { position:absolute;width:100px;text-align:center;
}
.time-ticks { position:absolute;width:2px;height:8px;background-color:#ccc;
}
.time-ticklabel { position:absolute;width:100px;text-align:center;color:#999
}
.time-timeplayer { position:absolute;color:#999;margin-left:18px;margin-right:18px;width:123px;
}
.time-playerslider{ background:#ccc;height:4px;width:80px;border:none;display:inline-block;
margin-left:6px;
}
.time-playerspeed { position:absolute;width:40px;text-align:center;font-size:9px;color:#999;
}
.time-playerslider.ui-slider .ui-slider-handle {
height:0px;width:0px;margin-top:7px;cursor:pointer;
border-left: 5px solid transparent;border-right: 5px solid transparent;
border-bottom: 8px solid #999;
}
.time-timeview { position:absolute;color:#666;overflow:hidden;width:100%;cursor:e-resize;
}
.time-labels { position:absolute;font-weight:bold;background-color:#f8f8f8;padding-left:4px;
height:16px;
}
.ve-unselectable { -moz-user-select: none; -khtml-user-select: none;
-webkit-user-select: none; -ms-user-select: none; user-select: none;
}
.story-title { margin:12px;font-size:24px;color:#555;font-weight:bold
}
.story-pic { margin-left:16px;vertical-align:top;cursor:zoom-in;margin-right:12px;
border:1px solid #999;max-width:100px;width:50%;float:left;
}
.story-desc { margin-left:16px;color:#333;font-size:11px;margin-right:12px;margin-bottom:10px
}
.story-header { margin-left:4px;font-size:12px;color:#555;font-weight:bold;margin-bottom:8px;
}
.story-date { color:#999;font-size:9px;
}
.story-cite { margin:12px;text-align:right;font-size:9px;color:#006600;
}
.story-return { position:absolute;top:8px;left:8px;border-radius:10px;padding-left:8px;padding-right:8px;
font-size:10px;height:13px;background-color:#eee;text-align:center;cursor:pointer;color:#990000;
}
.ve-base { position:absolute;height:100%;width:100%;
}
.ve-left { }
.ve-right { background-color:#eee;overflow-y:auto;
}
.ve-bottom { background-color:#f8f8f8;width:100%;
}
.ve-splash { text-align:center;vertical-align:center;pointer-events:none;
}
.ve-is { border-radius:10px;padding-left:8px;padding-right:8px;padding-top:1px;
border:1px solid #999;font-size:12px;height;20px;width:200px;
}
.ve-bs { border-radius:10px;padding-left:8px;padding-right:8px;padding-top:1px;
border:1px solid #999;font-size:12px;height;20px;color:#666;cursor:pointer;
}
</style>
</head>
<body>
<div id="showDiv" style="opacity:0" class="ve-base">
<div id="bottomDiv" style="position:absolute;top:0px;opacity:inherit" class="ve-bottom ve-unselectable">
<img id="settingsBut" src="img/settingsbut.gif" style="position:absolute;cursor:pointer">
</div>
<div id="leftDiv" style="position:absolute;opacity:inherit" class="ve-left"></div>
<div id="rightDiv" style="position:absolute;opacity:inherit" class="ve-right"></div>
<div id="lrSiz" style="position:absolute;width:8px;cursor:col-resize;opacity:inherit" class="ve-unselectable" title="Resize panes">
<div id="lrSiz1" style="position:absolute;width:20px;height:100%;left:-8px" class="ve-unselectable"></div>
</div>
<div id="bSiz" style="position:absolute;height:8px;width:100%;cursor:row-resize;opacity:inherit" class="ve-unselectable" title="Resize timeline">
<div id="bSiz1" style="position:absolute;height:20px;width:100%" class="ve-unselectable"></div>
</div>
</div>
<div id="splashDiv" class="ve-splash"><img src="img/velogo.png"></div>
<script>
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// DISPLAY
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
var curJson={},mps={},tln={},pop={},dtl={},sto={};
var paneAnimationTimer=null; // Times pane animations
var imageAnimationTimer=[]; // Times image animations
var isMobile=false; // Flag for mobile devices
var host="//viseyes.org/visualeyes/"; // Set host for database save/load
var userName="",password="",curShow=0; // Login info
var lastClickTime=0; // Store last click time
var drupalMan=false; // Flag for drupal manager
var curSpanStart,curSpanEnd,curTime; // Current timings
var qmf=null; // File system
var curShow=""; // Current show
var _this=this; // Save context for callbacks
var origLR=.66, origUD=.75; // Pane size to come back to
function ResizePanes() // RESIZE PANES
{
var wid=$("#showDiv").width(); // Width
var hgt=$("#showDiv").height(); // Height
var cx=wid*curJson.leftRightSplit; // Center
var cy=hgt*curJson.upDownSplit; // Center
$("#leftDiv").width(cx); // Set left width
$("#rightDiv").width(wid-cx); // Set right width
$("#rightDiv").css("left",cx+"px"); // Set right pos
$("#leftDiv").height(cy); // Set left height
$("#rightDiv").height(hgt); // Set right height
$("#lrSiz").css("left",cx+"px"); // Set lr size pos
$("#lrSiz").height(hgt); // Set lr size height
$("#bSiz").css("top",cy+"px"); // Set b size pos
$("#bSiz").width(cx); // Set b size width
$("#bottomDiv").width(cx); // Set bottom width
$("#bottomDiv").height(hgt-cy); // Set bottom height
$("#bottomDiv").css("top",cy+"px"); // Set lr size pos
$("#settingsBut").css({ top:$("#bottomDiv").height()-18,left:cx-18}); // Settings button
mps.UpdateMapSize(); // Update map size to div size
tln.UpdateTimeline(); // Update timeline to div size
}
function LoadShow(data) // LOAD A SHOW
{
if (data.qmfmsg == "private") { // If a private file
AlertBox("Private project","Sorry, but this project is marked <i>private</i>. You will need to supply the password to load it");
return; // Quit
}
else if (data.qmfmsg == "error") { // If an error
AlertBox("Sorry, but there was an error loading this project"); // Show
return; // Quit
}
if (qmf.curFile) // If a good file
curShow=qmf.curFile; // Set curshow
if (data.sheet) { // If a spreadsheet spec'd
dtl.GetSpreadsheet(data.sheet,true,null,function(mobs) { // Get spreadsheet data
var i,key;
for (i=0;i<mobs.length;++i) // For each mob
for (key in mobs[i]) { // For each field in mob
if (mobs[i][key]) // If not null
mobs[i][key]=(""+mobs[i][key]).replace(/(\s)$/,""); // Strip trailing space
}
data.mobs=mobs; // Set mobs
InitProject(data); // Re-init project
},true);
}
else
InitProject(data); // Init project
}
function InitProject(data) // INIT PROJECT
{
var i,s,e,v,t,id;
if (data) curJson=data; // If data, set it
if (!curJson.mobs) curJson.mobs=[]; // Alloc if empty
if (curJson.panTime == undefined) curJson.panTime=.5; // Default to 500ms
mps.ClearLayers(); // Clear all layera
if (!data) {
curJson.sheet="";
curJson.upDownSplit=.75;
curJson.leftRightSplit=.66;
}
origLR=curJson.leftRightSplit; // Save return ratio
origUD=curJson.upDownSplit; // Save return ratio
for (i=0;i<curJson.mobs.length;++i) { // For each mob
o=curJson.mobs[i]; // Point at mob
o.color=ColorToHex(o.color); // Convert named color
o.mapColor=ColorToHex(o.mapColor); // Convert named color
o.edge=ColorToHex(o.edge); // Convert named color
if (o.start) o.start=pop.DateToTime(o.start); // Convert date to time
if (o.end) o.end=pop.DateToTime(o.end); // Convert date to time
if (o.opacity > 1) o.opacity/=100; // 0-100 to 0-1
s=e=0; // Assume not timed
if (o.show) { // If show mode spec'd
if (o.show.match(/s/i)) s=o.start; // Start timed
if (o.show.match(/e/i)) e=o.end; // End timed
if (o.show.match(/off/i)) s=e=-1; // Hide it
if (o.show.match(/g/i)) s=o.start; // When controlled by timeline segment
}
if (o.marker || o.mapMarker) { // If a marker spec'd
var marker=o.mapMarker ? o.mapMarker : o.marker; // Use mapMarker first, then marker
o.type="icon"; // Assume icon
if (marker.match(/kml/i)) { // A KML file
o.type="kml"; // Set type
if (!isNaN(marker.split(".")[0])) // If a number only
marker="getkml.php?id="+marker.split(".")[0]; // Load from qdata
o.lid=mps.AddKMLLayer(marker,o.opacity,o.id,s,e); // Add KML layer
}
else if (o.marker && (o.marker.toLowerCase() == "path")) { // A path
var dots=[];
o.type="path"; // Set type
if (!o.desc) // No desc
continue; // Don't add
v=o.desc.split(","); // Split by comma
for (j=0;j<v.length;++j) { // For each one spec'd
id=curJson.mobs[FindMobByID(v[j])]; // Point at mob
if ((id == undefined) || (id < 0) || (!id.where)) // Mob not found or no where set
continue; // Skip it
t=id.start; // Get time
t=pop.DateToTime(t); // +/- min past 1970
if (!j) s=e=t; // Init to 1st mob
vv=(""+id.where).split(","); // Split into parts
vv=ol.proj.transform([vv[0]-0,""+vv[1]-0],'EPSG:4326',mps.curProjection); // Transform
vv.push(t); // Add time
dots.push(vv); // Add dot
s=Math.min(s,t); // Earliest
e=Math.max(e,t); // Latest
}
var ew=o.size ? o.size : 2; // Set size with 2 pixel default
var eo=o.opacity ? o.opacity : 1; // Set opacity with 1.0 default
if (o.mapMarker) { // If adding a header marker
sty={ m:o.mapMarker }; // Use mapMarker
o.mapColor ? sty.f=o.mapColor : sty.f=o.color; // Use map options first, then path options
o.mapEdge ? sty.s=o.mapEdge : sty.s=o.edge;
o.mapSize ? sty.w=o.mapSize : sty.w=o.size;
o.mapOpacity ? sty.a=o.mapOpacity : sty.a=eo;
o.header=mps.AddMarkerLayer("0,0",sty,i+"h","");
}
dots=dots.sort(function(a, b) { return a[2]-b[2]; }); // Sort ascending by time
o.lid=mps.AddPathLayer(dots,o.color,ew,eo,s,o.end ? o.end: e,o.show,o.header);// Add path to overlays
}
else if (marker.match(/\.png|.gif|\.jpg|\.jpeg|drive\.google/i) && o.where && ((""+o.where.split(",")).length > 3)) { // An image file with a full georef
o.type="image"; // Set type
marker=ConvertFromGoogleDrive(marker); // Get direct link if google drive
o.lid=mps.AddImageLayer(marker,o.where, o.opacity,s,e); // Add image layer
}
else if (marker.toLowerCase() == "segment") // A segment
o.type="segment"; // Set type
else if (marker.toLowerCase() == "init") // An init
o.type="init"; // Set type
else if (marker.toLowerCase() == "story") // An init
o.type="init"; // Set type
else if (o.marker && (o.marker.toLowerCase() == "label")) // A label
o.type="label"; // Set type
else if (marker.toLowerCase() == "data") { // Data
o.type="story"; // Set type
dtl.GetSpreadsheet(o.where, false, null, function(data) { // Get spreadsheet data
o.src=data // Save data
}, true);
}
else if (marker.match(/choro/i)) { // A choro
o.type="choro"; // Set type
o.base=FindMobByID(o.where.split(":")[0]); // Find mod index of base layer
if (o.base != -1) { // If found
o.base=curJson.mobs[o.base].lid; // Get layer id of base
o.lid=mps.AddChoroplethLayer(o.color,o.edge,o.size, o.opacity,o.base,o.where,s,e); // Add choro layer
}
}
else if (marker.match(/:/)) // A feature click
o.type="feature"; // Set type
else if (o.where) { // Must be an icon
var sty={}; // Not style
var eo=o.opacity ? o.opacity : 1; // Set opacity with 1.0 default
o.type="icon"; // Set type
o.mapMarker ? sty.m=o.mapMarker : sty.m=o.marker; // Use map marker first, then time marker
o.mapTitle ? sty.t=o.mapTitle : sty.t=o.title;
o.mapDesc ? sty.d=o.mapDesc : sty.d=o.desc;
o.mapColor ? sty.f=o.mapColor : sty.f=o.color;
o.mapEdge ? sty.s=o.mapEdge : sty.s=o.edge;
o.mapSize ? sty.w=o.mapSize : sty.w=o.size;
o.mapTextCol ? sty.tc=o.mapTextCol : sty.tc=curJson.mapTextCol;
o.mapTextFont ? sty.tf=o.mapTextFont : sty.tf=curJson.mapTextFont;
o.mapOpacity ? sty.a=o.mapOpacity : sty.a=eo;
mps.AddMarkerLayer(o.where,sty,i,s,e,o.show); // Add marker to overlays
}
}
}
mps.SetBaseMap(curJson.baseMap); // Set basemap layer
tln.InitTimeline(curJson); // Initialize timeline
mps.MarkerLayerToTop(); // Make marker layer the top-most layer
sto.InitStory(curJson); // Initialize story
ResizePanes(); // Resize panes
if (curJson.mapStartPos) mps.Goto(curJson.mapStartPos); // Position map
}
function Draw(time) // DRAW PROJECT
{
mps.UpdateMap(time,curJson.timeFormat,curJson.panTime); // Update map layers
// sto.UpdateStory(time,curJson.timeFormat); // Update story pane
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// EVENTS
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
$(document).ready(function() { // When loaded
var i;
if (window.addEventListener) // If supported this way
window.addEventListener("message",shivaEventHandler,false); // Add event handler
else // Use other method
window.attachEvent("message",shivaEventHandler); // Add handler
isMobile=navigator.userAgent.match(/(ipad|iphone|ipod|android)/i) ? true : false; // Set mobile flag
var url=window.location.search.substring(1); // Get query string
qmf=new QmediaFile("//qmediaplayer.com/",4); // Alloc file system
drupalMan=(""+url).match(/pr=d/); // If called from Drupal manager
if (!url) // Nothing on command line
url=456; // Use default
if (drupalMan) url=""; // If drupal, kill url
if (url && !isNaN(url)) { // If a number
curShow=url; // Save show number
url="//qmediaplayer.com/loadshow.php?id="+url; // Get from db
}
else if ((url) && (!url.match(/\./))) // No file extension
url+=".json"; // Add txt
$.ajax({ url: url, dataType:'jsonp' }); // Get jsonp and call LoadShow() from it
$("#lrSiz").draggable({ // DRAG L-R WIDTH HANDLER
cursorAt:{left:16}, iframeFix:true, // Cursor offset
cursor: "col-resize", axis:"x", // X-only
start: function(event, ui) { // On drag start
$("#lrSiz1").css({ width:"500px", left:"-500px" }); // Widen hiding div
},
drag: function(event, ui) { // On drag
var wid=$("#showDiv").width(); // Max width
curJson.leftRightSplit=Math.max(0,Math.min(1,(event.clientX-8)/wid));// Set ratio between windows
if (Math.abs(curJson.leftRightSplit-.66) < .015) // If close to center
curJson.leftRightSplit=.66; // Snap it there
ResizePanes(); // Resize panes
},
stop: function(event, ui) { // On drag end
$("#lrSiz1").css({ width:"20px", left:"-8px" }); // Contract hiding div
ResizePanes(); // Resize panes
}
});
$("#bSiz").draggable({ // DRAG TRANSCRIPT HEIGHT HANDLER
cursor: "row-resize", axis:"y", // Y-only
stop: function(event, ui) { // When done
ResizePanes; // Resize panes when done
},
drag: function(event, ui) { // On drag
var hgt=$("#showDiv").height(); // Max height
curJson.upDownSplit=Math.max(0,Math.min(1,(event.clientY-8)/hgt)); // Set ratio between windows
if (Math.abs(curJson.upDownSplit-.75) < .015) // If close to center
curJson.upDownSplit=.75; // Snap it there
ResizePanes(); // Resize panes
}
});
$("#lrSiz").hover( // L-R width
function(){ $(this).css("background-color","#acc3db")}, // Highlight
function(){ $(this).css("background-color","transparent") // Hide
});
$("#bSiz").hover( // Bottom height
function(){ $(this).css("background-color","#acc3db")}, // Highlight
function(){ $(this).css("background-color","transparent") // Hide
});
$("#splashDiv").delay(1000).animate({ opacity:0},500); // Hide logo
$("#showDiv").animate({ opacity:1},5000, function() { // Show interface
ResizePanes(); // Resize panes
});
$(window).resize(ResizePanes); // Dynamic resizing
pop=new Popup("leftDiv"); // Alloc popup module
mps=new Space("leftDiv",pop); // Alloc map module
tln=new Timeline("bottomDiv",pop); // Alloc time module
dtl=new DataLoad(); // Alloc data module
sto=new Story("rightDiv",pop); // Alloc story module
mps.InitMap(); // Init map
InitProject(); // Init project
if (drupalMan) // If called from Drupal manager
window.parent.postMessage("ShivaReady=true","*"); // Send message to parent wind
});
function SendShivaMessage(src, msg) // SEND SHIVA MESSAGE
{
var str=src; // Add src and window
if (msg) // If more to it
str+="|"+msg; // Add it
if (window.parent) // If has a parent
window.parent.postMessage(str,"*"); // Send message to parent wind
else // Local
window.postMessage(str,"*"); // Send message to wind
}
function shivaEventHandler(e) // ON SHIVA EVENT
{
// trace(e.data);
if (e.data && e.data.match(/Space=/)) { // If a space event
var v=e.data.split("|"); // Split into parts
if (e.data.match(/=time/i)) // Set time
tln.Goto(v[1]); // Move timeline
if (e.data.match(/=where/i)) // Set position
mps.Goto(v[1]) // Move map
if (e.data.match(/=zoom/i)) { // Set position
$("#rightDiv").html(""); // Clear div
var vv=v[1].split(","); // Divide param
if (vv[1]) // If a percentage spec'd
AnimatePanes("map",vv[1]/100,undefined,function() { // Animate pane there
pop.DrawZoomer("rightDiv",vv[0],2,4); // Show zoomer
$("#rightDiv").append("<br><div class='story-return' style='position:static' onclick='ClearPopUps();sto.pop.Sound(\"click\",curJson.muteSound)'>Back to story</div>");
});
else{
pop.DrawZoomer("rightDiv",vv[0],2,4); // Show zoomer
$("#rightDiv").append("<br><div class='story-return' style='position:static' onclick='ClearPopUps();sto.pop.Sound(\"click\",curJson.muteSound)'>Back to story</div>");
}
}
else if (e.data.match(/=show/i)) { // Set position
var i;
var vv=v[1].split(","); // Get array of ids
for (i=0;i<vv.length;++i) // For each one spec'd
if (vv[i] && (vv[i].match(/\/\//))) // A url
ShowIframe(vv[i]); // Show in story pane
}
}
else if (e.data && e.data.match(/Time=/)) { // If a time event
var v=e.data.split("|"); // Split into parts
if (e.data.match(/=where/i)) // Set position
mps.Goto(v[1]) // Move map
else if (e.data.match(/=time/i)) // New time
Draw(v[1]) // Redraw
if (e.data.match(/=zoom/i)) { // Set position
$("#rightDiv").html(""); // Clear div
var vv=v[1].split(","); // Divide param
if (vv[1]) // If a percentage spec'd
AnimatePanes("map",vv[1]/100,undefined,function() { // Animate pane there
pop.DrawZoomer("rightDiv",vv[0],2,4); // Show zoomer
$("#rightDiv").append("<br><div class='story-return' style='position:static' onclick='ClearPopUps();sto.pop.Sound(\"click\",curJson.muteSound)'>Back to story</div>");
});
else{
pop.DrawZoomer("rightDiv",vv[0],2,4); // Show zoomer
$("#rightDiv").append("<br><div class='story-return' style='position:static' onclick='ClearPopUps();sto.pop.Sound(\"click\",curJson.muteSound)'>Back to story</div>");
}
}
else if (e.data.match(/=show/i)) { // Set position
var i;
var vv=v[1].split(","); // Get array of ids
for (i=0;i<vv.length;++i) // For each one spec'd
if (vv[i] && (vv[i].match(/\/\//))) // A url
ShowIframe(vv[i]); // Show in story pane
else
vv[i]=FindMobByID(vv[i]); // Convert to mob index
mps.DrawMapLayers(vv,v[2]) // Show markers(s)
}
}
}
$("#settingsBut").click(function(e) { // SETTINGS BUTTON CLICK
if (e.ctrlKey && curJson.sheet) { // If just refreshing spreadsheet
dtl.GetSpreadsheet(curJson.sheet,true,null,function(data) { // Get spreadsheet data
curJson.mobs=data; // Set mobs
InitProject(curJson); // Re-init project
},true);
pop.Sound("ding"); // Ding
return; // Quit
}
var str="<table><tr height='18'>";
str+="<tr><td>Mute clicks?</td><td><input id='setmute' type='checkbox'></td></tr>";
str+="<tr><td>Title</td><td><input id='settitle' class='ve-is' style='width:220px' type='input'></td></tr>";
str+="<tr><td>Spreadsheet</td><td><input id='setsheet' class='ve-is' style='width:220px' type='input'></td></tr>";
str+="<tr><td>L-R split % </td><td>";
str+="<input id='setlr' class='ve-is' style='width:30px' type='input'> U-D split % ";
str+="<input id='setud' class='ve-is' style='width:30px' type='input'></td></tr>";
str+="<tr><td>Start/end </td><td>";
str+="<input id='setstart' class='ve-is' style='width:70px' value='"+curJson.start+"' type='input'> to ";
str+="<input id='setend' class='ve-is' style='width:70px' value='"+curJson.end+"' type='input'></td></tr>";
str+="<tr><td>Date format </td><td>";
str+=MakeSelect("settime",false,["Year","Mo/Year","Mon Year","Mo/Day/Year","Mon Day, Year"],curJson.timeFormat)+"</td></tr>";
str+="<tr><td>Map label color</td><td><input id='setstcol' class='ve-is' style='width:50px' type='input'></td></tr>";
str+="<tr><td>Map Label font</td><td><input id='setstfont' class='ve-is' style='width:160px' type='input'></td></tr>";
str+="<tr><td>Map start</td><td><input id='setstartpos' class='ve-is' style='width:220px' type='input'></td></tr>";
str+="<tr><td>Map base </td><td>"+MakeSelect("setbase",false,["Satellite","Terrain","Earth","Watercolor","B&W","Roadmap"],curJson.baseMap);
str+="<tr><td>Map pan time</td><td><input id='setpan' class='ve-is' style='width:80px' type='input'> <i>(in seconds)</i></td></tr>";
str+="<tr><td>Map location</td><td><input id='setwhere' class='ve-is' style='width:220px' type='input'></td></tr>";
str+="<tr><td>Map point</td><td><input id='setpoint' class='ve-is' style='width:220px' type='input'></td></tr>";
str+="<tr><td colspan=2><br></td> <tr>";
str+="<tr><td>Options</td><td>"+MakeSelect("setfile",false,["Choose","Load","Save","Save as...","Delete","Undelete","Drawing","Geo-reference"],"Save/Load");
str+="  <i>"+(_this.curShow ? "#"+_this.curShow : '')+"</i> "
str+="Help <a href='https://docs.google.com/document/d/161td5ZuqKqT5R5r9z1P8AxBA6l9LaP-eYl_RvCyvw2g/edit?usp=sharing' target='_blank'>";
str+="<img src='img/helpicon.gif' style='vertical-align:bottom' title='Show help'></a></td>";
str+="</tr></table>";
pop.Dialog("VisualEyes settings",str, function() {
getDataFromInputs(); // Get data from inputs
if (curJson.sheet) { // If a sheet spec'd
dtl.GetSpreadsheet(curJson.sheet,true,null,function(data) { // Get spreadsheet data
curJson.mobs=data; // Set mobs
InitProject(curJson); // Re-init project
},true);
}
else // No sheet spec'd
InitProject(curJson); // Re-init project
});
$("#setpan").val(curJson.panTime); // Set pan time
$("#setbase").val(curJson.baseMap); // Set base
$("#settime").val(curJson.timeFormat); // Set timeformat
$("#setstart").val(curJson.start); // Set start
$("#setend").val(curJson.end); // Set end
$("#setstcol").val(curJson.mapTextCol); // Set map label color
$("#setstfont").val(curJson.mapTextFont); // Set map label font
$("#setsheet").val(curJson.sheet); // Set spreadsheet
$("#settitle").val(curJson.title); // Set title
$("#setstartpos").val(curJson.mapStartPos); // Set map starting position
$("#setlr").val(Math.floor(curJson.leftRightSplit*100)); // Set lr split
$("#setud").val(Math.floor(curJson.upDownSplit*100)); // Set ud split
pop.ColorPicker("setstcol",-1,true); // Init color
function getDataFromInputs() { // GET DATA FROM DIALOG ELEMENTS
curJson.panTime=$("#setpan").val(); // Set map pan time
curJson.mapTextCol=$("#setstcol").val(); // Set map label color
curJson.mapTextFont=$("#setstfont").val(); // Set map label font
curJson.start=$("#setstart").val(); // Set start
curJson.leftRightSplit=Math.min(1,Math.max(0,$("#setlr").val()/100)); // Set lr split
curJson.upDownSplit=Math.min(1,Math.max(0,$("#setud").val()/100)); // Set ud split
curJson.end=$("#setend").val(); // Set end
curJson.mapStartPos=$("#setstartpos").val(); // Set end
curJson.title=$("#settitle").val(); // Set sheet
curJson.sheet=$("#setsheet").val(); // Set sheet
tln.timeFormat=curJson.timeFormat=$("#settime").val(); // Get timeformat
curJson.baseMap=$("#setbase").val(); // Get base
mps.SetBaseMap(curJson.baseMap); // Set basemap layer
curJson.muteSound=$("#setmute").prop("checked"); // Set mute
}
$("#setbase").on("change", function(e) { // BASE HANDLER
mps.SetBaseMap($("#setbase").val()); // Set basemap layer
});
$("#setstcol").on("click", function(e) { // LAB COLOR HANDLER
pop.ColorPicker("setstcol",-1); // Set label text color
});
$("#setfile").on("change", function(e) { // BASE HANDLER
switch($(this).val()) { // Route on choice
case "Load" : // Load
$("#dialogDiv").remove(); // Close dialog
qmf.Load(); // Get data
break;
case "Save" : // Save
getDataFromInputs(); // Get data from inputs
qmf.Save(0); // Save data
break;
case "Save as...": qmf.Save(1); break; // Save as..
case "Delete": qmf.Delete(0); break; // Delete
case "Undelete": qmf.Delete(1); break; // Undelete
case "Drawing": mps.DrawingTool(); break; // Run KML drawing tool
case "Geo-reference": mps.GeoReference("//farm9.staticflickr.com/8019/7310697988_18eb47c466_z.jpg"); break; // Georef
}
$(this).val("Choose"); // Reset select
});
}); // End settings
function SaveUserData(data, type) // SAVE DATA TO USERDATA
{
pop.LogIn( function(userName, password, title) { // Log in
var dat={};
var url=host+"savedata.php"; // Base file
dat["email"]=userName; // Add email
dat["password"]=password; // Add password
dat["title"]=title; // Add title
dat["type"]=type; // Add type
dat["data"]=data.replace(/"/g,"\\\"");
$.ajax({ url:url,dataType:'text',type:"POST",crossDomain:true,data:dat, // Post data
success: function(d) { // On success
if (d.match(/new:/i)) // Success
_this.pop.Sound("ding"); // Ding
else // Failure
_this.pop.Sound("delete"); // Error sound
},
error: function(xhr,status,error) { // Error
_this.pop.Sound("delete") // Error sound
}
});
},true); // Ask for title too
}
function GetUserData(type) // LOAD USER DATA FILE
{
pop.LogIn( function(userName, password) { // Log in
var url=host+"getdata.php?type="+type; // Base file
if (userName) url+="&email="+userName; // If email, add to query line
$.ajax({ url:url, dataType:'jsonp'}); // Get data and pass to popListFiles()
});
}
function LoadUserData(data) // HANDLE INCOMING DATA LOAD
{
var i,f,s,os;
var fs=new ol.format.KML().readFeatures(data.data); // Read in features
for (i=0;i<fs.length;++i){ // For each feature
f=fs[i].clone(); // Clone feature
if (f.get("Style")) // If an embedded style
os=f.get("Style")[0]; // Get embedded style
if (f.getGeometry().getType() == "Point") // If a marker
s=new ol.style.Style({ // Alloc text style
image: new ol.style.Circle( { // Draw circle
radius: os.getStroke().getWidth(), // Ewid controls size
fill: new ol.style.Fill({
color: RGBtoRGBA(os.getFill().getColor())
})
}),
text: new ol.style.Text( { // Text style
textAlign: "left", textBaseline: "middle", // Set alignment
font: "bold 14px Arial", // Set font
text: "XXXX", // Set label
fill: new ol.style.Fill({color: "#fff" }), // Set text color
stroke: new ol.style.Stroke( { color: "#666", width: 1 }), // Set edge
offsetX: os.getStroke().getWidth()+8 // Set offset
})
});
else
s=new ol.style.Style( { // Alloc style
fill: new ol.style.Fill( { color: RGBtoRGBA(os.getFill().getColor()) } ), // Fill
stroke: new ol.style.Stroke( { color: RGBtoRGBA(os.getStroke().getColor()), width: os.getStroke().getWidth() }) // Edge
});
f.setStyle(s); // Style it
f.getGeometry().transform("EPSG:4326","EPSG:3857"); // Project
f.setId("SEG-"+Math.floor(Math.random()*999999)); // Set id
mps.drawingLayer.getSource().addFeature(f); // Add to layer
}
mps.DrawMapLayers(); // Redraw map
function RGBtoRGBA(c) { // CONVERT ARRAY TO rgba()
return "rgba("+c[0]+","+c[1]+","+c[2]+","+c[3]+")";
}
}
function popListFiles(files) // CALLBACK TO List()
{
pop.FileSelect(files,function(id) { // Select fiels
var url=host+"loaddata.php?id="+id; // Base file
$.ajax({ url:url,dataType:'jsonp'}); // Get data
});
}
function AnimatePanes(which, end, dur, callback) // ANIMATE CHANGE OF PANE RATIO
{
var start;
if (which == "map") start=curJson.leftRightSplit; // Get current map
else if (which == "time") start=curJson.upDownSplit; // Get current timeline ratio
var dif=Math.abs(end-start); // Difference
if ((dif < .05) || (paneAnimationTimer)) { // If close enough or animating alredy
clearInterval(paneAnimationTimer); // Kill timer
paneAnimationTimer=null; // Clear timer var
if (which == "map") curJson.leftRightSplit=end; // Set map ratio
else if (which == "time") curJson.upDownSplit=end; // Set timeline ratio
if (dif) // If not there yet
ResizePanes(); // Resize
if (callback) callback(); // If a callback defined
return; // Quit
}
clearInterval(paneAnimationTimer); // Kill timer
paneAnimationTimer=null; // Clear timer var
var startTime=new Date().getTime(); // Set start
if (dur == undefined) // If no duration set
dur=.5; // Set default
dur=dur*1000; // Secs to ms
paneAnimationTimer=setInterval(onAnimate,24); // Set timer ~40ps
function onAnimate() {
var now=(new Date().getTime()-startTime)/dur; // Get now
now=1.0-((Math.cos(3.1414*Math.min(now,1))+1)/2.0); // Full cosine curve
var pos=start+(end-start)*now; // Get val
if (now > .99) { // If done
clearInterval(paneAnimationTimer); // Kill timer
pos=end; // Force to end
paneAnimationTimer=null; // Null it out
if (callback) callback(); // If a callback defined
}
if (which == "map") curJson.leftRightSplit=pos; // Set map ratio
else if (which == "time") curJson.upDownSplit=pos; // Set timeline ratio
ResizePanes(); // Resize
}
}
$("body").keyup(function(e) { // KEY DOWN HANDLER
if (e.altKey && (e.keyCode == 82)) { // Alt-R
if (curJson.sheet) // If a spreadsheet spec'd
dtl.GetSpreadsheet(curJson.sheet,true,null,function(mobs) { // Get spreadsheet data
curJson.mobs=mobs; // Set mobs
InitProject(curJson); // Re-init project
pop.Sound("ding"); // Ding
},true);
}
});
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// HELPERS
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function trace(msg, p1, p2, p3, p4) // CONSOLE
{
if (p4 != undefined)
console.log(msg,p1,p2,p3,p4);
else if (p3 != undefined)
console.log(msg,p1,p2,p3);
else if (p2 != undefined)
console.log(msg,p1,p2);
else if (p1 != undefined)
console.log(msg,p1);
else
console.log(msg);
}
function FindMobByID(id) // FIND MOB BY ITS ID
{
var i,o;
var n=curJson.mobs.length; // Get length
for (i=0;i<n;++i) { // For each mob
o=curJson.mobs[i].id; // Get id
if (o && o.indexOf(id) != -1) // If it matches
return i; // Return index of mob
}
return -1; // Return nothing found
}
function ColorToHex(color) // Convert a color name to hex
{
if (!color || color.match(/#/)) // Nothing or already hex
return color; // Return color
color=color.toLowerCase(); // Force lc
switch (color) { // Route on color
case "white": color="#ffffff"; break;
case "gray1": color="#cccccc"; break;
case "gray2": color="#888888"; break;
case "gray": color="#888888"; break;
case "gray3": color="#444444"; break;
case "black": color="#000000"; break;
case "gray": color="#888888"; break;
case "red": color="#990000"; break;
case "green": color="#009900"; break;
case "blue": color="#000099"; break;
case "orange": color="#ffa500"; break;
case "skyblue": color="#87ceeb"; break;
case "yellow": color="#ffd700"; break;
}
return color; // Return color
}
function MakeSelect(id, multi, items, sel, extra, values) // CREATE HTML SELECT
{
var str="<select class='ve-bs' id='"+id+"'"; // Header
if (multi) // Multi select
str+="multiple='multiple' size='"+multi+"'"; // Add flag
if (extra) // If extra param
str+=extra; // Add them
str+=">"; // End header
for (i=0;i<items.length;++i) { // For each option
str+="<option"; // Add tag
if (sel == items[i]) // If selected
str+=" selected='selected'" // Add tag
if (values && values[i]) // If has a value
str+=" value='"+values[i]+"'"; // Add it
str+=">"+items[i]+"</option>"; // End option
}
return str+"</select>"; // End select
}
function tim(time)
{
return pop.FormatTime(time,"Mo/Day/Year");
}
function ClearPopUps() // CLOSE ALL OPEN POPUPS
{
/*
Close any open popups zoomers, webpages, or alerts.
*/
$("#st-webpage").remove(); // Remove old page popup
$("#alertBoxDiv").remove(); // Remove oldalert boxe
$("#st-popup").remove(); // Remove old popup
$("#colorPickerDiv").remove(); // Remove old colorpicker
AnimatePanes("map",origLR,undefined, function() { // Animate pane back
sto.UpdateStory(curTime,curJson.timeFormat); // Update story pane
});
}
function ShowIframe(url) // SHOW IFRAME AND RETURN BUTTON
{
var str="<iframe id='popupIF' frameborder='0' height='"+($(window).height()-2)+"' width='100%' style='opacity:0,border:1px solid #666' src='"+url+"'/>";
str+="<div class='story-return' onclick='ClearPopUps();sto.pop.Sound(\"click\",curJson.muteSound)'>Back to story</div>";
$("#rightDiv").html(str);
}
function ConvertFromGoogleDrive(url) // CONVERT GOOGLE DRIVE LINK TO DIRECT LINK
{
if (url && url.match(/drive\.google/i)) { // A google drive image
var id=url.match(/\?id=(.+)/i); // Extract id
if (!id) // Nothing there
id=url.match(/\/d\/(.*?)\//); // Try this way
if (id) // An id found
url="//drive.google.com/uc?export=download&id="+id[1]; // Construct 'direct' link
}
return url; // Return link
}
</script>
</body></html>