cartodb/lib/assets/javascripts/builder/routes/router.js
2020-06-15 10:58:47 +08:00

253 lines
6.8 KiB
JavaScript

var Backbone = require('backbone');
var _ = require('underscore');
var checkAndBuildOpts = require('builder/helpers/required-opts');
var populateRoute = require('./populate-route');
var ROUTE_LAYERS = 'layers';
var ROUTE_WIDGETS = 'widgets';
var ROUTE_SETTINGS = 'settings';
var BASE_LAYER_ROUTE = 'layer/:layerId';
var ROUTE_WIDGET = 'widget/:widgetId';
var ROUTE_BASEMAP = 'basemap';
var ROUTE_LAYER_DATA_TAB = BASE_LAYER_ROUTE + '/data';
var ROUTE_LAYER_ANALYSES_TAB = BASE_LAYER_ROUTE + '/analyses(/:nodeId)';
var ROUTE_LAYER_STYLE_TAB = BASE_LAYER_ROUTE + '/style';
var ROUTE_LAYER_POPUPS_TAB = BASE_LAYER_ROUTE + '/popups';
var ROUTE_LAYER_LEGENDS_TAB = BASE_LAYER_ROUTE + '/legends';
var ROUTE_MODAL = 'modal';
var ROUTE_ADD_POINT = BASE_LAYER_ROUTE + '/add/point';
var ROUTE_ADD_LINE = BASE_LAYER_ROUTE + '/add/line';
var ROUTE_ADD_POLYGON = BASE_LAYER_ROUTE + '/add/polygon';
var EDIT_FEATURE = BASE_LAYER_ROUTE + '/edit/:featureId';
var REQUIRED_OPTS = [
'modals',
'editorModel',
'widgetDefinitionsCollection',
'handleModalsRoute',
'handleAnalysesRoute',
'handleWidgetRoute'
];
var ROUTES = [
['root', ''],
['root', ROUTE_LAYERS],
['settings', ROUTE_SETTINGS],
['layer', BASE_LAYER_ROUTE],
['widgets', ROUTE_WIDGETS],
['widget', ROUTE_WIDGET],
['layer_data', ROUTE_LAYER_DATA_TAB],
['layer_analyses', ROUTE_LAYER_ANALYSES_TAB],
['layer_style', ROUTE_LAYER_STYLE_TAB],
['layer_style', BASE_LAYER_ROUTE],
['layer_popups', ROUTE_LAYER_POPUPS_TAB],
['layer_legends', ROUTE_LAYER_LEGENDS_TAB],
['add_feature_point', ROUTE_ADD_POINT],
['add_feature_line', ROUTE_ADD_LINE],
['add_feature_polygon', ROUTE_ADD_POLYGON],
['edit_feature', EDIT_FEATURE],
['modal', ROUTE_MODAL],
['basemap', ROUTE_BASEMAP]
];
module.exports = (function () {
var initialized = false;
var routeModel = new Backbone.Model();
// keep last route before a modal, so we can replace /modal with it
var previousRoute;
// Routes that should not be kept as a "previous" route
var UNSTORABLE_ROUTES;
function generateRoute (routeName, model) {
return function () {
model.set('currentRoute', [routeName].concat(Array.prototype.slice.call(arguments)));
};
}
return {
init: function (options) {
if (initialized) {
throw new Error('Router can only be initialized once');
}
checkAndBuildOpts(options, REQUIRED_OPTS, this);
var self = this;
initialized = true;
this.appRouter = new Backbone.Router();
ROUTES.forEach(function (route) {
self.appRouter.route(route[1], generateRoute(route[0], routeModel));
});
UNSTORABLE_ROUTES = [
ROUTE_ADD_POINT,
ROUTE_ADD_LINE,
ROUTE_ADD_POLYGON,
EDIT_FEATURE
].map(function (route) {
return self.appRouter._routeToRegExp(route);
});
this._initBinds();
},
_initBinds: function () {
this.getRouteModel().on('change:currentRoute', this._onChangeRoute, this);
},
_onChangeRoute: function (routeModel) {
var currentRoute = routeModel.get('currentRoute');
if (!currentRoute) return;
this._handleModalsRoute(currentRoute, this._modals);
this._handleAnalysesRoute(currentRoute);
this._handleWidgetRoute(currentRoute, this._widgetDefinitionsCollection);
this._editorModel.set('edition', false);
},
getRouter: function () {
return this.appRouter;
},
getRouteModel: function () {
return routeModel;
},
goBack: function () {
Backbone.history.history.back();
},
goToDefaultRoute: function () {
this.navigate('');
},
replaceWithRoot: function () {
this.navigate('', { replace: true });
},
goToBaseMap: function (layerId) {
this.navigate(ROUTE_BASEMAP);
},
goToLayerList: function () {
this.navigate(ROUTE_LAYERS);
},
goToSettings: function () {
this.navigate(ROUTE_SETTINGS);
},
goToDataTab: function (layerId) {
this.navigate(populateRoute(ROUTE_LAYER_DATA_TAB, { layerId: layerId }));
},
goToAnalysisTab: function (layerId, options) {
this.navigate(populateRoute(ROUTE_LAYER_ANALYSES_TAB, { layerId: layerId }), options);
},
goToAnalysisNode: function (layerId, nodeId, options) {
var args = { layerId: layerId, nodeId: nodeId };
this.navigate(populateRoute(ROUTE_LAYER_ANALYSES_TAB, args), options);
},
goToStyleTab: function (layerId) {
this.navigate(populateRoute(ROUTE_LAYER_STYLE_TAB, { layerId: layerId }));
},
goToPopupsTab: function (layerId) {
this.navigate(populateRoute(ROUTE_LAYER_POPUPS_TAB, { layerId: layerId }));
},
goToLegendsTab: function (layerId) {
this.navigate(populateRoute(ROUTE_LAYER_LEGENDS_TAB, { layerId: layerId }));
},
goToWidgetList: function () {
this.navigate(ROUTE_WIDGETS);
},
goToWidget: function (widgetId) {
var route = routeModel.get('currentRoute');
var options = {};
if (_.isArray(route) && route[0] === 'widget') {
options.replace = true;
}
this.navigate(populateRoute(ROUTE_WIDGET, { widgetId: widgetId }), options);
},
getCurrentRoute: function () {
return Backbone.history.getPath();
},
saveCurrentRoute: function () {
var currentRoute = this.getCurrentRoute();
var canBeSaved = !UNSTORABLE_ROUTES.some(function (regex) {
return regex.test(currentRoute);
});
if (canBeSaved === true) {
previousRoute = currentRoute;
}
},
addPoint: function (layerId) {
this._addFeature(ROUTE_ADD_POINT, layerId);
},
addLine: function (layerId) {
this._addFeature(ROUTE_ADD_LINE, layerId);
},
addPolygon: function (layerId) {
this._addFeature(ROUTE_ADD_POLYGON, layerId);
},
goToPreviousRoute: function (options) {
previousRoute = previousRoute || options.fallback;
if (previousRoute !== null && previousRoute !== undefined) {
this.navigate(previousRoute, options.options);
previousRoute = null;
} else {
Backbone.history.history.back();
}
},
_addFeature: function (route, layerId) {
this.navigate(populateRoute(route, { layerId: layerId }));
},
editFeature: function (feature) {
var featureId = feature.get('cartodb_id');
var layerId = feature.getLayerId();
this.navigate(populateRoute(EDIT_FEATURE, {
layerId: layerId,
featureId: featureId
}));
},
navigate: function (route, options) {
this.saveCurrentRoute();
options = _.extend({
trigger: true
}, options);
this.appRouter.navigate(route, options);
},
replaceState: function (route) {
var root = Backbone.history.root;
var newRoute = root + route;
window.history.replaceState(null, null, newRoute);
}
};
})();