Skip to content

Instantly share code, notes, and snippets.

@JoeAlamo
Created October 25, 2016 15:41
Show Gist options
  • Save JoeAlamo/e3c1718cd0440c309e4de62c7fbd1966 to your computer and use it in GitHub Desktop.
Save JoeAlamo/e3c1718cd0440c309e4de62c7fbd1966 to your computer and use it in GitHub Desktop.
Demo of interactive visio topology
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Ocucon Camera Topology Demo</title>
<style>
#topology-container {
width: 700px;
height: 495px;
margin-bottom: 40px;
}
rect:hover {
cursor: pointer;
}
</style>
<!-- Latest compiled and minified CSS -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<!-- Optional theme -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap-theme.min.css" integrity="sha384-rHyoN1iRsVXV4nD0JutlnGaslCJuC7uwjduW9SVrLvRYooPp2bWYgmgJQIXwl/Sp" crossorigin="anonymous">
</head>
<body>
<div class="container">
<div class="row">
<div class="col-xs-8 col-xs-offset-2">
<header>
<h2 id="mode-title">View Mode</h2>
<div class="row">
<button id="mode-edit" class="btn btn-primary">Edit</button>
<button class="btn btn-default pull-right edit-mode-controls" data-toggle="modal" data-target="#add-camera-modal">Add Camera</button>
</div>
</header>
<div id="topology-container">
<svg id="visio-svg" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 700 495" >
<image width="700" height="495" xlink:href="visio.png">
</image>
</svg>
</div>
<div class="edit-mode-controls">
<div class="row">
<div class="col-xs-6">
<button id="edit-cancel" class="btn btn-danger pull-left">Cancel</button>
</div>
<div class="col-xs-6">
<button id="edit-save" class="btn btn-success pull-right">Save</button>
</div>
</div>
</div>
<p>Double click on a created camera to either edit or view it.</p>
</div>
</div>
<div class="modal fade" id="add-camera-modal" tabindex="-1" role="dialog" aria-labelledby="add-camera-modal-label">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
<h4 class="modal-title" id="add-camera-modal-label">Select a camera</h4>
</div>
<div class="modal-body">
<label for="add-camera-select">Select which camera you would like to add</label>
<select id="add-camera-select" name="add-camera-select">
<option value="1" selected>1</option>
<option value="2">2</option>
<option value="3">3</option>
<option value="4">4</option>
<option value="5">5</option>
</select>
<p><i>Show most recent footage here for selected camera</i></p>
<p>Once you have added the camera, drag it to its location in the store.</p>
<p>Double click a camera to edit it.</p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
<button type="button" id="add-camera" class="btn btn-primary">Add camera</button>
</div>
</div>
</div>
</div>
<div class="modal fade" id="edit-camera-modal" tabindex="-1" role="dialog" aria-labelledby="edit-camera-modal-label">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
<h4 class="modal-title" id="edit-camera-modal-label">Edit camera</h4>
</div>
<div class="modal-body">
<input type="hidden" id="local-camera-id">
<label for="edit-camera-select">Change the camera</label>
<select id="edit-camera-select" name="edit-camera-select">
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
<option value="4">4</option>
<option value="5">5</option>
</select>
<p>Show most recent footage here for selected camera</p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
<button type="button" id="edit-camera" class="btn btn-primary">Edit camera</button>
</div>
</div>
</div>
</div>
<div class="modal fade" id="view-camera-modal" tabindex="-1" role="dialog" aria-labelledby="view-camera-modal-label">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
<h4 class="modal-title" id="view-camera-modal-label"></h4>
</div>
<div class="modal-body">
<h3></h3>
<p>Show most recent footage here for selected camera</p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
</div><!-- CONTAINER -->
<script src="https://code.jquery.com/jquery-3.1.1.js" integrity="sha256-16cdPddA6VdVInumRGo6IbivbERE8p7CQR3HzTBuELA=" crossorigin="anonymous"></script>
<!-- Latest compiled and minified JavaScript -->
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/snap.svg/0.4.1/snap.svg.js"></script>
<script>
$(document).ready(function(e) {
if (typeof(Storage) === 'undefined') {
alert("HTML5 storage is required for this little demo :)");
return false;
}
var EDIT_MODE = false;
var snap = Snap('#visio-svg'),
cameraTotal = 0;
var init = function () {
// Load previously saved cameras
if (localStorage.cameras !== undefined) {
initCameras();
}
EDIT_MODE ? initEditMode() : initViewMode();
};
var initViewMode = function() {
EDIT_MODE = false;
$('#mode-title').text('View mode');
$('#mode-edit').show();
$('.edit-mode-controls').hide();
$('rect[data-camera-id]').tooltip();
};
var initEditMode = function() {
EDIT_MODE = true;
$('#mode-title').text('Edit mode');
$('#mode-edit').hide();
$('.edit-mode-controls').show();
$('rect[data-camera-id]').tooltip('destroy');
};
var initCameras = function() {
try {
var cameras = JSON.parse(localStorage.cameras);
$.each(cameras, function(key, camera) {
var rect = snap.rect(camera.x, camera.y, camera.width, camera.height);
rect.attr({
'fill': '#000',
'fill-opacity': 0.4,
'stroke': 'black',
'transform': camera.transform,
'data-camera-id': camera.id,
'data-id': (++cameraTotal),
'data-toggle': 'tooltip',
'data-title': 'Camera ' + camera.id,
'data-container': 'body'
});
rect.addClass('svg-camera');
rect.drag(move, start);
rect.dblclick(click);
})
} catch (e) {
console.log('Failed to parse local stored cameras');
}
};
$('#mode-edit').on('click', initEditMode);
$('#edit-cancel').on('click', initViewMode);
$('#edit-save').on('click', function () {
saveCameras();
initViewMode();
});
$('#add-camera').on('click', function(e) {
var cameraId = $('#add-camera-select').val();
var rect = snap.rect(25, 25, 20, 10);
rect.attr({
'fill': '#000',
'fill-opacity': 0.4,
'stroke': 'black',
'data-camera-id': cameraId,
'data-id': (++cameraTotal),
'data-toggle': 'tooltip',
'data-title': 'Camera ' + cameraId,
'data-container': 'body'
});
rect.addClass('svg-camera');
rect.drag(move, start);
rect.dblclick(click);
$('#add-camera-modal').modal('hide');
});
var move = function(dx,dy) {
if (!EDIT_MODE) {
return;
}
this.attr({
transform: this.data('origTransform') + (this.data('origTransform') ? "T" : "t") + [dx, dy]
});
};
var start = function() {
if (!EDIT_MODE) {
return;
}
this.data('origTransform', this.transform().local );
};
var click = function(e) {
EDIT_MODE ? showEditModal(e) : showViewModal(e);
};
var saveCameras = function() {
// Iterate through rect objects in svg canvas
var cameraRects = $('#visio-svg>rect.svg-camera'),
cameras = [];
// Save data-camera-id and x,y,transform
cameraRects.each(function (index, element) {
var el = $(element);
cameras.push({
'id': el.attr('data-camera-id'),
'x': el.attr('x'),
'y': el.attr('y'),
'width': el.attr('width'),
'height': el.attr('height'),
'transform': el.attr('transform')
})
});
// Save to local storage
localStorage.cameras = JSON.stringify(cameras);
};
var showEditModal = function (e) {
var editModal = $('#edit-camera-modal'),
cameraId = $(e.target).attr('data-camera-id'),
localCameraId = $(e.target).attr('data-id'),
cameraSelect = editModal.find('#edit-camera-select');
cameraSelect.val(cameraId);
editModal.find('#local-camera-id').val(localCameraId);
editModal.modal('show');
};
var showViewModal = function (e) {
var viewModal = $('#view-camera-modal'),
cameraId = $(e.target).attr('data-camera-id');
viewModal.find('#view-camera-modal-label').text('Camera ' + cameraId);
viewModal.find('.modal-body>h3').text('Viewing camera ' + cameraId);
viewModal.modal('show');
};
$('#edit-camera-modal #edit-camera').on('click', function () {
var localId = $('#edit-camera-modal').find('#local-camera-id').val();
var cameraId = $('#edit-camera-modal').find('#edit-camera-select').val();
$('#visio-svg').find('rect[data-id="' + localId + '"]').attr({
'data-camera-id': cameraId,
'data-original-title': 'Camera ' + cameraId
});
$('#edit-camera-modal').modal('hide');
});
init();
});
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment