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.
 11 
 12     JSXGraph is free software dual licensed under the GNU LGPL or MIT License.
 13     
 14     You can redistribute it and/or modify it under the terms of the
 15     
 16       * GNU Lesser General Public License as published by
 17         the Free Software Foundation, either version 3 of the License, or
 18         (at your option) any later version
 19       OR
 20       * MIT License: https://github.com/jsxgraph/jsxgraph/blob/master/LICENSE.MIT
 21     
 22     JSXGraph is distributed in the hope that it will be useful,
 23     but WITHOUT ANY WARRANTY; without even the implied warranty of
 24     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 25     GNU Lesser General Public License for more details.
 26     
 27     You should have received a copy of the GNU Lesser General Public License and
 28     the MIT License along with JSXGraph. If not, see <http://www.gnu.org/licenses/>
 29     and <http://opensource.org/licenses/MIT/>.
 30  */
 31 
 32 
 33 /*global JXG: true, define: true, jQuery: true, window: true, document: true, navigator: true, require: true, module: true, console: true */
 34 /*jslint nomen:true, plusplus:true, forin:true*/
 35 
 36 /* depends:
 37  */
 38 
 39 /**
 40  * @fileoverview The JSXGraph object is defined in this file. JXG.JSXGraph controls all boards.
 41  * It has methods to create, save, load and free boards. Additionally some helper functions are
 42  * defined in this file directly in the JXG namespace.
 43  * @version 0.83
 44  */
 45 
 46 define([], function () {
 47 
 48     "use strict";
 49 
 50     var jxg = {};
 51 
 52     // make sure JXG.extend is not defined
 53     // If jsxgraph is loaded via loadjsxgraph.js, this is required, but JXG.extend will be undefined
 54     // If jsxgraph is compiled as an amd module, it is possible that another jsxgraph version is already loaded and we
 55     // therefore must not re-use the global JXG variable. But in this case JXG.extend will already be defined.
 56     // This is the reason for this check.
 57     if (typeof JXG === 'object' && !JXG.extend) {
 58         jxg = JXG;
 59     }
 60 
 61     // We need the following two methods "extend" and "shortcut" to create the JXG object via JXG.extend.
 62 
 63     /**
 64      * Copy all properties of the <tt>extension</tt> object to <tt>object</tt>.
 65      * @param {Object} object
 66      * @param {Object} extension
 67      * @param {Boolean} [onlyOwn=false] Only consider properties that belong to extension itself, not any inherited properties.
 68      * @param {Boolean} [toLower=false] If true the keys are convert to lower case. This is needed for visProp, see JXG#copyAttributes
 69      */
 70     jxg.extend = function (object, extension, onlyOwn, toLower) {
 71         var e, e2;
 72 
 73         onlyOwn = onlyOwn || false;
 74         toLower = toLower || false;
 75 
 76         // the purpose of this for...in loop is indeed to use hasOwnProperty only if the caller
 77         // explicitly wishes so.
 78         for (e in extension) {
 79             if (!onlyOwn || (onlyOwn && extension.hasOwnProperty(e))) {
 80                 if (toLower) {
 81                     e2 = e.toLowerCase();
 82                 } else {
 83                     e2 = e;
 84                 }
 85 
 86                 object[e2] = extension[e];
 87             }
 88         }
 89     };
 90 
 91     jxg.extend(jxg, /** @lends JXG */ {
 92         /**
 93          * Store a reference to every board in this central list. This will at some point
 94          * replace JXG.JSXGraph.boards.
 95          * @type Object
 96          */
 97         boards: {},
 98 
 99         /**
100          * Store the available file readers in this structure.
101          * @type Object
102          */
103         readers: {},
104 
105         /**
106          * Associative array that keeps track of all constructable elements registered
107          * via {@link JXG.JSXGraph.registerElement}.
108          * @type Object
109          */
110         elements: {},
111 
112         /**
113          * This registers a new construction element to JSXGraph for the construction via the {@link JXG.Board.create}
114          * interface.
115          * @param {String} element The elements name. This is case-insensitive, existing elements with the same name
116          * will be overwritten.
117          * @param {Function} creator A reference to a function taking three parameters: First the board, the element is
118          * to be created on, a parent element array, and an attributes object. See {@link JXG.createPoint} or any other
119          * <tt>JXG.create...</tt> function for an example.
120          */
121         registerElement: function (element, creator) {
122             element = element.toLowerCase();
123             this.elements[element] = creator;
124         },
125 
126         /**
127          * Register a file reader.
128          * @param {function} reader A file reader. This object has to provide two methods: <tt>prepareString()</tt>
129          * and <tt>read()</tt>.
130          * @param {Array} ext
131          */
132         registerReader: function (reader, ext) {
133             var i, e;
134 
135             for (i = 0; i < ext.length; i++) {
136                 e = ext[i].toLowerCase();
137 
138                 if (typeof this.readers[e] !== 'function') {
139                     this.readers[e] = reader;
140                 }
141             }
142         },
143 
144         /**
145          * Creates a shortcut to a method, e.g. {@link JXG.Board#createElement} is a shortcut to {@link JXG.Board#create}.
146          * Sometimes the target is undefined by the time you want to define the shortcut so we need this little helper.
147          * @param {Object} object The object the method we want to create a shortcut for belongs to.
148          * @param {String} fun The method we want to create a shortcut for.
149          * @returns {Function} A function that calls the given method.
150          */
151         shortcut: function (object, fun) {
152             return function () {
153                 return object[fun].apply(this, arguments);
154             };
155         },
156 
157         /**
158          * s may be a string containing the name or id of an element or even a reference
159          * to the element itself. This function returns a reference to the element. Search order: id, name.
160          * @param {JXG.Board} board Reference to the board the element belongs to.
161          * @param {String} s String or reference to a JSXGraph element.
162          * @returns {Object} Reference to the object given in parameter object
163          * @deprecated Use {@link JXG.Board#select}
164          */
165         getRef: function (board, s) {
166             return board.select(s);
167         },
168 
169         /**
170          * This is just a shortcut to {@link JXG.getRef}.
171          * @deprecated Use {@link JXG.Board#select}.
172          */
173         getReference: function (board, s) {
174             return board.select(s);
175         },
176 
177         /**
178          * Add something to the debug log. If available a JavaScript debug console is used. Otherwise
179          * we're looking for a HTML div with id "debug". If this doesn't exist, too, the output is omitted.
180          * @param s An arbitrary number of parameters.
181          * @see JXG#debugWST
182          */
183         debugInt: function (s) {
184             var i, p;
185 
186             for (i = 0; i < arguments.length; i++) {
187                 p = arguments[i];
188                 if (typeof window === 'object' && window.console && console.log) {
189                     console.log(p);
190                 } else if (typeof document === 'object' && document.getElementById('debug')) {
191                     document.getElementById('debug').innerHTML += p + "<br/>";
192                 }
193             }
194         },
195 
196         /**
197          * Add something to the debug log. If available a JavaScript debug console is used. Otherwise
198          * we're looking for a HTML div with id "debug". If this doesn't exist, too, the output is omitted.
199          * This method adds a stack trace (if available).
200          * @param s An arbitrary number of parameters.
201          * @see JXG#debug
202          */
203         debugWST: function (s) {
204             var e = new Error();
205 
206             jxg.debugInt.apply(this, arguments);
207 
208             if (e && e.stack) {
209                 jxg.debugInt('stacktrace');
210                 jxg.debugInt(e.stack.split('\n').slice(1).join('\n'));
211             }
212         },
213 
214         debugLine: function (s) {
215             var e = new Error();
216 
217             jxg.debugInt.apply(this, arguments);
218 
219             if (e && e.stack) {
220                 jxg.debugInt('Called from', e.stack.split('\n').slice(2, 3).join('\n'));
221             }
222         },
223 
224         /**
225          * Add something to the debug log. If available a JavaScript debug console is used. Otherwise
226          * we're looking for a HTML div with id "debug". If this doesn't exist, too, the output is omitted.
227          * @param s An arbitrary number of parameters.
228          * @see JXG#debugWST
229          * @see JXG#debugLine
230          * @see JXG#debugInt
231          */
232         debug: function (s) {
233             jxg.debugInt.apply(this, arguments);
234         }
235     });
236 
237     return jxg;
238 });
239