1 /* 2 Copyright 2008-2016 3 Matthias Ehmann, 4 Michael Gerhaeuser, 5 Carsten Miller, 6 Bianca Valentin, 7 Alfred Wassermann, 8 Peter Wilfahrt 9 10 This file is part of JSXGraph and JSXCompressor. 11 12 JSXGraph is free software dual licensed under the GNU LGPL or MIT License. 13 JSXCompressor is free software dual licensed under the GNU LGPL or Apache 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 OR 23 * Apache License Version 2.0 24 25 JSXGraph is distributed in the hope that it will be useful, 26 but WITHOUT ANY WARRANTY; without even the implied warranty of 27 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 28 GNU Lesser General Public License for more details. 29 30 You should have received a copy of the GNU Lesser General Public License, Apache 31 License, and the MIT License along with JSXGraph. If not, see 32 <http://www.gnu.org/licenses/>, <https://www.apache.org/licenses/LICENSE-2.0.html>, 33 and <http://opensource.org/licenses/MIT/>. 34 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 /* depends: 42 */ 43 44 /** 45 * @fileoverview The JSXGraph object is defined in this file. JXG.JSXGraph controls all boards. 46 * It has methods to create, save, load and free boards. Additionally some helper functions are 47 * defined in this file directly in the JXG namespace. 48 */ 49 50 define([], function () { 51 52 "use strict"; 53 54 /** 55 * JXG is the top object of JSXGraph and defines the namespace 56 */ 57 var jxg = {}; 58 59 // Make sure JXG.extend is not defined 60 // If jsxgraph is loaded via loadjsxgraph.js, this is required, but JXG.extend will be undefined 61 // If jsxgraph is compiled as an amd module, it is possible that another jsxgraph version is already loaded and we 62 // therefore must not re-use the global JXG variable. But in this case JXG.extend will already be defined. 63 // This is the reason for this check. 64 if (typeof JXG === 'object' && !JXG.extend) { 65 jxg = JXG; 66 } 67 68 // We need the following two methods "extend" and "shortcut" to create the JXG object via JXG.extend. 69 70 /** 71 * Copy all properties of the <tt>extension</tt> object to <tt>object</tt>. 72 * @param {Object} object 73 * @param {Object} extension 74 * @param {Boolean} [onlyOwn=false] Only consider properties that belong to extension itself, not any inherited properties. 75 * @param {Boolean} [toLower=false] If true the keys are convert to lower case. This is needed for visProp, see JXG#copyAttributes 76 */ 77 jxg.extend = function (object, extension, onlyOwn, toLower) { 78 var e, e2; 79 80 onlyOwn = onlyOwn || false; 81 toLower = toLower || false; 82 83 // the purpose of this for...in loop is indeed to use hasOwnProperty only if the caller 84 // explicitly wishes so. 85 for (e in extension) { 86 if (!onlyOwn || (onlyOwn && extension.hasOwnProperty(e))) { 87 if (toLower) { 88 e2 = e.toLowerCase(); 89 } else { 90 e2 = e; 91 } 92 93 object[e2] = extension[e]; 94 } 95 } 96 }; 97 98 jxg.extend(jxg, /** @lends JXG */ { 99 /** 100 * Store a reference to every board in this central list. This will at some point 101 * replace JXG.JSXGraph.boards. 102 * @type Object 103 */ 104 boards: {}, 105 106 /** 107 * Store the available file readers in this structure. 108 * @type Object 109 */ 110 readers: {}, 111 112 /** 113 * Associative array that keeps track of all constructable elements registered 114 * via {@link JXG.JSXGraph.registerElement}. 115 * @type Object 116 */ 117 elements: {}, 118 119 /** 120 * This registers a new construction element to JSXGraph for the construction via the {@link JXG.Board.create} 121 * interface. 122 * @param {String} element The elements name. This is case-insensitive, existing elements with the same name 123 * will be overwritten. 124 * @param {Function} creator A reference to a function taking three parameters: First the board, the element is 125 * to be created on, a parent element array, and an attributes object. See {@link JXG.createPoint} or any other 126 * <tt>JXG.create...</tt> function for an example. 127 */ 128 registerElement: function (element, creator) { 129 element = element.toLowerCase(); 130 this.elements[element] = creator; 131 }, 132 133 /** 134 * Register a file reader. 135 * @param {function} reader A file reader. This object has to provide two methods: <tt>prepareString()</tt> 136 * and <tt>read()</tt>. 137 * @param {Array} ext 138 */ 139 registerReader: function (reader, ext) { 140 var i, e; 141 142 for (i = 0; i < ext.length; i++) { 143 e = ext[i].toLowerCase(); 144 145 if (typeof this.readers[e] !== 'function') { 146 this.readers[e] = reader; 147 } 148 } 149 }, 150 151 /** 152 * Creates a shortcut to a method, e.g. {@link JXG.Board#createElement} is a shortcut to {@link JXG.Board#create}. 153 * Sometimes the target is undefined by the time you want to define the shortcut so we need this little helper. 154 * @param {Object} object The object the method we want to create a shortcut for belongs to. 155 * @param {String} fun The method we want to create a shortcut for. 156 * @returns {Function} A function that calls the given method. 157 */ 158 shortcut: function (object, fun) { 159 return function () { 160 return object[fun].apply(this, arguments); 161 }; 162 }, 163 164 /** 165 * s may be a string containing the name or id of an element or even a reference 166 * to the element itself. This function returns a reference to the element. Search order: id, name. 167 * @param {JXG.Board} board Reference to the board the element belongs to. 168 * @param {String} s String or reference to a JSXGraph element. 169 * @returns {Object} Reference to the object given in parameter object 170 * @deprecated Use {@link JXG.Board#select} 171 */ 172 getRef: function (board, s) { 173 jxg.deprecated('JXG.getRef()', 'Board.select()'); 174 return board.select(s); 175 }, 176 177 /** 178 * This is just a shortcut to {@link JXG.getRef}. 179 * @deprecated Use {@link JXG.Board#select}. 180 */ 181 getReference: function (board, s) { 182 jxg.deprecated('JXG.getReference()', 'Board.select()'); 183 return board.select(s); 184 }, 185 186 /** 187 * s may be the string containing the id of an HTML tag that hosts a JSXGraph board. 188 * This function returns the reference to the board. 189 * @param {String} s String of an HTML tag that hosts a JSXGraph board 190 * @returns {Object} Reference to the board or null. 191 */ 192 getBoardByContainerId: function(s) { 193 var b; 194 for (b in JXG.boards) { 195 if (JXG.boards.hasOwnProperty(b) && 196 JXG.boards[b].container === s) { 197 return JXG.boards[b]; 198 } 199 } 200 201 return null; 202 }, 203 204 /** 205 * This method issues a warning to the developer that the given function is deprecated 206 * and, if available, offers an alternative to the deprecated function. 207 * @param {String} what Describes the function that is deprecated 208 * @param {String} [replacement] The replacement that should be used instead. 209 */ 210 deprecated: function (what, replacement) { 211 var warning = what + ' is deprecated.'; 212 213 if (replacement) { 214 warning += ' Please use ' + replacement + ' instead.'; 215 } 216 217 jxg.warn(warning); 218 }, 219 220 /** 221 * Outputs a warning via console.warn(), if available. If console.warn() is 222 * unavailable this function will look for an HTML element with the id 'warning' 223 * and append the warning to this element's innerHTML. 224 * @param {String} warning The warning text 225 */ 226 warn: function (warning) { 227 if (typeof window === 'object' && window.console && console.warn) { 228 console.warn('WARNING:', warning); 229 } else if (typeof document === 'object' && document.getElementById('warning')) { 230 document.getElementById('debug').innerHTML += 'WARNING: ' + warning + '<br />'; 231 } 232 }, 233 234 /** 235 * Add something to the debug log. If available a JavaScript debug console is used. Otherwise 236 * we're looking for a HTML div with id "debug". If this doesn't exist, too, the output is omitted. 237 * @param s An arbitrary number of parameters. 238 * @see JXG#debugWST 239 */ 240 debugInt: function (s) { 241 var i, p; 242 243 for (i = 0; i < arguments.length; i++) { 244 p = arguments[i]; 245 if (typeof window === 'object' && window.console && console.log) { 246 console.log(p); 247 } else if (typeof document === 'object' && document.getElementById('debug')) { 248 document.getElementById('debug').innerHTML += p + "<br/>"; 249 } 250 } 251 }, 252 253 /** 254 * Add something to the debug log. If available a JavaScript debug console is used. Otherwise 255 * we're looking for a HTML div with id "debug". If this doesn't exist, too, the output is omitted. 256 * This method adds a stack trace (if available). 257 * @param s An arbitrary number of parameters. 258 * @see JXG#debug 259 */ 260 debugWST: function (s) { 261 var e = new Error(); 262 263 jxg.debugInt.apply(this, arguments); 264 265 if (e && e.stack) { 266 jxg.debugInt('stacktrace'); 267 jxg.debugInt(e.stack.split('\n').slice(1).join('\n')); 268 } 269 }, 270 271 debugLine: function (s) { 272 var e = new Error(); 273 274 jxg.debugInt.apply(this, arguments); 275 276 if (e && e.stack) { 277 jxg.debugInt('Called from', e.stack.split('\n').slice(2, 3).join('\n')); 278 } 279 }, 280 281 /** 282 * Add something to the debug log. If available a JavaScript debug console is used. Otherwise 283 * we're looking for a HTML div with id "debug". If this doesn't exist, too, the output is omitted. 284 * @param s An arbitrary number of parameters. 285 * @see JXG#debugWST 286 * @see JXG#debugLine 287 * @see JXG#debugInt 288 */ 289 debug: function (s) { 290 jxg.debugInt.apply(this, arguments); 291 } 292 }); 293 294 return jxg; 295 }); 296