geojs 1.9.1 → 1.9.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "geojs",
3
- "version": "1.9.1",
3
+ "version": "1.9.4",
4
4
  "description": "JavaScript Geo Visualization and Analysis Library",
5
5
  "homepage": "https://github.com/OpenGeoscience/geojs",
6
6
  "license": "Apache-2.0",
@@ -67,7 +67,7 @@
67
67
  "karma-coverage": "^2.1.1",
68
68
  "karma-firefox-launcher": "^2.1.2",
69
69
  "karma-jasmine": "^5.0.0",
70
- "karma-jasmine-html-reporter": "^1.7.0",
70
+ "karma-jasmine-html-reporter": "^2.0.0",
71
71
  "karma-sinon": "^1.0.5",
72
72
  "karma-sourcemap-loader": "^0.3.8",
73
73
  "karma-spec-reporter": "^0.0.34",
@@ -85,7 +85,7 @@
85
85
  "shader-loader": "^1.3.1",
86
86
  "sinon": "^14.0.0",
87
87
  "style-loader": "^3.3.1",
88
- "stylus": "^0.57.0",
88
+ "stylus": "^0.58.1",
89
89
  "stylus-loader": "^7.0.0",
90
90
  "terser-webpack-plugin": "^5.3.1",
91
91
  "touch-emulator": "^1.0.0",
package/src/action.js CHANGED
@@ -16,10 +16,7 @@ var geo_action = {
16
16
  zoomrotate: 'geo_action_zoom_rotate',
17
17
  zoomselect: 'geo_action_zoomselect',
18
18
 
19
- // annotation actions
20
- annotation_line: 'geo_annotation_line',
21
- annotation_polygon: 'geo_annotation_polygon',
22
- annotation_rectangle: 'geo_annotation_rectangle',
19
+ // annotation actions -- some are also added by the registry
23
20
  annotation_edit_handle: 'geo_annotation_edit_handle'
24
21
  };
25
22
 
@@ -151,6 +151,14 @@ var annotation = function (type, args) {
151
151
  return m_id;
152
152
  };
153
153
 
154
+ /**
155
+ * Assign a new id to this annotation.
156
+ */
157
+ this.newId = function () {
158
+ annotationId += 1;
159
+ m_id = annotationId;
160
+ };
161
+
154
162
  /**
155
163
  * Get or set the name of this annotation.
156
164
  *
@@ -49,6 +49,17 @@ var textFeature = require('./textFeature');
49
49
  * style object.
50
50
  */
51
51
 
52
+ /**
53
+ * @typedef {geo.util.polyop.spec} geo.util.polyop.annotationLayerSpec
54
+ * @extends {geo.util.polyop.spec}
55
+ * @property {string} [keepAnnotations='exact'] Determine which annotations are
56
+ * present after a boolean operation. `'exact'` replaces modified
57
+ * annotations with the results; unmodified annotations are left as is.
58
+ * `'all'` replaces all annotations, so unchanged annotations may be
59
+ * converted to polygonAnnotations. `'none'` discards all existing
60
+ * annotations and only keeps modified results.
61
+ */
62
+
52
63
  /**
53
64
  * Layer to handle direct interactions with different features. Annotations
54
65
  * (features) can be created by calling mode(<name of feature>) or cancelled
@@ -470,6 +481,9 @@ var annotationLayer = function (arg) {
470
481
  this.addAnnotation = function (annotation, gcs, update) {
471
482
  var pos = $.inArray(annotation, m_annotations);
472
483
  if (pos < 0) {
484
+ while (m_this.annotationById(annotation.id())) {
485
+ annotation.newId();
486
+ }
473
487
  m_this.geoTrigger(geo_event.annotation.add_before, {
474
488
  annotation: annotation
475
489
  });
@@ -1247,11 +1261,15 @@ var annotationLayer = function (arg) {
1247
1261
  this.toPolygonList = function (opts) {
1248
1262
  const poly = [];
1249
1263
  opts = opts || {};
1250
- opts.annotationIndices = [];
1264
+ const indices = [];
1265
+ if (!opts.annotationIndices) {
1266
+ opts.annotationIndices = {};
1267
+ }
1268
+ opts.annotationIndices[m_this.id()] = indices;
1251
1269
  m_annotations.forEach((annotation, idx) => {
1252
1270
  if (annotation.toPolygonList) {
1253
1271
  annotation.toPolygonList(opts).forEach((p) => poly.push(p));
1254
- opts.annotationIndices.push(idx);
1272
+ indices.push(idx);
1255
1273
  }
1256
1274
  });
1257
1275
  return poly;
@@ -1261,8 +1279,8 @@ var annotationLayer = function (arg) {
1261
1279
  * Replace appropriate annotations with a list of polygons.
1262
1280
  *
1263
1281
  * @param {geo.polygonList} poly A list of polygons.
1264
- * @param {geo.util.polyop.spec} [opts] This contains annotationIndices and
1265
- * correspondence used to track annotations.
1282
+ * @param {geo.util.polyop.annotationLayerSpec} [opts] This contains
1283
+ * annotationIndices and correspondence used to track annotations.
1266
1284
  * @returns {this}
1267
1285
  */
1268
1286
  this.fromPolygonList = function (poly, opts) {
@@ -1274,14 +1292,15 @@ var annotationLayer = function (arg) {
1274
1292
  const keepIds = {};
1275
1293
  const reusedIds = {};
1276
1294
  let correspond, exact, annot;
1277
- if (opts.annotationIndices && opts.correspond && opts.correspond.poly1 && opts.annotationIndices.length === opts.correspond.poly1.length) {
1295
+ const indices = (opts.annotationIndices || {})[m_this.id()];
1296
+ if (indices && opts.correspond && opts.correspond.poly1 && indices.length === opts.correspond.poly1.length) {
1278
1297
  correspond = opts.correspond.poly1;
1279
1298
  exact = opts.correspond.exact1;
1280
1299
  annot = m_this.annotations();
1281
1300
  }
1282
- if (keep !== 'all' && keep !== 'none') {
1301
+ if (keep !== 'all' && keep !== 'none' && annot) {
1283
1302
  annot.forEach((oldAnnot, idx) => {
1284
- if (opts.annotationIndices.indexOf(idx) < 0) {
1303
+ if (indices.indexOf(idx) < 0) {
1285
1304
  keepIds[oldAnnot.id()] = true;
1286
1305
  }
1287
1306
  });
@@ -1295,7 +1314,7 @@ var annotationLayer = function (arg) {
1295
1314
  if (correspond) {
1296
1315
  for (let i = 0; i < correspond.length; i += 1) {
1297
1316
  if (correspond[i] && correspond[i].indexOf(idx) >= 0) {
1298
- const orig = annot[opts.annotationIndices[i]];
1317
+ const orig = annot[indices[i]];
1299
1318
  if (keep !== 'all' && keep !== 'none' && exact && exact[i] && exact[i].indexOf(idx) >= 0) {
1300
1319
  keepIds[orig.id()] = true;
1301
1320
  return;
@@ -1332,7 +1351,7 @@ var annotationLayer = function (arg) {
1332
1351
  }
1333
1352
  // add new annotations
1334
1353
  polyAnnot.forEach((p) => {
1335
- m_this.addAnnotation(registry.createAnnotation('polygon', p), m_this.gcs(), false);
1354
+ m_this.addAnnotation(registry.createAnnotation('polygon', p), m_this.map().gcs(), false);
1336
1355
  update = true;
1337
1356
  });
1338
1357
  if (update) {
@@ -46,9 +46,12 @@ var util = require('./util');
46
46
  * divided by the sine of half the angle between segments, then a bevel join
47
47
  * is used instead. This is a single value that applies to all lines. If a
48
48
  * function, it is called with `(data)`.
49
- * @property {boolean|function} [uniformLine=false] Boolean indicating if each
50
- * line has a uniform style (uniform stroke color, opacity, and width). Can
51
- * vary by line.
49
+ * @property {boolean|string|function} [uniformLine=false] Boolean indicating
50
+ * if each line has a uniform style (uniform stroke color, opacity, and
51
+ * width). Can vary by line. A value of `'drop'` will modify rendered
52
+ * vertex order by dropping duplicates and setting later values to zero
53
+ * opacity. This can be faster but makes it so updating the style array
54
+ * can no longer be used.
52
55
  * @property {number|function} [antialiasing] Antialiasing distance in pixels.
53
56
  * Values must be non-negative. A value greater than 1 will produce a
54
57
  * visible gradient. This is a single value that applies to all lines.
@@ -182,7 +185,7 @@ var lineFeature = function (arg) {
182
185
  const current = lineRecord[j];
183
186
  let p = posFunc(current, j, d, index);
184
187
  if (onlyInvertedY) {
185
- p.y = -p.y;
188
+ p = {x: p.x, y: -p.y};
186
189
  } else if (gcs !== mapgcs) {
187
190
  p = transform.transformCoordinates(gcs, mapgcs, p);
188
191
  }
@@ -25,8 +25,8 @@ var Mousetrap = require('mousetrap');
25
25
  * event must occur within this time in milliseconds of the mouse down
26
26
  * event for it to be considered a click.
27
27
  * @property {boolean|number} [click.cancelOnMove=true] If true, don't generate
28
- * click events if the mouse moved at all. If a positive number, the distance
29
- * at which to cancel click events when the mouse moves.
28
+ * click events if the mouse moved at all. If a positive number, the
29
+ * distance at which to cancel click events when the mouse moves.
30
30
  * @property {object} [keyboard] An object describing which keyboard events are
31
31
  * handled.
32
32
  * @property {object} [keyboard.actions] An object with different actions that
@@ -39,6 +39,9 @@ var Mousetrap = require('mousetrap');
39
39
  * an object with keys of the meta keys that are required to be down or
40
40
  * up for that scale action to trigger. If the value of the meta key is
41
41
  * truthy, it must be down. If `false`, it must be up.
42
+ * @property {string[]} [keyboard.metakeyMouseEvents] A list of meta keys
43
+ * * that, when typed singly, trigger a repeat of the last mousemove or
44
+ * actionmove event so that listeners can update metakey information.
42
45
  * @property {boolean} [keyboard.focusHighlight=true] If truthy, when the map
43
46
  * gains focus, a highlight style is shown around it. This gives an
44
47
  * indicator that keyboard events will affect the map, but may not be
@@ -294,6 +297,10 @@ var mapInteractor = function (args) {
294
297
  1: {shift: true, ctrl: true},
295
298
  2: {shift: true, ctrl: false}
296
299
  },
300
+ /* This is a list of meta keys that when typed singly trigger a repeat
301
+ * of the last mousemove or actionmove event so that listeners can
302
+ * update metakey information. */
303
+ metakeyMouseEvents: ['shift', 'ctrl', 'shift+ctrl', 'shift+alt', 'shift+meta'],
297
304
  /* if focusHighlight is truthy, then a class is added to the map such
298
305
  * that when the map gets focus, it is indicated inside the border of
299
306
  * the map -- browsers usually show focus on the outside, which isn't
@@ -648,6 +655,35 @@ var mapInteractor = function (args) {
648
655
  }
649
656
  };
650
657
 
658
+ /**
659
+ * Repeat a mousemove or actionmove event with new metakey information.
660
+ *
661
+ * @param {event} [evt] A Mousetrap event with the key change.
662
+ * @fires geo.event.mousemove
663
+ * @fires geo.event.actionmove
664
+ */
665
+ this._repeatMouseMoveEvent = function (evt) {
666
+ if (!m_mouse || !m_mouse.modifiers) {
667
+ return;
668
+ }
669
+ const old = {
670
+ alt: m_mouse.modifiers.alt,
671
+ ctrl: m_mouse.modifiers.ctrl,
672
+ meta: m_mouse.modifiers.meta,
673
+ shift: m_mouse.modifiers.shift
674
+ };
675
+ m_this._getMouseModifiers(evt);
676
+ if (m_mouse.modifiers.alt === old.alt && m_mouse.modifiers.ctrl === old.ctrl && m_mouse.modifiers.meta === old.meta && m_mouse.modifiers.shift === old.shift) {
677
+ return;
678
+ }
679
+ if (m_state.boundDocumentHandlers) {
680
+ m_this.map().geoTrigger(geo_event.actionmove, {
681
+ state: m_this.state(), mouse: m_this.mouse(), event: evt});
682
+ } else {
683
+ m_this.map().geoTrigger(geo_event.mousemove, m_this.mouse());
684
+ }
685
+ };
686
+
651
687
  /**
652
688
  * Retrigger a mouse movement with the current mouse state.
653
689
  * @fires geo.event.mousemove
@@ -711,6 +747,13 @@ var mapInteractor = function (args) {
711
747
  bound = bound.concat(m_options.keyboard.actions[keyAction]);
712
748
  }
713
749
  }
750
+ if (m_options.keyboard.metakeyMouseEvents) {
751
+ m_options.keyboard.metakeyMouseEvents.forEach((meta) => {
752
+ m_keyHandler.bind(meta, m_this._repeatMouseMoveEvent, 'keydown');
753
+ m_keyHandler.bind(meta, m_this._repeatMouseMoveEvent, 'keyup');
754
+ bound.push(meta);
755
+ });
756
+ }
714
757
  m_boundKeys = bound;
715
758
  }
716
759
  $node.toggleClass(
@@ -2095,7 +2138,7 @@ var mapInteractor = function (args) {
2095
2138
  preventDefault: function () {},
2096
2139
  simulated: true
2097
2140
  };
2098
- m_keyHandler.trigger(keys);
2141
+ m_keyHandler.trigger(keys, options.event);
2099
2142
  return;
2100
2143
  }
2101
2144
 
package/src/registry.js CHANGED
@@ -1,4 +1,6 @@
1
1
  var $ = require('jquery');
2
+ var geo_action = require('./action');
3
+
2
4
  var widgets = {
3
5
  dom: {}
4
6
  };
@@ -398,6 +400,7 @@ util.registerAnnotation = function (name, func, features) {
398
400
  console.warn('The ' + name + ' annotation is already registered');
399
401
  }
400
402
  annotations[name] = {func: func, features: features || {}};
403
+ geo_action['annotation_' + name] = 'geo_annotation_' + name;
401
404
  return old;
402
405
  };
403
406
 
@@ -816,7 +816,9 @@ var trackFeature = function (arg) {
816
816
  {
817
817
  track: util.identityFunction,
818
818
  position: util.identityFunction,
819
- time: (d, i) => (d.t !== undefined ? d.t : i)
819
+ time: (d, i) => (d.t !== undefined ? d.t : i),
820
+ uniformLine: 'drop',
821
+ closed: false
820
822
  },
821
823
  arg.style === undefined ? {} : arg.style
822
824
  );
@@ -327,16 +327,19 @@ function generateCorrespondence(poly1, poly2, newpoly, results) {
327
327
  results[ekey] = Array(poly.length);
328
328
  poly.forEach((p, idx) => {
329
329
  const found = {};
330
+ let missed = 0;
330
331
  p.forEach((h) => h.forEach((pt) => {
331
332
  const key = '_' + pt[0] + '_' + pt[1];
332
333
  if (pts[key]) {
333
334
  pts[key].forEach((val) => {
334
335
  found[val] = (found[val] || 0) + 1;
335
336
  });
337
+ } else {
338
+ missed += 1;
336
339
  }
337
340
  }));
338
341
  Object.keys(found).forEach((nidx) => {
339
- if (found[nidx] === counts[+nidx]) {
342
+ if (found[nidx] === counts[+nidx] && !missed && p.length === newpoly[+nidx].length) {
340
343
  if (!results[ekey][idx]) {
341
344
  results[ekey][idx] = [];
342
345
  }
@@ -269,6 +269,7 @@ var webgl_lineFeature = function (arg) {
269
269
  closedVal = closed[i];
270
270
  firstPosIdx3 = posIdx3;
271
271
  maxj = lineItem.length + (closedVal === 2 ? 1 : 0);
272
+ let skipped = 0;
272
273
  for (j = 0; j < maxj; j += 1, posIdx3 += 3) {
273
274
  lidx = j;
274
275
  if (j === lineItem.length) {
@@ -329,9 +330,17 @@ var webgl_lineFeature = function (arg) {
329
330
  }
330
331
 
331
332
  if (j) {
333
+ if (uniform === 'drop' && j > 1 && position[vert[0].pos] === position[vert[1].pos] && position[vert[0].pos + 1] === position[vert[1].pos + 1]) {
334
+ skipped += 1;
335
+ continue;
336
+ }
332
337
  /* zero out the z position. This can be changed if we handle it in
333
338
  * the shader. */
334
339
  for (k = 0; k < orderLen; k += 1, dest += 1, dest3 += 3) {
340
+ if (uniform === 'drop' && vert[0].strokeOpacity <= 0 && vert[1].strokeOpacity <= 0) {
341
+ strokeOpacityBuf[dest] = -1;
342
+ continue;
343
+ }
335
344
  orderk0 = order[k][0];
336
345
  v1 = vert[orderk0];
337
346
  v2 = vert[1 - orderk0];
@@ -370,6 +379,11 @@ var webgl_lineFeature = function (arg) {
370
379
  }
371
380
  }
372
381
  }
382
+ if (skipped) {
383
+ for (k = 0; k < skipped * orderLen; k += 1, dest += 1, dest3 += 3) {
384
+ strokeOpacityBuf[dest] = -1;
385
+ }
386
+ }
373
387
  }
374
388
 
375
389
  if (!onlyStyle) {