jupyterlab-emrys
Version:
A computational environment for Jupyter. Powered by Emrys
155 lines (154 loc) • 5.36 kB
JavaScript
// Copyright (c) Jupyter Development Team.
// Distributed under the terms of the Modified BSD License.
"use strict";
var __extends = (this && this.__extends) || function (d, b) {
for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
var phosphor_widget_1 = require('phosphor-widget');
var docregistry_1 = require('../docregistry');
var json_1 = require('../notebook/common/json');
var leaflet = require('leaflet');
/**
* The class name added to a map widget.
*/
var MAP_CLASS = 'jp-MapWidget';
/**
* A widget for maps.
*/
var MapWidget = (function (_super) {
__extends(MapWidget, _super);
/**
* Construct a new map widget.
*/
function MapWidget(context) {
var _this = this;
_super.call(this);
this._fitted = false;
this._sized = false;
this._width = -1;
this._height = -1;
this._geojson = null;
this._context = context;
this.node.tabIndex = -1;
this.addClass(MAP_CLASS);
this._map = leaflet.map(this.node).fitWorld();
leaflet.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: 'Map data (c) <a href="https://openstreetmap.org">OpenStreetMap</a> contributors',
min_zoom: 0,
max_zoom: 18,
}).addTo(this._map);
// Since we keep track of the widget size, we monkeypatch the map
// to use our information instead of doing a DOM read every time it needs
// the size info. We can stop monkeypatching when we have a size hint change
// available from leaflet (cf.
// https://github.com/Leaflet/Leaflet/issues/4200#issuecomment-233616337 and
// https://github.com/jupyter/jupyterlab/pull/454#discussion_r71349224)
this._map.getSize = function () {
var map = _this._map;
if (!map._size || map._sizeChanged) {
if (_this._width < 0 || _this._height < 0) {
return map.prototype.getSize.call(map);
}
map._size = new leaflet.Point(_this._width, _this._height);
map._sizeChanged = false;
}
return map._size.clone();
};
context.model.contentChanged.connect(function () {
_this.update();
});
context.pathChanged.connect(function () {
_this.update();
});
}
/**
* Dispose of the resources used by the widget.
*/
MapWidget.prototype.dispose = function () {
if (this.isDisposed) {
return;
}
this._context = null;
this._map.remove();
this._map = null;
this._geojsonLayer = null;
_super.prototype.dispose.call(this);
};
/**
* Handle `update-request` messages for the widget.
*/
MapWidget.prototype.onUpdateRequest = function (msg) {
this.title.text = this._context.path.split('/').pop();
if (!this.isAttached) {
return;
}
var content = this._context.model.toString();
var geojson = content ? JSON.parse(content) : content;
if (json_1.deepEqual(geojson, this._geojson)) {
return;
}
// we're attached to the DOM and have new layer content now
if (this._geojsonLayer) {
this._map.removeLayer(this._geojsonLayer);
}
this._geojson = geojson;
this._geojsonLayer = null;
if (geojson) {
this._geojsonLayer = leaflet.geoJson(geojson, {
pointToLayer: function (feature, latlng) {
return leaflet.circleMarker(latlng);
}
});
this._map.addLayer(this._geojsonLayer);
this._fitLayerBounds();
}
};
/**
* A message handler invoked on a 'resize' message.
*/
MapWidget.prototype.onResize = function (msg) {
this._sized = true;
this._width = msg.width;
this._height = msg.height;
this._map.invalidateSize(true);
this._fitLayerBounds();
};
/**
* Make the map fit the geojson layer bounds only once when all info is available.
*/
MapWidget.prototype._fitLayerBounds = function () {
if (!this._fitted && this._sized && this._geojsonLayer) {
this._map.fitBounds(this._geojsonLayer.getBounds());
this._fitted = true;
}
};
/**
* A message handler after the widget is attached to the DOM.
*/
MapWidget.prototype.onAfterAttach = function () {
this.update();
};
return MapWidget;
}(phosphor_widget_1.Widget));
exports.MapWidget = MapWidget;
/**
* A widget factory for maps.
*/
var MapWidgetFactory = (function (_super) {
__extends(MapWidgetFactory, _super);
function MapWidgetFactory() {
_super.apply(this, arguments);
}
/**
* Create a new widget given a context.
*/
MapWidgetFactory.prototype.createNew = function (context, kernel) {
var widget = new MapWidget(context);
this.widgetCreated.emit(widget);
return widget;
};
return MapWidgetFactory;
}(docregistry_1.ABCWidgetFactory));
exports.MapWidgetFactory = MapWidgetFactory;