jsxgraph 1.4.3 → 1.4.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.
@@ -1,5 +1,5 @@
1
1
  /*
2
- JSXGraph 1.4.3
2
+ JSXGraph 1.4.4
3
3
 
4
4
  Copyright 2008-2022
5
5
  Matthias Ehmann,
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "jsxgraph",
3
3
  "description": "Interactive geometry, plotting, visualization",
4
4
  "homepage": "https://jsxgraph.org",
5
- "version": "1.4.3",
5
+ "version": "1.4.4",
6
6
  "main": "distrib/jsxgraphcore.js",
7
7
  "types": "distrib/index.d.ts",
8
8
  "maintainers": [
package/src/3d/box3d.js CHANGED
@@ -48,7 +48,8 @@ define(['jxg', 'utils/type', 'math/math', 'math/geometry', '3d/view3d'
48
48
  rear = [0, 0, 0], // x, y, z
49
49
  front = [0, 0, 0], // x, y, z
50
50
  from, to,
51
- vec1, vec2, range1, range2, na,
51
+ vec1, vec2, range1, range2,
52
+ na, na_parent,
52
53
  ticks_attr,
53
54
  axes = {};
54
55
 
@@ -64,9 +65,8 @@ define(['jxg', 'utils/type', 'math/math', 'math/geometry', '3d/view3d'
64
65
  }
65
66
  }
66
67
 
67
- // Axes
68
+ // Main 3D axes
68
69
  attr = Type.copyAttributes(attributes, board.options, 'axes3d');
69
-
70
70
  pos = attr.axesposition;
71
71
  for (i = 0; i < directions.length; i++) {
72
72
  // Run through ['x', 'y', 'z']
@@ -115,7 +115,7 @@ define(['jxg', 'utils/type', 'math/math', 'math/geometry', '3d/view3d'
115
115
  name: '', visible: false, withLabel: false
116
116
  });
117
117
 
118
- // Planes
118
+ // Front and rear planes
119
119
  for (i = 0; i < directions.length; i++) {
120
120
  // Run through ['x', 'y', 'z']
121
121
  i1 = (i + 1) % 3;
@@ -135,13 +135,14 @@ define(['jxg', 'utils/type', 'math/math', 'math/geometry', '3d/view3d'
135
135
  range2 = [rear[i2], front[i2]];
136
136
  na = dir + 'Plane' + sides[j];
137
137
 
138
+ attr = Type.copyAttributes(attributes, board.options, 'axes3d', na);
138
139
  axes[na] =
139
- view.create('plane3d', [from, vec1, vec2, range1, range2], attr[na.toLowerCase()]);
140
+ view.create('plane3d', [from, vec1, vec2, range1, range2], attr);
140
141
  axes[na].D3.elType = 'axisplane3d';
141
142
  }
142
143
  }
143
144
 
144
- // Axes on planes
145
+ // Axes on front and rear planes
145
146
  for (i = 0; i < directions.length; i++) {
146
147
  // Run through ['x', 'y', 'z']
147
148
  dir = directions[i];
@@ -150,6 +151,7 @@ define(['jxg', 'utils/type', 'math/math', 'math/geometry', '3d/view3d'
150
151
  i1 = (i + k) % 3;
151
152
  dir1 = directions[i1];
152
153
  na = dir + 'Plane' + sides[j] + dir1.toUpperCase() + 'Axis';
154
+ na_parent = dir + 'Plane' + sides[j];
153
155
 
154
156
  from = [0, 0, 0];
155
157
  to = [0, 0, 0];
@@ -158,11 +160,13 @@ define(['jxg', 'utils/type', 'math/math', 'math/geometry', '3d/view3d'
158
160
  from[i1] = rear[i1];
159
161
  to[i1] = front[i1];
160
162
 
161
- axes[na] = view.create('axis3d', [from, to], attr[na.toLowerCase()]);
163
+ attr = Type.copyAttributes(attributes, board.options, 'axes3d', na);
164
+ axes[na] = view.create('axis3d', [from, to], attr);
165
+ axes[na_parent].addChild(axes[na]);
166
+ axes[na_parent].inherits.push(axes[na]);
162
167
  }
163
168
  }
164
169
  }
165
- // axes.Y2Dxy = view.create('axis3d', [[0, sy, sz], [0, ey, sz]], attr);
166
170
 
167
171
  return axes;
168
172
  };
@@ -31,6 +31,68 @@
31
31
  define(['jxg', 'utils/type', '3d/view3d'
32
32
  ], function (JXG, Type, ThreeD) {
33
33
  "use strict";
34
+
35
+
36
+ /**
37
+ * @class This element creates a 3D parametric surface.
38
+ * @pseudo
39
+ * @description A 3D parametric surface is defined by a function
40
+ * <i>F: R<sup>2</sup> &rarr; R<sup>3</sup></i>.
41
+ *
42
+ * @name ParametricSurface3D
43
+ * @augments Curve
44
+ * @constructor
45
+ * @type Object
46
+ * @throws {Exception} If the element cannot be constructed with the given parent objects an exception is thrown.
47
+ * @param {Function_Function_Function_Array_Array} F<sub>X</sub>,F<sub>Y</sub>,F<sub>Z</sub>,rangeX,rangeY
48
+ * F<sub>X</sub>(u,v), F<sub>Y</sub>(u,v), F<sub>Z</sub>(u,v) are functions returning a number, rangeU is the array containing
49
+ * lower and upper bound for the range of parameter u, rangeV is the array containing
50
+ * lower and upper bound for the range of parameter v. rangeU and rangeV may also be functions returning an array of length two.
51
+ * @example
52
+ * var view = board.create('view3d',
53
+ * [[-6, -3], [8, 8],
54
+ * [[-5, 5], [-5, 5], [-5, 5]]]);
55
+ *
56
+ * // Sphere
57
+ * var c = view.create('parametricsurface3d', [
58
+ * (u, v) => 2 * Math.sin(u) * Math.cos(v),
59
+ * (u, v) => 2 * Math.sin(u) * Math.sin(v),
60
+ * (u, v) => 2 * Math.cos(u),
61
+ * [0, 2 * Math.PI],
62
+ * [0, Math.PI]
63
+ * ], {
64
+ * strokeColor: '#ff0000',
65
+ * stepsU: 30,
66
+ * stepsV: 30
67
+ * });
68
+ *
69
+ * </pre><div id="JXG52da0ecc-1ba9-4d41-850c-36e5120025a5" class="jxgbox" style="width: 500px; height: 500px;"></div>
70
+ * <script type="text/javascript">
71
+ * (function() {
72
+ * var board = JXG.JSXGraph.initBoard('JXG52da0ecc-1ba9-4d41-850c-36e5120025a5',
73
+ * {boundingbox: [-8, 8, 8,-8], axis: false, showcopyright: false, shownavigation: false});
74
+ * var view = board.create('view3d',
75
+ * [[-6, -3], [8, 8],
76
+ * [[-5, 5], [-5, 5], [-5, 5]]]);
77
+ *
78
+ * // Sphere
79
+ * var c = view.create('parametricsurface3d', [
80
+ * (u, v) => 2 * Math.sin(u) * Math.cos(v),
81
+ * (u, v) => 2 * Math.sin(u) * Math.sin(v),
82
+ * (u, v) => 2 * Math.cos(u),
83
+ * [0, 2 * Math.PI],
84
+ * [0, Math.PI]
85
+ * ], {
86
+ * strokeColor: '#ff0000',
87
+ * stepsU: 20,
88
+ * stepsV: 20
89
+ * });
90
+ *
91
+ * })();
92
+ *
93
+ * </script><pre>
94
+ *
95
+ */
34
96
  ThreeD.createParametricSurface = function (board, parents, attributes) {
35
97
  var view = parents[0],
36
98
  attr,
@@ -54,9 +116,11 @@ define(['jxg', 'utils/type', '3d/view3d'
54
116
  el.updateDataArray = function () {
55
117
  var steps_u = Type.evaluate(this.visProp.stepsu),
56
118
  steps_v = Type.evaluate(this.visProp.stepsv),
119
+ r_u = Type.evaluate(this.D3.range_u), // Type.evaluate(range_u),
120
+ r_v = Type.evaluate(this.D3.range_v), // Type.evaluate(range_v),
57
121
  res = view.getMesh(this.D3.X, this.D3.Y, this.D3.Z,
58
- this.D3.range_u.concat([steps_u]),
59
- this.D3.range_v.concat([steps_v]));
122
+ r_u.concat([steps_u]),
123
+ r_v.concat([steps_v]));
60
124
  this.dataX = res[0];
61
125
  this.dataY = res[1];
62
126
  };
@@ -66,6 +130,81 @@ define(['jxg', 'utils/type', '3d/view3d'
66
130
  };
67
131
  JXG.registerElement('parametricsurface3d', ThreeD.createParametricSurface);
68
132
 
133
+ /**
134
+ * @class This element creates a 3D function graph.
135
+ * @pseudo
136
+ * @description A 3D function graph is defined by a function
137
+ * <i>F: R<sup>2</sup> &rarr; R</i>.
138
+ *
139
+ * @name Functiongraph3D
140
+ * @augments ParametricSurface3D
141
+ * @constructor
142
+ * @type Object
143
+ * @throws {Exception} If the element cannot be constructed with the given parent objects an exception is thrown.
144
+ * @param {Function_Array_Array} F,rangeX,rangeY F(x,y) is a function returning a number, rangeX is the array containing
145
+ * lower and upper bound for the range of x, rangeY is the array containing
146
+ * lower and upper bound for the range of y.
147
+ * @example
148
+ * var box = [-5, 5];
149
+ * var view = board.create('view3d',
150
+ * [
151
+ * [-6, -3], [8, 8],
152
+ * [box, box, box]
153
+ * ],
154
+ * {
155
+ * xPlaneRear: {visible: false},
156
+ * yPlaneRear: {visible: false},
157
+ * });
158
+ *
159
+ * // Function F to be plotted
160
+ * var F = (x, y) => Math.sin(x * y / 4);
161
+ *
162
+ * // 3D surface
163
+ * var c = view.create('functiongraph3d', [
164
+ * F,
165
+ * box, // () => [-s.Value()*5, s.Value() * 5],
166
+ * box, // () => [-s.Value()*5, s.Value() * 5],
167
+ * ], {
168
+ * strokeWidth: 0.5,
169
+ * stepsU: 70,
170
+ * stepsV: 70
171
+ * });
172
+ *
173
+ * </pre><div id="JXG87646dd4-9fe5-4c21-8734-089abc612515" class="jxgbox" style="width: 500px; height: 500px;"></div>
174
+ * <script type="text/javascript">
175
+ * (function() {
176
+ * var board = JXG.JSXGraph.initBoard('JXG87646dd4-9fe5-4c21-8734-089abc612515',
177
+ * {boundingbox: [-8, 8, 8,-8], axis: false, showcopyright: false, shownavigation: false});
178
+ * var box = [-5, 5];
179
+ * var view = board.create('view3d',
180
+ * [
181
+ * [-6, -3], [8, 8],
182
+ * [box, box, box]
183
+ * ],
184
+ * {
185
+ * xPlaneRear: {visible: false},
186
+ * yPlaneRear: {visible: false},
187
+ * });
188
+ *
189
+ * // Function F to be plotted
190
+ * var F = (x, y) => Math.sin(x * y / 4);
191
+ *
192
+ * // 3D surface
193
+ * var c = view.create('functiongraph3d', [
194
+ * F,
195
+ * box, // () => [-s.Value()*5, s.Value() * 5],
196
+ * box, // () => [-s.Value()*5, s.Value() * 5],
197
+ * ], {
198
+ * strokeWidth: 0.5,
199
+ * stepsU: 70,
200
+ * stepsV: 70
201
+ * });
202
+ *
203
+ * })();
204
+ *
205
+ * </script><pre>
206
+ *
207
+ */
69
208
  ThreeD.createFunctiongraph = function (board, parents, attributes) {
70
209
  var view = parents[0],
71
210
  X = function(u, v) { return u; },
@@ -78,4 +217,4 @@ define(['jxg', 'utils/type', '3d/view3d'
78
217
  };
79
218
  JXG.registerElement('functiongraph3d', ThreeD.createFunctiongraph);
80
219
 
81
- });
220
+ });
package/src/3d/view3d.js CHANGED
@@ -363,11 +363,81 @@ define(['jxg', 'options', 'base/constants', 'utils/type', 'math/math', 'base/ele
363
363
  });
364
364
 
365
365
  /**
366
+ * @class This element creates a 3D view.
367
+ * @pseudo
368
+ * @description A View3D element provides the container and the methods to create and display 3D elements.
369
+ * It is contained in a JSXGraph board.
370
+ * @name View3D
371
+ * @augments JXG.View3D
372
+ * @constructor
373
+ * @type Object
374
+ * @throws {Exception} If the element cannot be constructed with the given parent objects an exception is thrown.
375
+ * @param {Array_Array_Array} lower,dim,cube Here, lower is an array of the form [x, y] and
376
+ * dim is an array of the form [w, h].
377
+ * The arrays [x, y] and [w, h] define the 2D frame into which the 3D cube is
378
+ * (roughly) projected.
379
+ * cube is an array of the form [[x1, x2], [y1, y2], [z1, z2]]
380
+ * which determines the coordinate ranges of the 3D cube.
381
+ *
382
+ * @example
383
+ * var bound = [-5, 5];
384
+ * var view = board.create('view3d',
385
+ * [[-6, -3],
386
+ * [8, 8],
387
+ * [bound, bound, bound]],
388
+ * {
389
+ * // Main axes
390
+ * axesPosition: 'center',
391
+ * xAxis: { strokeColor: 'blue', strokeWidth: 3},
392
+ *
393
+ * // Planes
394
+ * xPlaneRear: { fillColor: 'yellow', mesh3d: {visible: false}},
395
+ * yPlaneFront: { visible: true, fillColor: 'blue'},
396
+ *
397
+ * // Axes on planes
398
+ * xPlaneRearYAxis: {strokeColor: 'red'},
399
+ * xPlaneRearZAxis: {strokeColor: 'red'},
400
+ *
401
+ * yPlaneFrontXAxis: {strokeColor: 'blue'},
402
+ * yPlaneFrontZAxis: {strokeColor: 'blue'},
403
+ *
404
+ * zPlaneFrontXAxis: {visible: false},
405
+ * zPlaneFrontYAxis: {visible: false}
406
+ * });
407
+ *
408
+ * </pre><div id="JXGdd06d90e-be5d-4531-8f0b-65fc30b1a7c7" class="jxgbox" style="width: 500px; height: 500px;"></div>
409
+ * <script type="text/javascript">
410
+ * (function() {
411
+ * var board = JXG.JSXGraph.initBoard('JXGdd06d90e-be5d-4531-8f0b-65fc30b1a7c7',
412
+ * {boundingbox: [-8, 8, 8,-8], axis: false, showcopyright: false, shownavigation: false});
413
+ * var bound = [-5, 5];
414
+ * var view = board.create('view3d',
415
+ * [[-6, -3], [8, 8],
416
+ * [bound, bound, bound]],
417
+ * {
418
+ * // Main axes
419
+ * axesPosition: 'center',
420
+ * xAxis: { strokeColor: 'blue', strokeWidth: 3},
421
+ *
422
+ * // Planes
423
+ * xPlaneRear: { fillColor: 'yellow', mesh3d: {visible: false}},
424
+ * yPlaneFront: { visible: true, fillColor: 'blue'},
425
+ *
426
+ * // Axes on planes
427
+ * xPlaneRearYAxis: {strokeColor: 'red'},
428
+ * xPlaneRearZAxis: {strokeColor: 'red'},
429
+ *
430
+ * yPlaneFrontXAxis: {strokeColor: 'blue'},
431
+ * yPlaneFrontZAxis: {strokeColor: 'blue'},
432
+ *
433
+ * zPlaneFrontXAxis: {visible: false},
434
+ * zPlaneFrontYAxis: {visible: false}
435
+ * });
436
+ *
437
+ * })();
438
+ *
439
+ * </script><pre>
366
440
  *
367
- * @param {*} board
368
- * @param {*} parents
369
- * @param {*} attributes
370
- * @returns
371
441
  */
372
442
  ThreeD.createView3D = function (board, parents, attributes) {
373
443
  var view, frame, attr,
package/src/base/board.js CHANGED
@@ -816,8 +816,12 @@ define([
816
816
  */
817
817
  getCoordsTopLeftCorner: function () {
818
818
  var cPos, doc, crect,
819
- docElement = this.document.documentElement || this.document.body.parentNode,
820
- docBody = this.document.body,
819
+ // In ownerDoc we need the "real" document object.
820
+ // The first version is used in the case of shadowDom,
821
+ // the second case in the "normal" case.
822
+ ownerDoc = this.document.ownerDocument || this.document,
823
+ docElement = ownerDoc.documentElement || this.document.body.parentNode,
824
+ docBody = ownerDoc.body,
821
825
  container = this.containerObj,
822
826
  // viewport, content,
823
827
  zoom, o;
@@ -3340,7 +3344,7 @@ define([
3340
3344
  }
3341
3345
 
3342
3346
  // If div is invisible - do nothing
3343
- if (w <= 0 || h <= 0) {
3347
+ if (w <= 0 || h <= 0 || Type.isNaN(w) || Type.isNaN(h)) {
3344
3348
  return;
3345
3349
  }
3346
3350
 
@@ -4746,12 +4750,12 @@ define([
4746
4750
  this.inUpdate = true;
4747
4751
 
4748
4752
  if (this.attr.minimizereflow === 'all' && this.containerObj && this.renderer.type !== 'vml') {
4749
- storeActiveEl = document.activeElement; // Store focus element
4753
+ storeActiveEl = this.document.activeElement; // Store focus element
4750
4754
  insert = this.renderer.removeToInsertLater(this.containerObj);
4751
4755
  }
4752
4756
 
4753
4757
  if (this.attr.minimizereflow === 'svg' && this.renderer.type === 'svg') {
4754
- storeActiveEl = document.activeElement;
4758
+ storeActiveEl = this.document.activeElement;
4755
4759
  insert = this.renderer.removeToInsertLater(this.renderer.svgRoot);
4756
4760
  }
4757
4761
 
@@ -5374,7 +5378,7 @@ define([
5374
5378
  o2 = o2.parentNode;
5375
5379
  while (o2 !== o) {
5376
5380
  this.cssTransMat = Mat.matMatMult(Env.getCSSTransformMatrix(o), this.cssTransMat);
5377
- o2 = o2.parentNode;
5381
+ o2 = o2.parentNode || o2.host;
5378
5382
  }
5379
5383
 
5380
5384
  o = o.offsetParent;
@@ -5944,7 +5948,7 @@ define([
5944
5948
 
5945
5949
  id = id || this.container;
5946
5950
  this._fullscreen_inner_id = id;
5947
- inner_node = document.getElementById(id);
5951
+ inner_node = this.document.getElementById(id);
5948
5952
  wrap_id = 'fullscreenwrap_' + id;
5949
5953
 
5950
5954
  // Wrap a div around the JSXGraph div.
@@ -5990,16 +5994,16 @@ define([
5990
5994
  return;
5991
5995
  }
5992
5996
 
5993
- document.fullscreenElement = document.fullscreenElement ||
5994
- document.webkitFullscreenElement ||
5995
- document.mozFullscreenElement ||
5996
- document.msFullscreenElement;
5997
+ this.document.fullscreenElement = this.document.fullscreenElement ||
5998
+ this.document.webkitFullscreenElement ||
5999
+ this.document.mozFullscreenElement ||
6000
+ this.document.msFullscreenElement;
5997
6001
 
5998
- inner_node = document.getElementById(inner_id);
6002
+ inner_node = this.document.getElementById(inner_id);
5999
6003
  // If full screen mode is started we have to remove CSS margin around the JSXGraph div.
6000
6004
  // Otherwise, the positioning of the fullscreen div will be false.
6001
6005
  // When leaving the fullscreen mode, the margin is put back in.
6002
- if (document.fullscreenElement) {
6006
+ if (this.document.fullscreenElement) {
6003
6007
  // Just entered fullscreen mode
6004
6008
 
6005
6009
  // Get the data computed in board.toFullscreen()
@@ -6011,7 +6015,7 @@ define([
6011
6015
  // Further, the CSS margin has to be removed when in fullscreen mode,
6012
6016
  // and must be restored later.
6013
6017
  inner_node._cssFullscreenStore = {
6014
- id: document.fullscreenElement.id,
6018
+ id: this.document.fullscreenElement.id,
6015
6019
  isFullscreen: true,
6016
6020
  margin: inner_node.style.margin,
6017
6021
  width: inner_node.style.width,
@@ -6027,16 +6031,16 @@ define([
6027
6031
  // of the JSXGraph div.
6028
6032
  Env.scaleJSXGraphDiv(document.fullscreenElement.id, inner_id, res.scale, res.vshift);
6029
6033
 
6030
- // Clear document.fullscreenElement, because Safari doesn't to it and
6034
+ // Clear this.document.fullscreenElement, because Safari doesn't to it and
6031
6035
  // when leaving full screen mode it is still set.
6032
- document.fullscreenElement = null;
6036
+ this.document.fullscreenElement = null;
6033
6037
 
6034
6038
  } else if (Type.exists(inner_node._cssFullscreenStore)) {
6035
6039
  // Just left the fullscreen mode
6036
6040
 
6037
6041
  // Remove the CSS rules added in Env.scaleJSXGraphDiv
6038
6042
  try {
6039
- document.styleSheets[document.styleSheets.length - 1].deleteRule(0);
6043
+ this.document.styleSheets[this.document.styleSheets.length - 1].deleteRule(0);
6040
6044
  } catch (err) {
6041
6045
  console.log('JSXGraph: Could not remove CSS rules for full screen mode');
6042
6046
  }
@@ -6044,7 +6048,6 @@ define([
6044
6048
  inner_node._cssFullscreenStore.isFullscreen = false;
6045
6049
  inner_node.style.margin = inner_node._cssFullscreenStore.margin;
6046
6050
  inner_node.style.width = inner_node._cssFullscreenStore.width;
6047
-
6048
6051
  }
6049
6052
 
6050
6053
  this.updateCSSTransforms();
@@ -42,7 +42,7 @@ define(['jxg'], function (JXG) {
42
42
 
43
43
  var major = 1,
44
44
  minor = 4,
45
- patch = 3,
45
+ patch = 4,
46
46
  add = '', //'dev'
47
47
  version = major + '.' + minor + '.' + patch + (add ? '-' + add : ''),
48
48
  constants;
@@ -592,9 +592,6 @@ define([
592
592
  b.addChild(t);
593
593
  }
594
594
 
595
-
596
-
597
-
598
595
  t.elType = 'midpoint';
599
596
  t.setParents([a.id, b.id]);
600
597
 
@@ -804,14 +801,21 @@ define([
804
801
  };
805
802
 
806
803
  /**
807
- * @class A parallel is a line through a given point with the same slope as a given line.
804
+ * @class A parallel is a line through a given point with the same slope as a given line or
805
+ * the line through two given point.
806
+ * <p>
807
+ * If original line is given as a JSXGraph line object, the resulting parallel line will be defined by the given point and an
808
+ * infinitely far away point (an ideal point). That means, the line can not be shortened to a segment.
809
+ * <p>
810
+ * If the original line is given as two points, the resulting parallel line can be shortened to a a segment.
808
811
  * @pseudo
809
812
  * @name Parallel
810
813
  * @augments Line
811
814
  * @constructor
812
815
  * @type JXG.Line
813
816
  * @throws {Error} If the element cannot be constructed with the given parent objects an exception is thrown.
814
- * @param {JXG.Line_JXG.Point} l,p The constructed line contains p and has the same slope as l.
817
+ * @param {JXG.Line_JXG.Point} l,p The constructed line contains p and has the same slope as l. Alternative parameters are p1, p2, p: The
818
+ * constructed line contains p and has the same slope as the line through p1 and p2.
815
819
  * @example
816
820
  * // Create a parallel
817
821
  * var p1 = board.create('point', [0.0, 2.0]);
@@ -829,22 +833,47 @@ define([
829
833
  * var plex1_p3 = plex1_board.create('point', [3.0, 3.0]);
830
834
  * var plex1_pl1 = plex1_board.create('parallel', [plex1_l1, plex1_p3]);
831
835
  * </script><pre>
836
+ * @example
837
+ * var p1, p2, p3, l1, pl1;
838
+ *
839
+ * p1 = board.create('point', [0.0, 2.0]);
840
+ * p2 = board.create('point', [2.0, 1.0]);
841
+ * l1 = board.create('line', [p1, p2]);
842
+ *
843
+ * p3 = board.create('point', [1.0, 3.0]);
844
+ * pl1 = board.create('parallel', [p1, p2, p3], {straightFirst: false, straightLast: false});
845
+ *
846
+ * </pre><div id="JXGd643305d-20c3-4a88-91f9-8d0c4448594f" class="jxgbox" style="width: 300px; height: 300px;"></div>
847
+ * <script type="text/javascript">
848
+ * (function() {
849
+ * var board = JXG.JSXGraph.initBoard('JXGd643305d-20c3-4a88-91f9-8d0c4448594f',
850
+ * {boundingbox: [-8, 8, 8,-8], axis: true, showcopyright: false, shownavigation: false});
851
+ * var p1, p2, p3, l1, pl1;
852
+ *
853
+ * p1 = board.create('point', [0.0, 2.0]);
854
+ * p2 = board.create('point', [2.0, 1.0]);
855
+ * l1 = board.create('line', [p1, p2]);
856
+ *
857
+ * p3 = board.create('point', [1.0, 3.0]);
858
+ * pl1 = board.create('parallel', [p1, p2, p3], {straightFirst: false, straightLast: false});
859
+ *
860
+ * })();
861
+ *
862
+ * </script><pre>
863
+ *
832
864
  */
833
865
  JXG.createParallel = function (board, parents, attributes) {
834
- var p, pp, pl, li, i, attr;
866
+ var p, pp, pl, li, i, attr, ty = 1;
835
867
 
836
868
  for (i = 0; i < parents.length; ++i) {
837
869
  parents[i] = board.select(parents[i]);
838
870
  }
839
871
  p = null;
840
872
  if (parents.length === 3) {
873
+ // Line / segment through point parents[2] which is parallel to line through parents[0] and parents[1]
841
874
  parents = Type.providePoints(board, parents, attributes, 'point');
842
- // line through point parents[2] which is parallel to line through parents[0] and parents[1]
843
875
  p = parents[2];
844
- /** @ignore */
845
- li = function () {
846
- return Mat.crossProduct(parents[0].coords.usrCoords, parents[1].coords.usrCoords);
847
- };
876
+ ty = 0;
848
877
  } else if (Type.isPointType(board, parents[0])) {
849
878
  // Parallel to line parents[1] through point parents[0]
850
879
  p = Type.providePoints(board, [parents[0]], attributes, 'point')[0];
@@ -866,11 +895,19 @@ define([
866
895
  }
867
896
 
868
897
  attr = Type.copyAttributes(attributes, board.options, 'parallel', 'point');
869
- pp = board.create('point', [
870
- function () {
871
- return Mat.crossProduct([1, 0, 0], li());
872
- }
873
- ], attr);
898
+ if (ty === 1) {
899
+ // Line is given by line element. The parallel line is
900
+ // constructed as line through an ideal point.
901
+ pp = board.create('point', [
902
+ function () {
903
+ return Mat.crossProduct([1, 0, 0], li());
904
+ }
905
+ ], attr);
906
+ } else {
907
+ // Line is given by two points. The parallel line is
908
+ // constructed as line through two finite point.
909
+ pp = board.create('parallelpoint', parents, attr);
910
+ }
874
911
  pp.isDraggable = true;
875
912
 
876
913
  attr = Type.copyAttributes(attributes, board.options, 'parallel');
@@ -904,31 +941,33 @@ define([
904
941
  };
905
942
 
906
943
  /**
907
- * @class An arrow parallel is a parallel segment with an arrow attached.
944
+ * @class An arrow parallel is a segment with an arrow attached which is parallel through a given segment, given by its defining two points,
945
+ * through a given point.
946
+ * <p>
908
947
  * @pseudo
909
948
  * @constructor
910
949
  * @name Arrowparallel
911
950
  * @type Parallel
912
951
  * @augments Parallel
913
952
  * @throws {Error} If the element cannot be constructed with the given parent objects an exception is thrown.
914
- * @param {JXG.Line_JXG.Point} l,p The constructed arrow contains p and has the same slope as l.
953
+ * @param JXG.Point_JXG.Point_JXG.Point} p1, p2,p3 The constructed arrow contains p3 and has the same slope as the line through p1 and p2.
915
954
  * @example
916
955
  * // Create a parallel
917
956
  * var p1 = board.create('point', [0.0, 2.0]);
918
957
  * var p2 = board.create('point', [2.0, 1.0]);
919
- * var l1 = board.create('line', [p1, p2]);
958
+ * var l1 = board.create('segment', [p1, p2]);
920
959
  *
921
960
  * var p3 = board.create('point', [3.0, 3.0]);
922
- * var pl1 = board.create('arrowparallel', [l1, p3]);
961
+ * var pl1 = board.create('arrowparallel', [p1, p2, p3]);
923
962
  * </pre><div class="jxgbox" id="JXGeeacdf99-036f-4e83-aeb6-f7388423e369" style="width: 400px; height: 400px;"></div>
924
963
  * <script type="text/javascript">
925
964
  * (function () {
926
965
  * var plex1_board = JXG.JSXGraph.initBoard('JXGeeacdf99-036f-4e83-aeb6-f7388423e369', {boundingbox: [-1, 9, 9, -1], axis: true, showcopyright: false, shownavigation: false});
927
966
  * var plex1_p1 = plex1_board.create('point', [0.0, 2.0]);
928
967
  * var plex1_p2 = plex1_board.create('point', [2.0, 1.0]);
929
- * var plex1_l1 = plex1_board.create('line', [plex1_p1, plex1_p2]);
968
+ * var plex1_l1 = plex1_board.create('segment', [plex1_p1, plex1_p2]);
930
969
  * var plex1_p3 = plex1_board.create('point', [3.0, 3.0]);
931
- * var plex1_pl1 = plex1_board.create('arrowparallel', [plex1_l1, plex1_p3]);
970
+ * var plex1_pl1 = plex1_board.create('arrowparallel', [plex1_p1, plex1_p2, plex1_p3]);
932
971
  * })();
933
972
  * </script><pre>
934
973
  */
package/src/jsxgraph.js CHANGED
@@ -228,6 +228,7 @@ define([
228
228
  */
229
229
  _setARIA: function(container, attr) {
230
230
  var doc = attr.document || document,
231
+ doc_glob,
231
232
  node_jsx, newNode, parent,
232
233
  id_label, id_description;
233
234
 
@@ -236,18 +237,19 @@ define([
236
237
  }
237
238
 
238
239
  node_jsx = doc.getElementById(container);
240
+ doc_glob = node_jsx.ownerDocument; // This is the window.document element, needed below.
239
241
  parent = node_jsx.parentNode;
240
242
 
241
243
  id_label = container + '_ARIAlabel';
242
244
  id_description = container + '_ARIAdescription';
243
245
 
244
- newNode = doc.createElement('div');
246
+ newNode = doc_glob.createElement('div');
245
247
  newNode.innerHTML = attr.title;
246
248
  newNode.setAttribute('id', id_label);
247
249
  newNode.style.display = 'none';
248
250
  parent.insertBefore(newNode, node_jsx);
249
251
 
250
- newNode = doc.createElement('div');
252
+ newNode = doc_glob.createElement('div');
251
253
  newNode.innerHTML = attr.description;
252
254
  newNode.setAttribute('id', id_description);
253
255
  newNode.style.display = 'none';
@@ -273,12 +275,12 @@ define([
273
275
  }
274
276
 
275
277
  id = board.containerObj.getAttribute('aria-labelledby');
276
- node = document.getElementById(id);
278
+ node = doc.getElementById(id);
277
279
  if (node && node.parentNode) {
278
280
  node.parentNode.removeChild(node);
279
281
  }
280
282
  id = board.containerObj.getAttribute('aria-describedby');
281
- node = document.getElementById(id);
283
+ node = doc.getElementById(id);
282
284
  if (node && node.parentNode) {
283
285
  node.parentNode.removeChild(node);
284
286
  }