1 /* 2 Copyright 2008-2021 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 60 // check and table are initialized at the end of the life 61 var table, 62 waitlist = [], 63 checkwaitlist = true, 64 checkJXG = function () { 65 return JXG; 66 }, 67 makeCheck = function (s) { 68 var a = s.split('.'); 69 70 return function () { 71 var i, r = JXG; 72 73 if (!r) { 74 return r; 75 } 76 77 for (i = 0; i < a.length; i++) { 78 r = r[a[i]]; 79 if (!r) { 80 break; 81 } 82 } 83 84 return r; 85 }; 86 }; 87 88 define = function (deps, factory) { 89 var i, oldlength, undef, 90 resDeps = [], 91 inc = true; 92 93 if (deps === undef) { 94 deps = []; 95 } 96 97 window.wait = waitlist; 98 99 if (factory === undef) { 100 factory = function () {}; 101 } 102 103 for (i = 0; i < deps.length; i++) { 104 resDeps.push(table[deps[i]]()); 105 if (!resDeps[i]) { 106 inc = false; 107 break; 108 } 109 } 110 111 if (inc) { 112 factory.apply(this, resDeps); 113 } else if (checkwaitlist) { 114 waitlist.push([deps, factory]); 115 } 116 117 if (checkwaitlist) { 118 // don't go through the waitlist while we're going through the waitlist 119 checkwaitlist = false; 120 oldlength = 0; 121 122 // go through the waitlist until no more modules can be loaded 123 while (oldlength !== waitlist.length) { 124 oldlength = waitlist.length; 125 126 // go through the waitlist, look if another module can be initialized 127 for (i = 0; i < waitlist.length; i++) { 128 if (define.apply(this, waitlist[i])) { 129 waitlist.splice(i, 1); 130 } 131 } 132 } 133 134 checkwaitlist = true; 135 } 136 137 return inc; 138 }; 139 140 JXG.isMetroApp = function () { 141 return typeof window === 'object' && window.clientInformation && window.clientInformation.appVersion && window.clientInformation.appVersion.indexOf('MSAppHost') > -1; 142 }; 143 144 //////////////////////////////////////////////////////////////////////////////// 145 /////////////////////// this exists also in sketchometry /////////////////////// 146 //////////////////////////////////////////////////////////////////////////////// 147 148 JXG.Load = (function () { 149 function createHTMLElement(tagName, attr) { 150 var el = document.createElement(tagName), i, 151 a_name, a_value, a_object; 152 153 for (i = 0; i < Object.keys(attr).length; i++) { 154 a_name = Object.keys(attr)[i]; 155 a_value = attr[a_name]; 156 157 a_object = document.createAttribute(a_name); 158 a_object.nodeValue = a_value; 159 el.setAttributeNode(a_object); 160 } 161 162 return el; 163 } 164 165 var allowDocumentWrite = true; 166 167 window.onload = function () { 168 allowDocumentWrite = false; 169 }; 170 171 var requirePathLocation = 'href'; 172 173 return { 174 requirePath: window.location.href, 175 176 setRequirePathToScriptFile: function (filename) { 177 var scripts, reg, i, s, requirePath = ''; 178 179 if (requirePathLocation === filename) { 180 return; 181 } 182 183 scripts = document.getElementsByTagName('script'); 184 reg = new RegExp(filename + '(\\?.*)?$'); 185 186 for (i = 0; i < scripts.length; i++) { 187 s = scripts[i]; 188 if (s.src && s.src.match(reg)) { 189 requirePath = s.src.replace(reg, ''); 190 JXG.Load.requirePath = requirePath; 191 requirePathLocation = filename; 192 break; 193 } 194 } 195 }, 196 197 setRequirePathToHref: function () { 198 JXG.Load.requirePath = window.location.href; 199 requirePathLocation = 'href'; 200 }, 201 202 JSfiles: function (fileArray, preventCaching, root) { 203 var postfix = '', i, file; 204 205 preventCaching = preventCaching || false; 206 if (preventCaching) { 207 postfix = '?v=' + (new Date()).getTime(); 208 } 209 root = root || JXG.Load.requirePath; 210 if (root.substr(-1) !== '/') { 211 root += '/'; 212 } 213 214 for (i = 0; i < fileArray.length; i++) { 215 file = fileArray[i]; 216 217 if (file.substr(-2) !== 'js') { 218 file += '.js'; 219 } 220 (function (include) { 221 var src = root + include + postfix, 222 el, head; 223 if (JXG.isMetroApp() || !allowDocumentWrite) { 224 el = createHTMLElement('script', { 225 type: 'text/javascript', 226 src: src, 227 }); 228 head = document.getElementsByTagName('head')[0]; 229 head.appendChild(el); 230 } else { 231 // avoid inline code manipulation 232 document.write('<script type="text/javascript" src="' + src + '"><\/script>'); 233 } 234 }(file)); 235 } 236 }, 237 238 CSSfiles: function (fileArray, preventCaching, root) { 239 var postfix = '', i, file; 240 241 preventCaching = preventCaching || false; 242 if (preventCaching) { 243 postfix = '?v=' + (new Date()).getTime(); 244 } 245 root = root || JXG.Load.requirePath; 246 if (root.substr(-1) !== '/') { 247 root += '/'; 248 } 249 250 for (i = 0; i < fileArray.length; i++) { 251 file = fileArray[i]; 252 253 if (file.substr(-3) !== 'css') { 254 file += '.css'; 255 } 256 (function (include) { 257 var href = root + include + postfix, 258 el = createHTMLElement('link', { 259 rel: 'stylesheet', 260 type: 'text/javascript', 261 href: href, 262 }), 263 head = document.getElementsByTagName('head')[0]; 264 head.appendChild(el); 265 }(file)); 266 } 267 }, 268 269 HTMLfileASYNC: function (file, innerHTMLof, doAfter, preventCaching, root) { 270 var postfix = ''; 271 272 doAfter = doAfter || function () {}; 273 preventCaching = preventCaching || false; 274 if (preventCaching) { 275 postfix = '?v=' + (new Date()).getTime(); 276 } 277 root = root || JXG.Load.requirePath; 278 if (root.substr(-1) !== '/') { 279 root += '/'; 280 } 281 282 if (file.substr(-4) !== 'html') { 283 file += '.html'; 284 } 285 (function (include) { 286 var url = root + include + postfix; 287 288 var xhr = new XMLHttpRequest(); 289 xhr.onreadystatechange = function () { 290 if (xhr.readyState === 4) { 291 if (xhr.status === 200) { 292 innerHTMLof.innerHTML = xhr.responseText; 293 doAfter(); 294 } 295 } 296 }; 297 298 xhr.open('POST', url, true); 299 xhr.send(); 300 }(file)); 301 }, 302 }; 303 })(); 304 305 //////////////////////////////////////////////////////////////////////////////// 306 ///////////////////////////////////// end ////////////////////////////////////// 307 //////////////////////////////////////////////////////////////////////////////// 308 309 // Has to be a String for Makefile! 310 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'; 311 JXG.Load.setRequirePathToScriptFile('loadjsxgraph.js'); 312 JXG.Load.JSfiles(JXG.Load.baseFiles.split(','), preventCachingFiles); 313 JXG.Load.baseFiles = null; 314 JXG.serverBase = JXG.Load.requirePath + 'server/'; 315 316 // This is a table with functions which check the availability 317 // of certain namespaces, functions and classes. With this structure 318 // we are able to get a rough check if a specific dependency is available. 319 table = { 320 'jsxgraph': checkJXG, 321 'jxg': checkJXG, 322 'options': makeCheck('Options'), 323 324 'base/board': makeCheck('Board'), 325 'base/chart': checkJXG, 326 'base/circle': checkJXG, 327 'base/composition': makeCheck('Composition'), 328 'base/constants': checkJXG, 329 'base/coords': makeCheck('Coords'), 330 'base/coordselement': makeCheck('CoordsElement'), 331 'base/curve': checkJXG, 332 'base/element': makeCheck('GeometryElement'), 333 'base/group': checkJXG, 334 'base/image': checkJXG, 335 'base/line': checkJXG, 336 'base/point': checkJXG, 337 'base/polygon': checkJXG, 338 'base/text': checkJXG, 339 'base/ticks': checkJXG, 340 'base/transformation': checkJXG, 341 'base/turtle': checkJXG, 342 343 'element/arc': checkJXG, 344 'element/centroid': checkJXG, 345 'element/composition': checkJXG, 346 'element/conic': checkJXG, 347 'element/locus': checkJXG, 348 'element/measure': checkJXG, 349 'element/sector': checkJXG, 350 'element/slider': checkJXG, 351 'element/square': checkJXG, 352 'element/triangle': checkJXG, 353 'element/checkbox': checkJXG, 354 'element/input': checkJXG, 355 'element/button': checkJXG, 356 'element/foreignobject': checkJXG, 357 358 'math/bst': makeCheck('Math.BST'), 359 'math/qdt': makeCheck('Math.Quadtree'), 360 'math/complex': makeCheck('Complex'), 361 'math/geometry': makeCheck('Math.Geometry'), 362 'math/math': makeCheck('Math'), 363 'math/probfuncs': makeCheck('Math.ProbFuncs'), 364 'math/ia': makeCheck('Math.IntervalArithmetic'), 365 'math/extrapolate': makeCheck('Math.Extrapolate'), 366 'math/metapost': makeCheck('Math.Metapost'), 367 'math/numerics': makeCheck('Math.Numerics'), 368 'math/nlp': makeCheck('Math.Nlp'), 369 'math/plot': makeCheck('Math.Plot'), 370 'math/poly': makeCheck('Math.Poly'), 371 'math/statistics': makeCheck('Math.Statistics'), 372 'math/symbolic': makeCheck('Math.Symbolic'), 373 374 'parser/datasource': makeCheck('DataSource'), 375 'parser/geonext': makeCheck('GeonextParser'), 376 'parser/ca': makeCheck('CA'), 377 'parser/jessiecode': makeCheck('JessieCode'), 378 379 'reader/cinderella': makeCheck('CinderellaReader'), 380 'reader/file': makeCheck('FileReader'), 381 'reader/geogebra': makeCheck('GeogebraReader'), 382 'reader/geonext': makeCheck('GeonextReader'), 383 'reader/graph': makeCheck('GraphReader'), 384 'reader/intergeo': makeCheck('IntergeoReader'), 385 'reader/sketch': makeCheck('SketchReader'), 386 'reader/tracenpoche': makeCheck('TracenpocheReader'), 387 388 'renderer/abstract': makeCheck('AbstractRenderer'), 389 'renderer/canvas': makeCheck('CanvasRenderer'), 390 'renderer/no': makeCheck('NoRenderer'), 391 'renderer/svg': makeCheck('SVGRenderer'), 392 'renderer/vml': makeCheck('VMLRenderer'), 393 394 'server/server': makeCheck('Server'), 395 396 'utils/base64': makeCheck('Util.Base64'), 397 'utils/color': checkJXG, 398 'utils/dump': makeCheck('Dump'), 399 'utils/encoding': makeCheck('Util.UTF8'), 400 'utils/env': checkJXG, 401 'utils/event': makeCheck('EventEmitter'), 402 'utils/expect': makeCheck('Expect'), 403 'utils/type': checkJXG, 404 'utils/uuid': makeCheck('Util'), 405 'utils/xml': makeCheck('XML'), 406 'utils/zip': makeCheck('Util') 407 }; 408 }()); 409