jsxgraph 1.9.1 → 1.9.2

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.
Files changed (48) hide show
  1. package/CHANGELOG.md +49 -0
  2. package/distrib/docs.zip +0 -0
  3. package/distrib/geogebra.min.js +2 -2
  4. package/distrib/geonext.min.js +2 -2
  5. package/distrib/intergeo.min.js +2 -2
  6. package/distrib/jsxgraph.css +1 -1
  7. package/distrib/jsxgraph.zip +0 -0
  8. package/distrib/jsxgraphcore.js +3 -3
  9. package/distrib/jsxgraphcore.mjs +3 -3
  10. package/distrib/jsxgraphcore.mjs.map +1 -1
  11. package/distrib/jsxgraphsrc.js +2328 -1508
  12. package/distrib/jsxgraphsrc.mjs +2328 -1508
  13. package/distrib/jsxgraphsrc.mjs.map +1 -1
  14. package/distrib/sketch.min.js +3 -3
  15. package/package.json +4 -4
  16. package/src/3d/box3d.js +4 -1
  17. package/src/3d/circle3d.js +10 -9
  18. package/src/3d/curve3d.js +2 -0
  19. package/src/3d/linspace3d.js +18 -55
  20. package/src/3d/point3d.js +6 -0
  21. package/src/3d/polygon3d.js +1 -0
  22. package/src/3d/sphere3d.js +47 -43
  23. package/src/3d/surface3d.js +1 -0
  24. package/src/3d/view3d.js +1504 -1067
  25. package/src/base/board.js +176 -55
  26. package/src/base/circle.js +3 -1
  27. package/src/base/constants.js +1 -1
  28. package/src/base/curve.js +1 -0
  29. package/src/base/element.js +38 -30
  30. package/src/base/line.js +93 -105
  31. package/src/base/polygon.js +1 -1
  32. package/src/base/text.js +5 -1
  33. package/src/element/button.js +62 -12
  34. package/src/element/checkbox.js +6 -2
  35. package/src/element/grid.js +6 -6
  36. package/src/element/input.js +9 -6
  37. package/src/element/slider.js +42 -39
  38. package/src/jsxgraph.js +5 -3
  39. package/src/math/geometry.js +86 -64
  40. package/src/math/math.js +47 -5
  41. package/src/options.js +45 -0
  42. package/src/options3d.js +82 -5
  43. package/src/parser/jessiecode.js +2 -1
  44. package/src/parser/prefix.js +8 -1
  45. package/src/reader/sketch.js +106 -0
  46. package/src/renderer/svg.js +16 -6
  47. package/src/utils/env.js +2 -2
  48. package/src/utils/type.js +27 -15
package/src/base/board.js CHANGED
@@ -553,6 +553,13 @@ JXG.Board = function (container, renderer, id,
553
553
  */
554
554
  this.hasPointerUp = false;
555
555
 
556
+ /**
557
+ * Array containing the events related to resizing that have event listeners.
558
+ * @type Array
559
+ * @default []
560
+ */
561
+ this.resizeHandlers = [];
562
+
556
563
  /**
557
564
  * Offset for large coords elements like images
558
565
  * @type Array
@@ -749,6 +756,7 @@ JXG.extend(
749
756
 
750
757
  if (
751
758
  !Type.isPoint(object) &&
759
+ !Type.isPoint3D(object) &&
752
760
  object.elementClass !== Const.OBJECT_CLASS_LINE &&
753
761
  object.type !== Const.OBJECT_TYPE_ANGLE
754
762
  ) {
@@ -1883,9 +1891,23 @@ JXG.extend(
1883
1891
  *
1884
1892
  **********************************************************/
1885
1893
 
1894
+ /**
1895
+ * Suppresses the default event handling.
1896
+ * Used for context menu.
1897
+ *
1898
+ * @param {Event} e
1899
+ * @returns {Boolean} false
1900
+ */
1901
+ suppressDefault: function (e) {
1902
+ if (Type.exists(e)) {
1903
+ e.preventDefault();
1904
+ }
1905
+ return false;
1906
+ },
1907
+
1886
1908
  /**
1887
1909
  * Add all possible event handlers to the board object
1888
- * which move objects, i.e. mouse, pointer and touch events.
1910
+ * that move objects, i.e. mouse, pointer and touch events.
1889
1911
  */
1890
1912
  addEventHandlers: function () {
1891
1913
  if (Env.supportsPointerEvents()) {
@@ -1895,31 +1917,60 @@ JXG.extend(
1895
1917
  this.addTouchEventHandlers();
1896
1918
  }
1897
1919
 
1920
+ if (this.containerObj !== null) {
1921
+ // this.containerObj.oncontextmenu = this.suppressDefault;
1922
+ Env.addEvent(this.containerObj, 'contextmenu', this.suppressDefault, this);
1923
+ }
1924
+
1898
1925
  // This one produces errors on IE
1899
1926
  // // Env.addEvent(this.containerObj, 'contextmenu', function (e) { e.preventDefault(); return false;}, this);
1900
-
1901
1927
  // This one works on IE, Firefox and Chromium with default configurations. On some Safari
1902
1928
  // or Opera versions the user must explicitly allow the deactivation of the context menu.
1903
- if (this.containerObj !== null) {
1904
- this.containerObj.oncontextmenu = function (e) {
1905
- if (Type.exists(e)) {
1906
- e.preventDefault();
1907
- }
1908
- return false;
1909
- };
1929
+ },
1930
+
1931
+ /**
1932
+ * Remove all event handlers from the board object
1933
+ */
1934
+ removeEventHandlers: function () {
1935
+ if ((this.hasPointerHandlers || this.hasMouseHandlers || this.hasTouchHandlers) &&
1936
+ this.containerObj !== null
1937
+ ) {
1938
+ Env.removeEvent(this.containerObj, 'contextmenu', this.suppressDefault, this);
1910
1939
  }
1940
+
1941
+ this.removeMouseEventHandlers();
1942
+ this.removeTouchEventHandlers();
1943
+ this.removePointerEventHandlers();
1944
+
1945
+ this.removeFullscreenEventHandlers();
1946
+ this.removeKeyboardEventHandlers();
1947
+ this.removeResizeEventHandlers();
1948
+
1949
+ // if (Env.isBrowser) {
1950
+ // if (Type.exists(this.resizeObserver)) {
1951
+ // this.stopResizeObserver();
1952
+ // } else {
1953
+ // Env.removeEvent(window, 'resize', this.resizeListener, this);
1954
+ // this.stopIntersectionObserver();
1955
+ // }
1956
+ // Env.removeEvent(window, 'scroll', this.scrollListener, this);
1957
+ // }
1911
1958
  },
1912
1959
 
1913
1960
  /**
1914
- * Add resize event handlers
1961
+ * Add resize related event handlers
1915
1962
  *
1916
1963
  */
1917
1964
  addResizeEventHandlers: function () {
1965
+ // var that = this;
1966
+
1967
+ this.resizeHandlers = [];
1918
1968
  if (Env.isBrowser) {
1919
1969
  try {
1920
1970
  // Supported by all new browsers
1921
1971
  // resizeObserver: triggered if size of the JSXGraph div changes.
1922
1972
  this.startResizeObserver();
1973
+ this.resizeHandlers.push('resizeobserver');
1923
1974
  } catch (err) {
1924
1975
  // Certain Safari and edge version do not support
1925
1976
  // resizeObserver, but intersectionObserver.
@@ -1927,39 +1978,82 @@ JXG.extend(
1927
1978
  Env.addEvent(window, 'resize', this.resizeListener, this);
1928
1979
  // intersectionObserver: triggered if JSXGraph becomes visible.
1929
1980
  this.startIntersectionObserver();
1981
+ this.resizeHandlers.push('resize');
1930
1982
  }
1931
1983
  // Scroll event: needs to be captured since on mobile devices
1932
1984
  // sometimes a header bar is displayed / hidden, which triggers a
1933
1985
  // resize event.
1934
1986
  Env.addEvent(window, 'scroll', this.scrollListener, this);
1987
+ this.resizeHandlers.push('scroll');
1988
+
1989
+ // On browser print:
1990
+ // we need to call the listener when having @media: print.
1991
+ try {
1992
+ // window.matchMedia("print").addEventListener('change', this.printListenerMatch.apply(this, arguments));
1993
+ window.matchMedia("print").addEventListener('change', this.printListenerMatch.bind(this));
1994
+ window.matchMedia("screen").addEventListener('change', this.printListenerMatch.bind(this));
1995
+ this.resizeHandlers.push('print');
1996
+ } catch (err) {
1997
+ JXG.debug("Error adding printListener", err);
1998
+ }
1999
+ // if (Type.isFunction(MediaQueryList.prototype.addEventListener)) {
2000
+ // window.matchMedia("print").addEventListener('change', function (mql) {
2001
+ // if (mql.matches) {
2002
+ // that.printListener();
2003
+ // }
2004
+ // });
2005
+ // } else if (Type.isFunction(MediaQueryList.prototype.addListener)) { // addListener might be deprecated
2006
+ // window.matchMedia("print").addListener(function (mql, ev) {
2007
+ // if (mql.matches) {
2008
+ // that.printListener(ev);
2009
+ // }
2010
+ // });
2011
+ // }
1935
2012
 
1936
- // Env.addEvent(window, 'beforeprint', this.beforeprintListener, this);
1937
- // window.matchMedia("print").addEventListener(this.beforeprintListener, this);
2013
+ // When closing the print dialog we again have to resize.
2014
+ // Env.addEvent(window, 'afterprint', this.printListener, this);
2015
+ // this.resizeHandlers.push('afterprint');
1938
2016
  }
1939
2017
  },
1940
2018
 
1941
2019
  /**
1942
- * Remove all event handlers from the board object
2020
+ * Remove resize related event handlers
2021
+ *
1943
2022
  */
1944
- removeEventHandlers: function () {
1945
- this.removeMouseEventHandlers();
1946
- this.removeTouchEventHandlers();
1947
- this.removePointerEventHandlers();
1948
-
1949
- this.removeFullscreenEventHandlers();
1950
- this.removeKeyboardEventHandlers();
1951
-
1952
- if (Env.isBrowser) {
1953
- if (Type.exists(this.resizeObserver)) {
1954
- this.stopResizeObserver();
1955
- } else {
1956
- Env.removeEvent(window, 'resize', this.resizeListener, this);
1957
- this.stopIntersectionObserver();
2023
+ removeResizeEventHandlers: function () {
2024
+ var i, e;
2025
+ if (this.resizeHandlers.length > 0 && Env.isBrowser) {
2026
+ for (i = 0; i < this.resizeHandlers.length; i++) {
2027
+ e = this.resizeHandlers[i];
2028
+ switch (e) {
2029
+ case 'resizeobserver':
2030
+ if (Type.exists(this.resizeObserver)) {
2031
+ this.stopResizeObserver();
2032
+ }
2033
+ break;
2034
+ case 'resize':
2035
+ Env.removeEvent(window, 'resize', this.resizeListener, this);
2036
+ if (Type.exists(this.intersectionObserver)) {
2037
+ this.stopIntersectionObserver();
2038
+ }
2039
+ break;
2040
+ case 'scroll':
2041
+ Env.removeEvent(window, 'scroll', this.scrollListener, this);
2042
+ break;
2043
+ case 'print':
2044
+ window.matchMedia("print").removeEventListener('change', this.printListenerMatch.bind(this), false);
2045
+ window.matchMedia("screen").removeEventListener('change', this.printListenerMatch.bind(this), false);
2046
+ break;
2047
+ // case 'afterprint':
2048
+ // Env.removeEvent(window, 'afterprint', this.printListener, this);
2049
+ // break;
2050
+ }
1958
2051
  }
1959
- Env.removeEvent(window, 'scroll', this.scrollListener, this);
2052
+ this.resizeHandlers = [];
1960
2053
  }
1961
2054
  },
1962
2055
 
2056
+
1963
2057
  /**
1964
2058
  * Registers pointer event handlers.
1965
2059
  */
@@ -4155,10 +4249,13 @@ JXG.extend(
4155
4249
 
4156
4250
  /**
4157
4251
  * Update the width and height of the JSXGraph container div element.
4158
- * Read actual values with getBoundingClientRect(),
4252
+ * If width and height are not supplied, read actual values with offsetWidth/Height,
4159
4253
  * and call board.resizeContainer() with this values.
4160
4254
  * <p>
4161
4255
  * If necessary, also call setBoundingBox().
4256
+ * @param {Number} [width=this.containerObj.offsetWidth] Width of the container element
4257
+ * @param {Number} [height=this.containerObj.offsetHeight] Height of the container element
4258
+ * @returns
4162
4259
  *
4163
4260
  * @see JXG.Board#startResizeObserver
4164
4261
  * @see JXG.Board#resizeListener
@@ -4166,18 +4263,28 @@ JXG.extend(
4166
4263
  * @see JXG.Board#setBoundingBox
4167
4264
  *
4168
4265
  */
4169
- updateContainerDims: function () {
4170
- var w, h,
4171
- bb, css,
4266
+ updateContainerDims: function (width, height) {
4267
+ var w = width,
4268
+ h = height,
4269
+ // bb,
4270
+ css,
4172
4271
  width_adjustment, height_adjustment;
4173
4272
 
4174
- // Get size of the board's container div
4175
- bb = this.containerObj.getBoundingClientRect();
4176
- w = bb.width;
4177
- h = bb.height;
4273
+ if (width === undefined) {
4274
+ // Get size of the board's container div
4275
+ //
4276
+ // offsetWidth/Height ignores CSS transforms,
4277
+ // getBoundingClientRect includes CSS transforms
4278
+ //
4279
+ // bb = this.containerObj.getBoundingClientRect();
4280
+ // w = bb.width;
4281
+ // h = bb.height;
4282
+ w = this.containerObj.offsetWidth;
4283
+ h = this.containerObj.offsetHeight;
4284
+ }
4178
4285
 
4179
- // Subtract the border size
4180
- if (window && window.getComputedStyle) {
4286
+ if (width === undefined && window && window.getComputedStyle) {
4287
+ // Subtract the border size
4181
4288
  css = window.getComputedStyle(this.containerObj, null);
4182
4289
  width_adjustment = parseFloat(css.getPropertyValue('border-left-width')) + parseFloat(css.getPropertyValue('border-right-width'));
4183
4290
  if (!isNaN(width_adjustment)) {
@@ -4205,7 +4312,6 @@ JXG.extend(
4205
4312
  if (Type.exists(this._prevDim) && this._prevDim.w === w && this._prevDim.h === h) {
4206
4313
  return;
4207
4314
  }
4208
-
4209
4315
  // Set the size of the SVG or canvas element
4210
4316
  this.resizeContainer(w, h, true);
4211
4317
  this._prevDim = {
@@ -4237,11 +4343,13 @@ JXG.extend(
4237
4343
  }
4238
4344
 
4239
4345
  this.resizeObserver = new ResizeObserver(function (entries) {
4346
+ var bb;
4240
4347
  if (!that._isResizing) {
4241
4348
  that._isResizing = true;
4349
+ bb = entries[0].contentRect;
4242
4350
  window.setTimeout(function () {
4243
4351
  try {
4244
- that.updateContainerDims();
4352
+ that.updateContainerDims(bb.width, bb.height);
4245
4353
  } catch (err) {
4246
4354
  that.stopResizeObserver();
4247
4355
  } finally {
@@ -4356,10 +4464,22 @@ JXG.extend(
4356
4464
  }
4357
4465
  },
4358
4466
 
4359
- beforeprintListener: function(evt) {
4360
- // console.log("beforeprint")
4467
+ /**
4468
+ * Update the container before and after printing.
4469
+ * @param {Event} [evt]
4470
+ */
4471
+ printListener: function(evt) {
4361
4472
  this.updateContainerDims();
4362
- // this.resizeListener();
4473
+ },
4474
+
4475
+ /**
4476
+ * Wrapper for printListener to be used in mediaQuery matches.
4477
+ * @param {MediaQueryList} mql
4478
+ */
4479
+ printListenerMatch: function (mql) {
4480
+ if (mql.matches) {
4481
+ this.printListener();
4482
+ }
4363
4483
  },
4364
4484
 
4365
4485
  /**********************************************************
@@ -5180,14 +5300,11 @@ JXG.extend(
5180
5300
  * @returns {JXG.Board} Reference to the board.
5181
5301
  */
5182
5302
  zoomElements: function (elements) {
5183
- var i,
5184
- e,
5303
+ var i, e,
5185
5304
  box,
5186
5305
  newBBox = [Infinity, -Infinity, -Infinity, Infinity],
5187
- cx,
5188
- cy,
5189
- dx,
5190
- dy,
5306
+ cx, cy,
5307
+ dx, dy,
5191
5308
  d;
5192
5309
 
5193
5310
  if (!Type.isArray(elements) || elements.length === 0) {
@@ -5487,8 +5604,10 @@ JXG.extend(
5487
5604
  box = this.getBoundingBox(); // This is the actual bounding box.
5488
5605
  }
5489
5606
 
5490
- this.canvasWidth = Math.max(parseFloat(canvasWidth), Mat.eps);
5491
- this.canvasHeight = Math.max(parseFloat(canvasHeight), Mat.eps);
5607
+ // this.canvasWidth = Math.max(parseFloat(canvasWidth), Mat.eps);
5608
+ // this.canvasHeight = Math.max(parseFloat(canvasHeight), Mat.eps);
5609
+ this.canvasWidth = parseFloat(canvasWidth);
5610
+ this.canvasHeight = parseFloat(canvasHeight);
5492
5611
 
5493
5612
  if (!dontset) {
5494
5613
  this.containerObj.style.width = this.canvasWidth + 'px';
@@ -5499,8 +5618,8 @@ JXG.extend(
5499
5618
  if (!dontSetBoundingBox) {
5500
5619
  this.setBoundingBox(box, this.keepaspectratio, 'keep');
5501
5620
  } else {
5502
- oX = (this.canvasWidth - oldWidth) / 2;
5503
- oY = (this.canvasHeight - oldHeight) / 2;
5621
+ oX = (this.canvasWidth - oldWidth) * 0.5;
5622
+ oY = (this.canvasHeight - oldHeight) * 0.5;
5504
5623
 
5505
5624
  this.moveOrigin(
5506
5625
  this.origin.scrCoords[1] + oX,
@@ -6055,7 +6174,10 @@ JXG.extend(
6055
6174
  h = this.canvasHeight;
6056
6175
  if (keepaspectratio) {
6057
6176
  if (this.keepaspectratio) {
6058
- ratio = ux / uy; // Keep this ratio if keepaspectratio was true
6177
+ ratio = ux / uy; // Keep this ratio if keepaspectratio was true
6178
+ if (isNaN(ratio)) {
6179
+ ratio = 1.0;
6180
+ }
6059
6181
  } else {
6060
6182
  ratio = 1.0;
6061
6183
  }
@@ -6120,7 +6242,6 @@ JXG.extend(
6120
6242
  [this.canvasWidth, this.canvasHeight],
6121
6243
  this
6122
6244
  ).usrCoords;
6123
-
6124
6245
  return [ul[1], ul[2], lr[1], lr[2]];
6125
6246
  },
6126
6247
 
@@ -551,7 +551,9 @@ JXG.extend(
551
551
  }
552
552
 
553
553
  if (this.method === "pointRadius") {
554
- return Math.abs(this.updateRadius());
554
+ return (Type.evaluate(this.visProp.nonnegativeonly)) ?
555
+ Math.max(0.0, this.updateRadius()) :
556
+ Math.abs(this.updateRadius());
555
557
  }
556
558
 
557
559
  return NaN;
@@ -37,7 +37,7 @@ import JXG from "../jxg.js";
37
37
 
38
38
  var major = 1,
39
39
  minor = 9,
40
- patch = 1,
40
+ patch = 2,
41
41
  add = '', // 'dev' 'beta'
42
42
  version = major + '.' + minor + '.' + patch + (add ? '-' + add : ''),
43
43
  constants;
package/src/base/curve.js CHANGED
@@ -1353,6 +1353,7 @@ JXG.extend(
1353
1353
  delta = [where[0] - p.usrCoords[1], where[1] - p.usrCoords[2]];
1354
1354
  }
1355
1355
  this.setPosition(Const.COORDS_BY_USER, delta);
1356
+ return this.board.update(this);
1356
1357
  }
1357
1358
  return this;
1358
1359
  },
@@ -329,6 +329,8 @@ JXG.GeometryElement = function (board, attributes, type, oclass) {
329
329
  */
330
330
  this.lastDragTime = new Date();
331
331
 
332
+ this.view = null;
333
+
332
334
  if (arguments.length > 0) {
333
335
  /**
334
336
  * Reference to the board associated with the element.
@@ -1011,44 +1013,50 @@ JXG.extend(
1011
1013
  var i, len, s, len_s, obj, val;
1012
1014
 
1013
1015
  if (this.needsUpdate) {
1014
- // Handle the element
1015
- if (parent_val !== undefined) {
1016
- this.visPropCalc.visible = parent_val;
1016
+ if (Type.exists(this.view) && Type.evaluate(this.view.visProp.visible) === false) {
1017
+ // Handle hiding of view3d
1018
+ this.visPropCalc.visible = false;
1019
+
1017
1020
  } else {
1018
- val = Type.evaluate(this.visProp.visible);
1021
+ // Handle the element
1022
+ if (parent_val !== undefined) {
1023
+ this.visPropCalc.visible = parent_val;
1024
+ } else {
1025
+ val = Type.evaluate(this.visProp.visible);
1019
1026
 
1020
- // infobox uses hiddenByParent
1021
- if (Type.exists(this.hiddenByParent) && this.hiddenByParent) {
1022
- val = false;
1023
- }
1024
- if (val !== "inherit") {
1025
- this.visPropCalc.visible = val;
1027
+ // infobox uses hiddenByParent
1028
+ if (Type.exists(this.hiddenByParent) && this.hiddenByParent) {
1029
+ val = false;
1030
+ }
1031
+ if (val !== "inherit") {
1032
+ this.visPropCalc.visible = val;
1033
+ }
1026
1034
  }
1027
- }
1028
1035
 
1029
- // Handle elements which inherit the visibility
1030
- len = this.inherits.length;
1031
- for (s = 0; s < len; s++) {
1032
- obj = this.inherits[s];
1033
- if (Type.isArray(obj)) {
1034
- len_s = obj.length;
1035
- for (i = 0; i < len_s; i++) {
1036
+ // Handle elements which inherit the visibility
1037
+ len = this.inherits.length;
1038
+ for (s = 0; s < len; s++) {
1039
+ obj = this.inherits[s];
1040
+ if (Type.isArray(obj)) {
1041
+ len_s = obj.length;
1042
+ for (i = 0; i < len_s; i++) {
1043
+ if (
1044
+ Type.exists(obj[i]) /*&& Type.exists(obj[i].rendNode)*/ &&
1045
+ Type.evaluate(obj[i].visProp.visible) === "inherit"
1046
+ ) {
1047
+ obj[i]
1048
+ .prepareUpdate()
1049
+ .updateVisibility(this.visPropCalc.visible);
1050
+ }
1051
+ }
1052
+ } else {
1036
1053
  if (
1037
- Type.exists(obj[i]) /*&& Type.exists(obj[i].rendNode)*/ &&
1038
- Type.evaluate(obj[i].visProp.visible) === "inherit"
1054
+ Type.exists(obj) /*&& Type.exists(obj.rendNode)*/ &&
1055
+ Type.evaluate(obj.visProp.visible) === "inherit"
1039
1056
  ) {
1040
- obj[i]
1041
- .prepareUpdate()
1042
- .updateVisibility(this.visPropCalc.visible);
1057
+ obj.prepareUpdate().updateVisibility(this.visPropCalc.visible);
1043
1058
  }
1044
1059
  }
1045
- } else {
1046
- if (
1047
- Type.exists(obj) /*&& Type.exists(obj.rendNode)*/ &&
1048
- Type.evaluate(obj.visProp.visible) === "inherit"
1049
- ) {
1050
- obj.prepareUpdate().updateVisibility(this.visPropCalc.visible);
1051
- }
1052
1060
  }
1053
1061
  }
1054
1062