1 /*
  2     Copyright 2008-2022
  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.
 12 
 13     JSXGraph is free software dual licensed under the GNU LGPL or MIT License.
 14 
 15     You can redistribute it and/or modify it under the terms of the
 16 
 17       * GNU Lesser General Public License as published by
 18         the Free Software Foundation, either version 3 of the License, or
 19         (at your option) any later version
 20       OR
 21       * MIT License: https://github.com/jsxgraph/jsxgraph/blob/master/LICENSE.MIT
 22 
 23     JSXGraph is distributed in the hope that it will be useful,
 24     but WITHOUT ANY WARRANTY; without even the implied warranty of
 25     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 26     GNU Lesser General Public License for more details.
 27 
 28     You should have received a copy of the GNU Lesser General Public License and
 29     the MIT License along with JSXGraph. If not, see <http://www.gnu.org/licenses/>
 30     and <http://opensource.org/licenses/MIT/>.
 31  */
 32 
 33 /*global JXG: true, document: true*/
 34 /*jslint nomen: true, plusplus: true, regexp: true*/
 35 
 36 /* depends:
 37  */
 38 
 39 /**
 40  * JSXGraph namespace. Holds all classes, objects, functions and variables belonging to JSXGraph
 41  * to reduce the risk of interfering with other JavaScript code.
 42  * @namespace
 43  */
 44 var JXG = {},
 45     define;
 46 
 47 (function () {
 48 
 49     'use strict';
 50 
 51     //////////////////////////////////////////////////////////////////////////
 52     //// Set this constant to 'true' to add an timestamp to each imported ////
 53     //// file. This ensures that the most up-to-date files are always     ////
 54     //// used during development.                                         ////
 55     ////                                                                  ////
 56     ////             Attention! Slows down the loading time!              ////
 57     //////////////////////////////////////////////////////////////////////////
 58     var preventCachingFiles = true,
 59         // check and table are initialized at the end of the life
 60         table,
 61         waitlist = [],
 62         checkwaitlist = true,
 63         checkJXG = function () {
 64             return JXG;
 65         },
 66         makeCheck = function (s) {
 67             var a = s.split('.');
 68 
 69             return function () {
 70                 var i, r = JXG;
 71 
 72                 if (!r) {
 73                     return r;
 74                 }
 75 
 76                 for (i = 0; i < a.length; i++) {
 77                     r = r[a[i]];
 78                     if (!r) {
 79                         break;
 80                     }
 81                 }
 82 
 83                 return r;
 84             };
 85         };
 86 
 87     define = function (deps, factory) {
 88         var i, oldlength, undef,
 89             resDeps = [],
 90             inc = true;
 91 
 92         if (deps === undef) {
 93             deps = [];
 94         }
 95 
 96         window.wait = waitlist;
 97 
 98         if (factory === undef) {
 99             factory = function () {};
100         }
101 
102         for (i = 0; i < deps.length; i++) {
103             resDeps.push(table[deps[i]]());
104             if (!resDeps[i]) {
105                 inc = false;
106                 break;
107             }
108         }
109 
110         if (inc) {
111             factory.apply(this, resDeps);
112         } else if (checkwaitlist) {
113             waitlist.push([deps, factory]);
114         }
115 
116         if (checkwaitlist) {
117             // don't go through the waitlist while we're going through the waitlist
118             checkwaitlist = false;
119             oldlength = 0;
120 
121             // go through the waitlist until no more modules can be loaded
122             while (oldlength !== waitlist.length) {
123                 oldlength = waitlist.length;
124 
125                 // go through the waitlist, look if another module can be initialized
126                 for (i = 0; i < waitlist.length; i++) {
127                     if (define.apply(this, waitlist[i])) {
128                         waitlist.splice(i, 1);
129                     }
130                 }
131             }
132 
133             checkwaitlist = true;
134         }
135 
136         return inc;
137     };
138 
139     JXG.isMetroApp = function () {
140         return typeof window === 'object' && window.clientInformation && window.clientInformation.appVersion && window.clientInformation.appVersion.indexOf('MSAppHost') > -1;
141     };
142 
143     ////////////////////////////////////////////////////////////////////////////////
144     /////////////////////// this exists also in sketchometry ///////////////////////
145     ////////////////////////////////////////////////////////////////////////////////
146 
147     JXG.Load = (function () {
148         var requirePathLocation = 'href',
149         allowDocumentWrite = true;
150 
151         function createHTMLElement(tagName, attr) {
152             var el = document.createElement(tagName), i,
153                 a_name, a_value, a_object;
154 
155             for (i = 0; i < Object.keys(attr).length; i++) {
156                 a_name = Object.keys(attr)[i];
157                 a_value = attr[a_name];
158 
159                 a_object = document.createAttribute(a_name);
160                 a_object.nodeValue = a_value;
161                 el.setAttributeNode(a_object);
162             }
163 
164             return el;
165         }
166 
167         window.onload = function () {
168             allowDocumentWrite = false;
169         };
170 
171         return {
172             requirePath: window.location.href,
173 
174             setRequirePathToScriptFile: function (filename) {
175                 var scripts, reg, i, s, requirePath = '';
176 
177                 if (requirePathLocation === filename) {
178                     return;
179                 }
180 
181                 scripts = document.getElementsByTagName('script');
182                 reg = new RegExp(filename + '(\\?.*)?$');
183 
184                 for (i = 0; i < scripts.length; i++) {
185                     s = scripts[i];
186                     if (s.src && s.src.match(reg)) {
187                         requirePath = s.src.replace(reg, '');
188                         JXG.Load.requirePath = requirePath;
189                         requirePathLocation = filename;
190                         break;
191                     }
192                 }
193             },
194 
195             setRequirePathToHref: function () {
196                 JXG.Load.requirePath = window.location.href;
197                 requirePathLocation = 'href';
198             },
199 
200             JSfiles: function (fileArray, preventCaching, root) {
201                 var postfix = '', i, file;
202 
203                 preventCaching = preventCaching || false;
204                 if (preventCaching) {
205                     postfix = '?v=' + (new Date()).getTime();
206                 }
207                 root = root || JXG.Load.requirePath;
208                 if (root.substr(-1) !== '/') {
209                     root += '/';
210                 }
211 
212                 for (i = 0; i < fileArray.length; i++) {
213                     file = fileArray[i];
214 
215                     if (file.substr(-2) !== 'js') {
216                         file += '.js';
217                     }
218                     (function (include) {
219                         var src = root + include + postfix,
220                             el, head;
221                         if (JXG.isMetroApp() || !allowDocumentWrite) {
222                             el = createHTMLElement('script', {
223                                 type: 'text/javascript',
224                                 src: src,
225                             });
226                             head = document.getElementsByTagName('head')[0];
227                             head.appendChild(el);
228                         } else {
229                             // avoid inline code manipulation
230                             document.write('<script type="text/javascript" src="' + src + '"><\/script>');
231                         }
232                     }(file));
233                 }
234             },
235 
236             CSSfiles: function (fileArray, preventCaching, root) {
237                 var postfix = '', i, file;
238 
239                 preventCaching = preventCaching || false;
240                 if (preventCaching) {
241                     postfix = '?v=' + (new Date()).getTime();
242                 }
243                 root = root || JXG.Load.requirePath;
244                 if (root.substr(-1) !== '/') {
245                     root += '/';
246                 }
247 
248                 for (i = 0; i < fileArray.length; i++) {
249                     file = fileArray[i];
250 
251                     if (file.substr(-3) !== 'css') {
252                         file += '.css';
253                     }
254                     (function (include) {
255                         var href = root + include + postfix,
256                             el = createHTMLElement('link', {
257                                 rel: 'stylesheet',
258                                 type: 'text/javascript',
259                                 href: href,
260                             }),
261                             head = document.getElementsByTagName('head')[0];
262                         head.appendChild(el);
263                     }(file));
264                 }
265             },
266 
267             HTMLfileASYNC: function (file, innerHTMLof, doAfter, preventCaching, root) {
268                 var postfix = '';
269 
270                 doAfter = doAfter || function () {};
271                 preventCaching = preventCaching || false;
272                 if (preventCaching) {
273                     postfix = '?v=' + (new Date()).getTime();
274                 }
275                 root = root || JXG.Load.requirePath;
276                 if (root.substr(-1) !== '/') {
277                     root += '/';
278                 }
279 
280                 if (file.substr(-4) !== 'html') {
281                     file += '.html';
282                 }
283                 (function (include) {
284                     var url = root + include + postfix;
285 
286                     var xhr = new XMLHttpRequest();
287                     xhr.onreadystatechange = function () {
288                         if (xhr.readyState === 4) {
289                             if (xhr.status === 200) {
290                                 innerHTMLof.innerHTML = xhr.responseText;
291                                 doAfter();
292                             }
293                         }
294                     };
295 
296                     xhr.open('POST', url, true);
297                     xhr.send();
298                 }(file));
299             }
300         };
301     })();
302 
303     ////////////////////////////////////////////////////////////////////////////////
304     ///////////////////////////////////// end //////////////////////////////////////
305     ////////////////////////////////////////////////////////////////////////////////
306 
307     // Has to be a String for Makefile!
308     JXG.Load.baseFiles = 'jxg,base/constants,utils/type,utils/xml,utils/env,utils/event,utils/expect,utils/color,math/probfuncs,math/math,math/ia,math/extrapolate,math/numerics,math/nlp,math/plot,math/metapost,math/statistics,math/symbolic,math/geometry,math/clip,math/poly,math/complex,renderer/abstract,renderer/no,reader/file,parser/geonext,base/board,options,jsxgraph,base/element,base/coordselement,base/coords,base/point,base/line,base/group,base/circle,element/conic,base/polygon,base/curve,element/arc,element/sector,base/composition,element/composition,base/text,base/image,element/slider,element/measure,base/chart,base/transformation,base/turtle,base/ticks,utils/zip,utils/base64,utils/uuid,utils/encoding,server/server,element/locus,parser/datasource,parser/ca,parser/jessiecode,utils/dump,renderer/svg,renderer/vml,renderer/canvas,renderer/no,element/comb,element/slopetriangle,math/qdt,element/checkbox,element/input,element/button,base/foreignobject,options3d,3d/threed,3d/view3d,3d/point3d,3d/curve3d,3d/surface3d,3d/linspace3d,3d/box3d';
309     JXG.Load.setRequirePathToScriptFile('loadjsxgraph.js');
310     JXG.Load.JSfiles(JXG.Load.baseFiles.split(','), preventCachingFiles);
311     JXG.Load.baseFiles = null;
312     JXG.serverBase = JXG.Load.requirePath + 'server/';
313 
314     // This is a table with functions which check the availability
315     // of certain namespaces, functions and classes. With this structure
316     // we are able to get a rough check if a specific dependency is available.
317     table = {
318         'jsxgraph': checkJXG,
319         'jxg': checkJXG,
320         'options': makeCheck('Options'),
321 
322         'base/board': makeCheck('Board'),
323         'base/chart': checkJXG,
324         'base/circle': checkJXG,
325         'base/composition': makeCheck('Composition'),
326         'base/constants': checkJXG,
327         'base/coords': makeCheck('Coords'),
328         'base/coordselement': makeCheck('CoordsElement'),
329         'base/curve': checkJXG,
330         'base/element': makeCheck('GeometryElement'),
331         'base/group': checkJXG,
332         'base/image': checkJXG,
333         'base/line': checkJXG,
334         'base/point': checkJXG,
335         'base/polygon': checkJXG,
336         'base/text': checkJXG,
337         'base/ticks': checkJXG,
338         'base/transformation': checkJXG,
339         'base/turtle': checkJXG,
340 
341         'element/arc': checkJXG,
342         'element/centroid': checkJXG,
343         'element/composition': checkJXG,
344         'element/conic': checkJXG,
345         'element/locus': checkJXG,
346         'element/measure': checkJXG,
347         'element/sector': checkJXG,
348         'element/slider': checkJXG,
349         'element/square': checkJXG,
350         'element/triangle': checkJXG,
351         'element/checkbox': checkJXG,
352         'element/input': checkJXG,
353         'element/button': checkJXG,
354         'element/foreignobject': checkJXG,
355 
356         'math/bst': makeCheck('Math.BST'),
357         'math/qdt': makeCheck('Math.Quadtree'),
358         'math/complex': makeCheck('Complex'),
359         'math/geometry': makeCheck('Math.Geometry'),
360         'math/math': makeCheck('Math'),
361         'math/probfuncs': makeCheck('Math.ProbFuncs'),
362         'math/ia': makeCheck('Math.IntervalArithmetic'),
363         'math/extrapolate': makeCheck('Math.Extrapolate'),
364         'math/metapost': makeCheck('Math.Metapost'),
365         'math/numerics': makeCheck('Math.Numerics'),
366         'math/nlp': makeCheck('Math.Nlp'),
367         'math/plot': makeCheck('Math.Plot'),
368         'math/poly': makeCheck('Math.Poly'),
369         'math/statistics': makeCheck('Math.Statistics'),
370         'math/symbolic': makeCheck('Math.Symbolic'),
371 
372         'parser/datasource': makeCheck('DataSource'),
373         'parser/geonext': makeCheck('GeonextParser'),
374         'parser/ca': makeCheck('CA'),
375         'parser/jessiecode': makeCheck('JessieCode'),
376 
377         'reader/cinderella': makeCheck('CinderellaReader'),
378         'reader/file': makeCheck('FileReader'),
379         'reader/geogebra': makeCheck('GeogebraReader'),
380         'reader/geonext': makeCheck('GeonextReader'),
381         'reader/graph': makeCheck('GraphReader'),
382         'reader/intergeo': makeCheck('IntergeoReader'),
383         'reader/sketch': makeCheck('SketchReader'),
384         'reader/tracenpoche': makeCheck('TracenpocheReader'),
385 
386         'renderer/abstract': makeCheck('AbstractRenderer'),
387         'renderer/canvas': makeCheck('CanvasRenderer'),
388         'renderer/no': makeCheck('NoRenderer'),
389         'renderer/svg': makeCheck('SVGRenderer'),
390         'renderer/vml': makeCheck('VMLRenderer'),
391 
392         'server/server': makeCheck('Server'),
393 
394         'utils/base64': makeCheck('Util.Base64'),
395         'utils/color': checkJXG,
396         'utils/dump': makeCheck('Dump'),
397         'utils/encoding': makeCheck('Util.UTF8'),
398         'utils/env': checkJXG,
399         'utils/event': makeCheck('EventEmitter'),
400         'utils/expect': makeCheck('Expect'),
401         'utils/type': checkJXG,
402         'utils/uuid': makeCheck('Util'),
403         'utils/xml': makeCheck('XML'),
404         'utils/zip': makeCheck('Util'),
405 
406         '3d/threed': checkJXG,
407         '3d/view3d': checkJXG,
408         '3d/point3d': checkJXG,
409         '3d/curve3d': checkJXG,
410         '3d/surface3d': checkJXG,
411         '3d/linspace3d': checkJXG
412 
413     };
414 }());
415