kopia lustrzana https://github.com/FacilMap/facilmap
427 wiersze
11 KiB
JavaScript
427 wiersze
11 KiB
JavaScript
(function(fp, $, ng, undefined) {
|
|
|
|
var facilpadApp = angular.module("facilpad", [ ]);
|
|
|
|
function wrapApply($scope, f) {
|
|
return function() {
|
|
var context = this;
|
|
var args = arguments;
|
|
$scope.$apply(function() {
|
|
f.apply(context, args);
|
|
});
|
|
}
|
|
}
|
|
|
|
Function.prototype.fpWrapApply = function($scope) {
|
|
return wrapApply($scope, this);
|
|
};
|
|
|
|
// From http://stackoverflow.com/a/11277751/242365
|
|
facilpadApp.factory("socket", function($rootScope) {
|
|
var socket = io.connect(fp.SERVER);
|
|
|
|
var onBkp = socket.on;
|
|
socket.on = function(eventName, fn) {
|
|
if(fn)
|
|
arguments[1] = wrapApply($rootScope, fn);
|
|
onBkp.apply(this, [ eventName, fn ]);
|
|
};
|
|
var emitBkp = socket.emit;
|
|
socket.emit = function(eventName, data, cb) {
|
|
if(cb)
|
|
arguments[2] = wrapApply($rootScope, cb);
|
|
emitBkp.apply(this, arguments);
|
|
};
|
|
|
|
return socket;
|
|
});
|
|
|
|
facilpadApp.directive("fpDialog", function() {
|
|
return {
|
|
restrict: 'A',
|
|
link: function(scope, element, attrs) {
|
|
$(element).dialog({ autoOpen: false, modal: true, height: "auto", width: 600 });
|
|
}
|
|
}
|
|
});
|
|
|
|
facilpadApp.controller("PadCtrl", function($scope, socket, $timeout, $sce, $parse) {
|
|
|
|
$("#toolbox").menu();
|
|
function updateMenu() {
|
|
setTimeout(function() { $("#toolbox").menu("destroy").menu(); }, 0);
|
|
}
|
|
|
|
$scope.padData = null;
|
|
$scope.loaded = false;
|
|
$scope.markers = { };
|
|
$scope.lines = { };
|
|
$scope.views = { };
|
|
$scope.dialog = null;
|
|
$scope.dialogError = null;
|
|
$scope.saveViewName = null;
|
|
$scope.currentMarker = null;
|
|
$scope.currentLine = null;
|
|
$scope.messages = [ ];
|
|
$scope.padUrl = location.protocol + "//" + location.host + location.pathname;
|
|
$scope.error = false;
|
|
$scope.drawing = false;
|
|
|
|
socket.emit("setPadId", location.pathname.match(/[^\/]*$/)[0]);
|
|
|
|
bindSocketToScope($scope, socket);
|
|
|
|
$scope.onMove = function() {
|
|
if($scope.currentMarker)
|
|
$scope.currentMarker.xy = fp.posToXy($scope.currentMarker.position);
|
|
if($scope.currentLine && $scope.currentLine.clickPos)
|
|
$scope.currentLine.clickXy = fp.posToXy($scope.currentLine.clickPos);
|
|
};
|
|
|
|
fp.onMove = wrapApply($scope, $scope.onMove);
|
|
|
|
$scope.$watch("markers[currentMarker.id]", function() {
|
|
if($scope.currentMarker != null)
|
|
$scope.currentMarker = $scope.markers[$scope.currentMarker.id];
|
|
});
|
|
|
|
$scope.$watch("currentMarker", function() {
|
|
$scope.onMove();
|
|
});
|
|
|
|
$scope.$watch("currentMarker.style", function() {
|
|
if($scope.currentMarker != null)
|
|
fp.addMarker($scope.currentMarker);
|
|
});
|
|
|
|
$scope.$watch("lines[currentLine.id]", function() {
|
|
if($scope.currentLine != null)
|
|
$scope.currentLine = $.extend($scope.lines[$scope.currentLine.id], { clickPos : $scope.currentLine.clickPos, clickXy : $scope.currentLine.clickXy });
|
|
});
|
|
|
|
fp.onMoveEnd = function(bbox) {
|
|
socket.emit("updateBbox", bbox);
|
|
};
|
|
|
|
$scope.$watch("padData", function(newValue) {
|
|
if(newValue == null || $scope.loaded)
|
|
return;
|
|
|
|
$scope.loaded = true;
|
|
setTimeout(function() { // Avoid error with onMove being executed while inside $apply()
|
|
FacilPad.displayView(newValue.defaultView);
|
|
}, 0);
|
|
});
|
|
|
|
$scope.$watch("currentMarker", function() {
|
|
if($scope.currentMarker != null)
|
|
$scope.currentMarker.descriptionHtml = $scope.marked($scope.currentMarker.description);
|
|
});
|
|
|
|
$scope.$watch("currentMarker.description", function() {
|
|
if($scope.currentMarker != null)
|
|
$scope.currentMarker.descriptionHtml = $scope.marked($scope.currentMarker.description);
|
|
});
|
|
|
|
$scope.$watch("currentLine", function() {
|
|
if($scope.currentLine != null)
|
|
$scope.currentLine.descriptionHtml = $scope.marked($scope.currentLine.description);
|
|
});
|
|
|
|
$scope.$watch("currentLine.description", function() {
|
|
if($scope.currentLine != null)
|
|
$scope.currentLine.descriptionHtml = $scope.marked($scope.currentLine.description);
|
|
});
|
|
|
|
$scope.$watch("views", updateMenu);
|
|
|
|
$scope.marked = function(text) {
|
|
return text != null ? $sce.trustAsHtml(marked(text)) : null;
|
|
};
|
|
|
|
$scope.savePadData = function() {
|
|
var padData = $.extend({ }, $scope.padData);
|
|
delete padData.defaultView;
|
|
socket.emit("editPad", padData, function(err) {
|
|
if(err)
|
|
$scope.dialogError = err;
|
|
else
|
|
$scope.closeDialog();
|
|
});
|
|
};
|
|
|
|
fp.onClickMarker = wrapApply($scope, function(marker) {
|
|
$scope.currentLine = null;
|
|
if($scope.currentMarker && $scope.currentMarker.id == marker.id)
|
|
$scope.currentMarker = null;
|
|
else
|
|
$scope.currentMarker = marker;
|
|
});
|
|
|
|
fp.onClickLine = function(line, clickPos) {
|
|
$scope.currentMarker = null;
|
|
$scope.currentLine = line;
|
|
$scope.currentLine.clickPos = clickPos;
|
|
$scope.onMove();
|
|
}.fpWrapApply($scope);
|
|
|
|
$scope.addMarker = function() {
|
|
var message = $scope.showMessage("info", "Please click on the map to add a marker.");
|
|
fp.addClickListener(function(pos) {
|
|
$scope.$apply(function() {
|
|
$scope.closeMessage(message);
|
|
|
|
socket.emit("addMarker", { position: { lon: pos.lon, lat: pos.lat } }, function(err, marker) {
|
|
if(err)
|
|
return $scope.showMessage("error", err);
|
|
|
|
$scope.currentMarker = marker;
|
|
$scope.openDialog("edit-marker-dialog");
|
|
});
|
|
});
|
|
});
|
|
};
|
|
|
|
$scope.saveMarker = function(marker) {
|
|
socket.emit("editMarker", marker, function(err) {
|
|
if(err)
|
|
$scope.dialogError = err;
|
|
else
|
|
$scope.closeDialog();
|
|
})
|
|
};
|
|
|
|
$scope.deleteMarker = function(marker) {
|
|
socket.emit("deleteMarker", marker, function(err) {
|
|
if(err)
|
|
$scope.showMessage("error", err);
|
|
});
|
|
};
|
|
|
|
$scope.addLine = function() {
|
|
socket.emit("addLine", { points: [ ] }, function(err, line) {
|
|
$scope.currentLine = line;
|
|
$scope.drawing = true;
|
|
var message = $scope.showMessage("info", "Please click on the map to draw a line. Double-click to finish it.");
|
|
|
|
var lastPos = null;
|
|
var clickListener = function(pos) {
|
|
if(lastPos && pos.lon == lastPos.lon && pos.lat == lastPos.lat) {
|
|
$scope.closeMessage(message);
|
|
|
|
$scope.drawing = false;
|
|
|
|
// Finish drawing
|
|
socket.emit("editLine", { id: line.id, points: line.points }, function(err, line) {
|
|
if(err)
|
|
return $scope.showMessage("error", err);
|
|
|
|
$scope.currentLine = line;
|
|
$scope.currentLine.clickPos = pos;
|
|
$scope.onMove();
|
|
$scope.openDialog("edit-line-dialog");
|
|
});
|
|
} else {
|
|
line.points.push(pos);
|
|
line.actualPoints.push(pos);
|
|
fp.addLine(line);
|
|
fp.addClickListener(clickListener);
|
|
lastPos = pos;
|
|
}
|
|
}.fpWrapApply($scope);
|
|
|
|
fp.addClickListener(clickListener);
|
|
});
|
|
};
|
|
|
|
$scope.saveLine = function(line) {
|
|
socket.emit("editLine", line, function(err) {
|
|
if(err)
|
|
$scope.dialogError = err;
|
|
else
|
|
$scope.closeDialog();
|
|
})
|
|
};
|
|
|
|
$scope.deleteLine = function(line) {
|
|
socket.emit("deleteLine", line, function(err) {
|
|
if(err)
|
|
$scope.showMessage("error", err);
|
|
});
|
|
};
|
|
|
|
$scope.displayView = function(view) {
|
|
fp.displayView(view);
|
|
};
|
|
|
|
$scope.saveView = function() {
|
|
var view = fp.getCurrentView();
|
|
view.name = $scope.saveViewName;
|
|
socket.emit("addView", view, function(err) {
|
|
if(err)
|
|
$scope.dialogError = err;
|
|
else
|
|
$scope.closeDialog();
|
|
});
|
|
};
|
|
|
|
$scope.setDefaultView = function(view) {
|
|
socket.emit("editPad", { defaultView: view.id }, function(err) {
|
|
if(err)
|
|
$scope.dialogError = err;
|
|
});
|
|
};
|
|
|
|
$scope.deleteView = function(view) {
|
|
socket.emit("deleteView", { id: view.id }, function(err) {
|
|
if(err)
|
|
$scope.dialogError = err;
|
|
});
|
|
};
|
|
|
|
$scope.openDialog = function(id) {
|
|
var el = $("#"+id);
|
|
|
|
var preserve = el.attr("fp-preserve");
|
|
if(preserve)
|
|
$scope.dialogBkp = angular.copy($parse(preserve)($scope));
|
|
|
|
$scope.dialog = el.dialog("open").bind("dialogclose", wrapApply($scope, function() {
|
|
$scope.dialog = null;
|
|
$scope.dialogError = null;
|
|
|
|
if(preserve && $scope.dialogBkp !== undefined) // undefined is set in closeDialog()
|
|
$parse(preserve + " = fpPreserveRestore")($scope, { fpPreserveRestore: $scope.dialogBkp });
|
|
}));
|
|
};
|
|
|
|
$scope.closeDialog = function(restorePreserved) {
|
|
if(!restorePreserved)
|
|
$scope.dialogBkp = undefined;
|
|
|
|
setTimeout(function() { // dialogclose event handler calls $apply
|
|
$scope.dialog.dialog("close");
|
|
}, 0);
|
|
};
|
|
|
|
$scope.showMessage = function(type, message, lifetime) {
|
|
var messageObj = {
|
|
type: type,
|
|
message: message
|
|
};
|
|
$scope.messages.push(messageObj);
|
|
|
|
if(lifetime) {
|
|
$timeout(function() {
|
|
$scope.closeMessage(messageObj);
|
|
}, lifetime);
|
|
}
|
|
|
|
return messageObj;
|
|
};
|
|
|
|
$scope.closeMessage = function(message) {
|
|
var idx = $scope.messages.indexOf(message);
|
|
if(idx == -1)
|
|
return;
|
|
|
|
$scope.messages = $scope.messages.slice(0, idx).concat($scope.messages.slice(idx+1));
|
|
};
|
|
|
|
$scope.round = function(number, digits) {
|
|
var fac = Math.pow(10, digits);
|
|
return Math.round(number*fac)/fac;
|
|
};
|
|
|
|
$scope.formatTime = function(seconds) {
|
|
var hours = Math.floor(seconds/3600);
|
|
var minutes = Math.floor((seconds%3600)/60);
|
|
if(minutes < 10)
|
|
minutes = "0" + minutes;
|
|
return hours + ":" + minutes;
|
|
};
|
|
|
|
$scope.routingMode = function(mode) {
|
|
switch(mode) {
|
|
case "fastest":
|
|
case "shortest":
|
|
return " by car";
|
|
case "bicycle":
|
|
return " by bicycle";
|
|
case "pedestrian":
|
|
return " by foot";
|
|
default:
|
|
return "";
|
|
}
|
|
};
|
|
|
|
$scope.oppositeColour = function(colour) {
|
|
if(!colour)
|
|
return "000000";
|
|
|
|
var d1 = parseInt(colour.substr(0, 2), 16);
|
|
var d2 = parseInt(colour.substr(2, 2), 16);
|
|
var d3 = parseInt(colour.substr(4, 2), 16);
|
|
return ((d1+d2+d3)/3 <= 64) ? "ffffff" : "000000";
|
|
};
|
|
});
|
|
|
|
function bindSocketToScope($scope, socket) {
|
|
socket.on("padData", function(data) {
|
|
$scope.padData = data;
|
|
});
|
|
|
|
socket.on("marker", function(data) {
|
|
$scope.markers[data.id] = data;
|
|
|
|
fp.addMarker(data);
|
|
});
|
|
|
|
socket.on("deleteMarker", function(data) {
|
|
delete $scope.markers[data.id];
|
|
|
|
if($scope.currentMarker && $scope.currentMarker.id == data.id && $scope.dialog && $scope.dialog.attr("id") == "edit-marker-dialog") {
|
|
$scope.currentMarker = null;
|
|
$scope.closeDialog();
|
|
}
|
|
|
|
fp.deleteMarker(data);
|
|
});
|
|
|
|
socket.on("line", function(data) {
|
|
$scope.lines[data.id] = data;
|
|
|
|
fp.addLine(data);
|
|
});
|
|
|
|
socket.on("deleteLine", function(data) {
|
|
delete $scope.lines[data.id];
|
|
|
|
if($scope.currentLine && $scope.currentLine.id == data.id && $scope.dialog && $scope.dialog.attr("id") == "edit-line-dialog") {
|
|
$scope.currentLine = null;
|
|
$scope.closeDialog();
|
|
}
|
|
|
|
fp.deleteLine(data);
|
|
});
|
|
|
|
socket.on("view", function(data) {
|
|
$scope.views[data.id] = data;
|
|
});
|
|
|
|
socket.on("deleteView", function(data) {
|
|
delete $scope.views[data.id];
|
|
});
|
|
|
|
socket.on("disconnect", function() {
|
|
$scope.error = true;
|
|
|
|
$scope.showMessage("error", "The connection to the server was lost.");
|
|
})
|
|
}
|
|
|
|
$(function() {
|
|
ng.bootstrap(document, [ "facilpad" ]);
|
|
});
|
|
|
|
})(FacilPad, jQuery, angular); |