      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