Uncaught TypeError: _arc2.default.GreatCircle is not a constructor - leaflet

Trying to create plugin for react-leaflet. I am getting this error while
i am returning
L.Polyline.Arc(position.from, position.to, option)
This is my Component
import React, { PropTypes } from 'react';
import { Path } from 'react-leaflet';
import L from 'leaflet'
import { Arc } from './leaflet.arc';
export default class ArcLine extends Path {
static propTypes = {
children: PropTypes.oneOfType([
PropTypes.arrayOf(PropTypes.node),
PropTypes.node,
]),
option:PropTypes.object,
position: PropTypes.object.isRequired
};
createLeafletElement (props) {
const { position, option, ...options } = props
return L.Polyline.Arc(position.from, position.to, option)
}
updateLeafletElement (fromProps, toProps) {
if (toProps.position !== fromProps.position) {
this.leafletElement._createLatLngs(line, toProps.position.from)
}
this.setStyleIfChanged(fromProps, toProps)
}
}
./leaflet.arc is
import arc from 'arc';
/**
* Transform L.LatLng to {x, y} object
* #param {L.LatLng} latlng
* #returns {{x: {number}, y: {number}}}
* #private
*/
const _latLngToXY = latlng => ({
x: latlng.lng,
y: latlng.lat
});
/**
* Create array of L.LatLng objects from line produced by arc.js
* #param {object} line
* #param {L.LatLng} from
* #private
* #returns {Array}
*/
function _createLatLngs(line, from) {
if (line.geometries[0] && line.geometries[0].coords[0]) {
/**
* stores how many times arc is broken over 180 longitude
* #type {number}
*/
let wrap = from.lng - line.geometries[0].coords[0][0] - 360;
return line.geometries
.map(subLine => {
wrap += 360;
return subLine.coords.map(point => L.latLng([point[1], point[0] + wrap]));
})
.reduce((all, latlngs) => all.concat(latlngs));
} else {
return [];
}
}
if (!L) {
throw "Leaflet.js not included";
} else if (!arc && !arc.GreatCircle) {
throw "arc.js not included";
} else {
L.Polyline.Arc = function (from, to, options) {
from = L.latLng(from);
to = L.latLng(to);
debugger
var vertices = 10;
var arcOptions = {};
if (options) {
if (options.offset) {
arcOptions.offset = options.offset;
delete options.offset;
}
if (options.vertices) {
vertices = options.vertices;
delete options.vertices;
}
}
var generator = new arc.GreatCircle({x: from.lng, y: from.lat}, {x: to.lng, y: to.lat});
var line = generator.Arc(vertices, arcOptions);
var latLngs = [];
var wrap = 0; // counts how many times arc is broken over 180 degree
if (line.geometries[0] && line.geometries[0].coords[0])
wrap = from.lng - line.geometries[0].coords[0][0];
line.geometries.forEach(function(line) {
line.coords.forEach(function (point) {
latLngs.push(L.latLng(
[point[1], point[0] + wrap]
));
});
wrap += 360;
});
line.geometries[0].coords
return L.polyline(latLngs, options);
};
}
Why am i getting this error, any suggestion?

In this line here:
import { Arc } from './leaflet.arc'
...you are trying to import the Arc variable from your leaflet.arc file. However, in your leaflet.arc file it doesn't look like you are exporting anything, simply attaching the Arc function to Leaflet's Polyline object. Also, in the code in your component you are not even using the Arc variable that you are trying to import. So, the code fails because a property is trying to be read from the undefined export from leaflet.arc. It seems that you should probably just import the file without trying to import any objects.
TLDR:
Replace this line:
import { Arc } from './leaflet.arc'
with this:
import './leaflet.arc'

Related

Chrome Developer Tools - Performance profiling

In the below image (from chrome performance profiling tab for a API call), what is resource loading which costs 719 ms ?
If I visit the network tab, for the same API call, I see only 10.05 seconds.
What is resource loading mean here ? Is there any specific activity the browser does after receiving the data ?
As #wOxxOM stated, buildNetworkRequestDetails is being called from Source Code
From the statement by #Sanju singh :
that statement doesn't tell anything, why it is taking that much time to make the resource available?
I think its necessary to break down exactly what is happening..
Summary:
Activity Browser and Network Activity are using different algorithms for calculating completion. Network Activity is calculating the response times from the request and Activity Browser is calculating the response time + time it took to add it into the WebInspector tracer.
Looking at
/**
* #param {!TimelineModel.TimelineModel.NetworkRequest} request
* #param {!TimelineModel.TimelineModel.TimelineModelImpl} model
* #param {!Components.Linkifier.Linkifier} linkifier
* #return {!Promise<!DocumentFragment>}
*/
static async buildNetworkRequestDetails(request, model, linkifier) {
const target = model.targetByEvent(request.children[0]);
const contentHelper = new TimelineDetailsContentHelper(target, linkifier);
const category = TimelineUIUtils.networkRequestCategory(request);
const color = TimelineUIUtils.networkCategoryColor(category);
contentHelper.addSection(ls`Network request`, color);
if (request.url) {
contentHelper.appendElementRow(ls`URL`, Components.Linkifier.Linkifier.linkifyURL(request.url));
}
// The time from queueing the request until resource processing is finished.
const fullDuration = request.endTime - (request.getStartTime() || -Infinity);
if (isFinite(fullDuration)) {
let textRow = Number.millisToString(fullDuration, true);
// The time from queueing the request until the download is finished. This
// corresponds to the total time reported for the request in the network tab.
const networkDuration = request.finishTime - request.getStartTime();
// The time it takes to make the resource available to the renderer process.
const processingDuration = request.endTime - request.finishTime;
if (isFinite(networkDuration) && isFinite(processingDuration)) {
const networkDurationStr = Number.millisToString(networkDuration, true);
const processingDurationStr = Number.millisToString(processingDuration, true);
const cacheOrNetworkLabel = request.cached() ? ls`load from cache` : ls`network transfer`;
textRow += ls` (${networkDurationStr} ${cacheOrNetworkLabel} + ${processingDurationStr} resource loading)`;
}
contentHelper.appendTextRow(ls`Duration`, textRow);
}
if (request.requestMethod) {
contentHelper.appendTextRow(ls`Request Method`, request.requestMethod);
}
if (typeof request.priority === 'string') {
const priority = PerfUI.NetworkPriorities.uiLabelForNetworkPriority(
/** #type {!Protocol.Network.ResourcePriority} */ (request.priority));
contentHelper.appendTextRow(ls`Priority`, priority);
}
if (request.mimeType) {
contentHelper.appendTextRow(ls`Mime Type`, request.mimeType);
}
let lengthText = '';
if (request.memoryCached()) {
lengthText += ls` (from memory cache)`;
} else if (request.cached()) {
lengthText += ls` (from cache)`;
} else if (request.timing && request.timing.pushStart) {
lengthText += ls` (from push)`;
}
if (request.fromServiceWorker) {
lengthText += ls` (from service worker)`;
}
if (request.encodedDataLength || !lengthText) {
lengthText = `${Number.bytesToString(request.encodedDataLength)}${lengthText}`;
}
contentHelper.appendTextRow(ls`Encoded Data`, lengthText);
if (request.decodedBodyLength) {
contentHelper.appendTextRow(ls`Decoded Body`, Number.bytesToString(request.decodedBodyLength));
}
const title = ls`Initiator`;
const sendRequest = request.children[0];
const topFrame = TimelineModel.TimelineModel.TimelineData.forEvent(sendRequest).topFrame();
if (topFrame) {
const link = linkifier.maybeLinkifyConsoleCallFrame(target, topFrame, {tabStop: true});
if (link) {
contentHelper.appendElementRow(title, link);
}
} else {
const initiator = TimelineModel.TimelineModel.TimelineData.forEvent(sendRequest).initiator();
if (initiator) {
const initiatorURL = TimelineModel.TimelineModel.TimelineData.forEvent(initiator).url;
if (initiatorURL) {
const link = linkifier.maybeLinkifyScriptLocation(target, null, initiatorURL, 0, {tabStop: true});
if (link) {
contentHelper.appendElementRow(title, link);
}
}
}
}
if (!request.previewElement && request.url && target) {
request.previewElement = await Components.ImagePreview.ImagePreview.build(
target, request.url, false,
{imageAltText: Components.ImagePreview.ImagePreview.defaultAltTextForImageURL(request.url)});
}
if (request.previewElement) {
contentHelper.appendElementRow(ls`Preview`, request.previewElement);
}
return contentHelper.fragment;
}
We can easily see that the request parameter is of type
`TimelineModel.TimelineModel.NetworkRequest`
NetWorkRequest has the following code:
_didStopRecordingTraceEvents: function()
{
var metadataEvents = this._processMetadataEvents();
this._injectCpuProfileEvents(metadataEvents);
this._tracingModel.tracingComplete();
this._resetProcessingState();
var startTime = 0;
for (var i = 0, length = metadataEvents.page.length; i < length; i++) {
var metaEvent = metadataEvents.page[i];
var process = metaEvent.thread.process();
var endTime = i + 1 < length ? metadataEvents.page[i + 1].startTime : Infinity;
this._currentPage = metaEvent.args["data"] && metaEvent.args["data"]["page"];
for (var thread of process.sortedThreads()) {
if (thread.name() === WebInspector.TimelineModel.WorkerThreadName && !metadataEvents.workers.some(function(e) { return e.args["data"]["workerThreadId"] === thread.id(); }))
continue;
this._processThreadEvents(startTime, endTime, metaEvent.thread, thread);
}
startTime = endTime;
}
this._inspectedTargetEvents.sort(WebInspector.TracingModel.Event.compareStartTime);
this._cpuProfiles = null;
this._buildTimelineRecords();
this._buildGPUTasks();
this._insertFirstPaintEvent();
this._resetProcessingState();
this.dispatchEventToListeners(WebInspector.TimelineModel.Events.RecordingStopped);
},
We can see that endTime is being calculated from:
metaEvent.thread.process()
We can see that metaEvent.page is being set by:
_processMetadataEvents: function()
{
var metadataEvents = this._tracingModel.devToolsMetadataEvents();
var pageDevToolsMetadataEvents = [];
var workersDevToolsMetadataEvents = [];
for (var event of metadataEvents) {
if (event.name === WebInspector.TimelineModel.DevToolsMetadataEvent.TracingStartedInPage)
pageDevToolsMetadataEvents.push(event);
else if (event.name === WebInspector.TimelineModel.DevToolsMetadataEvent.TracingSessionIdForWorker)
workersDevToolsMetadataEvents.push(event);
}
if (!pageDevToolsMetadataEvents.length) {
// The trace is probably coming not from DevTools. Make a mock Metadata event.
var pageMetaEvent = this._loadedFromFile ? this._makeMockPageMetadataEvent() : null;
if (!pageMetaEvent) {
console.error(WebInspector.TimelineModel.DevToolsMetadataEvent.TracingStartedInPage + " event not found.");
return {page: [], workers: []};
}
pageDevToolsMetadataEvents.push(pageMetaEvent);
}
var sessionId = pageDevToolsMetadataEvents[0].args["sessionId"] || pageDevToolsMetadataEvents[0].args["data"]["sessionId"];
this._sessionId = sessionId;
var mismatchingIds = new Set();
/**
* #param {!WebInspector.TracingModel.Event} event
* #return {boolean}
*/
function checkSessionId(event)
{
var args = event.args;
// FIXME: put sessionId into args["data"] for TracingStartedInPage event.
if (args["data"])
args = args["data"];
var id = args["sessionId"];
if (id === sessionId)
return true;
mismatchingIds.add(id);
return false;
}
var result = {
page: pageDevToolsMetadataEvents.filter(checkSessionId).sort(WebInspector.TracingModel.Event.compareStartTime),
workers: workersDevToolsMetadataEvents.filter(checkSessionId).sort(WebInspector.TracingModel.Event.compareStartTime)
};
if (mismatchingIds.size)
WebInspector.console.error("Timeline recording was started in more than one page simultaneously. Session id mismatch: " + this._sessionId + " and " + mismatchingIds.valuesArray() + ".");
return result;
}

VSCode Selection to snippet

It's a beginner question so don't be to hard to me.
Example:
A,B,C,D, ..
I need to convert this string to the following output in VSCode
enum id name
{
value(0; A) { Caption = 'A'; }
value(1; B) { Caption = 'B'; }
value(2; C) { Caption = 'C'; }
value(3; D) { Caption = 'D'; }
}
I can read the selection and split it into separate tokens.
But I'm stuck when it comes to writing it back to my line.
My Code:
'use strict';
// The module 'vscode' contains the VS Code extensibility API
// Import the module and reference it with the alias vscode in your code below
//import * as vscode from 'vscode';
import { window, commands, Disposable, ExtensionContext, StatusBarAlignment, StatusBarItem, TextDocument, TextEditor, ViewColumn, workspace, TextLine, TextEdit, Uri, Position } from 'vscode';
import { stringify } from 'querystring';
// this method is called when your extension is activated
// your extension is activated the very first time the command is executed
export function activate(context: ExtensionContext) {
console.log('"Cg Helper" is now active!');
let cgHelper = new CgALHelper;
let disp = commands.registerCommand('extension.convertSelection2Enum', () =>{
cgHelper.convertSelection2Enum(window.activeTextEditor);
})
context.subscriptions.push(disp);
}
// this method is called when your extension is deactivated
export function deactivate() {
}
class CgALHelper
{
public convertSelection2Enum(editor: TextEditor)
{
this.convertTextLine2Enum(editor);
}
public convertInputText2Enum()
{
}
private convertTextLine2Enum(editor: TextEditor)
{
let line = editor.document.lineAt(editor.selection.active.line);
if (line != null && line.text != null)
{
window.showInformationMessage(line.text);
let tokens = line.text.split(',');
if (tokens[0] != null && tokens[0] != '' && tokens.length != 0 )
{
tokens.forEach(tok => {
// I'm stuck here !
});
} else
window.showErrorMessage('nothing to convert');
} else
window.showErrorMessage('Nothing to convert');
}
}
You want to construct a SnippetString. Snippet strings can be constructed incrementally:
const snippet = new vscode.SnippetString();
snippet.appendText('enum id name {');
tokens.forEach(tok => {
snippet.appendText(` value(0; ${tok}) { Caption = '${tok}'; }`)
});
snippet.appendText('}');
Then apply the snippet to the editor using TextEditor.insertSnippet:
editor.insertSnippet(snippet);

How can one make an ellipse in react-leaflet?

I am trying to draw an ellipse on a map made using react-leaflet, which has built-in support for circles and rectangles.
To achieve this, I am using code to produce an ellipse in (non-react) leaflet from here, that I have adapted and pasted below:
import * as L from 'leaflet';
L.SVG.include ({
_updateEllipse: function (layer) {
var // c = layer._point,
rx = layer._radiusX,
ry = layer._radiusY,
phi = layer._tiltDeg,
endPoint = layer._endPointParams;
var d = 'M' + endPoint.x0 + ',' + endPoint.y0 +
'A' + rx + ',' + ry + ',' + phi + ',' +
endPoint.largeArc + ',' + endPoint.sweep + ',' +
endPoint.x1 + ',' + endPoint.y1 + ' z';
this._setPath(layer, d);
}
});
L.Canvas.include ({
_updateEllipse: function (layer) {
if (layer._empty()) { return; }
var p = layer._point,
ctx = this._ctx,
r = layer._radiusX,
s = (layer._radiusY || r) / r;
this._drawnLayers[layer._leaflet_id] = layer;
ctx.save();
ctx.translate(p.x, p.y);
if (layer._tilt !== 0) {
ctx.rotate( layer._tilt );
}
if (s !== 1) {
ctx.scale(1, s);
}
ctx.beginPath();
ctx.arc(0, 0, r, 0, Math.PI * 2);
ctx.restore();
this._fillStroke(ctx, layer);
},
});
L.Ellipse = L.Path.extend({
options: {
fill: true,
startAngle: 0,
endAngle: 359.9
},
initialize: function (latlng, radii, tilt, options) {
L.setOptions(this, options);
this._latlng = L.latLng(latlng);
if (tilt) {
this._tiltDeg = tilt;
} else {
this._tiltDeg = 0;
}
if (radii) {
this._mRadiusX = radii[0];
this._mRadiusY = radii[1];
}
},
setRadius: function (radii) {
this._mRadiusX = radii[0];
this._mRadiusY = radii[1];
return this.redraw();
},
getRadius: function () {
return new L.point(this._mRadiusX, this._mRadiusY);
},
setTilt: function (tilt) {
this._tiltDeg = tilt;
return this.redraw();
},
getBounds: function () {
// TODO respect tilt (bounds are too big)
var lngRadius = this._getLngRadius(),
latRadius = this._getLatRadius(),
latlng = this._latlng;
return new L.LatLngBounds(
[latlng.lat - latRadius, latlng.lng - lngRadius],
[latlng.lat + latRadius, latlng.lng + lngRadius]);
},
// #method setLatLng(latLng: LatLng): this
// Sets the position of a circle marker to a new location.
setLatLng: function (latlng) {
this._latlng = L.latLng(latlng);
this.redraw();
return this.fire('move', {latlng: this._latlng});
},
// #method getLatLng(): LatLng
// Returns the current geographical position of the circle marker
getLatLng: function () {
return this._latlng;
},
setStyle: L.Path.prototype.setStyle,
_project: function () {
var lngRadius = this._getLngRadius(),
latRadius = this._getLatRadius(),
latlng = this._latlng,
pointLeft = this._map.latLngToLayerPoint([latlng.lat, latlng.lng - lngRadius]),
pointBelow = this._map.latLngToLayerPoint([latlng.lat - latRadius, latlng.lng]);
this._point = this._map.latLngToLayerPoint(latlng);
this._radiusX = Math.max(this._point.x - pointLeft.x, 1);
this._radiusY = Math.max(pointBelow.y - this._point.y, 1);
this._tilt = Math.PI * this._tiltDeg / 180;
this._endPointParams = this._centerPointToEndPoint();
this._updateBounds();
},
_updateBounds: function () {
// http://math.stackexchange.com/questions/91132/how-to-get-the-limits-of-rotated-ellipse
var sin = Math.sin(this._tilt);
var cos = Math.cos(this._tilt);
var sinSquare = sin * sin;
var cosSquare = cos * cos;
var aSquare = this._radiusX * this._radiusX;
var bSquare = this._radiusY * this._radiusY;
var halfWidth = Math.sqrt(aSquare*cosSquare+bSquare*sinSquare);
var halfHeight = Math.sqrt(aSquare*sinSquare+bSquare*cosSquare);
var w = this._clickTolerance();
var p = [halfWidth + w, halfHeight + w];
this._pxBounds = new L.Bounds(this._point.subtract(p), this._point.add(p));
},
_update: function () {
if (this._map) {
this._updatePath();
}
},
_updatePath: function () {
this._renderer._updateEllipse(this);
},
_getLatRadius: function () {
return (this._mRadiusY / 40075017) * 360;
},
_getLngRadius: function () {
return ((this._mRadiusX / 40075017) * 360) / Math.cos((Math.PI / 180) * this._latlng.lat);
},
_centerPointToEndPoint: function () {
// Convert between center point parameterization of an ellipse
// too SVG's end-point and sweep parameters. This is an
// adaptation of the perl code found here:
// http://commons.oreilly.com/wiki/index.php/SVG_Essentials/Paths
var c = this._point,
rx = this._radiusX,
ry = this._radiusY,
theta2 = (this.options.startAngle + this.options.endAngle) * (Math.PI / 180),
theta1 = this.options.startAngle * (Math.PI / 180),
delta = this.options.endAngle,
phi = this._tiltDeg * (Math.PI / 180);
// Determine start and end-point coordinates
var x0 = c.x + Math.cos(phi) * rx * Math.cos(theta1) +
Math.sin(-phi) * ry * Math.sin(theta1);
var y0 = c.y + Math.sin(phi) * rx * Math.cos(theta1) +
Math.cos(phi) * ry * Math.sin(theta1);
var x1 = c.x + Math.cos(phi) * rx * Math.cos(theta2) +
Math.sin(-phi) * ry * Math.sin(theta2);
var y1 = c.y + Math.sin(phi) * rx * Math.cos(theta2) +
Math.cos(phi) * ry * Math.sin(theta2);
var largeArc = (delta > 180) ? 1 : 0;
var sweep = (delta > 0) ? 1 : 0;
return {'x0': x0, 'y0': y0, 'tilt': phi, 'largeArc': largeArc,
'sweep': sweep, 'x1': x1, 'y1': y1};
},
_empty: function () {
return this._radiusX && this._radiusY && !this._renderer._bounds.intersects(this._pxBounds);
},
_containsPoint : function (p) {
// http://stackoverflow.com/questions/7946187/point-and-ellipse-rotated-position-test-algorithm
var sin = Math.sin(this._tilt);
var cos = Math.cos(this._tilt);
var dx = p.x - this._point.x;
var dy = p.y - this._point.y;
var sumA = cos * dx + sin * dy;
var sumB = sin * dx - cos * dy;
return sumA * sumA / (this._radiusX * this._radiusX) + sumB * sumB / (this._radiusY * this._radiusY) <= 1;
}
});
export const lellipse = function (latlng, radii, tilt, options) {
return new L.Ellipse(latlng, radii, tilt, options);
};
To create an ellipse to use with react-leaflet, I followed the example of Circle in react-leaflet to produce the following Ellipse component:
import PropTypes from 'prop-types'
import { lellipse as LeafletEllipse } from '../l.ellipse';
import Path from './Path'
import children from './propTypes/children'
import latlng from './propTypes/latlng'
import type { LatLng, MapLayerProps, PathOptions } from './types'
type LeafletElement = LeafletEllipse
type Props = {
center: LatLng,
mSemiMajorAxis: number,
mSemiMinorAxis: number,
degreeTiltFromWest: number,
} & MapLayerProps &
PathOptions &
Object
export default class Ellipse extends Path<LeafletElement, Props> {
static propTypes = {
center: latlng.isRequired,
mSemiMajorAxis: PropTypes.number.isRequired,
mSemiMinorAxis: PropTypes.number.isRequired,
degreeTiltFromWest: PropTypes.number.isRequired,
children: children,
}
createLeafletElement(props: Props): LeafletElement {
const { center, mSemiMajorAxis, mSemiMinorAxis, degreeTiltFromWest, ...options } = props
return new LeafletEllipse(center, [mSemiMajorAxis, mSemiMinorAxis], this.getOptions(options))
}
updateLeafletElement(fromProps: Props, toProps: Props) {
if (toProps.center !== fromProps.center) {
this.leafletElement.setLatLng(toProps.center);
}
if (toProps.degreeTiltFromWest !== fromProps.degreeTiltFromWest) {
this.leafletElement.setTilt(toProps.degreeTiltFromWest);
}
if (toProps.mSemiMinorAxis !== fromProps.mSemiMinorAxis || toProps.mSemiMajorAxis !== fromProps.mSemiMajorAxis) {
this.leafletElement.setRadius([toProps.mSemiMajorAxis, toProps.mSemiMinorAxis]);
}
}
}
The problem with the code is that it does not render an ellipse and it does not throw any errors. Could someone suggest how to render an ellipse with react-leaflet? Thanks.
Your createLeafletElement function is missing the tilt parameter. It should be:
createLeafletElement(props) {
const { center, mSemiMajorAxis, mSemiMinorAxis, degreeTiltFromWest, ...options } = props
return new LeafletEllipse(center, [mSemiMajorAxis, mSemiMinorAxis], degreeTiltFromWest, this.getOptions(options))
}
See below for the complete file (in ES6 rather than in typescript, as I find it clearer).
import React, { PropTypes } from 'react';
import { lellipse as LeafletEllipse } from './l.ellipse';
import { Path, withLeaflet } from 'react-leaflet';
class Ellipse extends Path {
static propTypes = {
center: PropTypes.arrayOf(PropTypes.number).isRequired,
mSemiMajorAxis: PropTypes.number.isRequired,
mSemiMinorAxis: PropTypes.number.isRequired,
degreeTiltFromWest: PropTypes.number.isRequired
}
createLeafletElement(props) {
const { center, mSemiMajorAxis, mSemiMinorAxis, degreeTiltFromWest, ...options } = props
return new LeafletEllipse(center, [mSemiMajorAxis, mSemiMinorAxis], degreeTiltFromWest, this.getOptions(options))
}
updateLeafletElement(fromProps, toProps) {
if (toProps.center !== fromProps.center) {
this.leafletElement.setLatLng(toProps.center);
}
if (toProps.degreeTiltFromWest !== fromProps.degreeTiltFromWest) {
this.leafletElement.setTilt(toProps.degreeTiltFromWest);
}
if (toProps.mSemiMinorAxis !== fromProps.mSemiMinorAxis || toProps.mSemiMajorAxis !== fromProps.mSemiMajorAxis) {
this.leafletElement.setRadius([toProps.mSemiMajorAxis, toProps.mSemiMinorAxis]);
}
}
}
export default class withLeaflet(Ellipse);

React Leaflet.Arc - Animate

I am trying create ReactLeafletArc Plugin with animation this is the code
if (!L) {
throw "Leaflet.js not included";
} else if (!arc || !arc.GreatCircle) {
throw "arc.js not included";
} else {
L.Polyline.Arc = function (from, to, options) {
from = L.latLng(from);
to = L.latLng(to);
var vertices = 10;
var arcOptions = {};
if (options) {
if (options.offset) {
arcOptions.offset = options.offset;
delete options.offset;
}
if (options.vertices) {
vertices = options.vertices;
delete options.vertices;
}
}
var generator = new arc.GreatCircle({ x: from.lng, y: from.lat }, { x: to.lng, y: to.lat });
var line = generator.Arc(vertices, arcOptions);
var latLngs = [];
var newLine = L.polyline(line.geometries[0].coords.map(function (c) {
return c.reverse();
}), options);
var totalLength = newLine._path.getTotalLength() * 4;
newLine._path.classList.add('path-start');
newLine._path.style.strokeDashoffset = totalLength;
newLine._path.style.strokeDasharray = totalLength;
setTimeout((function (path) {
return function () {
path.style.strokeDashoffset = 0;
};
})(newLine._path), 200);
return newLine;
};
}
I get error
Uncaught TypeError: Cannot read property 'getTotalLength' of undefined
with console.log(newLine) i can see that there is not _path.
NewClass
_bounds:L.LatLngBounds
_initHooksCalled:true
_latlngs:Array[100]
options:Object
__proto__:NewClass
But if i comment the part
var totalLength = newLine._path.getTotalLength() * 4;
newLine._path.classList.add('path-start');
newLine._path.style.strokeDashoffset = totalLength;
newLine._path.style.strokeDasharray = totalLength;
setTimeout((function (path) {
return function () {
path.style.strokeDashoffset = 0;
};
})(newLine._path), 200);
The line is created without animation and with console.log(newLine) i get this
NewClass
_bounds:L.LatLngBounds
_initHooksCalled:true
_latlngs:Array[100]
_leaflet_id:122
_map:NewClass
_mapToAdd:NewClass
_parts:Array[1]
_path:path
_pxBounds:L.Bounds
_renderer:NewClass
_rings:Array[1]
_zoomAnimated:true
options:Object
__proto__:NewClass
Any suggestion?

Xtext, transform ascii character to math symboles

How can a xtext editor translate (for example) -> to the latex symbol \rightarrow?
Have a look at the nice feature of autoedit
public class MyDslDefaultAutoEditStrategyProvider extends DefaultAutoEditStrategyProvider {
#Inject
protected Provider<ShortCutEditStrategy> shortCut;
#Override
protected void configureStringLiteral(IEditStrategyAcceptor acceptor) {
acceptor.accept(shortCut.get().configure("->", "\\rightarrow"), IDocument.DEFAULT_CONTENT_TYPE);
}
}
and dont forget the binding
override Class<? extends AbstractEditStrategyProvider> bindAbstractEditStrategyProvider() {
MyDslDefaultAutoEditStrategyProvider
}
It's quite easy using JavaScript. This simple script should help:
replaceText('->', '\rightarrow');
var replaceText = function (search, replaceWith) {
var area = document.getElementById("area");
var getCount = function (str, search) {
return str.split(search).length - 1;
};
if (area.value.indexOf(search) >= 0) {
var start = area.selectionStart;
var end = area.selectionEnd;
var textBefore = area.value.substr(0, end);
var lengthDiff = (replaceWith.length - search.length) * getCount(textBefore, search);
area.value = area.value.replace(search, replaceWith);
area.selectionStart = start + lengthDiff;
area.selectionEnd = end + lengthDiff;
}
};
This full text can be easily adapted for your use- here's a full example.
<textarea id="area"></textarea>
<script>
function keyDownTextField() {
replaceText('->', '\u2192');
}
var replaceText = function (search, replaceWith) {
var area = document.getElementById("area");
var getCount = function (str, search) {
return str.split(search).length - 1;
};
if (area.value.indexOf(search) >= 0) {
var start = area.selectionStart;
var end = area.selectionEnd;
var textBefore = area.value.substr(0, end);
var lengthDiff = (replaceWith.length - search.length) * getCount(textBefore, search);
area.value = area.value.replace(search, replaceWith);
area.selectionStart = start + lengthDiff;
area.selectionEnd = end + lengthDiff;
}
};
document.addEventListener("keydown", keyDownTextField, false);
</script>