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