jsxgraph 1.4.4 → 1.4.6
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/README.md +24 -0
- package/build/Readme.md +17 -0
- package/build/bin/jsxcompressor.js +1 -0
- package/build/bin/jsxgraphcore-min.js +7 -0
- package/build/bin/jsxgraphcore.js +83017 -0
- package/build/bin/jsxgraphcore.min.js +67 -0
- package/build/compressor.build.json +14 -0
- package/build/compressor.deps.js +8 -0
- package/build/core-amd.build.json +14 -0
- package/build/core-amd.deps.js +81 -0
- package/build/core.build.json +14 -0
- package/build/core.deps.js +102 -0
- package/build/plot.build.json +15 -0
- package/distrib/README.md +24 -0
- package/distrib/geogebra.min.js +1 -1
- package/distrib/geonext.min.js +1 -1
- package/distrib/index.d.ts +28 -7
- package/distrib/intergeo.min.js +1 -1
- package/distrib/jsxgraph.css +6 -0
- package/distrib/jsxgraphcore.js +3 -3
- package/distrib/jsxgraphsrc.js +3558 -1857
- package/distrib/sketch.min.js +1 -1
- package/package.json +1 -1
- package/src/3d/box3d.js +43 -38
- package/src/3d/curve3d.js +157 -53
- package/src/3d/element3d.js +84 -0
- package/src/3d/linspace3d.js +427 -146
- package/src/3d/point3d.js +360 -123
- package/src/3d/surface3d.js +140 -42
- package/src/3d/view3d.js +319 -164
- package/src/base/board.js +163 -78
- package/src/base/constants.js +8 -1
- package/src/base/curve.js +51 -9
- package/src/base/polygon.js +111 -69
- package/src/base/text.js +122 -19
- package/src/base/ticks.js +12 -3
- package/src/element/button.js +7 -3
- package/src/element/checkbox.js +8 -4
- package/src/element/composition.js +7 -1
- package/src/element/conic.js +2 -2
- package/src/element/input.js +9 -5
- package/src/jsxgraph.js +4 -1
- package/src/loadjsxgraph.js +13 -8
- package/src/math/clip.js +34 -134
- package/src/math/geometry.js +204 -3
- package/src/math/math.js +1 -2
- package/src/math/nlp.js +865 -774
- package/src/options.js +185 -12
- package/src/options3d.js +24 -7
- package/src/parser/jessiecode.js +9 -3
- package/src/renderer/abstract.js +26 -15
- package/src/renderer/canvas.js +2 -2
- package/src/renderer/svg.js +15 -2
- package/src/utils/env.js +36 -53
- package/src/utils/type.js +75 -2
- package/src/3d/threed.js +0 -38
package/src/base/polygon.js
CHANGED
|
@@ -80,6 +80,14 @@ define([
|
|
|
80
80
|
this.vertices = [];
|
|
81
81
|
for (i = 0; i < vertices.length; i++) {
|
|
82
82
|
this.vertices[i] = this.board.select(vertices[i]);
|
|
83
|
+
|
|
84
|
+
// The _is_new flag is replaced by _is_new_pol.
|
|
85
|
+
// Otherwise, the polygon would disappear if the last border element
|
|
86
|
+
// is removed (and the point has been provided by coordinates)
|
|
87
|
+
if (this.vertices[i]._is_new) {
|
|
88
|
+
delete this.vertices[i]._is_new;
|
|
89
|
+
this.vertices[i]._is_new_pol = true;
|
|
90
|
+
}
|
|
83
91
|
}
|
|
84
92
|
|
|
85
93
|
// Close the polygon
|
|
@@ -127,9 +135,9 @@ define([
|
|
|
127
135
|
// - add points (supplied as coordinate arrays by the user and created by Type.providePoints) as children to the polygon
|
|
128
136
|
for (i = 0; i < this.vertices.length - 1; i++) {
|
|
129
137
|
p = this.board.select(this.vertices[i]);
|
|
130
|
-
if (Type.exists(p.
|
|
138
|
+
if (Type.exists(p._is_new_pol)) {
|
|
131
139
|
this.addChild(p);
|
|
132
|
-
delete p.
|
|
140
|
+
delete p._is_new_pol;
|
|
133
141
|
} else {
|
|
134
142
|
p.addChild(this);
|
|
135
143
|
}
|
|
@@ -165,10 +173,7 @@ define([
|
|
|
165
173
|
JXG.extend(JXG.Polygon.prototype, /** @lends JXG.Polygon.prototype */ {
|
|
166
174
|
|
|
167
175
|
/**
|
|
168
|
-
*
|
|
169
|
-
* Implements W. Randolf Franklin's pnpoly method.
|
|
170
|
-
*
|
|
171
|
-
* See <a href="https://wrf.ecse.rpi.edu/Research/Short_Notes/pnpoly.html">https://wrf.ecse.rpi.edu/Research/Short_Notes/pnpoly.html</a>.
|
|
176
|
+
* Wrapper for JXG.Math.Geometry.pnpoly.
|
|
172
177
|
*
|
|
173
178
|
* @param {Number} x_in x-coordinate (screen or user coordinates)
|
|
174
179
|
* @param {Number} y_in y-coordinate (screen or user coordinates)
|
|
@@ -176,7 +181,9 @@ define([
|
|
|
176
181
|
* Possible values are <b>JXG.COORDS_BY_USER</b> and <b>JXG.COORDS_BY_SCREEN</b>.
|
|
177
182
|
* Default value is JXG.COORDS_BY_SCREEN
|
|
178
183
|
*
|
|
179
|
-
* @returns {Boolean} if (
|
|
184
|
+
* @returns {Boolean} if (x_in, y_in) is inside of the polygon.
|
|
185
|
+
* @see JXG.Math.Geometry#pnpoly
|
|
186
|
+
*
|
|
180
187
|
* @example
|
|
181
188
|
* var pol = board.create('polygon', [[-1,2], [2,2], [-1,4]]);
|
|
182
189
|
* var p = board.create('point', [4, 3]);
|
|
@@ -202,31 +209,7 @@ define([
|
|
|
202
209
|
*
|
|
203
210
|
*/
|
|
204
211
|
pnpoly: function(x_in, y_in, coord_type) {
|
|
205
|
-
|
|
206
|
-
x, y, crds,
|
|
207
|
-
v = this.vertices,
|
|
208
|
-
isIn = false;
|
|
209
|
-
|
|
210
|
-
if (coord_type === Const.COORDS_BY_USER) {
|
|
211
|
-
crds = new Coords(Const.COORDS_BY_USER, [x_in, y_in], this.board);
|
|
212
|
-
x = crds.scrCoords[1];
|
|
213
|
-
y = crds.scrCoords[2];
|
|
214
|
-
} else {
|
|
215
|
-
x = x_in;
|
|
216
|
-
y = y_in;
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
len = this.vertices.length;
|
|
220
|
-
for (i = 0, j = len - 2; i < len - 1; j = i++) {
|
|
221
|
-
if (((v[i].coords.scrCoords[2] > y) !== (v[j].coords.scrCoords[2] > y)) &&
|
|
222
|
-
(x < (v[j].coords.scrCoords[1] - v[i].coords.scrCoords[1]) *
|
|
223
|
-
(y - v[i].coords.scrCoords[2]) / (v[j].coords.scrCoords[2] - v[i].coords.scrCoords[2]) + v[i].coords.scrCoords[1])
|
|
224
|
-
) {
|
|
225
|
-
isIn = !isIn;
|
|
226
|
-
}
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
return isIn;
|
|
212
|
+
return Geometry.pnpoly(x_in, y_in, this.vertices, coord_type);
|
|
230
213
|
},
|
|
231
214
|
|
|
232
215
|
/**
|
|
@@ -590,9 +573,14 @@ define([
|
|
|
590
573
|
*
|
|
591
574
|
*/
|
|
592
575
|
addPoints: function (p) {
|
|
593
|
-
var args = Array.prototype.slice.call(arguments);
|
|
576
|
+
var idx, args = Array.prototype.slice.call(arguments);
|
|
594
577
|
|
|
595
|
-
|
|
578
|
+
if (this.elType === 'polygonalchain') {
|
|
579
|
+
idx = this.vertices.length - 1;
|
|
580
|
+
} else {
|
|
581
|
+
idx = this.vertices.length - 2;
|
|
582
|
+
}
|
|
583
|
+
return this.insertPoints.apply(this, [idx].concat(args));
|
|
596
584
|
},
|
|
597
585
|
|
|
598
586
|
/**
|
|
@@ -630,38 +618,65 @@ define([
|
|
|
630
618
|
*
|
|
631
619
|
*/
|
|
632
620
|
insertPoints: function (idx, p) {
|
|
633
|
-
var i, le;
|
|
621
|
+
var i, le, last, start, q;
|
|
634
622
|
|
|
635
623
|
if (arguments.length === 0) {
|
|
636
624
|
return this;
|
|
637
625
|
}
|
|
638
626
|
|
|
627
|
+
last = this.vertices.length - 1;
|
|
628
|
+
if (this.elType === 'polygon') {
|
|
629
|
+
last--;
|
|
630
|
+
}
|
|
639
631
|
|
|
640
|
-
|
|
632
|
+
// Wrong insertion index, get out of here
|
|
633
|
+
if (idx < -1 || idx > last) {
|
|
641
634
|
return this;
|
|
642
635
|
}
|
|
643
636
|
|
|
644
637
|
le = arguments.length - 1;
|
|
645
638
|
for (i = 1; i < le + 1; i++) {
|
|
646
|
-
this.
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
639
|
+
q = Type.providePoints(this.board, [arguments[i]], {}, 'polygon', ['vertices'])[0];
|
|
640
|
+
if (q._is_new) {
|
|
641
|
+
// Add the point as child of the polygon, but not of the borders.
|
|
642
|
+
this.addChild(q);
|
|
643
|
+
delete q._is_new;
|
|
644
|
+
}
|
|
645
|
+
this.vertices.splice(idx + i, 0, q);
|
|
652
646
|
}
|
|
647
|
+
|
|
653
648
|
if (this.withLines) {
|
|
654
|
-
|
|
655
|
-
|
|
649
|
+
start = idx + 1;
|
|
650
|
+
if (this.elType === 'polygon') {
|
|
651
|
+
if (idx < 0) {
|
|
652
|
+
// Add point(s) in the front
|
|
653
|
+
this.vertices[this.vertices.length - 1] = this.vertices[0];
|
|
654
|
+
this.borders[this.borders.length - 1].point2 = this.vertices[this.vertices.length - 1];
|
|
655
|
+
} else {
|
|
656
|
+
// Insert point(s) (middle or end)
|
|
657
|
+
this.borders[idx].point2 = this.vertices[start];
|
|
658
|
+
}
|
|
656
659
|
} else {
|
|
657
|
-
|
|
660
|
+
// Add point(s) in the front: do nothing
|
|
661
|
+
// Else:
|
|
662
|
+
if (idx >= 0) {
|
|
663
|
+
if (idx < this.borders.length) {
|
|
664
|
+
// Insert point(s) in the middle
|
|
665
|
+
this.borders[idx].point2 = this.vertices[start];
|
|
666
|
+
} else {
|
|
667
|
+
// Add point at the end
|
|
668
|
+
start = idx;
|
|
669
|
+
}
|
|
670
|
+
}
|
|
658
671
|
}
|
|
659
|
-
for (i =
|
|
672
|
+
for (i = start; i < start + le; i++) {
|
|
660
673
|
this.borders.splice(i, 0,
|
|
661
674
|
this.board.create('segment', [this.vertices[i], this.vertices[i + 1]], this.attr_line)
|
|
662
675
|
);
|
|
663
676
|
}
|
|
664
677
|
}
|
|
678
|
+
this.inherits = [];
|
|
679
|
+
this.inherits.push(this.vertices, this.borders);
|
|
665
680
|
this.board.update();
|
|
666
681
|
|
|
667
682
|
return this;
|
|
@@ -673,7 +688,8 @@ define([
|
|
|
673
688
|
* @returns {JXG.Polygon} Reference to the polygon
|
|
674
689
|
*/
|
|
675
690
|
removePoints: function (p) {
|
|
676
|
-
var i, j,
|
|
691
|
+
var i, j, j0, idx, firstPoint,
|
|
692
|
+
nvertices = [], nborders = [],
|
|
677
693
|
nidx = [], partition = [];
|
|
678
694
|
|
|
679
695
|
// Partition:
|
|
@@ -684,8 +700,11 @@ define([
|
|
|
684
700
|
// this gives us the borders, that can be removed and the borders we have to create.
|
|
685
701
|
|
|
686
702
|
|
|
687
|
-
//
|
|
688
|
-
|
|
703
|
+
// In case of polygon: remove the last vertex from the list of vertices since
|
|
704
|
+
// it is identical to the first
|
|
705
|
+
if (this.elType === 'polygon') {
|
|
706
|
+
firstPoint = this.vertices.pop();
|
|
707
|
+
}
|
|
689
708
|
|
|
690
709
|
// Collect all valid parameters as indices in nidx
|
|
691
710
|
for (i = 0; i < arguments.length; i++) {
|
|
@@ -693,12 +712,19 @@ define([
|
|
|
693
712
|
if (Type.isPoint(idx)) {
|
|
694
713
|
idx = this.findPoint(idx);
|
|
695
714
|
}
|
|
696
|
-
|
|
697
715
|
if (Type.isNumber(idx) && idx > -1 && idx < this.vertices.length && Type.indexOf(nidx, idx) === -1) {
|
|
698
716
|
nidx.push(idx);
|
|
699
717
|
}
|
|
700
718
|
}
|
|
701
719
|
|
|
720
|
+
if (nidx.length === 0) {
|
|
721
|
+
// Wrong index, get out of here
|
|
722
|
+
if (this.elType === 'polygon') {
|
|
723
|
+
this.vertices.push(firstPoint);
|
|
724
|
+
}
|
|
725
|
+
return this;
|
|
726
|
+
}
|
|
727
|
+
|
|
702
728
|
// Remove the polygon from each removed point's children
|
|
703
729
|
for (i = 0; i < nidx.length; i++) {
|
|
704
730
|
this.vertices[nidx[i]].removeChild(this);
|
|
@@ -709,7 +735,7 @@ define([
|
|
|
709
735
|
nvertices = this.vertices.slice();
|
|
710
736
|
nborders = this.borders.slice();
|
|
711
737
|
|
|
712
|
-
// Initialize the partition
|
|
738
|
+
// Initialize the partition with an array containing the last point to be removed
|
|
713
739
|
if (this.withLines) {
|
|
714
740
|
partition.push([nidx[nidx.length - 1]]);
|
|
715
741
|
}
|
|
@@ -719,7 +745,9 @@ define([
|
|
|
719
745
|
for (i = nidx.length - 1; i > -1; i--) {
|
|
720
746
|
nvertices[nidx[i]] = -1;
|
|
721
747
|
|
|
722
|
-
|
|
748
|
+
// Find gaps between the list of points to be removed.
|
|
749
|
+
// In this case a new partition is added.
|
|
750
|
+
if (this.withLines && nidx.length > 1 && (nidx[i] - 1 > nidx[i - 1])) {
|
|
723
751
|
partition[partition.length - 1][1] = nidx[i];
|
|
724
752
|
partition.push([nidx[i - 1]]);
|
|
725
753
|
}
|
|
@@ -737,7 +765,11 @@ define([
|
|
|
737
765
|
this.vertices.push(nvertices[i]);
|
|
738
766
|
}
|
|
739
767
|
}
|
|
740
|
-
|
|
768
|
+
|
|
769
|
+
// Close the polygon again
|
|
770
|
+
if (this.elType === 'polygon' &&
|
|
771
|
+
this.vertices.length > 1 &&
|
|
772
|
+
this.vertices[this.vertices.length - 1].id !== this.vertices[0].id) {
|
|
741
773
|
this.vertices.push(this.vertices[0]);
|
|
742
774
|
}
|
|
743
775
|
|
|
@@ -747,23 +779,28 @@ define([
|
|
|
747
779
|
for (j = partition[i][1] - 1; j < partition[i][0] + 1; j++) {
|
|
748
780
|
// special cases
|
|
749
781
|
if (j < 0) {
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
782
|
+
if (this.elType === 'polygon') {
|
|
783
|
+
// First vertex is removed, so the last border has to be removed, too
|
|
784
|
+
this.board.removeObject(this.borders[nborders.length - 1]);
|
|
785
|
+
nborders[nborders.length - 1] = -1;
|
|
786
|
+
}
|
|
787
|
+
} else if (j < nborders.length) {
|
|
788
|
+
this.board.removeObject(this.borders[j]);
|
|
789
|
+
nborders[j] = -1;
|
|
756
790
|
}
|
|
757
|
-
|
|
758
|
-
this.board.removeObject(this.borders[j]);
|
|
759
|
-
nborders[j] = -1;
|
|
760
791
|
}
|
|
761
792
|
|
|
762
|
-
//
|
|
763
|
-
//
|
|
764
|
-
// just to be sure...
|
|
793
|
+
// Only create the new segment if it's not the closing border.
|
|
794
|
+
// The closing border is getting a special treatment at the end.
|
|
765
795
|
if (partition[i][1] !== 0 && partition[i][0] !== nvertices.length - 1) {
|
|
766
|
-
nborders[partition[i][0] - 1] = this.board.create('segment', [
|
|
796
|
+
// nborders[partition[i][0] - 1] = this.board.create('segment', [
|
|
797
|
+
// nvertices[Math.max(partition[i][1] - 1, 0)],
|
|
798
|
+
// nvertices[Math.min(partition[i][0] + 1, this.vertices.length - 1)]
|
|
799
|
+
// ], this.attr_line);
|
|
800
|
+
nborders[partition[i][0] - 1] = this.board.create('segment', [
|
|
801
|
+
nvertices[partition[i][1] - 1],
|
|
802
|
+
nvertices[partition[i][0] + 1]
|
|
803
|
+
], this.attr_line);
|
|
767
804
|
}
|
|
768
805
|
}
|
|
769
806
|
|
|
@@ -775,10 +812,16 @@ define([
|
|
|
775
812
|
}
|
|
776
813
|
|
|
777
814
|
// if the first and/or the last vertex is removed, the closing border is created at the end.
|
|
778
|
-
if (
|
|
779
|
-
this.
|
|
815
|
+
if (this.elType === 'polygon' &&
|
|
816
|
+
this.vertices.length > 2 && // Avoid trivial case of polygon with 1 vertex
|
|
817
|
+
(partition[0][1] === this.vertices.length - 1 || partition[partition.length - 1][1] === 0)) {
|
|
818
|
+
this.borders.push(this.board.create('segment',
|
|
819
|
+
[this.vertices[0], this.vertices[this.vertices.length - 2]],
|
|
820
|
+
this.attr_line));
|
|
780
821
|
}
|
|
781
822
|
}
|
|
823
|
+
this.inherits = [];
|
|
824
|
+
this.inherits.push(this.vertices, this.borders);
|
|
782
825
|
|
|
783
826
|
this.board.update();
|
|
784
827
|
|
|
@@ -1025,7 +1068,6 @@ define([
|
|
|
1025
1068
|
return this.sutherlandHodgman(polygon);
|
|
1026
1069
|
}
|
|
1027
1070
|
|
|
1028
|
-
|
|
1029
1071
|
});
|
|
1030
1072
|
|
|
1031
1073
|
|
package/src/base/text.js
CHANGED
|
@@ -196,42 +196,63 @@ define([
|
|
|
196
196
|
var updateText, resolvedText,
|
|
197
197
|
ev_p = Type.evaluate(this.visProp.parse),
|
|
198
198
|
ev_um = Type.evaluate(this.visProp.usemathjax),
|
|
199
|
-
ev_uk = Type.evaluate(this.visProp.usekatex)
|
|
199
|
+
ev_uk = Type.evaluate(this.visProp.usekatex),
|
|
200
|
+
convertJessieCode = false;
|
|
200
201
|
|
|
201
202
|
this.orgText = text;
|
|
203
|
+
|
|
202
204
|
if (Type.isFunction(text)) {
|
|
205
|
+
// <value> tags will not be evaluated if text is provided by a function
|
|
203
206
|
this.updateText = function () {
|
|
204
|
-
resolvedText = text().toString();
|
|
207
|
+
resolvedText = text().toString(); // Evaluate function
|
|
205
208
|
if (ev_p && !ev_um && !ev_uk) {
|
|
206
209
|
this.plaintext = this.replaceSub(this.replaceSup(this.convertGeonextAndSketchometry2CSS(resolvedText)));
|
|
207
210
|
} else {
|
|
208
211
|
this.plaintext = resolvedText;
|
|
209
212
|
}
|
|
210
213
|
};
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
};
|
|
215
|
-
} else { // Parse
|
|
214
|
+
|
|
215
|
+
} else {
|
|
216
|
+
|
|
216
217
|
if (Type.isNumber(text)) {
|
|
217
218
|
this.content = Type.toFixed(text, Type.evaluate(this.visProp.digits));
|
|
218
|
-
} else {
|
|
219
|
-
|
|
220
|
-
|
|
219
|
+
} else if (Type.isString(text) && ev_p) {
|
|
220
|
+
|
|
221
|
+
if (Type.evaluate(this.visProp.useasciimathml)) { // ASCIIMathML
|
|
221
222
|
this.content = "'`" + text + "`'";
|
|
222
|
-
|
|
223
|
-
|
|
223
|
+
|
|
224
|
+
} else if (ev_um || ev_uk) { // MathJax or KaTeX
|
|
225
|
+
// Replace value-tags by functions
|
|
226
|
+
this.content = this.valueTagToJessieCode(text);
|
|
227
|
+
this.content = this.content.replace(/\\/g, "\\\\"); // Replace single backshlash by double
|
|
228
|
+
|
|
224
229
|
} else {
|
|
230
|
+
// No TeX involved.
|
|
225
231
|
// Converts GEONExT syntax into JavaScript string
|
|
226
232
|
// Short math is allowed
|
|
233
|
+
// Replace value-tags by functions
|
|
227
234
|
// Avoid geonext2JS calls
|
|
228
|
-
this.content = this.
|
|
235
|
+
this.content = this.poorMansTeX(this.valueTagToJessieCode(text));
|
|
229
236
|
}
|
|
237
|
+
convertJessieCode = true;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
// Generate function which returns the text to be displayed
|
|
241
|
+
if (convertJessieCode) {
|
|
242
|
+
|
|
243
|
+
// Convert JessieCode to JS function
|
|
244
|
+
updateText = this.board.jc.snippet(this.content, true, '', false);
|
|
245
|
+
|
|
246
|
+
// Ticks have been esacped in valueTagToJessieCode
|
|
247
|
+
this.updateText = function () {
|
|
248
|
+
this.plaintext = this.unescapeTicks(updateText());
|
|
249
|
+
};
|
|
250
|
+
} else {
|
|
251
|
+
this.updateText = function () {
|
|
252
|
+
this.plaintext = text;
|
|
253
|
+
};
|
|
254
|
+
|
|
230
255
|
}
|
|
231
|
-
updateText = this.board.jc.snippet(this.content, true, '', false);
|
|
232
|
-
this.updateText = function () {
|
|
233
|
-
this.plaintext = updateText();
|
|
234
|
-
};
|
|
235
256
|
}
|
|
236
257
|
},
|
|
237
258
|
|
|
@@ -584,11 +605,16 @@ define([
|
|
|
584
605
|
* Converts the GEONExT syntax of the <value> terms into JavaScript.
|
|
585
606
|
* Also, all Objects whose name appears in the term are searched and
|
|
586
607
|
* the text is added as child to these objects.
|
|
608
|
+
* This method is called if the attribute parse==true is set.
|
|
587
609
|
*
|
|
588
610
|
* @param{String} contentStr String to be parsed
|
|
589
611
|
* @param{Boolean} [expand] Optional flag if shortened math syntax is allowed (e.g. 3x instead of 3*x).
|
|
590
612
|
* @param{Boolean} [avoidGeonext2JS] Optional flag if geonext2JS should be called. For backwards compatibility
|
|
591
613
|
* this has to be set explicitely to true.
|
|
614
|
+
* @param{Boolean} [outputTeX] Optional flag which has to be true if the resulting term will be sent to MathJax or KaTeX.
|
|
615
|
+
* If true, "_" and "^" are NOT replaced by HTML tags sub and sup. Default: false, i.e. the replacement is done.
|
|
616
|
+
* This flag allows the combination of <value> tag containing calculations with TeX output.
|
|
617
|
+
*
|
|
592
618
|
* @private
|
|
593
619
|
* @see JXG.GeonextParser.geonext2JS
|
|
594
620
|
*/
|
|
@@ -596,13 +622,17 @@ define([
|
|
|
596
622
|
var res, term, i, j,
|
|
597
623
|
plaintext = '""';
|
|
598
624
|
|
|
599
|
-
//
|
|
625
|
+
// Revert possible jc replacement
|
|
600
626
|
contentStr = contentStr || '';
|
|
601
627
|
contentStr = contentStr.replace(/\r/g, '');
|
|
602
628
|
contentStr = contentStr.replace(/\n/g, '');
|
|
603
629
|
contentStr = contentStr.replace(/"/g, '\'');
|
|
604
630
|
contentStr = contentStr.replace(/'/g, "\\'");
|
|
605
631
|
|
|
632
|
+
// Old GEONExT syntax, not (yet) supported as TeX output.
|
|
633
|
+
// Otherwise, the else clause should be used.
|
|
634
|
+
// That means, i.e. the <arc> tag and <sqrt> tag are not
|
|
635
|
+
// converted into TeX syntax.
|
|
606
636
|
contentStr = contentStr.replace(/&arc;/g, '∠');
|
|
607
637
|
contentStr = contentStr.replace(/<arc\s*\/>/g, '∠');
|
|
608
638
|
contentStr = contentStr.replace(/<arc\s*\/>/g, '∠');
|
|
@@ -617,6 +647,8 @@ define([
|
|
|
617
647
|
if (i >= 0) {
|
|
618
648
|
while (i >= 0) {
|
|
619
649
|
plaintext += ' + "' + this.replaceSub(this.replaceSup(contentStr.slice(0, i))) + '"';
|
|
650
|
+
// plaintext += ' + "' + this.replaceSub(contentStr.slice(0, i)) + '"';
|
|
651
|
+
|
|
620
652
|
term = contentStr.slice(i + 7, j);
|
|
621
653
|
term = term.replace(/\s+/g, ''); // Remove all whitespace
|
|
622
654
|
if (expand === true) {
|
|
@@ -652,13 +684,84 @@ define([
|
|
|
652
684
|
plaintext += ' + "' + this.replaceSub(this.replaceSup(contentStr)) + '"';
|
|
653
685
|
plaintext = this.convertGeonextAndSketchometry2CSS(plaintext);
|
|
654
686
|
|
|
655
|
-
// This should replace &pi; by π
|
|
687
|
+
// This should replace e.g. &pi; by π
|
|
656
688
|
plaintext = plaintext.replace(/&/g, '&');
|
|
657
689
|
plaintext = plaintext.replace(/"/g, "'");
|
|
658
690
|
|
|
659
691
|
return plaintext;
|
|
660
692
|
},
|
|
661
693
|
|
|
694
|
+
valueTagToJessieCode: function(contentStr) {
|
|
695
|
+
var res, term, i, j,
|
|
696
|
+
expandShortMath = true,
|
|
697
|
+
textComps = [],
|
|
698
|
+
tick = '"';
|
|
699
|
+
|
|
700
|
+
contentStr = contentStr || '';
|
|
701
|
+
contentStr = contentStr.replace(/\r/g, '');
|
|
702
|
+
contentStr = contentStr.replace(/\n/g, '');
|
|
703
|
+
|
|
704
|
+
contentStr = contentStr.replace(/<value>/g, '<value>');
|
|
705
|
+
contentStr = contentStr.replace(/<\/value>/g, '</value>');
|
|
706
|
+
|
|
707
|
+
// Convert content of value tag (GEONExT/JessieCode) syntax into JavaScript syntax
|
|
708
|
+
i = contentStr.indexOf('<value>');
|
|
709
|
+
j = contentStr.indexOf('</value>');
|
|
710
|
+
if (i >= 0) {
|
|
711
|
+
while (i >= 0) {
|
|
712
|
+
// Add string fragment before <value> tag
|
|
713
|
+
textComps.push(tick + this.escapeTicks(contentStr.slice(0, i)) + tick);
|
|
714
|
+
|
|
715
|
+
term = contentStr.slice(i + 7, j);
|
|
716
|
+
term = term.replace(/\s+/g, ''); // Remove all whitespace
|
|
717
|
+
if (expandShortMath === true) {
|
|
718
|
+
term = this.expandShortMath(term);
|
|
719
|
+
}
|
|
720
|
+
res = term;
|
|
721
|
+
res = res.replace(/\\"/g, "'").replace(/\\'/g, "'");
|
|
722
|
+
|
|
723
|
+
// Hack: apply rounding once only.
|
|
724
|
+
if (res.indexOf('toFixed') < 0) {
|
|
725
|
+
// Output of a value tag
|
|
726
|
+
// Run the JessieCode parser
|
|
727
|
+
if (Type.isNumber((Type.bind(this.board.jc.snippet(res, true, '', false), this))())) {
|
|
728
|
+
// Output is number
|
|
729
|
+
textComps.push('(' + res + ').toFixed(' + (Type.evaluate(this.visProp.digits)) + ')');
|
|
730
|
+
} else {
|
|
731
|
+
// Output is a string
|
|
732
|
+
textComps.push('(' + res + ')');
|
|
733
|
+
}
|
|
734
|
+
} else {
|
|
735
|
+
textComps.push('(' + res + ')');
|
|
736
|
+
}
|
|
737
|
+
contentStr = contentStr.slice(j + 8);
|
|
738
|
+
i = contentStr.indexOf('<value>');
|
|
739
|
+
j = contentStr.indexOf('</value>');
|
|
740
|
+
}
|
|
741
|
+
}
|
|
742
|
+
// Add trailing string fragment
|
|
743
|
+
textComps.push(tick + this.escapeTicks(contentStr) + tick);
|
|
744
|
+
|
|
745
|
+
return textComps.join(' + ').replace(/&/g, '&');
|
|
746
|
+
},
|
|
747
|
+
|
|
748
|
+
poorMansTeX: function(s) {
|
|
749
|
+
s = s.replace(/<arc\s*\/*>/g, '∠')
|
|
750
|
+
.replace(/<arc\s*\/*>/g, '∠')
|
|
751
|
+
.replace(/<sqrt\s*\/*>/g, '√')
|
|
752
|
+
.replace(/<sqrt\s*\/*>/g, '√');
|
|
753
|
+
|
|
754
|
+
return this.convertGeonextAndSketchometry2CSS(this.replaceSub(this.replaceSup(s)));
|
|
755
|
+
},
|
|
756
|
+
|
|
757
|
+
escapeTicks: function(s) {
|
|
758
|
+
return s.replace(/"/g, '%22').replace(/'/g, '%27');
|
|
759
|
+
},
|
|
760
|
+
|
|
761
|
+
unescapeTicks: function(s) {
|
|
762
|
+
return s.replace(/%22/g, '"').replace(/%27/g, "'");
|
|
763
|
+
},
|
|
764
|
+
|
|
662
765
|
/**
|
|
663
766
|
* Converts the GEONExT tags <overline> and <arrow> to
|
|
664
767
|
* HTML span tags with proper CSS formatting.
|
package/src/base/ticks.js
CHANGED
|
@@ -659,6 +659,7 @@ define([
|
|
|
659
659
|
} else if (!ev_it) {
|
|
660
660
|
ticksDelta /= (ev_mt + 1);
|
|
661
661
|
}
|
|
662
|
+
// Now, ticksdelta is the distance between two minor ticks
|
|
662
663
|
this.ticksDelta = ticksDelta;
|
|
663
664
|
|
|
664
665
|
if (ticksDelta < Mat.eps) {
|
|
@@ -754,6 +755,8 @@ define([
|
|
|
754
755
|
*/
|
|
755
756
|
processTickPosition: function (coordsZero, tickPosition, ticksDelta, deltas) {
|
|
756
757
|
var x, y, tickCoords, ti,
|
|
758
|
+
isLabelPosition,
|
|
759
|
+
ticksPerLabel = Type.evaluate(this.visProp.ticksperlabel),
|
|
757
760
|
labelVal = null;
|
|
758
761
|
|
|
759
762
|
// Calculates tick coordinates
|
|
@@ -776,13 +779,19 @@ define([
|
|
|
776
779
|
// a multiple of the number of minorticks+1
|
|
777
780
|
tickCoords.major = Math.round(tickPosition / ticksDelta) % (Type.evaluate(this.visProp.minorticks) + 1) === 0;
|
|
778
781
|
|
|
782
|
+
if (!ticksPerLabel) {
|
|
783
|
+
// In case of null, 0 or false, majorTicks are labelled
|
|
784
|
+
ticksPerLabel = Type.evaluate(this.visProp.minorticks) + 1;
|
|
785
|
+
}
|
|
786
|
+
isLabelPosition = Math.round(tickPosition / ticksDelta) % (ticksPerLabel) === 0;
|
|
787
|
+
|
|
779
788
|
// Compute the start position and the end position of a tick.
|
|
780
789
|
// If both positions are out of the canvas, ti is empty.
|
|
781
790
|
ti = this.createTickPath(tickCoords, tickCoords.major);
|
|
782
791
|
if (ti.length === 3) {
|
|
783
792
|
this.ticks.push(ti);
|
|
784
|
-
if (
|
|
785
|
-
//
|
|
793
|
+
if (isLabelPosition && Type.evaluate(this.visProp.drawlabels)) {
|
|
794
|
+
// Create a label at this position
|
|
786
795
|
this.labelsData.push(
|
|
787
796
|
this.generateLabelData(
|
|
788
797
|
this.generateLabelText(tickCoords, coordsZero, labelVal),
|
|
@@ -1022,7 +1031,7 @@ define([
|
|
|
1022
1031
|
|
|
1023
1032
|
// if value is Number
|
|
1024
1033
|
if (Type.isNumber(value)) {
|
|
1025
|
-
labelText = (Math.round(value * 1.
|
|
1034
|
+
labelText = (Math.round(value * 1.e11) / 1.e11).toString();
|
|
1026
1035
|
if (labelText.length > Type.evaluate(this.visProp.maxlabellength) ||
|
|
1027
1036
|
labelText.indexOf('e') !== -1) {
|
|
1028
1037
|
|
package/src/element/button.js
CHANGED
|
@@ -71,7 +71,7 @@ define([
|
|
|
71
71
|
* @constructor
|
|
72
72
|
* @type JXG.Text
|
|
73
73
|
*
|
|
74
|
-
* @param {number,function_number,
|
|
74
|
+
* @param {number,function_number,function_String,function_function} x,y,label,handler Parent elements for button elements.
|
|
75
75
|
* <p>
|
|
76
76
|
* x and y are the coordinates of the lower left corner of the text box.
|
|
77
77
|
* The position of the text is fixed,
|
|
@@ -205,18 +205,22 @@ define([
|
|
|
205
205
|
// "\nPossible parents are: [x, y, label, handler]");
|
|
206
206
|
//}
|
|
207
207
|
|
|
208
|
+
// 1. Create empty button
|
|
208
209
|
par = [parents[0], parents[1], '<button type="button" style="width:100%;"></button>'];
|
|
209
|
-
|
|
210
210
|
t = board.create('text', par, attr);
|
|
211
211
|
t.type = Type.OBJECT_TYPE_BUTTON;
|
|
212
212
|
|
|
213
213
|
t.rendNodeButton = t.rendNode.childNodes[0];
|
|
214
214
|
t.rendNodeButton.id = t.rendNode.id + '_button';
|
|
215
|
-
t.rendNodeButton.innerHTML = parents[2];
|
|
215
|
+
// t.rendNodeButton.innerHTML = parents[2];
|
|
216
216
|
|
|
217
217
|
t.rendNodeTag = t.rendNodeButton; // Needed for unified treatment in setAttribute
|
|
218
218
|
t.rendNodeTag.disabled = !!attr.disabled;
|
|
219
219
|
|
|
220
|
+
// 2. Set parents[2] (string|function) as content of the button.
|
|
221
|
+
// abstract.js selects the correct DOM element for the update
|
|
222
|
+
t.setText(parents[2]);
|
|
223
|
+
|
|
220
224
|
// This sets the font-size of the button text
|
|
221
225
|
t.visPropOld.fontsize = "0px";
|
|
222
226
|
board.renderer.updateTextStyle(t, false);
|
package/src/element/checkbox.js
CHANGED
|
@@ -69,13 +69,13 @@ define([
|
|
|
69
69
|
* @constructor
|
|
70
70
|
* @type JXG.Text
|
|
71
71
|
*
|
|
72
|
-
* @param {number,function_number,
|
|
72
|
+
* @param {number,function_number,function_String,function} x,y,label Parent elements for checkbox elements.
|
|
73
73
|
* <p>
|
|
74
74
|
* x and y are the coordinates of the lower left corner of the text box.
|
|
75
75
|
* The position of the text is fixed,
|
|
76
76
|
* x and y are numbers. The position is variable if x or y are functions.
|
|
77
77
|
* <p>
|
|
78
|
-
* The label of the input element may be given as string.
|
|
78
|
+
* The label of the input element may be given as string or function.
|
|
79
79
|
* <p>
|
|
80
80
|
* The value of the checkbox can be controlled with the attribute <tt>checked</tt>
|
|
81
81
|
* <p>The HTML node can be accessed with <tt>element.rendNodeCheckbox</tt>
|
|
@@ -184,7 +184,7 @@ define([
|
|
|
184
184
|
'</span>'
|
|
185
185
|
];
|
|
186
186
|
|
|
187
|
-
//
|
|
187
|
+
// 1. Create checkbox element with empty label
|
|
188
188
|
t = board.create('text', par, attr);
|
|
189
189
|
t.type = Type.OBJECT_TYPE_CHECKBOX;
|
|
190
190
|
|
|
@@ -194,11 +194,15 @@ define([
|
|
|
194
194
|
t.rendNodeTag = t.rendNodeCheckbox; // Needed for unified treatment in setAttribute
|
|
195
195
|
t.rendNodeTag.disabled = !!attr.disabled;
|
|
196
196
|
|
|
197
|
-
t.rendNodeLabel.innerHTML = parents[2];
|
|
197
|
+
// t.rendNodeLabel.innerHTML = parents[2];
|
|
198
198
|
t.rendNodeCheckbox.id = t.rendNode.id + '_checkbox';
|
|
199
199
|
t.rendNodeLabel.id = t.rendNode.id + '_label';
|
|
200
200
|
t.rendNodeLabel.setAttribute('for', t.rendNodeCheckbox.id);
|
|
201
201
|
|
|
202
|
+
// 2. Set parents[2] (string|function) as label of the checkbox element.
|
|
203
|
+
// abstract.js selects the correct DOM element for the update
|
|
204
|
+
t.setText(parents[2]);
|
|
205
|
+
|
|
202
206
|
// This sets the font-size of the checkbox itself
|
|
203
207
|
t.visPropOld.fontsize = "0px";
|
|
204
208
|
board.renderer.updateTextStyle(t, false);
|