1 /*
  2     Copyright 2008-2026
  3         Matthias Ehmann,
  4         Michael Gerhaeuser,
  5         Carsten Miller,
  6         Bianca Valentin,
  7         Andreas Walter,
  8         Alfred Wassermann,
  9         Peter Wilfahrt
 10 
 11     This file is part of JSXGraph and JSXCompressor.
 12 
 13     JSXGraph is free software dual licensed under the GNU LGPL or MIT License.
 14     JSXCompressor is free software dual licensed under the GNU LGPL or Apache License.
 15 
 16     You can redistribute it and/or modify it under the terms of the
 17 
 18       * GNU Lesser General Public License as published by
 19         the Free Software Foundation, either version 3 of the License, or
 20         (at your option) any later version
 21       OR
 22       * MIT License: https://github.com/jsxgraph/jsxgraph/blob/master/LICENSE.MIT
 23       OR
 24       * Apache License Version 2.0
 25 
 26     JSXGraph is distributed in the hope that it will be useful,
 27     but WITHOUT ANY WARRANTY; without even the implied warranty of
 28     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 29     GNU Lesser General Public License for more details.
 30 
 31     You should have received a copy of the GNU Lesser General Public License, Apache
 32     License, and the MIT License along with JSXGraph. If not, see
 33     <https://www.gnu.org/licenses/>, <https://www.apache.org/licenses/LICENSE-2.0.html>,
 34     and <https://opensource.org/licenses/MIT/>.
 35 
 36  */
 37 
 38 /*global JXG: true, define: true, jQuery: true, window: true, document: true, navigator: true, require: true, module: true, console: true */
 39 /*jslint nomen:true, plusplus:true, forin:true*/
 40 
 41 /**
 42  * @fileoverview The JSXGraph object is defined in this file. JXG.JSXGraph controls all boards.
 43  * It has methods to create, save, load and free boards. Additionally some helper functions are
 44  * defined in this file directly in the JXG namespace.
 45  */
 46 
 47 /**
 48  * JXG is the top object of JSXGraph and defines the namespace
 49  *
 50  * @name JXG
 51  * @exports jxg as JXG
 52  * @namespace
 53  */
 54 var jxg = {};
 55 
 56 // Make sure JXG.extend is not defined.
 57 // If JSXGraph is compiled as an amd module, it is possible that another JSXGraph version is already loaded and we
 58 // therefore must not re-use the global JXG variable. But in this case JXG.extend will already be defined.
 59 // This is the reason for this check.
 60 // The try-statement is necessary, otherwise an error is thrown in certain imports, e.g. in deno.
 61 try {
 62     if (typeof JXG === "object" && !JXG.extend) {
 63         jxg = JXG;
 64     }
 65 } catch (e) {}
 66 
 67 // We need the following two methods "extend" and "shortcut" to create the JXG object via JXG.extend.
 68 
 69 /**
 70  * Copy all properties of the <tt>extension</tt> object to <tt>object</tt>.
 71  * @param {Object} object
 72  * @param {Object} extension
 73  * @param {Boolean} [onlyOwn=false] Only consider properties that belong to extension itself, not any inherited properties.
 74  * @param {Boolean} [toLower=false] If true the keys are convert to lower case. This is needed for visProp, see JXG#copyAttributes
 75  */
 76 jxg.extend = function (object, extension, onlyOwn, toLower) {
 77     var e, e2;
 78 
 79     onlyOwn = onlyOwn || false;
 80     toLower = toLower || false;
 81 
 82     // the purpose of this for...in loop is indeed to use hasOwnProperty only if the caller
 83     // explicitly wishes so.
 84     for (e in extension) {
 85         if (!onlyOwn || (onlyOwn && extension.hasOwnProperty(e))) {
 86             if (toLower) {
 87                 e2 = e.toLowerCase();
 88             } else {
 89                 e2 = e;
 90             }
 91 
 92             object[e2] = extension[e];
 93         }
 94     }
 95 };
 96 
 97 /**
 98  * Set a constant <tt>name</tt> in <tt>object</tt> to <tt>value</tt>. The value can't be changed after declaration.
 99  * @param {Object} object
100  * @param {String} name
101  * @param {Number|String|Boolean} value
102  * @param {Boolean} ignoreRedefine This should be left at its default: false.
103  */
104 jxg.defineConstant = function (object, name, value, ignoreRedefine) {
105     ignoreRedefine = ignoreRedefine || false;
106 
107     if (ignoreRedefine && jxg.exists(object[name])) {
108         return;
109     }
110 
111     Object.defineProperty(object, name, {
112         value: value,
113         writable: false,
114         enumerable: true,
115         configurable: false
116     });
117 };
118 
119 /**
120  * Copy all properties of the <tt>constants</tt> object in <tt>object</tt> as a constant.
121  * @param {Object} object
122  * @param {Object} constants
123  * @param {Boolean} [onlyOwn=false] Only consider properties that belong to extension itself, not any inherited properties.
124  * @param {Boolean} [toUpper=false] If true the keys are convert to lower case. This is needed for visProp, see JXG#copyAttributes
125  */
126 jxg.extendConstants = function (object, constants, onlyOwn, toUpper) {
127     var e, e2;
128 
129     onlyOwn = onlyOwn || false;
130     toUpper = toUpper || false;
131 
132     // The purpose of this for...in loop is indeed to use hasOwnProperty only if the caller explicitly wishes so.
133     for (e in constants) {
134         if (!onlyOwn || (onlyOwn && constants.hasOwnProperty(e))) {
135             if (toUpper) {
136                 e2 = e.toUpperCase();
137             } else {
138                 e2 = e;
139             }
140 
141             this.defineConstant(object, e2, constants[e]);
142         }
143     }
144 };
145 
146 jxg.extend(
147     jxg,
148     /** @lends JXG */ {
149         /**
150          * Store a reference to every board in this central list. This will at some point
151          * replace JXG.JSXGraph.boards.
152          * @type Object
153          */
154         boards: {},
155 
156         /**
157          * Store the available file readers in this structure.
158          * @type Object
159          */
160         readers: {},
161 
162         /**
163          * Associative array that keeps track of all constructable elements registered
164          * via {@link JXG.registerElement}.
165          * @type Object
166          */
167         elements: {},
168 
169         /**
170          * This registers a new construction element to JSXGraph for the construction via the {@link JXG.Board.create}
171          * interface.
172          * @param {String} element The elements name. This is case-insensitive, existing elements with the same name
173          * will be overwritten.
174          * @param {Function} creator A reference to a function taking three parameters: First the board, the element is
175          * to be created on, a parent element array, and an attributes object. See {@link JXG.createPoint} or any other
176          * <tt>JXG.create...</tt> function for an example.
177          */
178         registerElement: function (element, creator) {
179             element = element.toLowerCase();
180             this.elements[element] = creator;
181         },
182 
183         /**
184          * Register a file reader.
185          * @param {function} reader A file reader. This object has to provide two methods: <tt>prepareString()</tt>
186          * and <tt>read()</tt>.
187          * @param {Array} ext
188          */
189         registerReader: function (reader, ext) {
190             var i, e;
191 
192             for (i = 0; i < ext.length; i++) {
193                 e = ext[i].toLowerCase();
194 
195                 if (typeof this.readers[e] !== 'function') {
196                     this.readers[e] = reader;
197                 }
198             }
199         },
200 
201         /**
202          * Creates a shortcut to a method, e.g. {@link JXG.Board#createElement} is a shortcut to {@link JXG.Board#create}.
203          * Sometimes the target is undefined by the time you want to define the shortcut so we need this little helper.
204          * @param {Object} object The object the method we want to create a shortcut for belongs to.
205          * @param {String} fun The method we want to create a shortcut for.
206          * @returns {Function} A function that calls the given method.
207          */
208         shortcut: function (object, fun) {
209             return function () {
210                 return object[fun].apply(this, arguments);
211             };
212         },
213 
214         /**
215          * s may be a string containing the name or id of an element or even a reference
216          * to the element itself. This function returns a reference to the element. Search order: id, name.
217          * @param {JXG.Board} board Reference to the board the element belongs to.
218          * @param {String} s String or reference to a JSXGraph element.
219          * @returns {Object} Reference to the object given in parameter object
220          * @deprecated Use {@link JXG.Board#select}
221          */
222         getRef: function (board, s) {
223             jxg.deprecated("JXG.getRef()", "Board.select()");
224             return board.select(s);
225         },
226 
227         /**
228          * This is just a shortcut to {@link JXG.getRef}.
229          * @deprecated Use {@link JXG.Board#select}.
230          */
231         getReference: function (board, s) {
232             jxg.deprecated("JXG.getReference()", "Board.select()");
233             return board.select(s);
234         },
235 
236         /**
237          * s may be the string containing the id of an HTML tag that hosts a JSXGraph board.
238          * This function returns the reference to the board.
239          * @param  {String} s String of an HTML tag that hosts a JSXGraph board
240          * @returns {Object} Reference to the board or null.
241          */
242         getBoardByContainerId: function (s) {
243             var b;
244             for (b in JXG.boards) {
245                 if (JXG.boards.hasOwnProperty(b) && JXG.boards[b].container === s) {
246                     return JXG.boards[b];
247                 }
248             }
249 
250             return null;
251         },
252 
253         /**
254          * This method issues a warning to the developer that the given function is deprecated
255          * and, if available, offers an alternative to the deprecated function.
256          * @param {String} what Describes the function that is deprecated
257          * @param {String} [replacement] The replacement that should be used instead.
258          */
259         deprecated: function (what, replacement) {
260             var warning = what + " is deprecated.";
261 
262             if (replacement) {
263                 warning += " Please use " + replacement + " instead.";
264             }
265 
266             jxg.warn(warning);
267         },
268 
269         /**
270          * Outputs a warning via console.warn(), if available. If console.warn() is
271          * unavailable this function will look for an HTML element with the id 'warning'
272          * and append the warning to this element's innerText.
273          * @param {String} warning The warning text
274          */
275         warn: function (warning) {
276             if (typeof window === "object" && window.console && console.warn) {
277                 console.warn("WARNING:", warning);
278             } else if (typeof document === "object" && document.getElementById('warning')) {
279                 document.getElementById('debug').innerText += "WARNING: " + warning + '\n';
280             }
281         },
282 
283         /**
284          * Add something to the debug log. If available a JavaScript debug console is used. Otherwise
285          * we're looking for a HTML div with id "debug". If this doesn't exist, too, the output is omitted.
286          * @param s An arbitrary number of parameters.
287          * @see JXG.debugWST
288          */
289         debugInt: function (s) {
290             var i, p;
291 
292             for (i = 0; i < arguments.length; i++) {
293                 p = arguments[i];
294                 if (typeof window === "object" && window.console && console.log) {
295                     console.log(p);
296                 } else if (typeof document === "object" && document.getElementById('debug')) {
297                     document.getElementById('debug').innerText += p + '\n';
298                 }
299             }
300         },
301 
302         /**
303          * Add something to the debug log. If available a JavaScript debug console is used. Otherwise
304          * we're looking for a HTML div with id "debug". If this doesn't exist, too, the output is omitted.
305          * This method adds a stack trace (if available).
306          * @param s An arbitrary number of parameters.
307          * @see JXG.debug
308          */
309         debugWST: function (s) {
310             var e = new Error();
311 
312             jxg.debugInt.apply(this, arguments);
313 
314             if (e && e.stack) {
315                 jxg.debugInt('stacktrace');
316                 jxg.debugInt(e.stack.split("\n").slice(1).join("\n"));
317             }
318         },
319 
320         /**
321          * Add something to the debug log. If available a JavaScript debug console is used. Otherwise
322          * we're looking for a HTML div with id "debug". If this doesn't exist, too, the output is omitted.
323          * This method adds a line of the stack trace (if available).
324          *
325          * @param s An arbitrary number of parameters.
326          * @see JXG.debug
327          */
328         debugLine: function (s) {
329             var e = new Error();
330 
331             jxg.debugInt.apply(this, arguments);
332 
333             if (e && e.stack) {
334                 jxg.debugInt("Called from", e.stack.split("\n").slice(2, 3).join("\n"));
335             }
336         },
337 
338         /**
339          * Add something to the debug log. If available a JavaScript debug console is used. Otherwise
340          * we're looking for a HTML div with id "debug". If this doesn't exist, too, the output is omitted.
341          * @param s An arbitrary number of parameters.
342          * @see JXG.debugWST
343          * @see JXG.debugLine
344          * @see JXG.debugInt
345          */
346         debug: function (s) {
347             jxg.debugInt.apply(this, arguments);
348         },
349 
350         /**
351          * Initialize a new board.
352          * Alias of {@link JXG.JSXGraph.initBoard}.
353          * @param {String|Object} box id of or reference to the HTML element in which the board is painted.
354          * @param {Object} attributes An object that sets some of the board properties.
355          * See {@link JXG.Board} for a list of available attributes of the board.
356          * Most of these attributes can also be set globally via {@link JXG.Options}.
357          *
358          * @returns {JXG.Board} Reference to the created board.
359          *
360          * @see JXG.AbstractRenderer#drawNavigationBar
361          * @example
362          * var board = JXG.board('jxgbox', {
363          *     boundingbox: [-10, 5, 10, -5],
364          *     keepaspectratio: false,
365          *     axis: true
366          * });
367          *
368          * </pre><div id="JXG79b42d26-b664-451d-96b4-08bc25dd87d3" class="jxgbox" style="width: 600px; height: 300px;"></div>
369          * <script type="text/javascript">
370          *     (function() {
371          *         var board = JXG.board('JXG79b42d26-b664-451d-96b4-08bc25dd87d3', {
372          *         boundingbox: [-10, 5, 10, -5],
373          *         keepaspectratio: false,
374          *         axis: true
375          *     });
376          *
377          *     })();
378          *
379          * </script><pre>
380          *
381          *
382          * @example
383          * const board = JXG.board('jxgbox', {
384          *   boundingbox: [-10, 10, 10, -10],
385          *   axis: true,
386          *   showCopyright: true,
387          *   showFullscreen: true,
388          *   showScreenshot: false,
389          *   showClearTraces: false,
390          *   showInfobox: false,
391          *   showNavigation: true,
392          *   grid: false,
393          *   defaultAxes: {
394          *     x: {
395          *       withLabel: true,
396          *       label: {
397          *         position: '95% left',
398          *         offset: [-10, 10]
399          *       },
400          *       lastArrow: {
401          *         type: 4,
402          *         size: 10
403          *       }
404          *     },
405          *     y: {
406          *       withLabel: true,
407          *       label: {
408          *         position: '0.90fr right',
409          *         offset: [6, -6]
410          *       },
411          *       lastArrow: {
412          *         type: 4,
413          *         size: 10
414          *       }
415          *     }
416          *   }
417          * });
418          *
419          * </pre><div id="JXGd7a7705b-35bb-4193-bbd4-3e3fd92eb92c" class="jxgbox" style="width: 300px; height: 300px;"></div>
420          * <script type="text/javascript">
421          *     (function() {
422          *       var board = JXG.board('JXGd7a7705b-35bb-4193-bbd4-3e3fd92eb92c', {
423          *       boundingbox: [-10, 10, 10, -10],
424          *       axis: true,
425          *       showCopyright: true,
426          *       showFullscreen: true,
427          *       showScreenshot: false,
428          *       showClearTraces: false,
429          *       showInfobox: false,
430          *       showNavigation: true,
431          *       grid: false,
432          *       defaultAxes: {
433          *         x: {
434          *           withLabel: true,
435          *           label: {
436          *             position: '95% left',
437          *             offset: [0, 0]
438          *           },
439          *           lastArrow: {
440          *             type: 4,
441          *             size: 10
442          *           }
443          *         },
444          *         y: {
445          *           withLabel: true,
446          *           label: {
447          *             position: '0.90fr right',
448          *             offset: [0, 0]
449          *           },
450          *           lastArrow: {
451          *             type: 4,
452          *             size: 10
453          *           }
454          *         }
455          *       }
456          *     });
457          *
458          *     })();
459          *
460          * </script><pre>
461          * @example
462          * const board = JXG.board('jxgbox', {
463          *     boundingbox: [-5, 5, 5, -5],
464          *     intl: {
465          *         enabled: false,
466          *         locale: 'en-EN'
467          *     },
468          *     keepaspectratio: true,
469          *     axis: true,
470          *     defaultAxes: {
471          *         x: {
472          *             ticks: {
473          *                 intl: {
474          *                         enabled: true,
475          *                         options: {
476          *                             style: 'unit',
477          *                             unit: 'kilometer-per-hour',
478          *                             unitDisplay: 'narrow'
479          *                         }
480          *                 }
481          *             }
482          *         },
483          *         y: {
484          *             ticks: {
485          *             }
486          *         }
487          *     },
488          *     infobox: {
489          *         fontSize: 20,
490          *         intl: {
491          *             enabled: true,
492          *             options: {
493          *                 minimumFractionDigits: 4,
494          *                 maximumFractionDigits: 5
495          *             }
496          *         }
497          *     }
498          * });
499          *
500          * </pre><div id="JXGd84f4c84-f900-4d33-b001-e5f5f3ab0dd2" class="jxgbox" style="width: 600px; height: 600px;"></div>
501          * <script type="text/javascript">
502          *     (function() {
503          *         var board = JXG.board('JXGd84f4c84-f900-4d33-b001-e5f5f3ab0dd2', {
504          *         boundingbox: [-5, 5, 5, -5],
505          *         intl: {
506          *             enabled: false,
507          *             locale: 'en-EN'
508          *         },
509          *         keepaspectratio: true,
510          *         axis: true,
511          *         defaultAxes: {
512          *             x: {
513          *                 ticks: {
514          *                     intl: {
515          *                             enabled: true,
516          *                             options: {
517          *                                 style: 'unit',
518          *                                 unit: 'kilometer-per-hour',
519          *                                 unitDisplay: 'narrow'
520          *                             }
521          *                     }
522          *                 }
523          *             },
524          *             y: {
525          *                 ticks: {
526          *                 }
527          *             }
528          *         },
529          *         infobox: {
530          *             fontSize: 20,
531          *             intl: {
532          *                 enabled: true,
533          *                 options: {
534          *                     minimumFractionDigits: 4,
535          *                     maximumFractionDigits: 5
536          *                 }
537          *             }
538          *         }
539          *     });
540          *
541          *     })();
542          *
543          * </script><pre>
544          *
545          */
546         board: function (box, attributes) {
547             return this.JSXGraph.initBoard(box, attributes);
548         },
549 
550         /**
551          * Create a JSXGraph div element containing a JSXGraph board inside of a user supplied div.
552          * <p>
553          * The styling of the supplied div is up to the user, see the style-tag in the example below for
554          * one possibility. The CSS for the inner div, hosting the JSXGraph board, is supplied by the attributes
555          *  <pre>
556          *   jxgbox: {
557          *       style: 'width:640px;  aspect-ratio:2/1; background-color: white',
558          *       cssClass: '',
559          *       id: 'jxgbox'
560          *   }
561          * </pre>
562          * i.e. the div's style-attribute and a list of classes (separated by blanks) can be given.
563          * <p>
564          * By setting the attribute "clip" to false for selected
565          * elements (like sliders and texts), these elements can be positioned outside of the JSXGraph board. For those elements,
566          * the setting of the attributes "frozen:true, fixed:true" is recommended to make their position independent from zooming
567          * or panning the board coordinates.
568          * <p>
569          * However, not all elements will look good if displayed outside of the JSXGraph board - be careful.
570          *
571          * @param {String|Object} box id of or reference to the HTML element in which the board is painted into a sub-element of type div.
572          * @param {Object} attributes An object that sets some of the board properties and properties of the sub-element containing the board.
573          * See {@link JXG.Board} for a list of available attributes of the board.
574          * Most of these attributes can also be set globally via {@link JXG.Options}.
575          *
576          * @returns {JXG.Board} Reference to the created board.
577          *
578          * @example
579          *
580          * // Styling of the outer div
581          * <style>
582          * .container {
583          *   display: flex;
584          *   align-items: center;
585          *   justify-content: center;
586          *   width: 800px;
587          *   height: 500px;
588          *   overflow: hidden;
589          *   border: 1px black solid;
590          *   border-radius: 10px;
591          *   background-color: #eee;
592          * }
593          * </style>
594          * <div id="container" class="container"></div>
595          * <script type="text/javascript">
596          *        const board = JXG.appBox('container', {
597          *            jxgbox: {
598          *                // Styling of the inner div
599          *                style: 'width:640px;  aspect-ratio:2/1; background-color: white',
600          *                cssClass: '',
601          *                id: 'jxgbox'
602          *            },
603          *            boundingbox: [-5, 5, 5, -5],
604          *            axis: true,
605          *            showFullScreen: true
606          *        });
607          *
608          *        const point1 = board.create("point", [4, 1], { name: 'A' });
609          *        const point2 = board.create("point", [3, -1], {name: 'B'});
610          *        const point3 = board.create("point", [6, -1], { clip: false });
611          *
612          *        var sl = board.create('slider', [[-3, -6], [-1, -6], [-5, 1, 5]], {
613          *            clip: false,
614          *            frozen: true,
615          *            size: 16,
616          *            face: '[]',
617          *            name: 's'
618          *        });
619          *
620          *        var graph = board.create("functiongraph", ['s.Value() * x^3'], { clip: true });
621          *
622          * </script>
623          * </pre>
624          * <style>
625          * .container {
626          *   display: flex;
627          *   align-items: center;
628          *   justify-content: center;
629          *   width: 800px;
630          *   height: 500px;
631          *   overflow: hidden;
632          *   border: 1px black solid;
633          *   border-radius: 10px;
634          *   background-color: #eee;
635          * }
636          * </style>
637          * <div id="JXGd1c7bf6a-a571-4392-a289-e4ef44d57c88" class="container"></div>
638          * <script type="text/javascript">
639          *     (function() {
640          *        const board = JXG.appBox('JXGd1c7bf6a-a571-4392-a289-e4ef44d57c88', {
641          *            jxgbox: {
642          *                style: "width:640px;  aspect-ratio:2/1; background-color: white",
643          *                cssClass: "",
644          *                id: 'xxx'
645          *            },
646          *            boundingbox: [-5, 5, 5, -5],
647          *            axis: true,
648          *            showFullScreen: true
649          *        });
650          *
651          *        const point1 = board.create("point", [4, 1], { name: 'A' });
652          *        const point2 = board.create("point", [3, -1], {name: 'B'});
653          *        const point3 = board.create("point", [6, -1], { clip: false });
654          *
655          *        var sl = board.create('slider', [[-3, -6], [-1, -6], [-5, 1, 5]], {
656          *            clip: false,
657          *            size: 16,
658          *            face: '[]',
659          *            name: 's',
660          *            frozen: true
661          *        });
662          *
663          *        var graph = board.create("functiongraph", ['s.Value() * x^3'], { clip: true });
664          *
665          *     })();
666          *
667          * </script><pre>
668          *
669          */
670         appBox: function (box, attributes) {
671             var node, id, jxg_id, innerdiv,
672                 obb, bb, w, h,// rect,
673                 attr, board;
674 
675             if (!JXG.isBrowser) {
676                 throw new Error("JSXGraph: JXG.appBox needs a browser");
677             }
678             if (JXG.isString(box)) {
679                 // Hosting div is given as string
680                 node = document.getElementById(box);
681                 id = box;
682             } else {
683                 // Hosting div is given as object pointer
684                 node = box;
685                 id = box.getAttribute('id');
686             }
687 
688             innerdiv = document.createElement("div");
689 
690             attr = JXG.copyAttributes(attributes, JXG.Options, 'board').jxgbox;
691 
692             jxg_id = ((id !== null) ? id + '_' : '') + attr.id;
693             innerdiv.setAttribute('id', jxg_id);
694             innerdiv.className += 'jxgbox ';
695             innerdiv.className += attr.cssclass;
696             innerdiv.style = attr.style;
697 
698             obb = attr.outerbox;
699             if (obb !== null && JXG.isArray(obb)) {
700                 bb = JXG.copyAttributes(attributes, JXG.Options, 'board').boundingbox;
701                 node.style.position = 'relative';
702                 w = obb[2] - obb[0];
703                 h = obb[1] - obb[3];
704                 innerdiv.style.position = 'absolute';
705                 innerdiv.style.left = (100 * (bb[0] - obb[0]) / w) + '%';
706                 innerdiv.style.top = (100 * (obb[1] - bb[1]) / h) + '%';
707                 innerdiv.style.width = (100 * (bb[2] - bb[0]) / w) + '%';
708                 innerdiv.style.height = (100 * (bb[1] - bb[3]) / h) + '%';
709 
710                 // rect = node.getBoundingClientRect();
711                 // innerdiv.style.left = ((bb[0] - obb[0]) / w * rect.width) + 'px';
712                 // innerdiv.style.top = ((obb[1] - bb[1]) / h * rect.height) + 'px';
713                 // innerdiv.style.width = ((bb[2] - bb[0]) / w * rect.width) + 'px';
714                 // innerdiv.style.height = ((bb[1] - bb[3]) / h * rect.height) + 'px';
715             }
716 
717             node.appendChild(innerdiv);
718             attributes.moveTarget = node;
719 
720             board = this.board(innerdiv, attributes);
721 
722             innerdiv.style.overflow = 'visible';
723             if (board.renderer.type === 'svg') {
724                 board.renderer.svgRoot.style.overflow = 'visible';
725             } else {
726                 throw new Error("JSXGraph: JXG.appBox needs SVG renderer");
727             }
728 
729             return board;
730         },
731 
732         themes: {}
733     }
734 );
735 
736 export default jxg;
737