Subversion Repositories wimsdev

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
4897 bpr 1
/*
2
    Copyright 2008 - 2011
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: you can redistribute it and/or modify
13
    it under the terms of the GNU Lesser General Public License as published by
14
    the Free Software Foundation, either version 3 of the License, or
15
    (at your option) any later version.
16
 
17
    JSXGraph is distributed in the hope that it will be useful,
18
    but WITHOUT ANY WARRANTY; without even the implied warranty of
19
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20
    GNU Lesser General Public License for more details.
21
 
22
    You should have received a copy of the GNU Lesser General Public License
23
    along with JSXGraph.  If not, see <http://www.gnu.org/licenses/>.
24
*/
25
JXG.GeonextReader = {
26
 
27
    changeOriginIds: function (board, id) {
28
        if ((id == 'gOOe0') || (id == 'gXOe0') || (id == 'gYOe0') || (id == 'gXLe0') || (id == 'gYLe0')) {
29
            return board.id + id;
30
        } else {
31
            return id;
32
        }
33
    },
34
 
35
    /**
36
     * Retrieves data by TagName from an XML node.
37
     * @param {Node} node The Node that contains the data we want to get.
38
     * @param {String} tag The Name of the tag we are looking for.
39
     * @param {Number} [idx=0] getElementsByTagName returns an array; This parameter decides which element to use.
40
     * @param {Boolean} [fc=true] If True, the result will be the <tt>data</tt> of <tt>firstChild</tt> instead of the result node.
41
     * @returns {String} The gathered data
42
     */
43
    gEBTN: function (node, tag, idx, fc) {
44
        var tmp;
45
 
46
        if (!JXG.exists(node || !node.getElementsByTagName )/* || !JXG.exists(node.getElementsByTagName)*/) {
47
            return '';
48
        }
49
        // Default values for optional parameters idx and fc
50
        if (!JXG.exists(fc)) {
51
            fc = true;
52
        }
53
        idx = idx || 0;
54
        tmp = node.getElementsByTagName(tag);
55
        if (tmp.length > 0) {
56
            tmp = tmp[idx];
57
            if (fc && tmp.firstChild) {
58
                tmp = tmp.firstChild.data;
59
            }
60
        }
61
        return tmp;
62
    },
63
 
64
    /**
65
     * Set color properties of a geonext element.
66
     * Set stroke, fill, lighting, label and draft color attributes.
67
     * @param {Object} gxtEl element of which attributes are to set
68
     */
69
    colorProperties: function (gxtEl, Data) {
70
        var color = this.gEBTN(Data, 'color', 0, false),
71
            rgbo;
72
 
73
        //gxtEl.strokewidth = Data.getElementsByTagName('strokewidth')[0].firstChild.data;
74
        // colorStroke = strokeColor etc. is here for downwards compatibility:
75
        // once upon a time we used to create elements in here using the "new JXG.Element" constructor mechanism
76
        // then we changed to board.create + setProperty afterwords
77
        // now i want to use the board.create method with an appropriate attributes object to avoid setProperty calls
78
        // and as gxtEl happens to be somewhat like an attributes object it's  just slightly different so we adjust it
79
        // for downwards compatibility during the transformation of this reader we use both properties
80
 
81
        rgbo = JXG.rgba2rgbo(this.gEBTN(color, 'stroke'));
82
        gxtEl.strokeColor = rgbo[0];
83
        gxtEl.strokeOpacity = rgbo[1];
84
 
85
        rgbo = JXG.rgba2rgbo(this.gEBTN(color, 'lighting'));
86
        gxtEl.highlightStrokeColor = rgbo[0];
87
        gxtEl.highlightStrokeOpacity = rgbo[1];
88
 
89
        rgbo = JXG.rgba2rgbo(this.gEBTN(color, 'fill'));
90
        gxtEl.fillColor = rgbo[0];
91
        gxtEl.fillOpacity = rgbo[1];
92
 
93
        gxtEl.highlightFillColor = gxtEl.fillColor;
94
        gxtEl.highlightFillOpacity = gxtEl.fillOpacity;
95
 
96
        gxtEl.labelColor = JXG.rgba2rgbo(this.gEBTN(color, 'label'))[0];
97
        gxtEl.colorDraft = JXG.rgba2rgbo(this.gEBTN(color, 'draft'))[0];
98
 
99
        // GEONExT hides labels by setting opacity to 0.
100
        if (JXG.rgba2rgbo(this.gEBTN(color, 'label'))[1]==0) {
101
            gxtEl.withLabel = false;
102
        }
103
 
104
        // backwards compatibility
105
        gxtEl.colorStroke = gxtEl.strokeColor;
106
        gxtEl.colorFill = gxtEl.fillColor;
107
        gxtEl.colorLabel = gxtEl.labelColor;
108
 
109
        return gxtEl;
110
    },
111
 
112
    firstLevelProperties: function (gxtEl, Data) {
113
        if (!JXG.exists(Data) || !JXG.exists(Data.childNodes))
114
            return gxtEl;
115
 
116
        var arr = Data.childNodes, n, key;
117
 
118
        for (n = 0; n < arr.length; n++) {
119
            if (JXG.exists(arr[n].firstChild) && arr[n].nodeName !== 'data' && arr[n].nodeName !== 'straight') {
120
                key = arr[n].nodeName;
121
                gxtEl[key] = arr[n].firstChild.data;
122
            }
123
        }
124
 
125
        return gxtEl;
126
    },
127
 
128
    /**
129
     * Set the defining properties of a geonext element.
130
     * Writing the nodeName to ident; setting the name attribute and defining the element id.
131
     * @param {Object} gxtEl element of which attributes are to set
132
     */
133
    defProperties: function (gxtEl, Data) {
134
        // 3==TEXT_NODE, 8==COMMENT_NODE
135
        if (Data.nodeType==3 || Data.nodeType==8 ) {
136
            return null;
137
        }
138
 
139
        gxtEl.ident = Data.nodeName;
140
 
141
        if(gxtEl.ident == "text" || gxtEl.ident == "intersection" || gxtEl.ident == "composition") {
142
            gxtEl.name = '';
143
        } else {
144
            gxtEl.name = this.gEBTN(Data, 'name');
145
        }
146
 
147
        gxtEl.id = this.gEBTN(Data, 'id');
148
 
149
        return gxtEl;
150
    },
151
 
152
    visualProperties: function (gxtEl, Data) {
153
        gxtEl.visible = JXG.str2Bool(this.gEBTN(Data, 'visible'));
154
        gxtEl.trace = JXG.str2Bool(this.gEBTN(Data, 'trace'));
155
 
156
        return gxtEl;
157
    },
158
 
159
    transformProperties: function (gxtEl, type) {
160
        var facemap = [
161
                // 0-2
162
                'cross', 'cross', 'cross',
163
                // 3-6
164
                'circle', 'circle', 'circle', 'circle',
165
                // 7-9
166
                'square', 'square', 'square',
167
                // 10-12
168
                'plus', 'plus', 'plus'
169
            ], sizemap = [
170
                // 0-2
171
                2, 3, 4,
172
                // 3-6
173
                1, 2, 3, 4,
174
                // 7-9
175
                2, 3, 4,
176
                // 10-12
177
                2, 3, 4
178
            ];
179
 
180
        gxtEl.strokeWidth = gxtEl.strokewidth;
181
        gxtEl.face = facemap[parseInt(gxtEl.style, 10)] || 'cross';
182
        gxtEl.size = sizemap[parseInt(gxtEl.style, 10)] || 3;
183
 
184
        gxtEl.straightFirst = JXG.str2Bool(gxtEl.straightFirst);
185
        gxtEl.straightLast = JXG.str2Bool(gxtEl.straightLast);
186
 
187
        gxtEl.visible = JXG.str2Bool(gxtEl.visible);
188
        //gxtEl.withLabel = gxtEl.visible;           // withLabel is set in colorProperties()
189
        gxtEl.draft = JXG.str2Bool(gxtEl.draft);
190
        gxtEl.trace = JXG.str2Bool(gxtEl.trace);
191
 
192
        if (type==='point') {
193
            // Fill properties are ignored by GEONExT
194
            gxtEl.fillColor = gxtEl.strokeColor;
195
            gxtEl.highlightFillColor = gxtEl.highlightStrokeColor;
196
            gxtEl.fillOpacity = gxtEl.strokeOpacity;
197
            gxtEl.highlightFillOpacity = gxtEl.highlightStrokeOpacity;
198
        }
199
 
200
        delete gxtEl.color;
201
        return gxtEl;
202
    },
203
 
204
    readNodes: function (gxtEl, Data, nodeType, prefix) {
205
        var arr = this.gEBTN(Data, nodeType, 0, false).childNodes,
206
            key, n;
207
 
208
        for (n = 0; n < arr.length; n++) {
209
            if (arr[n].firstChild != null) {
210
                if (prefix != null) {
211
                    key = prefix + JXG.capitalize(arr[n].nodeName);
212
                } else {
213
                    key = arr[n].nodeName;
214
                }
215
                gxtEl[key] = arr[n].firstChild.data;
216
            }
217
        }
218
        return gxtEl;
219
    },
220
 
221
    subtreeToString: function (root) {
222
        try {
223
            // firefox
224
            return (new XMLSerializer()).serializeToString(root);
225
        } catch (e) {
226
            // IE
227
            return root.xml;
228
        }
229
    },
230
 
231
    readImage: function (node) {
232
        var pic = '',
233
            nod = node;
234
 
235
        if (nod != null) {
236
            pic = nod.data;
237
            while (nod.nextSibling != null) {
238
                nod = nod.nextSibling;
239
                pic += nod.data;
240
            }
241
        }
242
        return pic;
243
    },
244
 
245
    parseImage: function (board, fileNode, level, x, y, w, h, el) {
246
        var tag, id, im, picStr, tmpImg;
247
 
248
        if (fileNode == null) {
249
            return null;
250
        }
251
 
252
        if (fileNode.getElementsByTagName('src')[0] != null) {  // Background image
253
            tag = 'src';
254
        } else if (fileNode.getElementsByTagName('image')[0] != null) {
255
            tag = 'image';
256
        } else {
257
            return null;
258
        }
259
 
260
        picStr = this.readImage(this.gEBTN(fileNode, tag, 0, false).firstChild);
261
        if (picStr!='') {
262
            picStr = 'data:image/png;base64,' + picStr;
263
            if (tag=='src') {  // Background image
264
                x = this.gEBTN(fileNode, 'x');
265
                y = this.gEBTN(fileNode, 'y');
266
                w = this.gEBTN(fileNode, 'width');
267
                h = this.gEBTN(fileNode, 'height');
268
                im = board.create('image', [picStr,[x, y],[w, h]], {
269
                        anchor: el, layer: level
270
                        });
271
                return im;
272
            } else {
273
                // Image bound to an element
274
                // Read the original dimensions, i.e. the ratio h/w with the help of a temporary image.
275
                // We have to wait until the image is loaded, therefore
276
                // we need "onload".
277
                tmpImg = new Image();
278
                tmpImg.src = picStr;
279
                id = el.id + '_image';
280
                tmpImg.onload = function(){
281
                    // Now, we can read the original dimensions of the image.
282
                    var wOrg = this.width,
283
                        hOrg = this.height,
284
                        xf, yf, wf, hf, im, tRot;
285
 
286
                    if (el.elementClass == JXG.OBJECT_CLASS_LINE) {
287
                        // A line containing an image, runs through the horizontal middle
288
                        // of the image.
289
                        xf = function(){ return el.point1.X(); };
290
                        wf = function(){ return el.point1.Dist(el.point2); };
291
                        hf = function(){ return wf() * hOrg / wOrg; };
292
                        yf = function(){ return el.point1.Y() - hf() * 0.5; };
293
                        im = board.create('image', [picStr, [xf,yf], [wf,hf]], {
294
                                layer: level,
295
                                id: id,
296
                                anchor: el
297
                            });
298
                        tRot = board.create('transform', [
299
                                function () {
300
                                    return Math.atan2(el.point2.Y()-el.point1.Y(), el.point2.X()-el.point1.X())
301
                                },
302
                                el.point1
303
                            ], {
304
                                type:'rotate'
305
                            });
306
                        tRot.bindTo(im);
307
                        el.image = im;
308
                    } else if (el.elementClass == JXG.OBJECT_CLASS_POINT) {
309
                        wf = function(){ return wOrg / board.unitX; };
310
                        hf = function(){ return hOrg / board.unitY; };
311
                        xf = function(){ return el.X() - wf() * 0.5; };
312
                        yf = function(){ return el.Y() - hf() * 0.5; };
313
 
314
                        im = board.create('image', [picStr, [xf,yf], [wf,hf]], {
315
                                layer: level,
316
                                id: id,
317
                                anchor: el
318
                            });
319
                        board.renderer.hide(el.label.content);
320
                        el.image = im;
321
                    } else if (el.elementClass == JXG.OBJECT_CLASS_CIRCLE) {
322
                        // A circle containing an image
323
                        wf = function(){ return 2.0 * el.Radius(); };
324
                        hf = function(){ return wf() * hOrg / wOrg; };
325
                        xf = function(){ return el.midpoint.X() - wf() * 0.5; };
326
                        yf = function(){ return el.midpoint.Y() - hf() * 0.5; };
327
                        im = board.create('image', [picStr, [xf,yf], [wf,hf]], {
328
                            layer: level,
329
                            id: id,
330
                            anchor: el
331
                        });
332
                        el.image = im;
333
                    } else {
334
                        im = board.create('image', [picStr, [x, y], [w, h]], {
335
                            layer: level,
336
                            id: id,
337
                            anchor: el
338
                        });
339
                        el.image = im;
340
                    }
341
                };
342
            }
343
            return im;
344
        }
345
    },
346
 
347
    readConditions: function(node) {
348
        var i, s, ob,
349
            conditions = '';
350
 
351
        if (JXG.exists(node)) {
352
            for(i = 0; i < node.getElementsByTagName('data').length; i++) {
353
                ob = node.getElementsByTagName('data')[i];
354
                s = this.subtreeToString(ob);
355
                conditions += s;
356
            }
357
        }
358
 
359
        return conditions;
360
    },
361
 
362
    printDebugMessage: function(outputEl,gxtEl,nodetyp,success) {
363
        JXG.debug("* " + success + ":  " + nodetyp + " " + gxtEl.name + " " + gxtEl.id + "<br>\n");
364
    },
365
 
366
    /**
367
     * Reading the elements of a geonext file
368
     * @param {XMLTree} tree expects the content of the parsed geonext file returned by function parseFF/parseIE
369
     * @param {Object} board board object
370
     */
371
    readGeonext: function(tree, board) {
372
        var xmlNode, elChildNodes,
373
            s, Data, inter, boardData, el,
374
            conditions, tmp, strTrue = 'true', gxtReader = this;
375
 
376
        // maybe this is not necessary as we already provide layer options for sectors and circles via JXG.Options but
377
        // maybe these have to be the same for geonext.
378
        board.options.layer.sector = board.options.layer.angle;
379
        board.options.layer.circle = board.options.layer.angle;
380
 
381
        boardData = this.gEBTN(tree, 'board', 0, false);
382
        conditions = this.readConditions(boardData.getElementsByTagName('conditions')[0]);
383
 
384
        // set the origin
385
        xmlNode = this.gEBTN(boardData, 'coordinates', 0, false);
386
        tmp = this.gEBTN(xmlNode, 'origin', 0, false);
387
        board.origin = {
388
            usrCoords: [1, 0, 0],
389
            scrCoords: [1, parseFloat(this.gEBTN(tmp, 'x')), parseFloat(this.gEBTN(tmp, 'y'))]
390
        };
391
 
392
        // zoom level
393
        tmp = this.gEBTN(xmlNode, 'zoom', 0, false);
394
        board.zoomX = parseFloat(this.gEBTN(tmp, 'x'));
395
        board.zoomY = parseFloat(this.gEBTN(tmp, 'y'));
396
 
397
        // screen to user coordinates conversion
398
        tmp = this.gEBTN(xmlNode, 'unit', 0, false);
399
        board.unitX = parseFloat(this.gEBTN(tmp, 'x'));
400
        board.unitY = parseFloat(this.gEBTN(tmp, 'y'));
401
 
402
        // resize board
403
        if (board.options.takeSizeFromFile) {
404
            board.resizeContainer(this.gEBTN(boardData, 'width'), this.gEBTN(boardData, 'height'));
405
        }
406
 
407
        // check and set fontSize
408
        if (!(parseFloat(board.options.text.fontSize) > 0)) {
409
            board.options.text.fontSize = 12;
410
        }
411
 
412
        board.geonextCompatibilityMode = true;
413
 
414
        // jsxgraph chooses an id for the board but we don't want to use it, we want to use
415
        // the id stored in the geonext file. if you know why this is required, please note it here.
416
        delete(JXG.JSXGraph.boards[board.id]);
417
        board.id = this.gEBTN(boardData, 'id');
418
        JXG.JSXGraph.boards[board.id] = board;
419
 
420
        // this creates some basic elements present in every geonext construction but not explicitly present in the file
421
        board.initGeonextBoard();
422
 
423
        // Update of properties during update() is not necessary in GEONExT files
424
        // But it maybe necessary if we construct with JavaScript afterwards
425
        board.renderer.enhancedRendering = true;
426
 
427
        // Read background image
428
        this.parseImage(board, this.gEBTN(boardData, 'file', 0, false), board.options.layer['image']);
429
 
430
        board.options.grid.snapToGrid = (this.gEBTN(this.gEBTN(boardData, 'coordinates', 0, false), 'snap') == strTrue);
431
        //
432
        // TODO: Missing jsxgraph feature snapToPoint
433
        // If snapToGrid and snapToPoint are both true, point snapping is enabled
434
        if (board.options.grid.snapToGrid && this.gEBTN(this.gEBTN(boardData, 'grid', 1, false), 'pointsnap') == strTrue) {
435
            board.options.grid.snapToGrid = false;
436
        }
437
//board.options.grid.snapToGrid = false;
438
 
439
        xmlNode = this.gEBTN(boardData, 'grid', 1, false);
440
        tmp = this.gEBTN(xmlNode,  'x');
441
        if (tmp) {
442
            board.options.grid.gridX = 1 / parseFloat(tmp);
443
            board.options.grid.snapSizeX = parseFloat(tmp);
444
        }
445
        tmp = this.gEBTN(xmlNode,  'y');
446
        if (tmp) {
447
            board.options.grid.gridY = 1 / parseFloat(tmp);
448
            board.options.grid.snapSizeY = parseFloat(tmp);
449
        }
450
        //board.calculateSnapSizes();             // Seems not to be correct
451
        board.options.grid.gridDash = JXG.str2Bool(this.gEBTN(xmlNode, 'dash'));
452
 
453
        tmp = JXG.rgba2rgbo(this.gEBTN(xmlNode, 'color'));
454
        board.options.grid.gridColor = tmp[0];
455
        board.options.grid.gridOpacity = tmp[1];
456
 
457
        xmlNode = this.gEBTN(boardData, 'coordinates', 0, false);
458
        if (this.gEBTN(xmlNode, 'grid') == strTrue) {
459
            board.create('grid', []);
460
        }
461
 
462
        if (this.gEBTN(xmlNode, 'coord') == strTrue) {
463
            board.options.axis.ticks.majorHeight = 10;        // Hard coded default option
464
            board.options.axis.ticks.minorHeight = 4;         // Hard coded default option
465
            board.create('axis', [[0, 0], [1, 0]]);
466
            board.create('axis', [[0, 0], [0, 1]]);
467
        }
468
 
469
        board.containerObj.style.backgroundColor = JXG.rgba2rgbo(this.gEBTN(this.gEBTN(boardData, 'background', 0, false), 'color'))[0];
470
 
471
        elChildNodes = tree.getElementsByTagName("elements")[0].childNodes;
472
        for (s = 0; s < elChildNodes.length; s++) {
473
            (function (s) {
474
                var i, gxtEl = {},
475
                    l, x, y, w, h, c, numberDefEls,
476
                    el, p, inter, rgbo, tmp;
477
 
478
                Data = elChildNodes[s];
479
                gxtEl = gxtReader.defProperties(gxtEl, Data);
480
 
481
                // Skip text nodes
482
                if (!JXG.exists(gxtEl)) {
483
                    return;
484
                }
485
 
486
                gxtReader.printDebugMessage('debug', gxtEl, Data.nodeName.toLowerCase, 'READ:');
487
                switch (Data.nodeName.toLowerCase()) {
488
                    case "point":
489
                        gxtEl = gxtReader.colorProperties(gxtEl, Data);
490
                        gxtEl = gxtReader.visualProperties(gxtEl, Data);
491
                        gxtEl = gxtReader.firstLevelProperties(gxtEl, Data);
492
                        gxtEl = gxtReader.readNodes(gxtEl, Data, 'data');
493
                        gxtEl.fixed = JXG.str2Bool(gxtReader.gEBTN(Data, 'fix'));
494
                        gxtEl = gxtReader.transformProperties(gxtEl, 'point');
495
 
496
                        //try {
497
                            p = board.create('point', [parseFloat(gxtEl.x), parseFloat(gxtEl.y)], gxtEl);
498
 
499
                            var v = function(){ return p.visProp.visible; };
500
                            el = gxtReader.parseImage(board, Data, board.options.layer['image'], 0, 0, 0, 0, p);
501
                            gxtReader.printDebugMessage('debug', gxtEl, Data.nodeName, 'OK');
502
                        /*
503
                        if (JXG.exists(el)) {
504
                            el.visProp.visible = function() { return p.visProp.visible; };
505
                            alert(p.visProp.visible);
506
                            if (el.visProp.visible()) {el.showElement();} else {el.hideElement();}
507
                        }
508
                        */
509
                        //} catch(e) {
510
                        //    JXG.debug(e);
511
                        //}
512
                        break;
513
                    case "line":
514
                        gxtEl = gxtReader.colorProperties(gxtEl, Data);
515
                        gxtEl = gxtReader.visualProperties(gxtEl, Data);
516
                        gxtEl = gxtReader.firstLevelProperties(gxtEl, Data);
517
                        gxtEl = gxtReader.readNodes(gxtEl, Data, 'data');
518
                        gxtEl = gxtReader.readNodes(gxtEl, Data, 'straight', 'straight');
519
                        gxtEl = gxtReader.transformProperties(gxtEl);
520
 
521
                        gxtEl.first = gxtReader.changeOriginIds(board, gxtEl.first);
522
                        gxtEl.last = gxtReader.changeOriginIds(board, gxtEl.last);
523
 
524
                        l = board.create('line', [gxtEl.first, gxtEl.last], gxtEl);
525
 
526
                        gxtReader.parseImage(board, Data, board.options.layer['image'], 0, 0, 0, 0, l);
527
                        gxtReader.printDebugMessage('debug', gxtEl, Data.nodeName, 'OK');
528
                        break;
529
                    case "circle":
530
                        gxtEl = gxtReader.colorProperties(gxtEl, Data);
531
                        gxtEl = gxtReader.visualProperties(gxtEl, Data);
532
                        gxtEl = gxtReader.firstLevelProperties(gxtEl, Data);
533
 
534
                        tmp = gxtReader.gEBTN(Data, 'data', 0, false);
535
                        gxtEl.midpoint = gxtReader.changeOriginIds(board, gxtReader.gEBTN(tmp, 'midpoint'));
536
 
537
                        if (tmp.getElementsByTagName('radius').length > 0) {
538
                            gxtEl.radius = gxtReader.changeOriginIds(board, gxtReader.gEBTN(tmp, 'radius'));
539
                        } else if (tmp.getElementsByTagName('radiusvalue').length > 0) {
540
                            gxtEl.radius = gxtReader.gEBTN(tmp, 'radiusvalue');
541
                        }
542
                        gxtEl = gxtReader.transformProperties(gxtEl);
543
                        c = board.create('circle', [gxtEl.midpoint, gxtEl.radius], gxtEl);
544
 
545
                        gxtReader.parseImage(board, Data, board.options.layer['image'], 0, 0, 0, 0, c);
546
                        gxtReader.printDebugMessage('debug', gxtEl, Data.nodeName, 'OK');
547
                        break;
548
                    case "slider":
549
                        gxtEl = gxtReader.colorProperties(gxtEl, Data);
550
                        gxtEl = gxtReader.visualProperties(gxtEl, Data);
551
                        gxtEl = gxtReader.firstLevelProperties(gxtEl, Data);
552
 
553
                        gxtEl = gxtReader.readNodes(gxtEl, Data, 'data');
554
                        gxtEl.fixed = JXG.str2Bool(gxtReader.gEBTN(Data, 'fix'));
555
                        gxtEl = gxtReader.readNodes(gxtEl, Data, 'animate', 'animate');
556
                        gxtEl = gxtReader.transformProperties(gxtEl, 'point');
557
                        try {
558
                            gxtEl.parent = gxtReader.changeOriginIds(board, gxtEl.parent);
559
 
560
                            // if (board.isSuspendedUpdate) { board.unsuspendUpdate().suspendUpdate(); }
561
                            p = board.create('glider', [parseFloat(gxtEl.x), parseFloat(gxtEl.y), gxtEl.parent], gxtEl);
562
                            p.onPolygon = JXG.exists(gxtEl.onpolygon) && JXG.str2Bool(gxtEl.onpolygon);
563
 
564
                            gxtReader.parseImage(board, Data, board.options.layer['point'], 0, 0, 0, 0, p);
565
 
566
                            //if (board.isSuspendedUpdate) { board.unsuspendUpdate().suspendUpdate(); }
567
 
568
                            gxtReader.printDebugMessage('debug', gxtEl, Data.nodeName, 'OK');
569
                        } catch(e) {
570
                            JXG.debug("* <b>Err:</b>  Slider " + gxtEl.name + " " + gxtEl.id + ': '+ gxtEl.parent +"<br>\n");
571
                        }
572
                        break;
573
                    case "cas":
574
                        gxtEl = gxtReader.colorProperties(gxtEl, Data);
575
                        gxtEl = gxtReader.visualProperties(gxtEl, Data);
576
                        gxtEl = gxtReader.firstLevelProperties(gxtEl, Data);
577
                        gxtEl.fixed = JXG.str2Bool(Data.getElementsByTagName('fix')[0].firstChild.data);
578
                        gxtEl = gxtReader.readNodes(gxtEl, Data, 'data');
579
                        gxtEl = gxtReader.transformProperties(gxtEl, 'point');
580
 
581
                        p = board.create('point', [parseFloat(gxtEl.xval), parseFloat(gxtEl.yval)], gxtEl);
582
                        gxtReader.parseImage(board, Data, board.options.layer['point'], 0, 0, 0, 0, p);
583
                        p.addConstraint([gxtEl.x, gxtEl.y]);
584
                        gxtReader.printDebugMessage('debug', gxtEl, Data.nodeName, 'OK');
585
                        break;
586
                    case "intersection":
587
                        gxtEl = gxtReader.readNodes(gxtEl, Data, 'data');
588
                        xmlNode = Data.getElementsByTagName('first')[1];
589
 
590
                        gxtEl.outFirst = {};
591
                        gxtEl.outFirst = gxtReader.colorProperties(gxtEl.outFirst, xmlNode);
592
                        gxtEl.outFirst = gxtReader.visualProperties(gxtEl.outFirst, xmlNode);
593
                        gxtEl.outFirst = gxtReader.firstLevelProperties(gxtEl.outFirst, xmlNode);
594
                        gxtEl.outFirst.fixed = JXG.str2Bool(xmlNode.getElementsByTagName('fix')[0].firstChild.data);
595
                        gxtEl.outFirst = gxtReader.transformProperties(gxtEl.outFirst, 'point');
596
                        gxtEl.first = gxtReader.changeOriginIds(board, gxtEl.first);
597
                        gxtEl.last = gxtReader.changeOriginIds(board, gxtEl.last);
598
 
599
                        //if ((board.objects[gxtEl.first].type == JXG.OBJECT_TYPE_LINE || board.objects[gxtEl.first].type == JXG.OBJECT_TYPE_ARROW)
600
                        // && (board.objects[gxtEl.last].type == JXG.OBJECT_TYPE_LINE || board.objects[gxtEl.last].type == JXG.OBJECT_TYPE_ARROW)) {
601
                        if ((JXG.getReference(board, gxtEl.first).elementClass == JXG.OBJECT_CLASS_LINE)
602
                         && (JXG.getReference(board, gxtEl.last).elementClass == JXG.OBJECT_CLASS_LINE)) {
603
                            /*
604
                            inter = new JXG.Intersection(board, gxtEl.id, board.objects[gxtEl.first],
605
                                    board.objects[gxtEl.last], gxtEl.outFirst.id, '',
606
                                    gxtEl.outFirst.name, '');
607
                            inter.p.setProperty(gxtEl.outFirst);
608
                            */
609
                            inter = board.create('intersection', [board.objects[gxtEl.first], board.objects[gxtEl.last], 0], gxtEl.outFirst);
610
                            /* offensichtlich braucht man dieses if doch */
611
                            if (gxtEl.outFirst.visible == "false") {
612
                                inter.hideElement();
613
                            }
614
                        } else {
615
                            xmlNode = Data.getElementsByTagName('last')[1];
616
                            if (JXG.exists(xmlNode)) {
617
                                gxtEl.outLast = {};
618
                                gxtEl.outLast = gxtReader.colorProperties(gxtEl.outLast, xmlNode);
619
                                gxtEl.outLast = gxtReader.visualProperties(gxtEl.outLast, xmlNode);
620
                                gxtEl.outLast = gxtReader.firstLevelProperties(gxtEl.outLast, xmlNode);
621
                                gxtEl.outLast.fixed = JXG.str2Bool(xmlNode.getElementsByTagName('fix')[0].firstChild.data);
622
                                gxtEl.outLast = gxtReader.transformProperties(gxtEl.outLast, 'point');
623
                            /*
624
                                inter = new JXG.Intersection(board, gxtEl.id, board.objects[gxtEl.first],
625
                                    board.objects[gxtEl.last], gxtEl.outFirst.id, gxtEl.outLast.id,
626
                                    gxtEl.outFirst.name, gxtEl.outLast.name);
627
                                inter.p1.setProperty(gxtEl.outFirst);
628
                                inter.p2.setProperty(gxtEl.outLast);
629
                            */
630
                                inter = board.create('intersection', [board.objects[gxtEl.first], board.objects[gxtEl.last], 0], gxtEl.outFirst);
631
                                inter = board.create('intersection', [board.objects[gxtEl.first], board.objects[gxtEl.last], 1], gxtEl.outLast);
632
                            }
633
                        }
634
                        gxtReader.printDebugMessage('debug', gxtEl, Data.nodeName, 'OK');
635
                        break;
636
                    case "composition":
637
                        gxtEl = gxtReader.readNodes(gxtEl, Data, 'data');
638
                        gxtEl = gxtReader.firstLevelProperties(gxtEl, Data);
639
                        gxtEl.defEl = [];
640
                        numberDefEls = 0;
641
                        xmlNode = Data.getElementsByTagName('data')[0].getElementsByTagName('input');
642
                        for (i = 0; i < xmlNode.length; i++) {
643
                            gxtEl.defEl[i] = xmlNode[i].firstChild.data;
644
                            numberDefEls = i + 1;
645
                        }
646
 
647
                        // every composition produces at least one element and the data for this element is stored
648
                        // in gxtEl.out. if additional elements are created their data is read in the according case.
649
                        xmlNode = Data.getElementsByTagName('output')[0];
650
                        gxtEl.out = {};
651
                        gxtEl.out = gxtReader.colorProperties(gxtEl.out, xmlNode);
652
                        gxtEl.out = gxtReader.visualProperties(gxtEl.out, xmlNode);
653
                        gxtEl.out = gxtReader.firstLevelProperties(gxtEl.out, xmlNode);
654
                        gxtEl.out = gxtReader.transformProperties(gxtEl.out);
655
 
656
                        gxtEl.defEl[0] = gxtReader.changeOriginIds(board, gxtEl.defEl[0]);
657
                        gxtEl.defEl[1] = gxtReader.changeOriginIds(board, gxtEl.defEl[1]);
658
                        gxtEl.defEl[2] = gxtReader.changeOriginIds(board, gxtEl.defEl[2]);
659
 
660
                        // if (board.isSuspendedUpdate) { board.unsuspendUpdate().suspendUpdate(); }
661
                        switch (gxtEl.type) {
662
                            // ARROW_PARALLEL
663
                            case "210070":
664
                                gxtEl.out.fixed = gxtReader.gEBTN(xmlNode, 'fix');
665
 
666
                                xmlNode = Data.getElementsByTagName('output')[1];
667
                                gxtEl.outPoint = {};
668
                                gxtEl.outPoint = gxtReader.defProperties(gxtEl.outPoint, xmlNode);
669
                                gxtEl.outPoint = gxtReader.colorProperties(gxtEl.outPoint, xmlNode);
670
                                gxtEl.outPoint = gxtReader.visualProperties(gxtEl.outPoint, xmlNode);
671
                                gxtEl.outPoint = gxtReader.firstLevelProperties(gxtEl.outPoint, xmlNode);
672
                                gxtEl.outPoint = gxtReader.transformProperties(gxtEl.outPoint);
673
                                gxtEl.out.point = gxtEl.outPoint;
674
 
675
                                board.create('arrowparallel', [gxtEl.defEl[1], gxtEl.defEl[0]], gxtEl.out);
676
                                break;
677
 
678
                            // BISECTOR
679
                            case "210080":
680
                                gxtEl.out.straightFirst = false;
681
                                board.create('bisector', [gxtEl.defEl[0], gxtEl.defEl[1], gxtEl.defEl[2]], gxtEl.out);
682
                                break;
683
 
684
                            // CIRCUMCIRCLE
685
                            case "210090":
686
                                xmlNode = Data.getElementsByTagName('output')[1];
687
                                gxtEl.outCircle = {};
688
                                gxtEl.outCircle = gxtReader.defProperties(gxtEl.outCircle, xmlNode);
689
                                gxtEl.outCircle = gxtReader.colorProperties(gxtEl.outCircle, xmlNode);
690
                                gxtEl.outCircle = gxtReader.visualProperties(gxtEl.outCircle, xmlNode);
691
                                gxtEl.outCircle = gxtReader.firstLevelProperties(gxtEl.outCircle, xmlNode);
692
                                gxtEl.outCircle = gxtReader.transformProperties(gxtEl.outCircle);
693
                                gxtEl.outCircle.point = gxtEl.out;
694
                                board.create('circumcircle', [gxtEl.defEl[0], gxtEl.defEl[1], gxtEl.defEl[2]], gxtEl.outCircle);
695
                                break;
696
 
697
                            // CIRCUMCIRCLE_CENTER
698
                            case "210100":
699
                                board.create('circumcirclemidpoint', [gxtEl.defEl[0], gxtEl.defEl[1], gxtEl.defEl[2]], gxtEl.out);
700
                                break;
701
 
702
                            // MIDPOINT
703
                            case "210110":
704
                                board.create('midpoint', gxtEl.defEl.slice(0, numberDefEls), gxtEl.out);
705
                                break;
706
 
707
                             // MIRRORLINE
708
                            case "210120":
709
                                board.create('reflection', [gxtEl.defEl[1], gxtEl.defEl[0]], gxtEl.out);
710
                                break;
711
 
712
                            // MIRROR_POINT
713
                            case "210125":
714
                                board.create('mirrorpoint', [gxtEl.defEl[0], gxtEl.defEl[1]], gxtEl.out);
715
                                break;
716
 
717
                            // NORMAL
718
                            case "210130":
719
                                board.create('normal', [gxtEl.defEl[1], gxtEl.defEl[0]], gxtEl.out);
720
                                break;
721
 
722
                            // PARALLEL
723
                            case "210140":
724
                                board.create('parallel', [gxtEl.defEl[1], gxtEl.defEl[0]], gxtEl.out);
725
                                break;
726
 
727
                            // PARALLELOGRAM_POINT
728
                            case "210150":
729
                                board.create('parallelpoint', gxtEl.defEl.slice(0, numberDefEls), gxtEl.out);
730
                                break;
731
 
732
                            // PERPENDICULAR
733
                            case "210160":
734
                                // output[0] was already read and is stored in gxtEl.out
735
                                gxtEl.out.fixed = gxtReader.gEBTN(xmlNode, 'fix');
736
 
737
                                xmlNode = Data.getElementsByTagName('output')[1];
738
                                gxtEl.outLine = {};
739
                                gxtEl.outLine = gxtReader.defProperties(gxtEl.outLine, xmlNode);
740
                                gxtEl.outLine = gxtReader.colorProperties(gxtEl.outLine, xmlNode);
741
                                gxtEl.outLine = gxtReader.visualProperties(gxtEl.outLine, xmlNode);
742
                                gxtEl.outLine = gxtReader.firstLevelProperties(gxtEl.outLine, xmlNode);
743
                                gxtEl.outLine = gxtReader.readNodes(gxtEl.outLine, xmlNode, 'straight', 'straight');
744
                                gxtEl.outLine = gxtReader.transformProperties(gxtEl.outLine);
745
                                gxtEl.outLine.point = gxtEl.out;
746
 
747
                                board.create('perpendicularsegment', [gxtEl.defEl[1], gxtEl.defEl[0]], gxtEl.outLine);
748
                                break;
749
 
750
                            // PERPENDICULAR_POINT
751
                            case "210170":
752
                                board.create('perpendicularpoint', [gxtEl.defEl[1], gxtEl.defEl[0]], gxtEl.out);
753
                                break;
754
 
755
                            // ROTATION
756
                            case "210180":
757
                                throw new Error('JSXGraph: Element ROTATION not yet implemented.');
758
                                break;
759
 
760
                            // SECTOR
761
                            case "210190":
762
                                // sectors usually provide more than one output element but JSXGraph is not fully compatible
763
                                // to GEONExT sector elements. GEONExT sectors consist of two lines, a point, and a sector,
764
                                // JSXGraph uses a curve to display the sector incl. the borders, and
765
                                // a point and two lines. 
766
                                // Gliders on sectors also run through the borders.
767
                                gxtEl.out = gxtReader.defProperties(gxtEl.out, xmlNode);
768
                                gxtEl.out.firstArrow = JXG.str2Bool(gxtReader.gEBTN(xmlNode, 'firstarrow'));
769
                                gxtEl.out.lastArrow = JXG.str2Bool(gxtReader.gEBTN(xmlNode, 'lastarrow'));
770
 
771
                                // el = board.create('sector', gxtEl.defEl, gxtEl.out);
772
                                for (i=0; i<4;i++) {
773
                                    xmlNode = Data.getElementsByTagName('output')[i];
774
                                    gxtEl.out = gxtReader.defProperties(gxtEl.out, xmlNode);
775
                                    gxtEl.out = gxtReader.colorProperties(gxtEl.out, xmlNode);
776
                                    gxtEl.out = gxtReader.visualProperties(gxtEl.out, xmlNode);
777
                                    gxtEl.out = gxtReader.firstLevelProperties(gxtEl.out, xmlNode);
778
                                    gxtEl.out = gxtReader.transformProperties(gxtEl.out);
779
 
780
                                    if (i==0) {
781
                                        el = board.create('sector', gxtEl.defEl, gxtEl.out);
782
                                    } else if (i==1) {
783
                                        p = board.create('point', [
784
                                            function(){
785
                                                var p1 = JXG.getRef(board,gxtEl.defEl[1]), p2 = JXG.getRef(board,gxtEl.defEl[2]);
786
                                                return p1.X() + (p2.X()-p1.X())*el.Radius/p1.Dist(p2);
787
                                            },
788
                                            function(){
789
                                                var p1 = JXG.getRef(board,gxtEl.defEl[1]), p2 = JXG.getRef(board,gxtEl.defEl[2]);
790
                                                return p1.Y() + (p2.Y()-p1.Y())*el.Radius/p1.Dist(p2);
791
                                            }], gxtEl.out);
792
                                        //p = JXG.getReference(board,gxtEl.defEl[2]);
793
                                    } else if (i==2) {
794
                                        el = board.create('segment', [gxtEl.defEl[1], gxtEl.defEl[0]], gxtEl.out);
795
                                    } else if (i==3) {
796
                                        el = board.create('segment', [gxtEl.defEl[1], p], gxtEl.out);
797
                                    }
798
                                }
799
                                break;
800
                            default:
801
                                throw new Error("JSXGraph: GEONExT-Element " + gxtEl.type + ' not implemented.');
802
                                break;
803
                        }
804
 
805
                        // if (board.isSuspendedUpdate) { board.unsuspendUpdate().suspendUpdate(); }
806
                        gxtReader.printDebugMessage('debug', gxtEl, Data.nodeName, 'OK');
807
                        break;
808
                    case "polygon":
809
                        gxtEl = gxtReader.colorProperties(gxtEl, Data);
810
                        gxtEl = gxtReader.firstLevelProperties(gxtEl, Data);
811
                        gxtEl.dataVertex = [];
812
                        // In Geonext file format the first vertex is equal to the last vertex:
813
                        for (i = 0; i < Data.getElementsByTagName('data')[0].getElementsByTagName('vertex').length-1; i++) {
814
                            gxtEl.dataVertex[i] = Data.getElementsByTagName('data')[0].getElementsByTagName('vertex')[i].firstChild.data;
815
                            gxtEl.dataVertex[i] = gxtReader.changeOriginIds(board, gxtEl.dataVertex[i]);
816
                        }
817
                        gxtEl.border = [];
818
                        gxtEl.lines = {
819
                            ids: []
820
                        };
821
                        for (i = 0; i < Data.getElementsByTagName('border').length; i++) {
822
                            gxtEl.border[i] = {};
823
                            xmlNode = Data.getElementsByTagName('border')[i];
824
                            gxtEl.border[i].id = xmlNode.getElementsByTagName('id')[0].firstChild.data;
825
                            gxtEl.lines.ids.push(gxtEl.border[i].id);
826
                            gxtEl.border[i].name = xmlNode.getElementsByTagName('name')[0].firstChild.data;
827
                            gxtEl.border[i].straightFirst = JXG.str2Bool(xmlNode.getElementsByTagName('straight')[0].getElementsByTagName('first')[0].firstChild.data);
828
                            gxtEl.border[i].straightLast = JXG.str2Bool(xmlNode.getElementsByTagName('straight')[0].getElementsByTagName('last')[0].firstChild.data);
829
                            gxtEl.border[i].strokeWidth = xmlNode.getElementsByTagName('strokewidth')[0].firstChild.data;
830
                            gxtEl.border[i].dash = JXG.str2Bool(xmlNode.getElementsByTagName('dash')[0].firstChild.data);
831
                            gxtEl.border[i].visible = JXG.str2Bool(xmlNode.getElementsByTagName('visible')[0].firstChild.data);
832
                            gxtEl.border[i].draft = JXG.str2Bool(xmlNode.getElementsByTagName('draft')[0].firstChild.data);
833
                            gxtEl.border[i].trace = JXG.str2Bool(xmlNode.getElementsByTagName('trace')[0].firstChild.data);
834
 
835
                            xmlNode = Data.getElementsByTagName('border')[i].getElementsByTagName('color')[0];
836
                            rgbo = JXG.rgba2rgbo(xmlNode.getElementsByTagName('stroke')[0].firstChild.data);
837
                            gxtEl.border[i].strokeColor = rgbo[0];
838
                            gxtEl.border[i].strokeOpacity = rgbo[1];
839
 
840
                            rgbo = JXG.rgba2rgbo(xmlNode.getElementsByTagName('lighting')[0].firstChild.data);
841
                            gxtEl.border[i].highlightStrokeColor = rgbo[0];
842
                            gxtEl.border[i].highlightStrokeOpacity = rgbo[1];
843
 
844
                            rgbo = JXG.rgba2rgbo(xmlNode.getElementsByTagName('fill')[0].firstChild.data);
845
                            gxtEl.border[i].fillColor = rgbo[0];
846
                            gxtEl.border[i].fillOpacity = rgbo[1];
847
 
848
                            gxtEl.border[i].highlightFillColor = gxtEl.border[i].fillColor;
849
                            gxtEl.border[i].highlightFillOpacity = gxtEl.border[i].fillOpacity;
850
 
851
                            gxtEl.border[i].labelColor = xmlNode.getElementsByTagName('label')[0].firstChild.data;
852
                            gxtEl.border[i].colorDraft = xmlNode.getElementsByTagName('draft')[0].firstChild.data;
853
                        }
854
                        gxtEl = gxtReader.transformProperties(gxtEl);
855
                        p = board.create('polygon', gxtEl.dataVertex, gxtEl);
856
 
857
                        // to emulate the geonext behaviour on invisible polygons
858
                        // A.W.: Why do we need this?
859
/*                        
860
                        if (!gxtEl.visible) {
861
                            p.setProperty({
862
                                fillColor: 'none',
863
                                highlightFillColor: 'none'
864
                            });
865
                        }
866
*/
867
                        for (i = 0; i < p.borders.length; i++) {
868
                            p.borders[i].setProperty(gxtEl.border[i]);
869
                        }
870
 
871
                        gxtReader.printDebugMessage('debug', gxtEl, Data.nodeName, 'OK');
872
                        break;
873
                    case "graph":
874
                        gxtEl = gxtReader.colorProperties(gxtEl, Data);
875
                        gxtEl = gxtReader.firstLevelProperties(gxtEl, Data);
876
                        gxtEl.funct = Data.getElementsByTagName('data')[0].getElementsByTagName('function')[0].firstChild.data;
877
 
878
                        c = board.create('curve', ['x',gxtEl.funct], {
879
                                id: gxtEl.id,
880
                                name: gxtEl.name,
881
                                strokeColor: gxtEl.strokeColor,
882
                                strokeWidth: gxtEl.strokeWidth,
883
                                fillColor: 'none',
884
                                highlightFillColor: 'none',
885
                                highlightStrokeColor: gxtEl.highlightStrokeColor,
886
                                visible: JXG.str2Bool(gxtEl.visible)
887
                            });
888
 
889
                        gxtReader.printDebugMessage('debug', gxtEl, Data.nodeName, 'OK');
890
                        break;
891
                    case "arrow":
892
                        gxtEl = gxtReader.colorProperties(gxtEl, Data);
893
                        gxtEl = gxtReader.visualProperties(gxtEl, Data);
894
                        gxtEl = gxtReader.firstLevelProperties(gxtEl, Data);
895
                        gxtEl = gxtReader.readNodes(gxtEl, Data, 'data');
896
                        gxtEl = gxtReader.readNodes(gxtEl, Data, 'straight', 'straight');
897
 
898
                        gxtEl = gxtReader.transformProperties(gxtEl);
899
                        gxtEl.first = gxtReader.changeOriginIds(board, gxtEl.first);
900
                        gxtEl.last = gxtReader.changeOriginIds(board, gxtEl.last);
901
 
902
                        l = board.create('arrow', [gxtEl.first, gxtEl.last], gxtEl);
903
 
904
                        gxtReader.printDebugMessage('debug', l, Data.nodeName, 'OK');
905
                        break;
906
                    case "arc":
907
                        gxtEl = gxtReader.colorProperties(gxtEl, Data);
908
                        gxtEl = gxtReader.visualProperties(gxtEl, Data);
909
                        gxtEl = gxtReader.firstLevelProperties(gxtEl, Data);
910
                        gxtEl = gxtReader.readNodes(gxtEl, Data, 'data');
911
 
912
                        gxtEl.firstArrow = JXG.str2Bool(Data.getElementsByTagName('lastarrow')[0].firstChild.data);   // It seems that JSXGraph and GEONExT
913
                        gxtEl.lastArrow = JXG.str2Bool(Data.getElementsByTagName('firstarrow')[0].firstChild.data);   // use opposite directions.
914
 
915
                        gxtEl = gxtReader.transformProperties(gxtEl);
916
 
917
                        gxtEl.midpoint = gxtReader.changeOriginIds(board, gxtEl.midpoint);
918
                        gxtEl.angle = gxtReader.changeOriginIds(board, gxtEl.angle);
919
                        gxtEl.radius = gxtReader.changeOriginIds(board, gxtEl.radius);
920
 
921
                        c = board.create('arc', [gxtEl.midpoint, gxtEl.radius, gxtEl.angle], gxtEl);
922
 
923
                        gxtReader.printDebugMessage('debug', c, Data.nodeName, 'OK');
924
                        break;
925
                    case "angle":
926
                        gxtEl = gxtReader.colorProperties(gxtEl, Data);
927
                        gxtEl = gxtReader.visualProperties(gxtEl, Data);
928
                        gxtEl = gxtReader.firstLevelProperties(gxtEl, Data);
929
                        gxtEl = gxtReader.readNodes(gxtEl, Data, 'data');
930
                        gxtEl = gxtReader.transformProperties(gxtEl);
931
 
932
                        try {
933
                            gxtEl.text = Data.getElementsByTagName('text')[0].firstChild.data;
934
                        } catch (e) {
935
                            gxtEl.text = '';
936
                        }
937
 
938
                        c = board.create('angle', [gxtEl.first, gxtEl.middle, gxtEl.last], gxtEl);
939
                        gxtReader.printDebugMessage('debug', gxtEl, Data.nodeName, 'OK');
940
                        break;
941
                    case "text":
942
                        if (gxtEl.id.match(/oldVersion/)) {
943
                            break;
944
                        }
945
                        gxtEl = gxtReader.colorProperties(gxtEl, Data);
946
                        gxtEl = gxtReader.visualProperties(gxtEl, Data);
947
                        gxtEl = gxtReader.firstLevelProperties(gxtEl, Data);
948
 
949
                        gxtEl = gxtReader.readNodes(gxtEl, Data, 'data');
950
                        gxtEl.mpStr = gxtReader.subtreeToString(Data.getElementsByTagName('data')[0].getElementsByTagName('mp')[0]);
951
                        gxtEl.mpStr = gxtEl.mpStr.replace(/<\/?mp>/g, '');
952
                        try {
953
                            if (Data.getElementsByTagName('data')[0].getElementsByTagName('parent')[0].firstChild) {
954
                                gxtEl.parent = Data.getElementsByTagName('data')[0].getElementsByTagName('parent')[0].firstChild.data;
955
                            }
956
                        } catch (e) {
957
                        }
958
 
959
                        gxtEl.condition = Data.getElementsByTagName('condition')[0].firstChild.data;
960
                        gxtEl.content = Data.getElementsByTagName('content')[0].firstChild.data;
961
                        gxtEl.fix = Data.getElementsByTagName('fix')[0].firstChild.data;
962
                        // not used gxtEl.digits = Data.getElementsByTagName('cs')[0].firstChild.data;
963
                        gxtEl.autodigits = Data.getElementsByTagName('digits')[0].firstChild.data;
964
                        gxtEl.parent = gxtReader.changeOriginIds(board, gxtEl.parent);
965
 
966
                        /*
967
                         * Not necessary: is handled by getTextAnchor() in parent element
968
                        // TODO: Polygons
969
                        // Handle parent elements of texts
970
                        if (JXG.exists(gxtEl.parent)) {
971
                            if (JXG.isPoint(gxtEl.parent)) {
972
                                gxtEl.x = (function (x, y, p) { return function() { return x + p.X(); }; })
973
                                        (gxtEl.x, gxtEl.y, JXG.getReference(board, gxtEl.parent));
974
                                gxtEl.y = (function (x, y, p) { return function() { return y + p.Y(); }; })
975
                                        (gxtEl.x, gxtEl.y, JXG.getReference(board, gxtEl.parent));
976
                            } else if (JXG.getReference(board, gxtEl.parent).elementClass == JXG.OBJECT_CLASS_CIRCLE) {  
977
                                gxtEl.x = (function (x, y, p) { return function() { return x + p.midpoint.X(); }; })
978
                                        (gxtEl.x, gxtEl.y, JXG.getReference(board, gxtEl.parent));
979
                                gxtEl.y = (function (x, y, p) { return function() { return y + p.midpoint.Y(); }; })
980
                                        (gxtEl.x, gxtEl.y, JXG.getReference(board, gxtEl.parent));
981
                            } else if (JXG.getReference(board, gxtEl.parent).elementClass == JXG.OBJECT_CLASS_LINE) {  
982
                                gxtEl.x = (function (x, y, p) { return function() { return x + (p.point1.X()+p.point2.X())*0.5; }; })
983
                                        (gxtEl.x, gxtEl.y, JXG.getReference(board, gxtEl.parent));
984
                                gxtEl.y = (function (x, y, p) { return function() { return y + (p.point1.Y()+p.point2.Y())*0.5; }; })
985
                                        (gxtEl.x, gxtEl.y, JXG.getReference(board, gxtEl.parent));
986
                            }
987
                        }
988
                        */
989
                        c = board.create('text', [gxtEl.x, gxtEl.y, gxtEl.mpStr], {
990
                                anchor: gxtEl.parent,
991
                                id: gxtEl.id,
992
                                name: gxtEl.name,
993
                                digits: gxtEl.autodigits,
994
                                isLabel: false,
995
                                strokeColor: gxtEl.colorLabel,
996
                                visible: JXG.str2Bool(gxtEl.visible)
997
                            });
998
                        break;
999
                    case 'parametercurve':
1000
                        gxtEl = gxtReader.colorProperties(gxtEl, Data);
1001
                        gxtEl = gxtReader.visualProperties(gxtEl, Data);
1002
                        gxtEl = gxtReader.firstLevelProperties(gxtEl, Data);
1003
                        gxtEl = gxtReader.transformProperties(gxtEl);                        
1004
                        gxtEl.functionx = Data.getElementsByTagName('functionx')[0].firstChild.data;
1005
                        gxtEl.functiony = Data.getElementsByTagName('functiony')[0].firstChild.data;
1006
                        gxtEl.min = Data.getElementsByTagName('min')[0].firstChild.data;
1007
                        gxtEl.max = Data.getElementsByTagName('max')[0].firstChild.data;
1008
 
1009
                        gxtEl.fillColor = 'none';
1010
                        gxtEl.highlightFillColor = 'none';
1011
 
1012
                        board.create('curve',
1013
                                    [ new Function('t', 'return ' + JXG.GeonextParser.geonext2JS(gxtEl.functionx, board) + ';' ),
1014
                                      new Function('t', 'return ' + JXG.GeonextParser.geonext2JS(gxtEl.functiony, board) + ';' ),
1015
                                      new Function('return ' + JXG.GeonextParser.geonext2JS(gxtEl.min, board) + ';' ),
1016
                                      new Function('return ' + JXG.GeonextParser.geonext2JS(gxtEl.max, board) + ';' )
1017
                                    ], gxtEl);
1018
                        /*
1019
                        c = new JXG.Curve(board, [
1020
                            't',gxtEl.functionx,gxtEl.functiony,gxtEl.min,gxtEl.max
1021
                        ], gxtEl.id, gxtEl.name);
1022
                        c.setProperty('strokeColor:' + gxtEl.colorStroke, 'strokeWidth:' + gxtEl.strokewidth, 'fillColor:none',
1023
                                'highlightStrokeColor:' + gxtEl.highlightStrokeColor);
1024
                        */
1025
                        gxtReader.printDebugMessage('debug', gxtEl, Data.nodeName, 'OK');
1026
                        break;
1027
                    case 'tracecurve':
1028
                        //try {
1029
                        gxtEl.tracepoint = Data.getElementsByTagName('tracepoint')[0].firstChild.data;
1030
                        gxtEl.traceslider = Data.getElementsByTagName('traceslider')[0].firstChild.data;
1031
                        JXG.getRef(board, gxtEl.tracepoint).setProperty({trace:true});
1032
                        //} catch(e) {}
1033
                        gxtReader.printDebugMessage('debug', gxtEl, Data.nodeName, '<b>ERR</b>');
1034
                        break;
1035
                    case 'group':
1036
                        gxtEl = gxtReader.colorProperties(gxtEl, Data);
1037
                        gxtEl = gxtReader.firstLevelProperties(gxtEl, Data);
1038
                        gxtEl.members = [
1039
                        ];
1040
                        for (i = 0; i < Data.getElementsByTagName('data')[0].getElementsByTagName('member').length; i++) {
1041
                            gxtEl.members[i] = Data.getElementsByTagName('data')[0].getElementsByTagName('member')[i].firstChild.data;
1042
                            gxtEl.members[i] = gxtReader.changeOriginIds(board, gxtEl.members[i]);
1043
                        }
1044
                        c = new JXG.Group(board, gxtEl.id, gxtEl.name, gxtEl.members);
1045
                        gxtReader.printDebugMessage('debug', gxtEl, Data.nodeName, 'OK');
1046
                        break;
1047
                    default:
1048
                        JXG.debug("* <b>Err:</b> " + Data.nodeName + " not yet implemented <br>\n");
1049
                }
1050
                delete(gxtEl);
1051
            })(s);
1052
        }
1053
        board.addConditions(conditions);
1054
    },
1055
 
1056
    decodeString: function(str) {
1057
        var unz;
1058
        if (str.indexOf("<GEONEXT>")<0){
1059
            unz = (new JXG.Util.Unzip(JXG.Util.Base64.decodeAsArray(str))).unzip(); // war Gunzip ME
1060
            if (unz=="")
1061
                return str;
1062
            else
1063
                return unz;
1064
        } else {
1065
            return str;
1066
        }
1067
    },
1068
 
1069
    prepareString: function(fileStr){
1070
        try {
1071
            if (fileStr.indexOf('GEONEXT')<0) {
1072
                fileStr = (this.decodeString(fileStr))[0][0];  // Base64 decoding
1073
            }
1074
            // Hacks to enable not well formed XML. Will be redone in Algebra.geonext2JS and Board.addConditions
1075
            fileStr = this.fixXML(fileStr);
1076
        } catch(e) {
1077
            fileStr = '';
1078
        }
1079
        return fileStr;
1080
    },
1081
 
1082
    fixXML: function(str) {
1083
        var arr = ["active", "angle", "animate", "animated", "arc", "area", "arrow", "author", "autodigits", "axis", "back", "background", "board", "border", "bottom", "buttonsize", "cas", "circle", "color", "comment", "composition", "condition", "conditions", "content", "continuous", "control", "coord", "coordinates", "cross", "cs", "dash", "data", "description", "digits", "direction", "draft", "editable", "elements", "event", "file", "fill", "first", "firstarrow", "fix", "fontsize", "free", "full", "function", "functionx", "functiony", "GEONEXT", "graph", "grid", "group", "height", "id", "image", "info", "information", "input", "intersection", "item", "jsf", "label", "last", "lastarrow", "left", "lefttoolbar", "lighting", "line", "loop", "max", "maximized", "member", "middle", "midpoint", "min", "modifier", "modus", "mp", "mpx", "multi", "name", "onpolygon", "order", "origin", "output", "overline", "parametercurve", "parent", "point", "pointsnap", "polygon", "position", "radius", "radiusnum", "radiusvalue", "right", "section", "selectedlefttoolbar", "showconstruction", "showcoord", "showinfo", "showunit", "showx", "showy", "size", "slider", "snap", "speed", "src", "start", "stop", "straight", "stroke", "strokewidth", "style", "term", "text", "top", "trace", "tracecurve", "tracepoint", "traceslider", "type", "unit", "value", "VERSION", "vertex", "viewport", "visible", "width", "wot", "x", "xooy", "xval", "y", "yval", "zoom"],
1084
                list = arr.join('|'),
1085
                regex = '\&lt;(/?('+list+'))\&gt;',
1086
                expr = new RegExp(regex,'g');
1087
 
1088
        // First, we convert all < to &lt; and > to &gt;
1089
        str = JXG.escapeHTML(str);
1090
        // Second, we convert all GEONExT tags of the form &lt;tag&gt; back to <tag>
1091
        str = str.replace(expr,'<$1>');
1092
 
1093
        str = str.replace(/(<content>.*)<arc>(.*<\/content>)/g,'$1&lt;arc&gt;$2');
1094
        str = str.replace(/(<mp>.*)<arc>(.*<\/mpx>)/g,'$1&lt;arc&gt;$2');
1095
        str = str.replace(/(<mpx>.*)<arc>(.*<\/mpx>)/g,'$1&lt;arc&gt;$2');
1096
        return str;
1097
    }
1098
 
1099
}; // end: GeonextReader