Initial commit
This commit is contained in:
@@ -0,0 +1,434 @@
|
||||
<?php
|
||||
include "connect.php";
|
||||
|
||||
$char_sql = "SELECT * FROM characters";
|
||||
$char_result = mysqli_query($conn, $char_sql);
|
||||
?>
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>Rebolusyon - Interactive Map and Timeline</title>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
|
||||
<script type="text/javascript" src="https://unpkg.com/vis-timeline@latest/standalone/umd/vis-timeline-graph2d.min.js"></script> <!-- VisTimeline JS -->
|
||||
<link href="https://unpkg.com/vis-timeline@latest/styles/vis-timeline-graph2d.min.css" rel="stylesheet" type="text/css" /> <!-- VisTimeline CSS -->
|
||||
<link href="dist/css/bootstrap.css" rel="stylesheet" type="text/css" /> <!-- Bootstrap CSS -->
|
||||
<link rel="stylesheet" href="fontawesome/css/font-awesome.min.css"> <!-- FontAwesome v4 CSS -->
|
||||
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css" integrity="sha256-p4NxAoJBhIIN+hmNHrzRCf9tD/miZyoHS5obTRR9BMY=" crossorigin="" /> <!-- Leaflet CSS -->
|
||||
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js" integrity="sha256-20nQCchB9co0qIjJZRGuk2/Z9VM+kNiyxNV1lvTlZBo=" crossorigin=""></script> <!-- Leaflet JS -->
|
||||
<style type="text/css">
|
||||
html, body, .container-fluid {
|
||||
height: 100%;
|
||||
}
|
||||
#visualization {
|
||||
font-size: 14px;
|
||||
}
|
||||
.vis-minor {
|
||||
font-size: 12px;
|
||||
}
|
||||
.vis-item-content {
|
||||
}
|
||||
.test1 {
|
||||
background-color: rgba(255, 0, 0, 0.2)
|
||||
}
|
||||
.test2 {
|
||||
background-color: rgba(0, 255, 0, 0.2)
|
||||
}
|
||||
.test3 {
|
||||
background-color: rgba(0, 0, 255, 0.2)
|
||||
}
|
||||
.txt14px {
|
||||
font-size: 14px;
|
||||
}
|
||||
.indent15px{
|
||||
text-indent: 15px;
|
||||
}
|
||||
#map {
|
||||
/* min-width: 500px;*/
|
||||
width: 100%;
|
||||
min-height: 500px;
|
||||
height: 100%;
|
||||
}
|
||||
/* width */
|
||||
::-webkit-scrollbar {
|
||||
width: 5px;
|
||||
}
|
||||
|
||||
/* Track */
|
||||
::-webkit-scrollbar-track {
|
||||
background: #f1f1f1;
|
||||
}
|
||||
|
||||
/* Handle */
|
||||
::-webkit-scrollbar-thumb {
|
||||
background: #888;
|
||||
}
|
||||
|
||||
/* Handle on hover */
|
||||
::-webkit-scrollbar-thumb:hover {
|
||||
background: #555;
|
||||
}
|
||||
</style>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<script type="text/javascript" src="dist/js/bootstrap.bundle.js"></script> <!-- Bootstrap JS -->
|
||||
|
||||
<div class="container-fluid d-flex flex-column">
|
||||
<div class="row">
|
||||
<h2 class="text-center">Rebolusyon</h2>
|
||||
<span class="text-center">Interactive Map and Timeline</span>
|
||||
<hr>
|
||||
</div>
|
||||
<div class="row flex-fill">
|
||||
<div class="col-xxl-3 col-xl-3 col-lg-3 col-md-4 d-flex flex-column">
|
||||
<div class="collapse" id="myCollapsible">
|
||||
<div class="card text-bg-light mb-3 txt14px" id="rebolcardcontent" style="overflow-y: scroll; max-height:475px;">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title rebol">Welcome!</h5>
|
||||
<p class="card-text">entry message welcome</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xxl-7 col-xl-6 col-lg-6 col-md-8 d-flex flex-column">
|
||||
<div id="map">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xxl-2 col-xl-3 col-lg-3 col-md-12 d-flex flex-column">
|
||||
<div class="card">
|
||||
<div class="card-body txt14px">
|
||||
Select characters to show on timeline:
|
||||
<br><br>
|
||||
<ul class="list-group">
|
||||
<?php
|
||||
if(mysqli_num_rows($char_result) > 0) {
|
||||
while ($row = mysqli_fetch_assoc($char_result)) {
|
||||
$charid = $row["char_id"];
|
||||
$char_name = $row["firstname"] . " " . $row["lastname"];
|
||||
$checkbox_id = "chbx_char_" . $row["char_id"];
|
||||
$onchangefunc = "testadd('" . $charid . "','" . $checkbox_id . "')";
|
||||
|
||||
echo '<li class="list-group-item input-group-sm">';
|
||||
echo '<input class="form-check-input me-1" type="checkbox" value="" id="' . $checkbox_id . '" onchange="' . $onchangefunc . '">';
|
||||
echo '<label class="form-check-label stretched-link txt14px" for="' . $checkbox_id . '">' . $char_name . '</label>';
|
||||
echo '</li>';
|
||||
}
|
||||
|
||||
} else {
|
||||
echo "No characters";
|
||||
}
|
||||
?>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row px-3">
|
||||
<div class="card">
|
||||
<div class="card-body txt14px">
|
||||
Timeline Controls:
|
||||
<button type="button" class="btn btn-sm" data-bs-toggle="tooltip" data-bs-placement="top" data-bs-title="Show All" id="fit">
|
||||
<i class="fa fa-expand" aria-hidden="true" ></i>
|
||||
</button>
|
||||
<button type="button" class="btn btn-sm" data-bs-toggle="tooltip" data-bs-placement="top" data-bs-title="Zoom In" id="zoomIn">
|
||||
<i class="fa fa-search-plus" aria-hidden="true"></i>
|
||||
</button>
|
||||
<button type="button" class="btn btn-sm" data-bs-toggle="tooltip" data-bs-placement="top" data-bs-title="Zoom Out" id="zoomOut">
|
||||
<i class="fa fa-search-minus" aria-hidden="true"></i>
|
||||
</button>
|
||||
<button type="button" class="btn btn-sm" data-bs-toggle="tooltip" data-bs-placement="top" data-bs-title="Move Left"id="moveLeft">
|
||||
<i class="fa fa-arrow-left" aria-hidden="true"></i>
|
||||
</button>
|
||||
<button type="button" class="btn btn-sm" data-bs-toggle="tooltip" data-bs-placement="top" data-bs-title="Move Right" id="moveRight">
|
||||
<i class="fa fa-arrow-right" aria-hidden="true"></i>
|
||||
</button>
|
||||
<button class="btn btn-sm" onclick="openCard('event', '2')">
|
||||
Test button
|
||||
</button>
|
||||
<!-- <button class="btn btn-sm" onclick="opencloseCollapse()">
|
||||
Test button
|
||||
</button> -->
|
||||
|
||||
<br />
|
||||
<hr>
|
||||
<div id="visualization"></div>
|
||||
<div id="log"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<!-- ---------------------------Timeline Data----------------------------- -->
|
||||
|
||||
<script type="text/javascript">
|
||||
|
||||
var cardopened = false;
|
||||
|
||||
var prev_card_id = "initial_card_id"; //prevents same card from reopening (id)
|
||||
var prev_card_type = "welcome_card_id"; //prevents same card from reopening (type)
|
||||
|
||||
//Open Welcome card
|
||||
opencloseCollapse();
|
||||
|
||||
//Initialize Tooltips
|
||||
const tooltipTriggerList = document.querySelectorAll('[data-bs-toggle="tooltip"]')
|
||||
const tooltipList = [...tooltipTriggerList].map(tooltipTriggerEl => new bootstrap.Tooltip(tooltipTriggerEl))
|
||||
|
||||
// Create Groups
|
||||
var groups = new vis.DataSet();
|
||||
|
||||
|
||||
// Create a DataSet (allows two way data-binding)
|
||||
var items = new vis.DataSet();
|
||||
|
||||
|
||||
// DOM element where the Timeline will be attached
|
||||
var container = document.getElementById('visualization');
|
||||
|
||||
// Configuration for the Timeline
|
||||
var options = {
|
||||
width: '100%',
|
||||
minHeight: '100px',
|
||||
maxHeight: '250px',
|
||||
min: new Date(1800, 1, 1), // lower limit of visible range
|
||||
max: new Date(2000, 1, 1), // upper limit of visible range
|
||||
zoomMin: 1000 * 60 * 60 * 24, // one day in milliseconds
|
||||
// stack: false,
|
||||
template: (itemData, element, data) => {
|
||||
if (data.isCluster) {
|
||||
return `<span class="cluster-header"></span><div> ${data.items.length} items </div>`;
|
||||
}
|
||||
else {
|
||||
return `<div>${data.content}</div>`;
|
||||
}
|
||||
},
|
||||
cluster: {
|
||||
titleTemplate: "Cluster containing {count} events. Zoom in to see the individual events.",
|
||||
maxItems: 2,
|
||||
},
|
||||
groupHeightMode: 'auto',
|
||||
groupTemplate: function (group) {
|
||||
var container = document.createElement("div");
|
||||
var span = document.createElement("span");
|
||||
var someparams = "'char','" + group.id + "'"
|
||||
span.innerHTML = '<input type = "image" src="img/' + group.filename + '" onclick="openCard(' + someparams + ')" />'
|
||||
container.insertAdjacentElement("beforeEnd", span);
|
||||
return container;
|
||||
}
|
||||
};
|
||||
|
||||
// Create a Timeline
|
||||
var timeline = new vis.Timeline(container, items, groups, options);
|
||||
timeline.setGroups(groups);
|
||||
|
||||
//showall from start to end
|
||||
document.getElementById("fit").onclick = function () {
|
||||
timeline.fit();
|
||||
};
|
||||
|
||||
//focus on selected item, open event card, and add location marker
|
||||
timeline.on("doubleClick", function (properties) {
|
||||
var selection = timeline.getSelection();
|
||||
timeline.focus(selection);
|
||||
var getselect = items.get(selection);
|
||||
console.log(getselect[0]);
|
||||
openCard('event', getselect[0].id);
|
||||
addMarker(getselect[0].marker_coord, getselect[0].location_name);
|
||||
});
|
||||
|
||||
//set timeline movement
|
||||
function move(percentage) {
|
||||
var range = timeline.getWindow();
|
||||
var interval = range.end - range.start;
|
||||
|
||||
timeline.setWindow({
|
||||
start: range.start.valueOf() - interval * percentage,
|
||||
end: range.end.valueOf() - interval * percentage,
|
||||
});
|
||||
}
|
||||
|
||||
// attach events to the navigation buttons
|
||||
document.getElementById("zoomIn").onclick = function () {
|
||||
timeline.zoomIn(1);
|
||||
};
|
||||
document.getElementById("zoomOut").onclick = function () {
|
||||
timeline.zoomOut(1);
|
||||
};
|
||||
document.getElementById("moveLeft").onclick = function () {
|
||||
move(0.5);
|
||||
};
|
||||
document.getElementById("moveRight").onclick = function () {
|
||||
move(-0.5);
|
||||
};
|
||||
|
||||
function testadd(groupid, chbxid){
|
||||
var yocheckbox = document.getElementById(chbxid);
|
||||
if (yocheckbox.checked == true) {
|
||||
add_char_group(groupid);
|
||||
add_char_events(groupid);
|
||||
} else {
|
||||
deletechar(groupid);
|
||||
}
|
||||
}
|
||||
|
||||
//Add Character Group dynamically via Ajax
|
||||
function add_char_group(groupid){
|
||||
$.ajax({ //create an ajax request to addgroup.php
|
||||
url:"addgroup.php",
|
||||
method:"POST",
|
||||
data:{id:groupid},
|
||||
dataType:"JSON",
|
||||
success: function(chardata){
|
||||
groups.add(chardata);
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
//Add Character items on timeline and unhide group
|
||||
function add_char_events(groupid){
|
||||
$.ajax({ //create an ajax request to addgroup.php
|
||||
url:"addevents.php",
|
||||
method:"POST",
|
||||
data:{id:groupid},
|
||||
dataType:"JSON",
|
||||
success: function(eventdata){
|
||||
var result = JSON.parse(JSON.stringify(eventdata, null, 2));
|
||||
items.add(result);
|
||||
timeline.fit();
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
//test get info from specific items
|
||||
function testselect(){
|
||||
var getselect = items.get({
|
||||
fields: ['id'],
|
||||
filter: function (item) {
|
||||
return (item.group == "jrizal");
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
//Remove Character items on timeline and hide group
|
||||
function deletechar(groupid){
|
||||
var getselect = items.get({
|
||||
fields: ['id'],
|
||||
filter: function (item) {
|
||||
return (item.group == groupid);
|
||||
}
|
||||
})
|
||||
items.remove(getselect);
|
||||
groups.remove(groupid);
|
||||
timeline.redraw();
|
||||
}
|
||||
|
||||
//Bootstrap Collapse function called via javascript function
|
||||
function openCard(content_type, content_id){
|
||||
if (cardopened == false) { //if card is closed, update card contents immediately
|
||||
updatecardcontents(content_type, content_id);
|
||||
opencloseCollapse();
|
||||
}
|
||||
if (cardopened == true) {
|
||||
if (prev_card_id != content_id) { //condition prevents reopening of the same card
|
||||
opencardinstruction(content_type, content_id);
|
||||
} else if (prev_card_id == content_id && prev_card_type != content_type) {
|
||||
opencardinstruction(content_type, content_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Open Card Instruction
|
||||
function opencardinstruction(content_type, content_id){
|
||||
opencloseCollapse();
|
||||
setTimeout(function(){
|
||||
updatecardcontents(content_type, content_id);
|
||||
}, 400);
|
||||
setTimeout(function(){
|
||||
opencloseCollapse();
|
||||
}, 500);
|
||||
}
|
||||
|
||||
//Update contents in card
|
||||
function updatecardcontents(content_type, content_id){
|
||||
if (content_type == 'char') {
|
||||
var getcharcontents = groups.get(content_id);
|
||||
// document.getElementById("rebolcardcontent").innerHTML = "<h5 class='card-title rebol'>Char page</h5><div class='d-flex justify-content-center'><div class='spinner-border' role='status'></div></div>";
|
||||
document.getElementById("rebolcardcontent").innerHTML = "<img src='img/card_img/" + getcharcontents.filename + "' class='card-img-top' alt=''><div class='card-body'><h5 class='card-title'>" + getcharcontents.content + "</h5><span class='text-secondary'>" + getcharcontents.title + "</span><br><span class='text-secondary'>" + getcharcontents.birth + " - " + getcharcontents.death + " (" + getcharcontents.age + " yrs old)</span><hr>" + getcharcontents.desc + "</div>";
|
||||
|
||||
}
|
||||
if (content_type == "event"){
|
||||
var geteventcontents = items.get(content_id);
|
||||
var date_raw = new Date(geteventcontents.start_raw);
|
||||
var date_formatted = formattedDate = new Intl.DateTimeFormat("en-US", { year: "numeric", month: "short", day: "2-digit",}).format(date_raw);
|
||||
|
||||
document.getElementById("rebolcardcontent").innerHTML = "<div class='card-body'><h5 class='card-title rebol'>" + geteventcontents.content + "</h5><h6>" + date_formatted + " - " + geteventcontents.location_name + "</h6>" + geteventcontents.desc + "</div>";
|
||||
}
|
||||
prev_card_id = content_id;
|
||||
prev_card_type = content_type;
|
||||
}
|
||||
|
||||
//Bootsrap Collapse toggle
|
||||
function opencloseCollapse(){
|
||||
var collapseElementList = [].slice.call(document.querySelectorAll('.collapse'))
|
||||
var collapseList = collapseElementList.map(function (collapseEl) {
|
||||
return new bootstrap.Collapse(collapseEl)
|
||||
})
|
||||
}
|
||||
|
||||
//Bootstrap Collapse trigger event after transition to shown
|
||||
var myCollapsible = document.getElementById('myCollapsible')
|
||||
myCollapsible.addEventListener('shown.bs.collapse', function () {
|
||||
cardopened = true;
|
||||
})
|
||||
|
||||
|
||||
//Bootstrap Collapse trigger event after transition to hidden
|
||||
var myCollapsible = document.getElementById('myCollapsible')
|
||||
myCollapsible.addEventListener('hidden.bs.collapse', function () {
|
||||
cardopened = false;
|
||||
})
|
||||
</script>
|
||||
|
||||
<!-- ---------------------------Leaflet Data----------------------------- -->
|
||||
|
||||
<script type="text/javascript">
|
||||
|
||||
console.log(L);
|
||||
|
||||
const map = L.map('map');
|
||||
map.setView([14.5982,120.9718], 10);
|
||||
|
||||
L.tileLayer('https://tiles.stadiamaps.com/tiles/alidade_smooth/{z}/{x}/{y}{r}.{ext}', {
|
||||
minZoom: 0,
|
||||
maxZoom: 16,
|
||||
attribution: '© <a href="https://www.stadiamaps.com/" target="_blank">Stadia Maps</a> © <a href="https://openmaptiles.org/" target="_blank">OpenMapTiles</a> © <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors',
|
||||
ext: 'png'
|
||||
}).addTo(map);
|
||||
|
||||
// L.marker([14.187234288690352, 121.12581741607673],{
|
||||
// title: "Calamba",
|
||||
// }).addTo(map);
|
||||
|
||||
function addMarker(marker_coord, location_name){
|
||||
|
||||
// console.log(marker_coord);
|
||||
L.marker((marker_coord).split(','),{
|
||||
title: location_name,
|
||||
}).addTo(map);
|
||||
// L.marker((marker_coord).split(',')).addTo(map);
|
||||
|
||||
map.flyTo((marker_coord).split(','));
|
||||
}
|
||||
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user