1 /*
  2     Copyright 2008-2013
  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             return board.select(s);
174         },
175 
176         /**
177          * This is just a shortcut to {@link JXG.getRef}.
178          * @deprecated Use {@link JXG.Board#select}.
179          */
180         getReference: function (board, s) {
181             return board.select(s);
182         },
183 
184         /**
185          * Add something to the debug log. If available a JavaScript debug console is used. Otherwise
186          * we're looking for a HTML div with id "debug". If this doesn't exist, too, the output is omitted.
187          * @param s An arbitrary number of parameters.
188          * @see JXG#debugWST
189          */
190         debugInt: function (s) {
191             var i, p;
192 
193             for (i = 0; i < arguments.length; i++) {
194                 p = arguments[i];
195                 if (typeof window === 'object' && window.console && console.log) {
196                     console.log(p);
197                 } else if (typeof document === 'object' && document.getElementById('debug')) {
198                     document.getElementById('debug').innerHTML += p + "<br/>";
199                 }
200             }
201         },
202 
203         /**
204          * Add something to the debug log. If available a JavaScript debug console is used. Otherwise
205          * we're looking for a HTML div with id "debug". If this doesn't exist, too, the output is omitted.
206          * This method adds a stack trace (if available).
207          * @param s An arbitrary number of parameters.
208          * @see JXG#debug
209          */
210         debugWST: function (s) {
211             var e = new Error();
212 
213             jxg.debugInt.apply(this, arguments);
214 
215             if (e && e.stack) {
216                 jxg.debugInt('stacktrace');
217                 jxg.debugInt(e.stack.split('\n').slice(1).join('\n'));
218             }
219         },
220 
221         debugLine: function (s) {
222             var e = new Error();
223 
224             jxg.debugInt.apply(this, arguments);
225 
226             if (e && e.stack) {
227                 jxg.debugInt('Called from', e.stack.split('\n').slice(2, 3).join('\n'));
228             }
229         },
230 
231         /**
232          * Add something to the debug log. If available a JavaScript debug console is used. Otherwise
233          * we're looking for a HTML div with id "debug". If this doesn't exist, too, the output is omitted.
234          * @param s An arbitrary number of parameters.
235          * @see JXG#debugWST
236          * @see JXG#debugLine
237          * @see JXG#debugInt
238          */
239         debug: function (s) {
240             jxg.debugInt.apply(this, arguments);
241         }
242     });
243 
244     return jxg;
245 });
246