Source: JSPtoJSXGcore.js

/**
 *
 *
 *
 */


/**
 * Divides one big string file (original Java Sketchpad code) into array of separate rows and returns rows (Array).
 * @method separateCommands
 * @param {String} a - Java Sketchpad code -string
 * @return {Array<String>} rows - separated rows from Java Sketchpad code as an array
 **/ 
function separateCommands(a) {
  var rows = [], indx = 0, i = 0, numbers = "1234567890", comment="";
  //for (var i=0; i<a.length; i++) {
  while (a.indexOf('<!--')>0 && a.indexOf('-->')>0) {
    //alert('!');
    a=a.slice(0, a.indexOf('<!--'))+a.slice(a.indexOf('-->')+3);
  }
  i = a.indexOf("{");
  while(i<a.length) {
    if (a[i] == '{' && numbers.indexOf(a[i+1])>=0) {
      indx = i;
      while (a[indx] != ";") indx++;
      if (comment.length > 0) {
        rows.push(comment + a.slice(i, indx+1));
        comment = "";
      }
      else 
        rows.push(a.slice(i, indx+1));
      i = indx;
    }
    else if (a[i] == '{' && a[i+1] == ',') { //arrowL or arrowF as commends in JSP code after command line
      indx = i;
      while (a[indx] != '}') indx++;
      rows.push(a.slice(i+2, indx));
      rows[rows.length-2] = rows[rows.length-2].slice(0, rows[rows.length-2].lastIndexOf(']')) + ", " + rows.pop() + "];";
      i = indx;     
    }
    else if (a[i] == '{' && numbers.indexOf(a[i+1])<0) {
      indx = i;
      while (a[indx] != '}') indx++; 
      comment = comment + '/*comment:'+a.slice(i+1, indx)+'*/';
      i = indx;
    } 
    i++;
  }
  return rows;
}

/** 
 *   Slices one row of JavaSketchpad code to javascript object that has following informtion:
 * - Row (row number in sketchpad code),
 * - Type (Type of sketchpad element as sketchpad constructor),
 * - JsxType (type as javascript understands element [in this algorithm]),
 * - Pos (includes info about position [x- and y-coordinates], possible name [buttons, texts, measurements] or/and objects [rows] that are referred to),
 * - Opts (sliced string from '[' to ']' in sketchpad code),
 * - Att (specific info included in Opts [sketchpad code sliced from '[' to ']'] as a jsxgraph attributes. This info includes following attributes: 
 *   Name, Color, Fixed, Visible, WithLabel, StrokeWidth, Straightlast, Straightfirst, AnchorX, Trace, Size, Infobox, LabelAlign
 * - Anim (has the info needed to create buttons [list of the objects (rows) referred to when creating a button],
 * @method sketchpadrowToJsxgElement
 * @param {String} a - One row of Java Sketchpad code
 * @return {Object} el - Object that has information separated from original Java Sketchpad element
 **/
function sketchpadrowToJsxgElement(a) {
  var el, row, type='', jsxtype='', ctype='', pos, opts, att, anim=[], tmpanim, labalig="", psize, sinfo, comment="", labelalign, arrowf=false, arrowl=false, snaptogrid="false", suf="", fixed=false, tmp="";
  this.a = a.trim();
  if (a.indexOf("font(")>0) {
    a = a.replace(a.slice(a.indexOf("font("), a.indexOf(")", a.indexOf("font("))+1), a.slice(a.indexOf("font(")+6, a.indexOf(")", a.indexOf("font("))-1));
  }
  /*if (a.indexOf('/*')>=0 && a.indexOf('*//*')>0) {
    el = {Row:0, Type:'commend', JsxType:'commend', isCommend:true};
    return el;
  }*/
  if (a.indexOf('/*comment:')>=0) {
    comment = a.slice(0, a.indexOf('*/')+2);
    comment = comment.replace('comment:', '');
    comment = comment.replace('*/', '*/\n')
    a = a.slice(a.indexOf('*/')+2, a.length-1);
    //alert("kommentti: "+comment +", rivi: "+a);
  }

  row = a.slice(a.indexOf("{")+1, a.indexOf("}"));
  type = a.slice(a.indexOf("}")+1, a.indexOf("(")).trim(); 
  if (a.indexOf(")[")>=0)
    pos = a.slice(a.indexOf("(")+1, a.indexOf(")[")).trim();
  else pos = a.slice(a.indexOf("(")+1, a.lastIndexOf(")", a.lastIndexOf("[")-1)).trim();
  
  opts = a.slice(a.indexOf("["), a.indexOf("]")+1).trim();

  if (type=="Calculate" || type=="Ratio/Points") {
    if (a.indexOf("layer(")>=0)
      a = a.replace(a.slice(a.indexOf("layer("), a.indexOf(")", a.indexOf("layer("))+1), "");
    if (a.indexOf("color(")>=0) {
      tmp = a.slice(a.indexOf("color("), a.indexOf(")", a.indexOf("color("))+1);
      a = a.replace(tmp, "colorvaluehere"); //change 'color(...)' to 'colorvaluehere'
    }
    if (a.indexOf("suffix")>0)
      pos = a.slice(a.indexOf("(")+1, a.lastIndexOf(")", a.indexOf("suffix")-1)+1).trim();
    else pos = a.slice(a.indexOf("(")+1, a.lastIndexOf(")")+1).trim();
    if (a.indexOf("colorvaluehere")>=0)
      a = a.replace("colorvaluehere",tmp); //change 'colorvaluehere' back to 'color(...)'
  }
  else if (type=="MoveButton" || type=="ShowButton" || type=="HideButton" || type=="SimultaneousButton") {
    //anim = eval("["+a.slice(a.indexOf('(', a.indexOf('(') + 1)+1, a.indexOf(')', a.indexOf(')') + 1))+"]");
    if (opts.indexOf("color(")==-1 && opts.indexOf("layer(")==-1)
      anim = eval("["+a.slice(a.lastIndexOf('(')+1, a.lastIndexOf(')'))+"]");
    else anim = eval("["+a.slice(a.lastIndexOf('(', a.lastIndexOf('['))+1, a.lastIndexOf(')', a.lastIndexOf('[')))+"]");
  }
  else if (type=="AnimateButton") {
    tmpanim = a.slice(a.indexOf(")")+1,a.lastIndexOf(")")) + "]";
    tmpanim = tmpanim.replace(/\(/g, "[");
    tmpanim = tmpanim.replace(/\)/g, "]");
    //animate [[object to animate, object on to animate], [animation speed], [], []]
    anim[0] = eval(tmpanim.slice(tmpanim.indexOf("["),tmpanim.indexOf("]")+1));
    anim[1] = eval(tmpanim.slice(tmpanim.indexOf("][")+1,tmpanim.indexOf("]",tmpanim.indexOf("][")+1)+1));
    anim[2] = eval(tmpanim.slice(tmpanim.indexOf("[",tmpanim.indexOf("][")+2), tmpanim.lastIndexOf("][")+1));
    anim[3] = eval(tmpanim.slice(tmpanim.lastIndexOf("][")+1,tmpanim.lastIndexOf("]")+1));
    for (var i=0; i<anim[0].length; i+=2) { //change to ms and other options, make extras zero
      anim[1][i] = anim[1][i]*1000; anim[1].splice(i+1,0,0);
      anim[2].splice(i+1,0,0);
      anim[3].splice(i+1,0,0);
    }
    //alert("anim[0]: "+anim[0] +", anim[1]:"+ anim[1] + ", anim[2]:"+ anim[2] + ", anim[3]:"+ anim[3]);
  }          
  
  //if JSP object type is measurement  set fixed true and ctype = 'measurements'
  if (type == 'Coordinates' || type == 'Length' || type == 'Angle' || type == 'Perimeter' || type == 'Circumference' || type == 'Radius' || type == 'Area' || type == 'Slope' || type == 'Distance' || type == 'Ratio/Segments' || type == 'Ratio/Points' || type == 'Calculate' || type == 'Parameter') {
    fixed = true;
    ctype = 'measurements'
  }
  
  /* ** POINT SIZE */
  psize = eval(document.getElementById('jsxpointsize').value);
  if (a.indexOf("psize(")>0) {
    psize = eval(a.slice(a.indexOf("psize(")+6, a.indexOf(")", a.indexOf("psize(")+6)));
  }

  /* ** SHOW INFOBOX */
  if (document.getElementById('jsxshowinfo').checked == true) sinfo = true;
  else sinfo = false;
  if (a.indexOf("showInfoBox")>0)
    sinfo = true;
  /* SHOW INFOBOX */

  /*LABEL ALIGNMENT */
  if (a.indexOf("labelAlign(")>0) {
    labalig = a.slice(a.indexOf("labelAlign(")+11, a.indexOf(")", a.indexOf("labelAlign(")));
  }
  labelalign = createLabelAlign(document.getElementById('jsxlabelalignment').value, 0);
  if (type == "VectorTranslation")
    labelalign = createLabelAlign(document.getElementById('jsxlabelalignment').value, 10);
  if (labalig.length>0) {
    labelalign = "{offset:["+labalig+"]}"; }
  /*LABEL ALIGNMENT */

  /* **ARROW */
  if (a.indexOf("arrowF")>0)
    arrowf = true;
  if (a.indexOf("arrowL")>0)
    arrowl = true;
  /* ARROW */

  /* ** SNAP TO */
  if (a.indexOf("snapToGrid")>0)
    snaptogrid = true;
  /* SNAP TO */



  att = {Name:'', Color:'black', Fixed:fixed, Visible:true, Withlabel:true, Strokewidth:1, Straightlast:true, Straightfirst:true, AnchorX:'middle', Info:0, Trace:false, Size:psize, Infobox:sinfo, LabelAlign:labelalign, Stop:false, ArrowF:arrowf, ArrowL:arrowl, SnapToGrid:snaptogrid, Suffix:suf};
  el = {Row:row, Type:type, JsxType:jsxtype, CType:ctype, Pos:pos, Opts:opts, Att:att, Anim:anim, comment};
  return el;
}

/**  
 * Changes property JsxType of an element given as object created in sketchpadrowToJsxgElement(string)
 * [mostly just changes property to lowercase letters]
 * Also change the CType (constructor type), possible types are:
 * points, straightlines, circles, measurements, transformations, images, buttons, coordinatesystem, locus
 * @method changeTypeToJSX
 * @param {Object} a - 
 * @return {Object} a - return the object
 */  
function changeTypeToJSX(a) {
  if (a.Type == "FixedPoint") {
      a.JsxType = 'point'; 
      a.Opts = a.Opts.replace("]",",fixed:true]"); 
      a.CType = 'points';
  } 
  else if (a.Type == "Point" || a.Type == "PlotXY") {
    a.JsxType = a.Type.toLowerCase();
    a.CType = 'points';
  }
  else if (a.Type == "Origin&Unit" || a.Type == "OriginAndUnit") {
    a.JsxType = 'originandunit';
    a.CType = 'coorninatesystem';
  }
  else if (a.Type == "Point on object") {
    a.JsxType = 'glider';
    a.CType = 'points';
  }
  else if (a.Type == "Midpoint") {
    a.JsxType = a.Type.toLowerCase();
    a.CType = 'points';
  }
  else if (a.Type=='Line' || a.Type == 'Segment' || a.Type == 'Ray' || a.Type == 'Parallel' || a.Type == 'Perpendicular') {
    a.JsxType = a.Type.toLowerCase();
    a.CType = 'straightlines';
  }
  else if (a.Type == 'Circle' || a.Type == 'Circle by radius') {
    a.JsxType = a.Type.toLowerCase();
    a.CType = 'circles';
  }
  else if (a.Type == "FixedText") {
    a.JsxType = 'text';
    a.CType = 'buttons';
  }
  else if (a.Type == "Intersect1" || a.Type == "Intersect2" || a.Type == "Intersect") {
    if (a.Type == "Intersect2") a.Att.Info = 1; else a.Att.Info = 0;
      a.JsxType = 'intersection'; 
    }
  else if (a.Type == 'Reflection' || a.Type == 'Dilation' || a.Type == 'Dilation/SegmentRatio' || a.Type == 'Dilation/3PtRatio' || a.Type == 'Dilation/MarkedRatio' || a.Type == 'Rotation' || a.Type == 'Rotation/MarkedAngle' || a.Type == 'Rotation/MeasuredAngle'  || a.Type == 'Translation' || a.Type == 'VectorTranslation' || a.Type == 'Translation/FixedAngle/MarkedDistance' || a.Type == 'PolarTranslation') {
    a.JsxType = a.Type.toLowerCase();
    a.CType = 'transformations';
  }
  else if (a.Type == 'Coordinates' || a.Type == 'Length' || a.Type == 'Angle' || a.Type == 'Perimeter' || a.Type == 'Circumference' || a.Type == 'Radius' || a.Type == 'Area' || a.Type == 'Slope' || a.Type == 'Distance' || a.Type == 'Ratio/Segments' || a.Type == 'Ratio/Points' || a.Type == 'Calculate' || a.Type == 'Parameter') {
    a.JsxType = a.Type.toLowerCase();
    a.CType = 'measurements'
  }
  else if (a.Type == 'ShowButton' || a.Type == 'HideButton' || a.Type == 'SimultaneousButton' || a.Type == 'AnimateButton' || a.Type == 'MoveButton') {
    a.JsxType = a.Type.toLowerCase();
    a.CType = 'buttons';
  }
  else if (a.Type == 'Polygon') {
    a.JsxType = 'polygon';
    a.CType = 'interiors';
  }
  else {
    a.JsxType = a.Type.toLowerCase();
    a.CType = 'unknown';
  }
  return a;
    
}

/**
 * Changes property Pos of an element given as object created in sketchpadrowToJsxgElement(string)
 * Outcome depends of type of the element as follows:
 * - Point will change Pos to array with point coordinates [x,y],
 * - Unit coord will change Pos to array with reference to object and a coordinate [ref to obj, y],
 * @method changePosInfoToJSX
 * @param {Object} a -
 * @param {Array} applets -
 * @param {Int} coordd - coord divider, this is read from the original code in the main function JSPtoSJX
 * @param {Double} scx - scale x factor, this is read in the main function
 * @param {Double} scy - scale y factor, this is read in the main function
 * @param {Int} hasoriginunit - origin&unit info read in the main function from the original code
 * @return {Object} a - return the object with changed values
 * ... 
 */  
function changePosInfoToJSX(a, applets, coordd, scx, scy, hasoriginunit) {

  var x,y,o,t,values = [], butvadj=0;
    //button vertical adjustment:
    if (document.getElementById('usebuttonstyle').checked == true) butvadj = document.getElementById('buttonverticaladjsel').value;

    x = a.Pos.slice(0,a.Pos.indexOf(","));
    y = a.Pos.slice(a.Pos.indexOf(",")+1,a.Pos.length);
    
    if (a.JsxType == 'point')
      a.Pos = changeToCoord(x,y,applets,coordd,scx,scy,hasoriginunit);
    else if (a.JsxType == 'unitpoint'){
      a.Pos = [eval(x), changeToCoord(x,y,applets,coordd,scx,scy,hasoriginunit)[1]]; 
    }
    else if (a.JsxType == 'originandunit')
      a.Pos = eval("["+a.Pos+"]");
    else if (a.JsxType == 'text' || a.JsxType == 'image') {
      y = a.Pos.slice(a.Pos.indexOf(",")+1,a.Pos.indexOf(",", a.Pos.indexOf(",")+1));
      t = a.Pos.slice(a.Pos.indexOf("'")+1,a.Pos.lastIndexOf("'"));
      t = cleanString(t);
      a.Pos = [changeToCoord(x,y,applets,coordd,scx,scy,hasoriginunit)[0],changeToCoord(x,y,applets,coordd,scx,scy,hasoriginunit)[1],t];
    }
    else if (a.JsxType == 'movebutton') {
      y = eval(a.Pos.slice(a.Pos.indexOf(",")+1,a.Pos.indexOf(",", a.Pos.indexOf(",")+1))) + eval(butvadj);
      o = 1000 * eval(a.Pos.slice(a.Pos.indexOf(",", a.Pos.indexOf(",")+1)+1, a.Pos.indexOf(",'")));     
        t = a.Pos.slice(a.Pos.indexOf("'")+1, a.Pos.lastIndexOf("'"));
      a.Pos = [changeToCoord(x,y,applets,coordd,scx,scy,hasoriginunit)[0],changeToCoord(x,y,applets,coordd,scx,scy,hasoriginunit)[1],o,t]; 
    }
    else if (a.JsxType == 'showbutton' || a.JsxType == 'hidebutton' || a.JsxType == 'simultaneousbutton' || a.JsxType == 'animatebutton') {
      y = eval(a.Pos.slice(a.Pos.indexOf(",")+1,a.Pos.indexOf(",", a.Pos.indexOf(",")+1))) + eval(butvadj); 
      t = a.Pos.slice(a.Pos.indexOf("'")+1,a.Pos.lastIndexOf("'")); 
        if (t.indexOf('F(')>=0) { t=t.replace(/F/g, '&#70;'); }
      a.Pos = [changeToCoord(x,y,applets,coordd,scx,scy,hasoriginunit)[0], changeToCoord(x,y,applets,coordd,scx,scy,hasoriginunit)[1], t];
    }
    else if (a.JsxType == 'ratio/points' || a.JsxType == 'angle') {
        values = eval("["+a.Pos.slice(0,a.Pos.lastIndexOf(",", a.Pos.indexOf("'")))+"]");
        values[3] = changeToCoord(values[3],values[4],applets,coordd,scx,scy,hasoriginunit)[0];
        values[4] = changeToCoord(values[3],values[4],applets,coordd,scx,scy,hasoriginunit)[1];
        values.push(a.Pos.slice(a.Pos.indexOf("'")+1,a.Pos.lastIndexOf("'")));
        a.Pos = values; 
    }
    else if (a.JsxType == 'distance' || a.JsxType == 'coordinates' || a.JsxType == 'ratio/segments') {
      values = eval("["+a.Pos.slice(0,a.Pos.lastIndexOf(",", a.Pos.indexOf("'")))+"]");
        values[2] = changeToCoord(values[2],values[3],applets,coordd,scx,scy,hasoriginunit)[0];
        values[3] = changeToCoord(values[2],values[3],applets,coordd,scx,scy,hasoriginunit)[1];
        values.push(a.Pos.slice(a.Pos.indexOf("'")+1,a.Pos.lastIndexOf("'")));
        a.Pos = values; 
    }
    else if (a.JsxType == 'length' || a.JsxType == 'circumference' || a.JsxType == 'radius' || a.JsxType == 'area' || a.JsxType == 'slope') {
      values = eval("["+a.Pos.slice(0,a.Pos.lastIndexOf(",", a.Pos.indexOf("'")))+"]");
      values[1] = changeToCoord(values[1],values[2],applets,coordd,scx,scy,hasoriginunit)[0];
      values[2] = changeToCoord(values[1],values[2],applets,coordd,scx,scy,hasoriginunit)[1];
      values.push(a.Pos.slice(a.Pos.indexOf("'")+1,a.Pos.lastIndexOf("'")));
      a.Pos = values;
    }
    else if (a.JsxType == 'calculate') {
      values = eval("["+ a.Pos.slice(0,a.Pos.indexOf(",", a.Pos.indexOf(",")+1)) + "]");
      values = changeToCoord(values[0],values[1],applets,coordd,scx,scy,hasoriginunit);
        values[2] = a.Pos.slice(a.Pos.indexOf("'")+1, a.Pos.lastIndexOf("'", a.Pos.lastIndexOf("'")-1));
        values[2] = values[2].slice(0, values[2].lastIndexOf("'"));
        values[2] = cleanString(values[2]);
        values[3] = a.Pos;
        values[4] = eval("["+a.Pos.slice(a.Pos.lastIndexOf("(")+1,a.Pos.lastIndexOf(")"))+"]");
        a.Pos = values;
    }
    else {
      //else if (a.JsxType == 'dilation/markedratio' || a.JsxType == 'line' || a.JsxType == 'segment' || a.JsxType == 'circle' || a.JsxType == 'circle by radius' || a.JsxType == 'perpendicular' || a.JsxType == 'intersection' || a.JsxType == 'glider' || a.JsxType == 'ray' || a.JsxType == 'reflection' || a.JsxType == 'midpoint' || a.JsxType == 'parallel' || a.JsxType == 'axisx' || a.JsxType == 'axisy' || a.JsxType == 'vectortranslation' || a.JsxType == 'translation' || a.JsxType == 'dilation/3ptratio') 
      a.Pos = eval("["+a.Pos+"]"); 
    } 

    return a;
}

/**
* Changes some values in original Java Sketchpad code into form that JSXGraph can understand.
* @method changeOptionsToJSX
* @param {Object} a - object a is created from original code and has the values that will be changed
* @return {Object} a - return object a with changed values
*/
function changeOptionsToJSX(a) {

  //change brackets
    a.Opts = a.Opts.replace("[", "{");
    a.Opts = a.Opts.replace("]", "}");
    a.Opts = a.Opts.replace(a.Opts.slice(a.Opts.indexOf("layer"), a.Opts.indexOf("layer")+9), "");

  //change color
  a.Opts = a.Opts.replace("black", "color:'black'");
    a.Opts = a.Opts.replace("white", "color:'white'");
    a.Opts = a.Opts.replace("red", "color:'red'");
    a.Opts = a.Opts.replace("blue", "color:'blue'");
    a.Opts = a.Opts.replace("green", "color:'green'");
    a.Opts = a.Opts.replace("yellow", "color:'yellow'");
    a.Opts = a.Opts.replace("magenta", "color:'magenta'");
    a.Opts = a.Opts.replace("cyan", "color:'cyan'");
    
    // change name
    a.Opts = a.Opts.replace("label('", "name:'");
    a.Opts = a.Opts.replace("'),", "',");
    a.Opts = a.Opts.replace("')", "'");
    
    // text alignment
    a.Opts = a.Opts.replace("justifyLeft", "anchorX:'left'");
    a.Opts = a.Opts.replace("justifyCenter", "anchorX:'middle'");
    a.Opts = a.Opts.replace("justifyRight", "anchorX:'right'");
    
    //change other options
  a.Opts = a.Opts.replace("hidden", "visible:false");
    a.Opts = a.Opts.replace("thick", "strokeWidth=2");
    a.Opts = a.Opts.replace("bold,", "");
    a.Opts = a.Opts.replace("{plain,", "{");
    a.Opts = a.Opts.replace("font(", "");
    a.Opts = a.Opts.replace("'Helvetica',", "");
    a.Opts = a.Opts.replace(",,", ",");
    
    return a;
}

/**
* Changes some attributes from original Java Sketchpad code into form that JSXGraph can understand
* @method changeAttributesToJSX(string) 
* @param {Object} a - object a is created from original code and has the values that will be changed
* @return {Object} a - return object a with changed values
*/
function changeAttributesToJSX(a) {
  var tmpcolor = [];
  
  // name attribute
  if (a.Opts.indexOf("label")>=0)
    a.Att.Name = a.Opts.slice(a.Opts.indexOf("label(")+7, a.Opts.indexOf("')", a.Opts.indexOf("label(")+8));
    if (document.getElementById('latex').checked == true)
      a.Att.Name = "\\\\("+a.Att.Name+"\\\\)"
        
  // colour attribute
  if (a.Opts.indexOf("white")>=0)
    a.Att.Color = 'grey';
  else if (a.Opts.indexOf("black")>=0)
    a.Att.Color = 'black';
  else if (a.Opts.indexOf("red")>=0)
    a.Att.Color = 'red';
  else if (a.Opts.indexOf("blue")>=0)
    a.Att.Color = 'blue';
  else if (a.Opts.indexOf("green")>=0)
    a.Att.Color = 'green'
  else if (a.Opts.indexOf("yellow")>=0)
    a.Att.Color = 'yellow'
  else if (a.Opts.indexOf("magenta")>=0)
    a.Att.Color = 'magenta';
  else if (a.Opts.indexOf("cyan")>=0)
    a.Att.Color = 'cyan';
  else if (a.Opts.indexOf("color(")>=0) {
    tmpcolor = eval("[" + a.Opts.slice(a.Opts.indexOf("color(")+6, a.Opts.indexOf(")", a.Opts.indexOf("color(")+6)) + "]");
    a.Att.Color = "#"+ rgbToHex(tmpcolor[0],tmpcolor[1],tmpcolor[2]);
  }
  
  // visible attribute
  if (a.Opts.indexOf("hidden")>=0)
    a.Att.Visible = false;
  if (a.Opts.indexOf("traced")>=0)
    a.Att.Trace = true;
  
  // thickness attribute  
  if (a.Opts.indexOf("thick3")>=0 || a.Opts.indexOf("thick")>=0)
    a.Att.Strokewidth = 3;
  if (a.Opts.indexOf("thick6")>=0)
    a.Att.Strokewidth = 6;
  if (a.Opts.indexOf("thick5")>=0)
    a.Att.Strokewidth = 5;
  if (a.Opts.indexOf("thick4")>=0)
    a.Att.Strokewidth = 4;
  if (a.Opts.indexOf("thick2")>=0)
    a.Att.Strokewidth = 2;
  if (a.Opts.indexOf("thick") <0 )
    a.Att.Strokewidth = 1;
  
  if (a.Opts.indexOf("fixed:true") >= 0)
    a.Att.Fixed = true;
  else if (a.Opts.indexOf("fixed:false") >= 0)
    a.Att.Fixed = false;
  
  // text alignment attribute 
  if (a.Opts.indexOf("justifyLeft") >= 0)
    a.Att.AnchorX = 'left';
  else if (a.Opts.indexOf("justifyCenter") >= 0)
    a.Att.AnchorX = 'middle';
  else if (a.Opts.indexOf("justifyRight") >= 0)
    a.Att.AnchorX = 'right';

  //suffix
  if (a.Opts.indexOf("suffix") >= 0) {
    a.Att.Suffix = a.Opts.slice(a.Opts.indexOf("'",a.Opts.indexOf("suffix"))+1, a.Opts.indexOf("'",a.Opts.indexOf("'",a.Opts.indexOf("suffix"))+1));
  }
  
  if (a.Opts.indexOf("_BREAK") >=0)
    a.Att.Stop = true;

  return a;    
}

/**
 * Get options as a full string {options}, that has all the options that are needed in construction of this object. 
 * The purpose of this function is to shorten the converted code. 
 * This is also to make changing of defaul options easier (for example point color).
 * @method getOptions
 * @param {Object} e - Object that has option values
 * @param {String} s - optional, extra option to add options string. This is for some special attributes. Function just adds s in the return string.
 * @return {String} options - String that has only the options needed, for example {name:'A', color:'red'}. There will be no options that values are default in JSXgraph syntax
 */
function getOptions(e, s) {
  //straightLast:"+el[i].Att.Straightlast+", straightFirst:"+el[i].Att.Straightfirst+", lastArrow:"+el[i].Att.ArrowL+", firstArrow:"+el[i].Att.ArrowF+"} );";

  var options = "{";
  
  if (e.CType == 'points') {
    options = options + "name:'"+e.Att.Name+"',";
    if (e.Att.Name.length > 0) options = options  + "label:"+e.Att.LabelAlign+",";
    if (e.Att.Color.length > 0) options = options + "color:'"+e.Att.Color+"',";
    if (!e.Att.Visible) options = options + "visible:"+e.Att.Visible+",";
    if (e.Att.Fixed) options = options + "fixed:"+e.Att.Fixed+",";
    if (e.Att.Size != 2) options = options + "size:"+e.Att.Size+",";
    //if (e.Att.Trace == true) options = options + "trace:"+e.Att.Trace+", ";
    if (!e.Att.Infobox) options = options + "showInfoBox:"+e.Att.Infobox+",";
    //if (e.Att.LabelAlign.length > 0 && e.Att.Name.length > 0) options = options + "label:"+e.Att.LabelAlign+",";
    if (e.Att.SnapToGrid == true) options = options + "snapToGrid:"+e.Att.SnapToGrid+",";
  }
  else if (e.CType == 'straightlines') {
    if (e.Att.Name.length > 0) options = options + "label:'"+e.Att.Name+"',";
    if (e.Att.Color.length > 0) options = options + "strokeColor:'"+e.Att.Color+"',";
    if (e.JsxType == 'ray') options = options + "straightFirst:false,";
    options = options + "strokeWidth:"+e.Att.Strokewidth+",";
    if (e.Att.ArrowL == true) options = options + "lastArrow:true,";
    if (e.Att.ArrowF == true) options = options + "firstArrow:true,";
    if (!e.Att.Visible) options = options + "visible:"+e.Att.Visible+",";
  }
  else if (e.CType == 'circles') {
    if (e.Att.Name.length > 0) options = options + "label:'"+e.Att.Name+"',";
    if (e.Att.Color.length > 0) options = options + "strokeColor:'"+e.Att.Color+"',";
    if (!e.Att.Visible) options = options + "visible:"+e.Att.Visible+",";
    options = options + "strokeWidth:"+e.Att.Strokewidth+",";
  }
  else if (e.CType == 'interiors') {
    //{name:'"+el[i].Att.Name+"', fillColor:'"+el[i].Att.Color+"', withLines:false,visible:"+el[i].Att.Visible+", highlight:false, showInfoBox:"+el[i].Att.Infobox+", label:"+el[i].Att.LabelAlign+"}
    options = options + "fillColor:'"+e.Att.Color+"',withLines:false,highlight:false,";
    if (!e.Att.Visible) options = options + "visible:"+e.Att.Visible+",";
    if (e.Att.Name.length > 0) options = options + "label:'"+e.Att.Name+"',";
  }
  else if (e.CType == 'transformations') {
    options = options + "name:'"+e.Att.Name+"',";
    if (e.Att.Name.length > 0) options = options + "label:"+e.Att.LabelAlign+",";
    if (e.Att.Color.length > 0 && e.Att.Color != 'black') options = options + "color:'"+e.Att.Color+"',";
    if (e.Att.Visible == false) options = options + "visible:false,";
    if (e.Att.Size != 2) options = options + "size:"+e.Att.Size+",";
    if (!e.Att.Infobox) options = options + "showInfoBox:"+e.Att.Infobox+",";
    options = options + s;
  }
  else if (e.CType == 'measurements') {
    if (e.Att.Color.length > 0 && e.Att.Color != 'black') options = options + "color:'"+e.Att.Color+"',";
    if (e.Att.Fixed) options = options + "fixed:true,";
  }
  else if (e.CType == 'buttons') {
    options = options + "fixed:true,";
    if (e.Att.Color.length > 0 && e.Att.Color != 'black') options = options + "color:'"+e.Att.Color+"',";
    if (e.JsxType=='text') options = options + "anchorX:'"+e.Att.AnchorX+"',";
  }
  else {
    options = options + "color:'"+e.Att.Color+"',";
  }

  if (options[options.length-1]==",")
    return options.slice(0,options.length-1) + "}";
  else 
    return options + "}";
}

/**
 * Simple string cleaning function (trim and replace all ' with "), return changed s (String).
 * @method cleanString
 * @param {String} s - string
 * @return {String} s - "cleaned" string
 */
function cleanString(s) {
  s = s.trim();
  s = s.replace(/'/g, "\"");
  return s;
}

/**
 * Checks if there is Origin&Unit constructor in code, and return originelements rownr (String).
 * @method getOrigin
 * @param {String} a - original Java Sketchpad code
 * @return {String} org - information that is in the Origin&Unit line between the brackets '(' and ')'
 */
function getOrigin(a) {
  var rw="", ind, org;
  if (a.indexOf('Origin&Unit')>=0)
    rw = a.slice(a.indexOf('(', a.indexOf('Origin&Unit'))+1, a.indexOf(',', a.indexOf('Origin&Unit')));
  else if (a.indexOf('OriginAndUnit')>=0)
    rw = a.slice(a.indexOf('(', a.indexOf('OriginAndUnit'))+1, a.indexOf(',', a.indexOf('OriginAndUnit')));
  rw = '{'+rw+'}';
  org = a.slice(a.indexOf('(',a.indexOf(rw))+1, a.indexOf(')',a.indexOf(rw)));
  //alert(org);
  return org;
}

/**
 * Function to change coordinates so that the (0,0) is the origo.
 * @method changeToCoord
 * @param {Int} x - x coordinate in Java Sketchpad form
 * @param {Int} y - y coordinate in Java Sketchpad form
 * @param {Array<Int>} appletsize - appletsize 
 * @param {Int} coord_div - coordinates dividor if coordinates has been set in Java Sketchpad code using Origin&Unit and Unitpoint commands
 * @param {Double} scalex - factor that is used in scaling the image horizontally
 * @param {Double} scaley - factor that is used in scaling the image vertically (this is not actually used, since the scalex and scaley are defines as the same value in main function)
 * @param {String} hasorigin - coordinates of origin if it has been changes in original Java Sketchapd code
 * @return {Array} - created coordinates (Array)
 */
function changeToCoord(x,y,appletsize, coord_div, scalex, scaley, hasorign) {
  var origin, moved_origin;
  origin = [appletsize[0]/coord_div/2, appletsize[1]/coord_div/2];
  if (hasorign.length > 0) {
    moved_origin = eval('['+hasorign+']');
    //moved_origin = hasorign;
    moved_origin[0] = moved_origin[0]*scalex; moved_origin[1] = moved_origin[1]*scaley; //alert(moved_origin);
    x = (-1*(origin[0]-((scalex*x)/coord_div))-((moved_origin[0]-(appletsize[0]/2))/coord_div));
    y = (origin[1]-((scaley*y)/coord_div)+((moved_origin[1]-(appletsize[1]/2))/coord_div));
  }
  else {
    x = (-1*(origin[0]-((scalex*x)/coord_div)));
    y = (origin[1]-((scaley*y)/coord_div));
  }
  return [Math.round(x*100)/100, Math.round(y*100)/100];
}

/** 
 * Function that creates and returns (Array) position of the glider point.
 * Param variables are string and number(a,b).
 * @method gliderPoint
 * @param {Object} a - JSXGraph Object
 * @param {Double} b - this is to set the glider point
 * @param {Object} c - Object circle
 * @return {Array} - coordinates for moving glider to right position
 */
function gliderPoint(a,b,c) {
  
  var d, dx, dy, x=0,y=0, p1x, p2x, p1y, p2y;
  if (a.getType() == 'segment' || a.getType() == 'line' || a.getType() == 'axis') {  
    //alert(a.getType() +", ");
    p1x = a.point1.X();
    p2x = a.point2.X();  
    p1y = a.point1.Y();  
    p2y = a.point2.Y();

    dx = Math.abs(p1x-p2x);
    dy = Math.abs(p1y-p2y);

    //alert(p1x+" , "+p1y+" , "+p2x+" , "+p2y+" , "+dx+" , "+dy+" , "+b);
    if (p2x<p1x)
      x=p2x+(dx*b);
    else
      x=p1x+(dx*b);
    if (p1y<p2y)
      y=p1y+(dy*b);
    else
      y=p2y+(dy*b);
    return [x,y];
  }      
  else if (a.getType() == 'parallel' || a.getType() == 'perpendicular') {
    x = a.point1.X()+b;
    y = a.point1.Y()+b;
    return [x,y];
  }
  else if (a.getType() == 'circle') {
    d = a.Radius();
    x = c.X() + d*Math.cos(b);
    y = c.Y() - d*Math.sin(b);
    return [x,y];
  }
} 

/** 
 * Calculates and returns path for the animation
 * @method getCircleAnimationPath
 * @param {Strign} object - object in convertor
 * @param {String} type - type of an object
 * @param {Int} direction - direction of the animation, possible values are 0 or 1, if not given direction will be 1
 * @return {String} path - retuns path as a string that has the array in it
 */
function getAnimationPath(object, type, direction) {
  var c = object;
  var path = []; 
  var next_tick = 0;
  var ticksaddon = 0.1;
  if (type == 'circle') {
    while (next_tick <= 1) {
      path.push("["+c+".X("+next_tick+"), "+c+".Y("+next_tick+")]");
      next_tick = Math.round((next_tick + ticksaddon)*10)/10; 
    }
    if (direction == 1) path = path.reverse();
    //path.pop();
  }
  else {
    if (direction == 0) {
      path.push("["+c+".point2.X(),"+c+".point2.Y()]");
      path.push("["+c+".point1.X(),"+c+".point1.Y()]");
      path.push("["+c+".point2.X(),"+c+".point2.Y()]");
    }
    else {
      path.push("["+c+".point1.X(),"+c+".point1.Y()]");
      path.push("["+c+".point2.X(),"+c+".point2.Y()]");
      path.push("["+c+".point1.X(),"+c+".point1.Y()]");
    }
  }

  return "["+path+"]";
}

/** 
 * This function creates label offset for the elements in jsxgboard
 * @method createLabelAlign
 * @param {String} l - value given in UI, direction for moving label
 * @param {String} a - value is how much to move the label
 * @return {String} - attribute to change label position in JSXGraph image 
 */
function createLabelAlign(l, a) {
  if (l == "ct") {return "{offset:[0,10]}"}
  else if (l == "rt") {return "{offset:[10,10]}"}
  else if (l == "rm") {return "{offset:[10,0]}"}
  else if (l == "rb") {return "{offset:[10,-10]}"}
  else if (l == "cb") {return "{offset:[0,-10]}"}
  else if (l == "lb") {return "{offset:[-10,-10]}"}
  else if (l == "lm") {return "{offset:[-10,0]}"}
  else if (l == "lt") {return "{offset:[-10,10]}"}
}

/** 
 * Help function to change colour from RBG to Hex
 * source: http://www.javascripter.net/faq/rgbtohex.htm 
 * @method rgbToHex
 * @param {String} R -
 * @param {String} G -
 * @param {String} B -
 * @return {String} toHex(R)+toHex(G)+toHex(B) - calculated Hex-colour
 */
function rgbToHex(R,G,B) {return toHex(R)+toHex(G)+toHex(B)}

/**
 * Help function to change colour from RBG to Hex
 * source: http://www.javascripter.net/faq/rgbtohex.htm 
 * @method toHex
 * @param {String} n - value to be changed
 * @return {String} changed Hex-value
 */
function toHex(n) {
  n = parseInt(n,10);
  if (isNaN(n)) return "00";
  n = Math.max(0,Math.min(n,255));
  return "0123456789ABCDEF".charAt((n-n%16)/16)
  + "0123456789ABCDEF".charAt(n%16);
} /* /source */

/**
 * Check if input (string) is jspcode with $variables
 * @method checkJSPStyle
 * @param {String} c - JSP code
 * @return {Boolean}
 */
function checkJSPStyle(c) {
  if (c.indexOf('$')>=0) //if there is $-char in code return false
    return false;
  return true;
}

/**
 * Changes all input code $name variablenames to {rownumber} representation and returns changed code (string)
 * @method varJSPtoNumJSP
 * @param {String} c - JSP code in $-form
 * @return {String} c - JAva Sketchpad code in {row no}-form
 */
function varJSPtoNumJSP(c) {
  var dList = [], dStr="", dVar="", indx1, indx2, j, dTmp="", commends=[];
  
  //check for commends and "extra" lines
  while (c.indexOf('${')>=0) {
    commends.push(c.slice(c.indexOf('${'), c.indexOf('$}')+2));
    c = c.replace(commends.pop(), "");
  }

  while (c.indexOf('#')>=0 && c.indexOf('#')<c.indexOf('$')) {
    commends.push(c.slice(c.indexOf('#'), c.indexOf('$')));
    c = c.replace(commends.pop(), "");
  }  

  for(var i=0; i<c.length; i++) {
    if (c[i] == '$' && c[i+1]!='{' && c[i+1]!='}') {
      indx1 = i;
      while (c[i]!=' ' && c[i]!=',' && c[i]!=')') i++;
      indx2 = i;
      
      dVar = c.slice(indx1,indx2)+'|';
      if (dStr.indexOf(dVar)==-1) {
        dStr = dStr + dVar;
        dList.push(dVar);
      }
    }
  }
  for(var i=0; i<dList.length; i++)
    dList[i] = dList[i].replace('|', '');

  for(var i=0; i<dList.length; i++) {
    j=i+1;
    c = c.replace(dList[i], "{"+j+"}");
    while(c.indexOf(dList[i])>=0 && (c[c.indexOf(dList[i])+dList[i].length] == ' ' || c[c.indexOf(dList[i])+dList[i].length] == ',' || c[c.indexOf(dList[i])+dList[i].length] == ')'))
      c = c.replace(dList[i], j);
    /*dTmp = dList[i]+" ";
    c = c.replace(/(dTmp)/gm, (j+" "));
    dTmp = dList[i]+",";
    c = c.replace(/(dTmp)/gm, (j+","));
    dTmp = dList[i]+")";
    c = c.replace(/(dTmp)/gm, (j+")"));
    dTmp="";*/
  }
  while (c.indexOf('$')>=0) {
    for (var i=0; i<dList.length; i++) {
      j=i+1;
      while(c.indexOf(dList[i])>=0 && (c[c.indexOf(dList[i])+dList[i].length] == ' ' || c[c.indexOf(dList[i])+dList[i].length] == ',' || c[c.indexOf(dList[i])+dList[i].length] == ')'))
        c = c.replace(dList[i], j);
    }
    while (c.indexOf('${')>=0)
      c = c.replace('${', '');
    while (c.indexOf('$}')>=0)
      c = c.replace('$}', '');
  }
  
  return c;
}

/**
 * Function to create string that contains funtion as a string for 'Calculate' operation.
 * E.g. input calculateFunction("A2+3*@sin_", [5]) will product a string "(Math.sin((3*(A+2))))", where A is replaced with value from row no 5 in Java Sketchpad code.
 * Inputs are string (a), array of element indexes (b) and measurements (calculations) in that indexes in array b are referring to.
 * Uses function mathCalc to create string.
 * @method calculateFunction(string, array, array)
 * @param {String} a - string that has the calculation, for example "A2+3*@sin_"
 * @param {Array<Int>} b - array of elements in calculate command that are used as variables. For example if command is Calculate(0,315,'f(x,y) = ','A2^ B2^ -')(53,54)[magenta], b will be [53,54]
 * @param {Array<String>} calc - has the calculations that jsptojsx convertor has created as strings. 
 * @return {String} ans - answer for the calculation
 */
function calculateFunction(a,b,calc) {

    var i, j=0, tmpstr="", obj = [], terms = [], ans="", vbstr="", indx=0, v_indx=0;    
    var abc = "ABCDEF", operators = "+-*/^%", functions = "sin_ cos_ tan_ abs_ sqrt ln__ rond trnc sgn_ asin acos atan log_"; 

    a = a.slice(a.lastIndexOf("'", a.lastIndexOf("'")-1)+1, a.lastIndexOf("'"));
        
    //Gettin values for variables here
    while (a.indexOf("#")>=0){
      indx = a.indexOf("#");
      /*if (a[indx+1] == 'A') j=0;
      else if (a[indx+1] == 'B') j=1;
      else if (a[indx+1] == 'C') j=2;
      else if (a[indx+1] == 'D') j=3;*/
      if (a[indx+2] == '1') v_indx=0;
      else v_indx = 1;
      tmpstr = calc[b[getNumberOfCharForCalculate(a[indx+1])]][v_indx];
      tmpstr = tmpstr.replace("function(){return ","");
      tmpstr = tmpstr.replace(";}","");
      while (tmpstr.indexOf("Dist")>=0)
        tmpstr = tmpstr.replace("Dist","dist"); //change Dist() because it has capital 'D'
      tmpstr = "|"+tmpstr+"|";
      vbstr = a.slice(indx, indx+3);
      while(a.indexOf(vbstr)>=0) 
              a = a.replace(vbstr, tmpstr); 
      vbstr="";
    }
    
    for (i=0; i<abc.length; i++) {
      if (a.indexOf(abc[i])>=0 ) {          
          //tmpstr = calc[b[j]];
          tmpstr = calc[b[getNumberOfCharForCalculate(abc[i])]];
          tmpstr = tmpstr.replace("function(){return ","");
          tmpstr = tmpstr.replace(";}","");
          while (tmpstr.indexOf("Dist")>=0)
            tmpstr = tmpstr.replace("Dist","dist"); //change Dist() because it has capital 'D'
          tmpstr = "|"+tmpstr+"|";   
          while(a.indexOf(abc[i])>=0 )
              a = a.replace(abc[i], " "+tmpstr+" "); 
          j++;
      }                
    }

    while (a.indexOf("dist")>=0)
      a=a.replace("dist","Dist"); //change all lowletter 'dist' back to 'Dist'

    for (i=0; i<a.length; i++){
        if (a[i] == "@") {
          i++; 
          terms.push(a[i++]+a[i++]+a[i++]+a[i]);
        }
        else if (a[i] == "|") {
          terms.push(a.slice(i+1,a.indexOf("|",i+1)));
          i = a.indexOf("|",i+1);
        }
        else if (operators.indexOf(a[i]) >= 0) {
          terms.push(a[i]);
        }
        else if (a[i] != " ") {
          var string =""; j=i;
          while(a[j] != " " && a[j] != "@" && operators.indexOf(a[j]) == -1 && abc.indexOf(a[j]) == -1) {
              string = string+a[j];
              j++; 
          } 
          terms.push(string); i=j-1;          
        } 
    } 

    for (i=0; i<terms.length; i++) {
      if (functions.indexOf(terms[i].toString()) >= 0) {
        ans = mathCalc(terms[i], obj.pop());
        obj.push(ans);              
      }
      else if (operators.indexOf(terms[i].toString()) >=0) {
        ans = mathCalc(terms[i], obj.pop(), obj.pop());
        obj.push(ans); 
      }
      else {
        obj.push(terms[i]);
      }
    }
    if (obj.length>0)
      ans = obj.pop();
  return ans;
}

/** 
 * Creates one calculation with given operator and inputs. Second input is optional.
 * E.g. mathCalc("+", "1", "5") returns string "(1+5)" and
 * mathCalc("@sin_", "3.14") returns string "Math.sin(3.14)".
 * @method  mathCalc
 * @param {String} f - mathematical operation
 * @param {String} a - mathematical value or expression
 * @param {String} b - mathematical value or expression
 * @return {String} mathematical expression as a JavaScript string
*/
function mathCalc(f,a,b) {
  if (f == "+") {return "("+b+"+"+a+")";}
    else if (f == "-") {return "("+b+"-"+a+")";}
    else if (f == "*") {return "("+b+"*"+a+")";}
    else if (f == "/") {return "("+b+"/"+a+")";;}
    else if (f == "^") {return "Math.pow("+b+","+a+")";}
    else if (f == "%") {return "(-1*"+a+")";}
    else if (f == "sin_") {return "Math.sin("+a+")";}
    else if (f == "cos_") {return "Math.cos("+a+")";}
    else if (f == "tan_") {return "Math.tan("+a+")";}
    else if (f == "abs_") {return "Math.abs("+a+")";}
    else if (f == "sqrt") {return "Math.sqrt("+a+")";}
    else if (f == "ln__") {return "Math.log("+a+")";}
    else if (f == "rond") {if (Math.abs(Math.abs(a)-Math.abs(Math.floor(a))) < Math.abs(Math.abs(a)-Math.abs(Math.ceil(a)))) return Math.floor(a); else return Math.ceil(a);}
    else if (f == "trnc") {return "Math.floor("+a+")";} //ROND / / SGN_!
    else if (f == "sgn_") {return "Math.sign("+a+")";}
    else if (f == "asin") {return "Math.asin("+a+")";}
    else if (f == "acos") {return "Math.acos("+a+")";}
    else if (f == "atan") {return "Math.atan("+a+")";}
    else if (f == "log_") {return "Math.log10("+a+")";}
}

/**
 * Simple function to get number of char for the Calculate operation (get order of variable)
 * @method getNumberOfCharForClaculation
 * @param {String} a - alphabet from A to F
 * @return {Int} integer from 0 to 5
 */
function getNumberOfCharForCalculate(a) {
  if (a=='A') return 0;
  else if (a=='B') return 1;
  else if (a=='C') return 2;
  else if (a=='D') return 3;
  else if (a=='E') return 4;
  else if (a=='F') return 5;
  else return 0;
}

/** JAVASKETCHPAD TO JSXGRAPH CONVERTER (updated 08.01.2017)
 * This is the main function, that creates converted JSXGraph code from code-input and other input elements.
 * Input variables are:
 * code_input that is jsp code we want to convert (String)
 * size_input (optional) has table size information as width and height for example [400,400] (Array)
 * elementname_input has the element name information (String)
 * isFullPageConvert has the info if we are using fullpage convertor (boolean)
 * @param {String} code_input - original Java Sketchpad code
 * @param {Array<Int>} size_input - tablesize
 * @param {String} elementname_input - element name
 * @param {Boolean} isFullPageConvert - if is full page conver
 * @return {String} codestring - converted code to JSXGraph
 */

function jspToJsx(code_input, size_input, elementname_input, isFullPageConvert) {
  
  var appletsize = [400,400], 
    boardsize = [-5,5,5,-5],
    drawaxis = false,
    zoom = 0.9,  
    unitx = 20,
    unity = 20,
    coord_div=1,
    locusPoints=30,
    scalex = 1.0,
    scaley = 1.0,
    mesaccu = 10,
    animticks = 50,
    borders_on = 0,
    butvertical = 0;
var evalstring = [],
    codestring ="",
    teststring = "<h3><u>Developer attributes</u></h3>", 
    origstring = "<h3><u>JavaSketchpad code</u></h3>", 
    tmpstring ="",
    errors ="<u>Errors:</u><br><br>",
    sketch ="",
    has_origin_unit = "",
    scriptsource,
    elid,
    elid,
    sgrid,
    buttonstyle="<sty"+"le>.jxgbox button {padding:",
    animtype;
var sketchrows = [],
    sketchrows_comment =[],
    elr =[],
    el =[],
    calc = [],     
    animate = [];
 
  /* reading sketchcode and setting 
   * coordinate system (if in code command UnitPoint, else 100px)
   */
  if (code_input.length>12)
    sketch = code_input;
  else 
    sketch = document.getElementById(code_input).value.replace(/(\r\n|\n|\r|" ")/gm,"");
  sketch = sketch.replace(/(\t)/gm, " ");
  sketch = sketch.trim();

  //check codestyle (and switch from JSP-$ if needed)
  if(!checkJSPStyle(sketch)) sketch = varJSPtoNumJSP(sketch);

    /* scaling factors
   */
  scalex = document.getElementById('scalewidth').value;
  scaley = scalex; //document.getElementById('scaleheight').value;

 /* setting coordinate system
 */
  if (sketch.indexOf("UnitPoint")>=0)
    coord_div=eval(sketch.slice(sketch.indexOf(",", sketch.indexOf("UnitPoint"))+1, sketch.indexOf(")", sketch.indexOf("UnitPoint")))) * scalex;

  if (sketch.indexOf("Origin&Unit")>=0 || sketch.indexOf("OriginAndUnit")>=0) {
    if (sketch.indexOf("$")<0) {
      has_origin_unit = getOrigin(sketch);
    }
  }


  
  /* appletsize
   * from input texy field or as user input from code
   * */
  if (size_input) {
    appletsize = size_input;
    document.getElementById('boardwidthinput').value = size_input[0] * scalex;
    document.getElementById('boardheightinput').value = size_input[1] * scaley;
  }
  else {
    appletsize = [document.getElementById('boardwidthinput').value * scalex, document.getElementById('boardheightinput').value * scaley];
    if (sketch.indexOf("WIDTH=")>=0 && sketch.indexOf("HEIGHT=")>=0) {
      appletsize = [sketch.slice(sketch.indexOf("WIDTH=")+6, sketch.indexOf("HEIGHT=")) * scalex, sketch.slice(sketch.indexOf("HEIGHT=")+7, sketch.indexOf("HEIGHT=")+10) * scaley];
      document.getElementById('boardwidthinput').value = sketch.slice(sketch.indexOf("WIDTH=")+6, sketch.indexOf("HEIGHT="));
      document.getElementById('boardheightinput').value = sketch.slice(sketch.indexOf("HEIGHT=")+7, sketch.indexOf("HEIGHT=")+10);
    }
  }
  /* boardsize
   * initializing by appletsize
   */
  boardsize = [(appletsize[0]/coord_div/2)*-1, appletsize[1]/coord_div/2, appletsize[0]/coord_div/2, (appletsize[1]/coord_div/2)*-1]
  
  /* setting unitx and unity
   * for hiding buttons outside the borders of the image
   */
  unitx = scalex*appletsize[0]/coord_div,
  unity = scaley*appletsize[1]/coord_div;

  /* getting user option of draw axis (yes/no)
   */
  if (document.getElementById('drawaxis').checked == true) drawaxis = true; else drawaxis = false;
  
  /* reading user input for zoom option (default value is 0.9)
   */
  zoom = document.getElementById('zoom').value;

  /* reading user input for measurement accuracy option (default value is one decimal)
   */
  mesaccu = document.getElementById('measurementaccuracy').value;

  /* show grid (yes/no)
   */
  if (document.getElementById('showgrid').checked == false) sgrid=false; else sgrid=true;

  // reading user input for boardname & element id name  
   //
  if (elementname_input) {
    boardname = elementname_input;
    elid = elementname_input;
  }
  else {
    boardname = document.getElementById('jsxgboardname').value;
    elid = document.getElementById('jsxgelementid').value;
  }

  // reading user input for jsxgraphcore.js source
  scriptsource = document.getElementById('source').value;

  // borders on?
  if (document.getElementById('jsxgimageborders').checked == true) borders_on = 1; 

  // getting animation type option
  animtype = document.getElementById('animationsel').value;
  if (animtype != "animtype1") animticks = eval(animtype.slice(10, 12));

  //buttonstyle
  if (document.getElementById('usebuttonstyle').checked == true) {
    buttonstyle="<sty"+"le>#"+boardname+" button {padding:";
    buttonstyle = buttonstyle + document.getElementById('buttonpaddingsel').value + "margin-top:"+ document.getElementById('buttonmargintopsel').value +"background-color:"+ document.getElementById('buttonbackgroundcolorsel').value +"}</sty"+"le>";
    butvertical = document.getElementById('buttonverticaladjsel').value;
  } else buttonstyle = "";

  // initializing board element for the html page (this program)

    document.getElementById("jsxgimage").innerHTML = buttonstyle.replace('#'+boardname, '.jxgbox')+"<h3><u>JSXGraph image</u></h3><table border='"+borders_on+"'><th><div class='jxgbox' id='JSXBoard' style='width: "+appletsize[0]+"px; height: "+appletsize[1]+"px; overflow: hidden; position: relative; background-color:white;'> </div></th></table>";
 
  // writing var board iniatilizing and variable definitions into codestring, evaluating them
   // and replacing boardname for generated code
   
  codestring = "var "+boardname+"_b = JXG.JSXGraph.initBoard('JSXBoard', {boundingbox:["+boardsize+"], originX:"+(scalex*appletsize[0]/coord_div/2)+", originY:"+(scaley*appletsize[1]/coord_div/2)+", zoomX:"+zoom+", zoomY:"+zoom+", keepaspectratio:false, axis:"+drawaxis+", showCopyright: false, showNavigation: false, grid: "+sgrid+"} );";
  codestring = codestring + "var "+elid+"_el=[]; var "+elid+"_transf=[]; var "+elid+"_transf2=[]; var "+elid+"_path1=[]; var "+elid+"_path2=[]; var "+elid+"_animLoop=[]; var "+elid+"_animOn=false; var "+elid+"_c=[];";
  //if (!isFullPageConvert)
  // JXG.Options.text.useMathJax = true;
    eval(codestring);
  if (!isFullPageConvert)
    codestring = codestring + "&#13;&#10;&#13;&#10;";
  codestring = codestring.replace("JSXBoard",boardname);

  //
  sketchrows = separateCommands(sketch);
  for (var i=0; i<sketchrows.length; i++) {
    elr[i] = sketchpadrowToJsxgElement(sketchrows[i]);
    origstring = origstring + sketchrows[i] +"<br>"; 
  }

  if (document.getElementById('originalcode').value == 'Yes' && !isFullPageConvert)
    document.getElementById("JSketchPadCode").innerHTML = origstring;

  // * * * * * * * Change attributes /
  for (var i=0; i<elr.length; i++) {

    changeTypeToJSX(elr[i]);
    changePosInfoToJSX(elr[i],appletsize,coord_div,scalex,scaley,has_origin_unit);
    changeAttributesToJSX(elr[i]);
    changeOptionsToJSX(elr[i]);
    teststring = teststring + "Row: "+elr[i].Row +", Type: "+elr[i].Type+", JsxType: "+elr[i].JsxType+", Pos: "+elr[i].Pos+", Opt: "+elr[i].Opts+", Att.Info: "+elr[i].Att.Info+ ", Anim: "+elr[i].Anim+"<br>";
  
  }
  if (document.getElementById('developerstuff').checked == true && !isFullPageConvert)
    document.getElementById("testing").innerHTML = teststring;
  
  for (var i=0; i<elr.length;i++) {
    el[elr[i].Row] = elr[i];
    sketchrows_comment[elr[i].Row] = elr[i];
  }

       
  codestring = "<br>"+"<script src='"+scriptsource+"'>"+"</scr"+"ipt>&#13&#10;"+buttonstyle+"&#13&#10;<table border='"+borders_on+"'><th>&#13&#10;<div class='jxgbox' id='"+boardname+"' style='width: "+appletsize[0]+"px; height: "+appletsize[1]+"px; overflow: hidden; position: relative; background-color:white;'></div>&#13&#10;</th></table>&#13&#10;<"+"script"+">&#13&#10;"+codestring;
  if (!isFullPageConvert)
    codestring = "&#13;&#10;"+codestring;

  //for (var i=0; i<el.length; i++) {
  for (var i in el) {

    if (el[i].Att.Stop)
      break;

    else {

      

      // POINTS * * * * /
      if (el[i].JsxType == 'point') {
        //evalstring[el[i].Row] = elid+"_el["+el[i].Row+"] = "+boardname+"_b.create('point', ["+el[i].Pos+"], {name:'"+el[i].Att.Name+"', color:'"+el[i].Att.Color+"', visible:"+el[i].Att.Visible+", fixed:"+el[i].Att.Fixed+", size:"+el[i].Att.Size+", showInfoBox:"+el[i].Att.Infobox+", label:"+el[i].Att.LabelAlign+", snapToGrid:"+el[i].Att.SnapToGrid+"} );";
        evalstring[el[i].Row] = elid+"_el["+el[i].Row+"] = "+boardname+"_b.create('point', ["+el[i].Pos+"], "+getOptions(el[i])+");";
      }
      else if (el[i].JsxType == 'unitpoint'){
        evalstring[el[i].Row] = elid+"_el["+el[i].Row+"] = "+boardname+"_b.create('point', [function(){return "+elid+"_el["+el[i].Pos[0]+"].X()+"+1+";}, function(){return "+elid+"_el["+el[i].Pos[0]+"].Y();}], {name:'"+el[i].Att.Name+"', color:'"+el[i].Att.Color+"', visible:"+el[i].Att.Visible+", size:"+el[i].Att.Size+", showInfoBox:"+el[i].Att.Infobox+", label:"+el[i].Att.LabelAlign+", snapToGrid:"+el[i].Att.SnapToGrid+"} );";
      }
      else if (el[i].JsxType == 'midpoint'){
        //evalstring[el[i].Row] = elid+"_el["+el[i].Row+"] = "+boardname+"_b.create('midpoint', ["+elid+"_el["+el[i].Pos[0]+"]], {name:'"+el[i].Att.Name+"', color:'"+el[i].Att.Color+"', visible:"+el[i].Att.Visible+", size:"+el[i].Att.Size+", showInfoBox:"+el[i].Att.Infobox+", label:"+el[i].Att.LabelAlign+", snapToGrid:"+el[i].Att.SnapToGrid+"} );";
        evalstring[el[i].Row] = elid+"_el["+el[i].Row+"] = "+boardname+"_b.create('midpoint', ["+elid+"_el["+el[i].Pos[0]+"]],"+getOptions(el[i])+");";
      }
      else if (el[i].JsxType == 'intersection') {
        evalstring[el[i].Row] = elid+"_el["+el[i].Row+"] = "+boardname+"_b.create('intersection', ["+elid+"_el["+el[i].Pos[0]+"],"+elid+"_el["+el[i].Pos[1]+"], "+el[i].Att.Info+"], {name:'"+el[i].Att.Name+"',color:'"+el[i].Att.Color+"', visible:"+el[i].Att.Visible+", size:"+el[i].Att.Size+", showInfoBox:"+el[i].Att.Infobox+", label:"+el[i].Att.LabelAlign+", alwaysIntersect:false, snapToGrid:"+el[i].Att.SnapToGrid+"} );";
      }
      else if (el[i].JsxType == 'glider') {
        tmpstring = gliderPoint(eval(elid+"_el["+el[i].Pos[0]+"]"),el[i].Pos[1],eval(elid+"_el["+el[el[i].Pos[0]].Pos[0]+"]"))[0]+","+gliderPoint(eval(elid+"_el["+el[i].Pos[0]+"]"),el[i].Pos[1],eval(elid+"_el["+el[el[i].Pos[0]].Pos[0]+"]"))[1];
        //evalstring[el[i].Row] = elid+"_el["+el[i].Row+"] = "+boardname+"_b.create('glider', ["+tmpstring+","+elid+"_el["+el[i].Pos[0]+"]], {name:'"+el[i].Att.Name+"', color:'"+el[i].Att.Color+"',visible:"+el[i].Att.Visible+", trace:"+el[i].Att.Trace+", size:"+el[i].Att.Size+", showInfoBox:"+el[i].Att.Infobox+", label:"+el[i].Att.LabelAlign+", snapToGrid:"+el[i].Att.SnapToGrid+"} );";
        evalstring[el[i].Row] = elid+"_el["+el[i].Row+"] = "+boardname+"_b.create('glider', ["+tmpstring+","+elid+"_el["+el[i].Pos[0]+"]], "+getOptions(el[i])+");";
      }
      else if (el[i].JsxType == 'plotxy') {
        // PlotXY(objRef1, objRef2, objRef3);
         // Defines the point on the coordinate system objRef2 specified horizontally by the value of measurement objRef3 and vertically by the value of objRef1. 
         // That is, PlotXY() plots the point (objRef3, objRef1) on objRef2.
         //
        evalstring[el[i].Row] = elid+"_el["+el[i].Row+"] = "+boardname+"_b.create('point', [function() {return "+elid+"_el["+el[el[i].Pos[1]].Pos[0]+"].X() + "+calc[el[i].Pos[2]]+";}, function() {return "+elid+"_el["+el[el[i].Pos[1]].Pos[0]+"].Y() + "+calc[el[i].Pos[0]]+";}],"+getOptions(el[i])+");";
      }

      // * * * * /POINTS /

      // CIRCLES * * * * * /

      else if (el[i].JsxType == 'circle') {
        //evalstring[el[i].Row] = elid+"_el["+el[i].Row+"] = "+boardname+"_b.create('"+el[i].JsxType+"', ["+elid+"_el["+el[i].Pos[0]+"],"+elid+"_el["+el[i].Pos[1]+"]], {name:'"+el[i].Att.Name+"', strokeColor:'"+el[i].Att.Color+"', visible:"+el[i].Att.Visible+", strokeWidth:"+el[i].Att.Strokewidth+", showInfoBox:"+el[i].Att.Infobox+", label:"+el[i].Att.LabelAlign+"} ); ";
        evalstring[el[i].Row] = elid+"_el["+el[i].Row+"] = "+boardname+"_b.create('"+el[i].JsxType+"', ["+elid+"_el["+el[i].Pos[0]+"],"+elid+"_el["+el[i].Pos[1]+"]],"+getOptions(el[i])+"); ";
      }
      else if (el[i].JsxType == 'circle by radius') {
        //evalstring[el[i].Row] = elid+"_el["+el[i].Row+"] = "+boardname+"_b.create('circle', ["+elid+"_el["+el[i].Pos[0]+"], function(){return "+elid+"_el["+el[i].Pos[1]+"].L();}], {name:'"+el[i].Att.Name+"', strokeColor:'"+el[i].Att.Color+"', visible:"+el[i].Att.Visible+", strokeWidth:"+el[i].Att.Strokewidth+", showInfoBox:"+el[i].Att.Infobox+", label:"+el[i].Att.LabelAlign+"} ); ";
        evalstring[el[i].Row] = elid+"_el["+el[i].Row+"] = "+boardname+"_b.create('circle', ["+elid+"_el["+el[i].Pos[0]+"], function(){return "+elid+"_el["+el[i].Pos[1]+"].L();}],"+getOptions(el[i])+"); ";
      }

      // * * * * * * /CIRCLES /

      // STAIGHT LINES * * * * /

      else if (el[i].JsxType == 'line' || el[i].JsxType == 'perpendicular' || el[i].JsxType == 'parallel') {
        //evalstring[el[i].Row] = elid+"_el["+el[i].Row+"] = "+boardname+"_b.create('"+el[i].JsxType+"', ["+elid+"_el["+el[i].Pos[0]+"],"+elid+"_el["+el[i].Pos[1]+"]], {fixed:true, name:'"+el[i].Att.Name+"',color:'"+el[i].Att.Color+"', visible:"+el[i].Att.Visible+", straightLast:"+el[i].Att.Straightlast+", straightFirst:"+el[i].Att.Straightfirst+", strokeWidth:"+el[i].Att.Strokewidth+", showInfoBox:"+el[i].Att.Infobox+", label:"+el[i].Att.LabelAlign+", lastArrow:"+el[i].Att.ArrowL+", firstArrow:"+el[i].Att.ArrowF+"} );";
        evalstring[el[i].Row] = elid+"_el["+el[i].Row+"] = "+boardname+"_b.create('"+el[i].JsxType+"', ["+elid+"_el["+el[i].Pos[0]+"],"+elid+"_el["+el[i].Pos[1]+"]],"+getOptions(el[i])+");";
      }
      else if (el[i].JsxType == 'segment') {
        //evalstring[el[i].Row] = elid+"_el["+el[i].Row+"] = "+boardname+"_b.create('"+el[i].JsxType+"', ["+elid+"_el["+el[i].Pos[0]+"],"+elid+"_el["+el[i].Pos[1]+"]], {name:'"+el[i].Att.Name+"',color:'"+el[i].Att.Color+"', visible:"+el[i].Att.Visible+", strokeWidth:"+el[i].Att.Strokewidth+", showInfoBox:"+el[i].Att.Infobox+", label:"+el[i].Att.LabelAlign+", lastArrow:"+el[i].Att.ArrowL+", firstArrow:"+el[i].Att.ArrowF+"} );";
        evalstring[el[i].Row] = elid+"_el["+el[i].Row+"] = "+boardname+"_b.create('"+el[i].JsxType+"', ["+elid+"_el["+el[i].Pos[0]+"],"+elid+"_el["+el[i].Pos[1]+"]],"+getOptions(el[i])+");";
      }
      else if (el[i].JsxType == 'ray') {
        //evalstring[el[i].Row] = elid+"_el["+el[i].Row+"] = "+boardname+"_b.create('line', ["+elid+"_el["+el[i].Pos[1]+"],"+elid+"_el["+el[i].Pos[0]+"]], {name:'"+el[i].Att.Name+"', color:'"+el[i].Att.Color+"', visible:"+el[i].Att.Visible+", straightLast:true, straightFirst:false, strokeWidth:"+el[i].Att.Strokewidth+", showInfoBox:"+el[i].Att.Infobox+", label:"+el[i].Att.LabelAlign+", lastArrow:"+el[i].Att.ArrowL+", firstArrow:"+el[i].Att.ArrowF+"} );";
        evalstring[el[i].Row] = elid+"_el["+el[i].Row+"] = "+boardname+"_b.create('line', ["+elid+"_el["+el[i].Pos[1]+"],"+elid+"_el["+el[i].Pos[0]+"]],"+getOptions(el[i])+");";    
      }
      else if (el[i].JsxType == 'axisx') {
        
          evalstring[el[i].Row] = elid+"_el["+el[i].Row+"] = "+boardname+"_b.create('axis', [["+elid+"_el["+el[i].Pos[0]+"][0].X(),"+elid+"_el["+el[i].Pos[0]+"][0].Y()], ["+elid+"_el["+el[i].Pos[0]+"][0].X()+1, "+elid+"_el["+el[i].Pos[0]+"][0].Y()]],{name:'"+el[i].Att.Name+"', color:'"+el[i].Att.Color+"', visible:"+el[i].Att.Visible+"}); " +elid+"_el["+el[i].Row+"].removeAllTicks();";
        
      }
      else if (el[i].JsxType == 'axisy') {
        
          evalstring[el[i].Row] = elid+"_el["+el[i].Row+"] = "+boardname+"_b.create('axis', [["+elid+"_el["+el[i].Pos[0]+"][0].X(),"+elid+"_el["+el[i].Pos[0]+"][0].Y()], ["+elid+"_el["+el[i].Pos[0]+"][0].X(), "+elid+"_el["+el[i].Pos[0]+"][0].Y()+1]],{name:'"+el[i].Att.Name+"', color:'"+el[i].Att.Color+"', visible:"+el[i].Att.Visible+"}); "+elid+"_el["+el[i].Row+"].removeAllTicks();";
        
      }
      // * * * * /STRAIGHT LINES /

      // INTERIORS * * * * * /

      else if (el[i].JsxType == 'polygon') {
        for (var j=0; j<el[i].Pos.length; j++) {
          if (j != el[i].Pos.length-1) tmpstring = tmpstring + elid+"_el["+el[i].Pos[j]+"],"; else tmpstring = tmpstring + elid+"_el["+el[i].Pos[j]+"],"; }
            evalstring[el[i].Row] = elid+"_el["+el[i].Row+"] = "+boardname+"_b.create('polygon', ["+tmpstring+"],"+getOptions(el[i])+");";
      }  

      // * * * * /INTERIORS /

      // TRANSFORMATIONS * * * * /

      else if (el[i].JsxType == 'reflection') {
        evalstring[el[i].Row] = elid+"_el["+el[i].Row+"] = "+boardname+"_b.create('"+el[i].JsxType+"', ["+elid+"_el["+el[i].Pos[0]+"],"+elid+"_el["+el[i].Pos[1]+"]],"+getOptions(el[i])+");";
      }
      else if (el[i].JsxType == 'dilation') {
        evalstring[el[i].Row] = elid+"_el["+el[i].Row+"] = "+boardname+"_b.create('point', [function(){return "+el[i].Pos[2]+"*("+elid+"_el["+el[i].Pos[0]+"].X()-"+elid+"_el["+el[i].Pos[1]+"].X())+"+elid+"_el["+el[i].Pos[1]+"].X();},function(){return "+el[i].Pos[2]+"*("+elid+"_el["+el[i].Pos[0]+"].Y()-"+elid+"_el["+el[i].Pos[1]+"].Y())+"+elid+"_el["+el[i].Pos[1]+"].Y();}],"+getOptions(el[i])+");";
      }
      else if (el[i].JsxType == 'dilation/segmentratio') {
        evalstring[el[i].Row] = elid+"_el["+el[i].Row+"] = "+boardname+"_b.create('point', [function(){return ("+elid+"_el["+el[i].Pos[2]+"].L()/"+elid+"_el["+el[i].Pos[3]+"].L())*("+elid+"_el["+el[i].Pos[0]+"].X()-"+elid+"_el["+el[i].Pos[1]+"].X())+"+elid+"_el["+el[i].Pos[1]+"].X();},function(){return ("+elid+"_el["+el[i].Pos[2]+"].L()/"+elid+"_el["+el[i].Pos[3]+"].L())*("+elid+"_el["+el[i].Pos[0]+"].Y()-"+elid+"_el["+el[i].Pos[1]+"].Y())+"+elid+"_el["+el[i].Pos[1]+"].Y();}],"+getOptions(el[i])+");";
      }
      else if (el[i].JsxType == 'dilation/3ptratio') {
        // Dilation/3PtRatio (objRef1, objRef2, objRef3, objRef4, objRef5);
         // Defines the image of any objRef1 dilated with respect to center point objRef2 by the signed ratio implied by the distances between points objRef3, 4, and 5. 
         // If these three points are A, B, and C, respectively, the three-point ratio implied by them is |AC|/|AB|. 
        
        evalstring[el[i].Row] = elid+"_el["+el[i].Row+"] = "+boardname+"_b.create('point', [function(){return Math.sign(Math.cos(JXG.Math.Geometry.rad("+elid+"_el["+el[i].Pos[3]+"], "+elid+"_el["+el[i].Pos[2]+"], "+elid+"_el["+el[i].Pos[4]+"]))) * ("+elid+"_el["+el[i].Pos[2]+"].Dist("+elid+"_el["+el[i].Pos[4]+"]) / "+elid+"_el["+el[i].Pos[2]+"].Dist("+elid+"_el["+el[i].Pos[3]+"])) * ("+elid+"_el["+el[i].Pos[0]+"].X() - "+elid+"_el["+el[i].Pos[1]+"].X()) + "+elid+"_el["+el[i].Pos[1]+"].X()},function() {return Math.sign(Math.cos(JXG.Math.Geometry.rad("+elid+"_el["+el[i].Pos[3]+"], "+elid+"_el["+el[i].Pos[2]+"], "+elid+"_el["+el[i].Pos[4]+"]))) * ("+elid+"_el["+el[i].Pos[2]+"].Dist("+elid+"_el["+el[i].Pos[4]+"]) / "+elid+"_el["+el[i].Pos[2]+"].Dist("+elid+"_el["+el[i].Pos[3]+"])) * ("+elid+"_el["+el[i].Pos[0]+"].Y() - "+elid+"_el["+el[i].Pos[1]+"].Y()) + "+elid+"_el["+el[i].Pos[1]+"].Y()}],"+getOptions(el[i])+");";

      }
      else if (el[i].JsxType == 'dilation/markedratio') {
        evalstring[el[i].Row] = elid+"_el["+el[i].Row+"] = "+boardname+"_b.create('point', [function(){var ratio = "+calc[el[i].Pos[2]]+";return ratio*("+elid+"_el["+el[i].Pos[0]+"].X()-"+elid+"_el["+el[i].Pos[1]+"].X())+"+elid+"_el["+el[i].Pos[1]+"].X();},function(){var ratio = "+calc[el[i].Pos[2]]+";return ratio*("+elid+"_el["+el[i].Pos[0]+"].Y()-"+elid+"_el["+el[i].Pos[1]+"].Y())+"+elid+"_el["+el[i].Pos[1]+"].Y();}],"+getOptions(el[i])+");";
      }
      else if (el[i].JsxType == 'rotation') {
      //5.5.6 Rotation (objRef1, objRef2, num);
        //Defines the image of any objRef1 rotated around center point objRef2 by the radian angle specified by num.
        //eval(elid+"_transf[el[i].Row] = "+boardname+"_b.create('transform', ["+el[i].Pos[2]+","+elid+"_el[el[i].Pos[1]]], {type:'rotate'})");          
        //codestring = codestring + 
        evalstring[el[i].Row] = elid+"_transf["+el[i].Row+"] = "+boardname+"_b.create('transform', ["+el[i].Pos[2]+","+elid+"_el["+el[i].Pos[1]+"]], {type:'rotate'});";
        evalstring[el[i].Row] = evalstring[el[i].Row] + elid+"_el["+el[i].Row+"] = "+boardname+"_b.create('point', ["+elid+"_el["+el[i].Pos[0]+"], "+elid+"_transf["+el[i].Row+"]], {name:'"+el[i].Att.Name+"', color:'"+el[i].Att.Color+"', visible:"+el[i].Att.Visible+", fixed:"+elid+"_el["+el[i].Pos[0]+"].getAttribute, size:"+el[i].Att.Size+", showInfoBox:"+el[i].Att.Infobox+", label:"+el[i].Att.LabelAlign+"} );";
      }     
      else if (el[i].JsxType == 'rotation/measuredangle') {
        //5.5.6 Rotation (objRef1, objRef2, objRef3);
         // Defines the image of any objRef1 rotated around center point objRef2 by the radian angle expressed by measurement objRef3.   
 //       eval(elid+"_transf[el[i].Row] = "+boardname+"_b.create('transform', [function(){return "+calc[el[i].Pos[2]]+"},"+elid+"_el[el[i].Pos[1]]], {type:'rotate'})");          
 //       codestring = codestring + elid+"_transf["+el[i].Row+"] = "+boardname+"_b.create('transform', [function(){return "+calc[+el[i].Pos[2]]+"},"+elid+"_el["+el[i].Pos[1]+"]], {type:'rotate'});";
        evalstring[el[i].Row] = elid+"_transf["+el[i].Row+"] = "+boardname+"_b.create('transform', [function(){return "+calc[+el[i].Pos[2]]+"},"+elid+"_el["+el[i].Pos[1]+"]], {type:'rotate'});" + elid+"_el["+el[i].Row+"] = "+boardname+"_b.create('point', ["+elid+"_el["+el[i].Pos[0]+"], "+elid+"_transf["+el[i].Row+"]],"+getOptions(el[i], "fixed:"+elid+"_el["+el[i].Pos[0]+"].getAttribute")+");";
      } 
      else if (el[i].JsxType == 'rotation/markedangle') {
        /* Rotation/MarkedAngle (objRef1, objRef2, objRef3, objRef4, objRef5);
         * Defines the image of any objRef1 rotated around center point objRef2 by the directed angle implied by the three points objRef3-objRef4-objRef5.       
         * JXG.Math.Geometry.rad("+elid+"_el["+el[i].Pos[2]+"], "+elid+"_el["+el[i].Pos[3]+"], "+elid+"_el["+el[i].Pos[4]+"])
         */
//        eval(elid+"_transf[el[i].Row] = "+boardname+"_b.create('transform', [function() {return JXG.Math.Geometry.rad("+elid+"_el["+el[i].Pos[2]+"], "+elid+"_el["+el[i].Pos[3]+"], "+elid+"_el["+el[i].Pos[4]+"]);},"+elid+"_el[el[i].Pos[1]]], {type:'rotate'})");          
//          codestring = codestring + elid+"_transf[el[i].Row] = "+boardname+"_b.create('transform', [function() {return JXG.Math.Geometry.rad("+elid+"_el["+el[i].Pos[2]+"], "+elid+"_el["+el[i].Pos[3]+"], "+elid+"_el["+el[i].Pos[4]+"]);},"+elid+"_el[el[i].Pos[1]]], {type:'rotate'});&#13;&#10;";
        evalstring[el[i].Row] = elid+"_transf[el[i].Row] = "+boardname+"_b.create('transform', [function() {return JXG.Math.Geometry.rad("+elid+"_el["+el[i].Pos[2]+"], "+elid+"_el["+el[i].Pos[3]+"], "+elid+"_el["+el[i].Pos[4]+"]);},"+elid+"_el[el[i].Pos[1]]], {type:'rotate'});" + elid+"_el["+el[i].Row+"] = "+boardname+"_b.create('point', ["+elid+"_el["+el[i].Pos[0]+"], "+elid+"_transf["+el[i].Row+"]],"+getOptions(el[i], "fixed:"+elid+"_el["+el[i].Pos[0]+"].getAttribute")+");";
          
      } 
      else if (el[i].JsxType == 'translation') { 
        //eval(elid+"_transf[el[i].Row] = "+boardname+"_b.create('transform', ["+scalex * el[i].Pos[1]/coord_div +", "+scaley * -1 * el[i].Pos[2]/coord_div +"], {type:'translate'});" );
        //codestring = codestring + elid+"_transf["+el[i].Row+"] = "+boardname+"_b.create('transform', ["+scalex*el[i].Pos[1]/coord_div+","+ scaley*el[i].Pos[2]/coord_div+"], {type:'translate'});";
          
        evalstring[el[i].Row] = elid+"_transf["+el[i].Row+"] = "+boardname+"_b.create('transform', ["+scalex*el[i].Pos[1]/coord_div+","+ scaley*el[i].Pos[2]/coord_div+"], {type:'translate'});" + elid+"_el["+el[i].Row+"] = "+boardname+"_b.create('point', ["+elid+"_el["+el[i].Pos[0]+"], "+elid+"_transf["+el[i].Row+"]],"+getOptions(el[i], "fixed:"+elid+"_el["+el[i].Pos[0]+"].getAttribute")+");";
          
      }
      else if (el[i].JsxType == 'translation/fixedangle/markeddistance') {
        /* Translation/FixedAngle/MarkedDistance (objRef1, objRef2, num);
         * Defines the image of any objRef1 translated by the distance expressed by measurement objRef2 in the direction expressed by num radians.
         * [ https://www.math.uni-bielefeld.de/~lisken/jsp/qref.html ] 
         */ 
        eval(elid+"_transf[el[i].Row] = "+boardname+"_b.create('transform', [function(){return Math.abs("+elid+"_el["+el[i].Pos[0]+"].X()-"+calc[el[i].Pos[1]]+")+"+elid+"_el["+el[i].Pos[0]+"].X();}, 0], {type:'translate'})");
        eval(elid+"_transf2[el[i].Row] = "+boardname+"_b.create('transform', ["+el[i].Pos[2]+", "+elid+"_el["+el[i].Pos[0]+"]], {type:'rotate'})");

        codestring = codestring + elid+"_transf["+el[i].Row+"] = "+boardname+"_b.create('transform', [function(){return Math.abs("+elid+"_el["+el[i].Pos[0]+"].X()-("+calc[el[i].Pos[1]]+"))+"+elid+"_el["+el[i].Pos[0]+"].X();}, 0], {type:'translate'});";
        codestring = codestring + elid+"_transf2["+el[i].Row+"] = "+boardname+"_b.create('transform', ["+el[i].Pos[2]+", "+elid+"_el["+el[i].Pos[0]+"]], {type:'rotate'});";
          
        evalstring[el[i].Row] = elid+"_el["+el[i].Row+"] = "+boardname+"_b.create('point', ["+elid+"_el["+el[i].Pos[0]+"], ["+elid+"_transf["+el[i].Row+"],"+elid+"_transf2["+el[i].Row+"]]],"+getOptions(el[i], "fixed:"+elid+"_el["+el[i].Pos[0]+"].getAttribute")+");";          
      }     
      else if (el[i].JsxType == 'translation/markedangle/markeddistance') {
        /* Translation/MarkedAngle/MarkedDistance (objRef1, objRef2, objRef3);
         * Defines the image of any objRef1 translated by the distance expressed by distance measurement objRef3 in the direction expressed by angle measurement objRef2.
         * [ https://www.math.uni-bielefeld.de/~lisken/jsp/qref.html ] 
         */
        eval(elid+"_transf[el[i].Row] = "+boardname+"_b.create('transform', [function(){return Math.abs("+elid+"_el["+el[i].Pos[0]+"].X()-("+calc[el[i].Pos[2]]+"/coord_div))+"+elid+"_el["+el[i].Pos[0]+"].X();}, 0], {type:'translate'})");
        eval(elid+"_transf2[el[i].Row] = "+boardname+"_b.create('transform', [function(){return "+calc[el[i].Pos[1]]+";}, "+elid+"_el["+el[i].Pos[0]+"]], {type:'rotate'})");
        codestring = codestring + elid+"_transf["+el[i].Row+"] = "+boardname+"_b.create('transform', [function(){return Math.abs("+elid+"_el["+el[i].Pos[0]+"].X()-("+calc[el[i].Pos[2]]+"/coord_div))+"+elid+"_el["+el[i].Pos[0]+"].X();}, 0], {type:'translate'});";
        codestring = codestring + elid+"_transf2["+el[i].Row+"] = "+boardname+"_b.create('transform', [function(){return "+calc[el[i].Pos[1]]+";}, "+elid+"_el["+el[i].Pos[0]+"]], {type:'rotate'});";
        evalstring[el[i].Row] = elid+"_el["+el[i].Row+"] = "+boardname+"_b.create('point', ["+elid+"_el["+el[i].Pos[0]+"], ["+elid+"_transf["+el[i].Row+"],"+elid+"_transf2["+el[i].Row+"]]],"+getOptions(el[i], "fixed:"+elid+"_el["+el[i].Pos[0]+"].getAttribute")+");";   
      }   
      else if (el[i].JsxType == 'vectortranslation') {
        // VectorTranslation (objRef1, objRef2, objRef3);
         // Defines the image of any objRef1 translated by the vector implied by two points objRef2 -> objRef3. 
         // objRef2 is the foot of the vector, and objRef3 is its tail. 
        if (eval(elid+"_el["+el[i].Pos[0]+"].getType()")=='point' || eval(elid+"_el["+el[i].Pos[0]+"].getType()")=='glider' || eval(elid+"_el["+el[i].Pos[0]+"].getType()")=='intersection' || eval(elid+"_el["+el[i].Pos[0]+"].getType()")=='reflection' || eval(elid+"_el["+el[i].Pos[0]+"].getType()")=='midpoint') {  
          evalstring[el[i].Row] = elid+"_el["+el[i].Row+"] = "+boardname+"_b.create('point', [function(){return "+elid+"_el["+el[i].Pos[0]+"].X()+(Math.sign("+elid+"_el["+el[i].Pos[2]+"].X()-"+elid+"_el["+el[i].Pos[1]+"].X()))*Math.abs("+elid+"_el["+el[i].Pos[1]+"].X()-"+elid+"_el["+el[i].Pos[2]+"].X());}, function(){return "+elid+"_el["+el[i].Pos[0]+"].Y()+(Math.sign("+elid+"_el["+el[i].Pos[2]+"].Y()-"+elid+"_el["+el[i].Pos[1]+"].Y()))*Math.abs("+elid+"_el["+el[i].Pos[1]+"].Y()-"+elid+"_el["+el[i].Pos[2]+"].Y());}],"+getOptions(el[i])+");";
        }
        // FOR SEGMENT
        else if (eval(elid+"_el["+el[i].Pos[0]+"].getType()")=='segment') {
          if (el[el[i].Pos[0]].Att.ArrowF == true) el[i].Att.ArrowF=true; 
          if (el[el[i].Pos[0]].Att.ArrowL == true) el[i].Att.ArrowL=true;       
          evalstring[el[i].Row] = elid+"_transf["+el[i].Row+"] = "+boardname+"_b.create('point', [function(){return "+elid+"_el["+el[i].Pos[0]+"].point1.X()+(Math.sign("+elid+"_el["+el[i].Pos[2]+"].X()-"+elid+"_el["+el[i].Pos[1]+"].X()))*Math.abs("+elid+"_el["+el[i].Pos[1]+"].X()-"+elid+"_el["+el[i].Pos[2]+"].X());}, function(){return "+elid+"_el["+el[i].Pos[0]+"].point1.Y()+(Math.sign("+elid+"_el["+el[i].Pos[2]+"].Y()-"+elid+"_el["+el[i].Pos[1]+"].Y()))*Math.abs("+elid+"_el["+el[i].Pos[1]+"].Y()-"+elid+"_el["+el[i].Pos[2]+"].Y());}], {visible:false} ); "+elid+"_transf2["+el[i].Row+"] = "+boardname+"_b.create('point', [function(){return "+elid+"_el["+el[i].Pos[0]+"].point2.X()+(Math.sign("+elid+"_el["+el[i].Pos[2]+"].X()-"+elid+"_el["+el[i].Pos[1]+"].X()))*Math.abs("+elid+"_el["+el[i].Pos[1]+"].X()-"+elid+"_el["+el[i].Pos[2]+"].X());}, function(){return "+elid+"_el["+el[i].Pos[0]+"].point2.Y()+(Math.sign("+elid+"_el["+el[i].Pos[2]+"].Y()-"+elid+"_el["+el[i].Pos[1]+"].Y()))*Math.abs("+elid+"_el["+el[i].Pos[1]+"].Y()-"+elid+"_el["+el[i].Pos[2]+"].Y());}], {visible:false} ); "+elid+"_el["+el[i].Row+"] = "+boardname+"_b.create('segment', ["+elid+"_transf["+el[i].Row+"], "+elid+"_transf2["+el[i].Row+"]], {name:'"+el[i].Att.Name+"', strokeWidth:"+el[i].Att.Strokewidth+", strokeColor:'"+el[i].Att.Color+"', visible:"+el[i].Att.Visible+", size:"+el[i].Att.Size+", showInfoBox:"+el[i].Att.Infobox+", label:"+el[i].Att.LabelAlign+", lastArrow:"+el[i].Att.ArrowL+", firstArrow:"+el[i].Att.ArrowF+"} );";
        }
        // FOR LINE
        else if (eval(elid+"_el["+el[i].Pos[0]+"].getType()")=='line') {          
          evalstring[el[i].Row] = elid+"_transf["+el[i].Row+"] = "+boardname+"_b.create('point', [function(){return "+elid+"_el["+el[i].Pos[0]+"].point1.X()+(Math.sign("+elid+"_el["+el[i].Pos[2]+"].X()-"+elid+"_el["+el[i].Pos[1]+"].X()))*Math.abs("+elid+"_el["+el[i].Pos[1]+"].X()-"+elid+"_el["+el[i].Pos[2]+"].X());}, function(){return "+elid+"_el["+el[i].Pos[0]+"].point1.Y()+(Math.sign("+elid+"_el["+el[i].Pos[2]+"].Y()-"+elid+"_el["+el[i].Pos[1]+"].Y()))*Math.abs("+elid+"_el["+el[i].Pos[1]+"].Y()-"+elid+"_el["+el[i].Pos[2]+"].Y());}], {visible:false} ); "+elid+"_transf2["+el[i].Row+"] = "+boardname+"_b.create('point', [function(){return "+elid+"_el["+el[i].Pos[0]+"].point2.X()+(Math.sign("+elid+"_el["+el[i].Pos[2]+"].X()-"+elid+"_el["+el[i].Pos[1]+"].X()))*Math.abs("+elid+"_el["+el[i].Pos[1]+"].X()-"+elid+"_el["+el[i].Pos[2]+"].X());}, function(){return "+elid+"_el["+el[i].Pos[0]+"].point2.Y()+(Math.sign("+elid+"_el["+el[i].Pos[2]+"].Y()-"+elid+"_el["+el[i].Pos[1]+"].Y()))*Math.abs("+elid+"_el["+el[i].Pos[1]+"].Y()-"+elid+"_el["+el[i].Pos[2]+"].Y());}], {visible:false} ); "+elid+"_el["+el[i].Row+"] = "+boardname+"_b.create('line', ["+elid+"_transf["+el[i].Row+"], "+elid+"_transf2["+el[i].Row+"]], {name:'"+el[i].Att.Name+"', strokeWidth:"+el[i].Att.Strokewidth+", strokeColor:'"+el[i].Att.Color+"', visible:"+el[i].Att.Visible+", size:"+el[i].Att.Size+", showInfoBox:"+el[i].Att.Infobox+", label:"+el[i].Att.LabelAlign+"} );";
        }
      }
      // * * * * * * /TRANSFORMATIONS /


      // * * * * * * IMAGES /

      else if (el[i].JsxType == 'image') {
        // Image (num1, num2, string);
         // Defines a rectangular picture image positioned in the plane at the (X, Y) location specified by (num1, num2). 
         // string specifies the URL of the image relative to the URL of the web page which contains this 
         //
        var imgWidth="", 
            imgHeight="";
        document.getElementById('hiddenimg').src = el[i].Pos[2];
        imgWidth = document.getElementById('hiddenimg').width;
        imgHeight = document.getElementById('hiddenimg').height;
        [imgWidth, imgHeight] = [imgWidth/coord_div, imgHeight/coord_div];      
        evalstring[el[i].Row] = elid+"_el["+el[i].Row+"] = "+boardname+"_b.create('image', ['"+el[i].Pos[2]+"',["+el[i].Pos[0]+","+el[i].Pos[1]+"], ["+imgWidth+","+imgHeight+"]], {visible:"+el[i].Att.Visible+"} );";
      }

      // * * * * * * /IMAGES /

      // MEASUREMENTS * * * * * /

      else if (el[i].JsxType == 'length') {
        // Length(obj1, numX, numY, string);
         // Constructs a measurement of the length of segment obj1.
        evalstring[el[i].Row] = "function "+elid+el[i].Row+"() {return "+elid+"_el["+el[i].Pos[0]+"].L();} ";

        calc[el[i].Row] = elid+el[i].Row+"()";

        evalstring[el[i].Row] = evalstring[el[i].Row] + elid+"_el["+el[i].Row+"] = "+boardname+"_b.create('text', ["+el[i].Pos[1]+","+el[i].Pos[2]+",function(){return '"+el[i].Pos[3] +"' + Math.round("+calc[el[i].Row]+"*"+mesaccu+")/"+mesaccu+";}], {name:'"+el[i].Att.Name+"', color:'"+el[i].Att.Color+"'} );";
      }
      else if (el[i].JsxType == 'angle') {
        //  Angle(obj1, obj2, obj3, numX, numY, string);
         // Constructs a measurement of the angle implied by the three points obj1, obj2, and obj3, with obj2 being the vertex of the angle. 
         // The angle will be reported as either a directed or an undirected angle, depending on the setting of the global DirectedAngles parameter.
        evalstring[el[i].Row] = "function "+elid+el[i].Row+"() {return JXG.Math.Geometry.rad("+elid+"_el["+el[i].Pos[0]+"],"+elid+"_el["+el[i].Pos[1]+"],"+elid+"_el["+el[i].Pos[2]+"])}";
        calc[el[i].Row] = elid+el[i].Row+"()";
        evalstring[el[i].Row] = evalstring[el[i].Row] + elid+"_el["+el[i].Row+"] = "+boardname+"_b.create('text', ["+el[i].Pos[3]+","+el[i].Pos[4]+",function(){return '"+el[i].Pos[5] +"' + Math.round("+calc[el[i].Row]+"*"+mesaccu+")/"+mesaccu+";}], {name:'"+el[i].Att.Name+"', color:'"+el[i].Att.Color+"', fixed:"+el[i].Att.Fixed+"} );";
      }
      else if (el[i].JsxType == 'circumference') {
        // Circumference(obj1, numX, numY, string);
         // Constructs a measurement of the circumference of circle or circle interior obj1.
        evalstring[el[i].Row] = "function "+elid+el[i].Row+"() {return "+elid+"_el["+el[i].Pos[0]+"].Radius()*Math.PI*2} ";
        calc[el[i].Row] = elid+el[i].Row+"()";
          evalstring[el[i].Row] = evalstring[el[i].Row] + elid+"_el["+el[i].Row+"] = "+boardname+"_b.create('text', ["+el[i].Pos[1]+","+el[i].Pos[2]+",function(){return '"+el[i].Pos[3]+"' + Math.round("+calc[el[i].Row]+"*"+mesaccu+")/"+mesaccu+";}], {name:'"+el[i].Att.Name+"', color:'"+el[i].Att.Color+"', fixed:"+el[i].Att.Fixed+"} );";
      }
      else if (el[i].JsxType == 'radius') {
        // Radius(obj1, numX, numY, string);
         // Constructs a measurement of the radius of circle or circle interior obj1.
        evalstring[el[i].Row] = "function "+elid+el[i].Row+"() {return "+elid+"_el["+el[i].Pos[0]+"].Radius()} ";
        calc[el[i].Row] = elid+el[i].Row+"()";
          evalstring[el[i].Row] = evalstring[el[i].Row] + elid+"_el["+el[i].Row+"] = "+boardname+"_b.create('text', ["+el[i].Pos[1]+","+el[i].Pos[2]+",function(){return '"+el[i].Pos[3]+"' + Math.round("+calc[el[i].Row]+"*"+mesaccu+")/"+mesaccu+";}], {name:'"+el[i].Att.Name+"', color:'"+el[i].Att.Color+"', fixed:"+el[i].Att.Fixed+"} );";
      }
      else if (el[i].JsxType == 'area') {
        // Area (obj1, numX, numY, string);
         // Constructs a measurement of the area of the circle, circle interior, or polygon interior obj1. Note that the area is reported in square distance units.
        evalstring[el[i].Row] = "function "+elid+el[i].Row+"() {return "+elid+"_el["+el[i].Pos[0]+"].Area()} ";
        calc[el[i].Row] = elid+el[i].Row+"()";
          evalstring[el[i].Row] = evalstring[el[i].Row] + elid+"_el["+el[i].Row+"] = "+boardname+"_b.create('text', ["+el[i].Pos[1]+","+el[i].Pos[2]+",function(){return '"+el[i].Pos[3]+"' + Math.round("+calc[el[i].Row]+"*"+mesaccu+")/"+mesaccu+";}], {name:'"+el[i].Att.Name+"', color:'"+el[i].Att.Color+"', fixed:"+el[i].Att.Fixed+"} );";
      }
      else if (el[i].JsxType == 'slope') {
        // Slope (obj1, numX, numY, string);
         // Constructs a measurement of the slope of straight object obj1.
        evalstring[el[i].Row] = "function "+elid+el[i].Row+"() {return "+elid+"_el["+el[i].Pos[0]+"].getSlope()} ";
        calc[el[i].Row] = elid+el[i].Row+"()";
          evalstring[el[i].Row] = evalstring[el[i].Row] + elid+"_el["+el[i].Row+"] = "+boardname+"_b.create('text', ["+el[i].Pos[1]+","+el[i].Pos[2]+",function(){return '"+el[i].Pos[3]+"' + Math.round("+calc[el[i].Row]+"*"+mesaccu+")/"+mesaccu+";}], {name:'"+el[i].Att.Name+"', color:'"+el[i].Att.Color+"', fixed:"+el[i].Att.Fixed+"} );";
      }
      else if (el[i].JsxType == 'calculate') {
        // Calculate(numX, numY, prefixStr, exprStr) (objRef1, ..., objRefN);
         // Constructs a measurement of the value of a calculated expression. numX, numY, and prefixStr are the standard left and top coordinates and prefix string of every measurement object; exprStr contains a representation of the expression to calculate, and objRef1 through objRefN are object identifiers of any other measurement objects the value of which act as components of the expression.
         /// 
         // The exprStr expression is expressed in reverse Polish notation (RPN), in which arithmetic operators follow their operands. RPN eliminates the need for parentheses, because the order of evaluation is strictly left-to-right. Thus "(1+2)/3" can be phrased in RPN as "1 2 + 3 /".
         // 
         // Valid tokens within exprStr include:
         // 
         // numeric constants. Any real number can be expressed, with an optional preliminary negative sign (for negative numbers) and an optional single decimal point (for expressing non-integer values). A numeric constant may include a terminal space to delimit it in circumstances where two numeric constants are adjacent.
         // +, -, /, *. These operators perform their standard arithmetic operation: addition, subtraction, division, and multiplication.
         // ^: This operator performs exponentiation.
         // %: This operator performs unary negation.
         // @xxxx: This operator applies a predefined function. xxxx is a four-character sequence indicating the function, and may be one of the following: sin_ (sine), cos_ (cosine), tan_ (tangent), abs_ (absolute value), sqrt (square root), ln__ (natural log), rond (rounding), trnc (truncation toward zero), sgn_ (signnum), asin (arcsine), acos (arccosine), atan (arctangent), or log_ (base-10 logarithm).
         // x where x is in {A-Z}. This operand substitutes the value of another measurement in the sketch: A corresponds to measurement objRef1, B corresponds to measurement objRef2, etc. It is an error to pass an operator that does not have a corresponding objRef; i. e. to refer to C when you only supply two objRefs in the construction (implicitly, A and B).
         // #xy where x is in {A-Z} and y is in {1-9}. This operand substitutes the value of component y of a vector-based measurement x. x refers to an objRef according to the same rules above (i. e. A is objRef1, B is objRef2, etc.). Parent objRefx must be a vector-based measurement: in DR3 of JavaSketchpad, the only vector-based measurement is the Coordinate pair. y indicates the component of the vector to isolate. In DR3, the only legal values for y are 1 and 2: 1 indicates the x-component of a coordinate pair, 2 indicates the y-component of that pair.
         // Examples:
         // 
         // Calculate(10, 10, 'Sum is ','AB+C+') (5, 6, 7);
         // 
         // Calculates the sum of measurement objects #5, 6, and 7 in the sketch, and positions their sum at (10, 10) on the coordinate plane.
         // 
         // Calculate(20, 20, 'Distance is ','#A1#B1-2^#A2#B2-2^+@sqrt') (8, 9);
         // 
         // Calculates the Euclidean distance (sqrt[dX^2+dY^2]) between the two coordinate pair measurements referenced as objects #8 and 9 in the sketch.
         // 
         // Note that a space character may be used inside exprStr to delimit individual tokens. This allows you to express one plus three as '1 3+' where '13+' would be interpreted as thirteen plus (whatever preceded it).
         // 
         // Note also that the objRef list must not be empty, even if no tokens in the expression refer to object references (i. e. even if the expression's value is constant). This is a limitation of DR3, and will be fixed in the next release.
        var tmp = [];
        for (var k=0; k<el[i].Pos[4].length; k++)
          tmp[k] = el[i].Pos[4][k];
        calc[el[i].Row] = calculateFunction(el[i].Pos[3],tmp,calc);
        if (el[i].Att.Visible)
          evalstring[el[i].Row] = (elid+"_el["+el[i].Row+"] = "+boardname+"_b.create('text', ["+el[i].Pos[0]+","+el[i].Pos[1]+",function(){return '"+el[i].Pos[2]+"' + Math.round(("+calc[el[i].Row]+")*"+mesaccu+")/"+mesaccu+" + '"+el[i].Att.Suffix+"';}],{name:'"+el[i].Att.Name+"', color:'"+el[i].Att.Color+"', fixed:"+el[i].Att.Fixed+"});");
        else {
          evalstring[el[i].Row] = (elid+"_el["+el[i].Row+"] = "+boardname+"_b.create('text', ["+el[i].Pos[0]+","+el[i].Pos[1]+",function(){return '"+el[i].Pos[2]+"' + Math.round(("+calc[el[i].Row]+")*"+mesaccu+")/"+mesaccu+" + '"+el[i].Att.Suffix+"';}],{name:'"+el[i].Att.Name+"', color:'"+el[i].Att.Color+"', fixed:"+el[i].Att.Fixed+"});");
          evalstring[el[i].Row] = evalstring[el[i].Row] + elid+"_el["+el[i].Row+"].hideElement();";
        }      
      }
      else if (el[i].JsxType == 'distance') {
        /// Distance(obj1, obj2, numX, numY, string);
         // Constructs a measurement of the distance between obj1 and obj2. 
         // obj2 must be a point, obj1 may be either a point or a straight object, 
         // in which case the distance is reported as the minimum (perpendicular) distance between point obj2 and the extended line containing obj1.
        evalstring[el[i].Row] = "function "+elid+el[i].Row+"() {return "+elid+"_el["+el[i].Pos[0]+"].Dist("+elid+"_el["+el[i].Pos[1]+"])} ";
        calc[el[i].Row] = elid+el[i].Row+"()";
          evalstring[el[i].Row] = evalstring[el[i].Row] + elid+"_el["+el[i].Row+"] = "+boardname+"_b.create('text', ["+el[i].Pos[2]+","+el[i].Pos[3]+",function(){return '"+el[i].Pos[4] +"' + Math.round("+calc[el[i].Row]+"*"+mesaccu+")/"+mesaccu+";}], {name:'"+el[i].Att.Name+"', color:'"+el[i].Att.Color+"', fixed:"+el[i].Att.Fixed+"} );";
      }
      else if (el[i].JsxType == 'ratio/segments') {
        // Ratio/Segments (obj1, obj2, numX, numY, string);
         // Constructs a measurement of the ratio of the length of segment obj1 to the length of segment obj2. That is, this construction measures |obj|/|obj2|.
        evalstring[el[i].Row] = "function "+elid+el[i].Row+"() {return "+elid+"_el["+el[i].Pos[0]+"].L() / "+elid+"_el["+el[i].Pos[1]+"].L()} ";
        calc[el[i].Row] = elid+el[i].Row+"()";
          evalstring[el[i].Row] = evalstring[el[i].Row] + elid+"_el["+el[i].Row+"] = "+boardname+"_b.create('text', ["+el[i].Pos[2]+","+el[i].Pos[3]+",function(){return '"+el[i].Pos[4] +"' + Math.round("+calc[el[i].Row]+"*"+mesaccu+")/"+mesaccu+";}], {name:'"+el[i].Att.Name+"', color:'"+el[i].Att.Color+"', fixed:"+el[i].Att.Fixed+"} );";
      }
      else if (el[i].JsxType == 'ratio/points') {
        /// Ratio/Points (obj1, obj2, obj3, numX, numY, string);
         // Constructs a measurement of the three-point ratio implied by points obj1, obj2, and obj3. 
         // If these points are A, B, and C, respectively, then the three-point ratio is |AC|/|AB|.        
        evalstring[el[i].Row] = "function "+elid+el[i].Row+"() {return Math.sign(Math.cos(JXG.Math.Geometry.rad("+elid+"_el["+el[i].Pos[1]+"], "+elid+"_el["+el[i].Pos[0]+"], "+elid+"_el["+el[i].Pos[2]+"])))*"+elid+"_el["+el[i].Pos[0]+"].Dist("+elid+"_el["+el[i].Pos[2]+"]) / "+elid+"_el["+el[i].Pos[0]+"].Dist("+elid+"_el["+el[i].Pos[1]+"])} ";
        calc[el[i].Row] = elid+el[i].Row+"()";
          evalstring[el[i].Row] = evalstring[el[i].Row] + elid+"_el["+el[i].Row+"] = "+boardname+"_b.create('text', ["+el[i].Pos[3]+","+el[i].Pos[4]+",function(){return '"+el[i].Pos[5]+"' + Math.round("+calc[el[i].Row]+"*"+mesaccu+")/"+mesaccu+" + '"+el[i].Att.Suffix+"';}],"+getOptions(el[i])+");"; 
      }
      // * * * * * /MEASUREMENTS /

      // BUTTONS /

      else if (el[i].JsxType == 'text') {
          evalstring[el[i].Row] = elid+"_el["+el[i].Row+"] = "+boardname+"_b.create('text', ["+el[i].Pos[0]+","+el[i].Pos[1]+",'"+el[i].Pos[2]+"'],"+getOptions(el[i])+");";
      }
      else if (el[i].JsxType == 'movebutton') {
        for (var j = 0; j < el[i].Anim.length; j+=2)
          tmpstring = tmpstring +elid+"_el["+el[i].Anim[j+1]+"].moveTo(["+elid+"_el["+el[i].Anim[j]+"].X(), "+elid+"_el["+el[i].Anim[j]+"].Y()],"+el[i].Pos[2]+");";
          evalstring[el[i].Row] = elid+"_el["+el[i].Row+"] = "+boardname+"_b.create('button', ["+el[i].Pos[0]+","+el[i].Pos[1]+", '"+el[i].Pos[3]+"', function() {"+tmpstring+"} ],"+getOptions(el[i])+");";
        el[i].Anim = tmpstring;

      }
      else if (el[i].JsxType == 'showbutton') {
        for (var j = 0; j < el[i].Anim.length; j++) {
          if (el[el[i].Anim[j]].CType == 'buttons' || el[el[i].Anim[j]].CType == 'measurements')
            tmpstring = tmpstring + elid+"_el["+el[i].Anim[j]+"].showElement();";
          else if (el[el[i].Anim[j]].JsxType == 'originandunit')
            tmpstring = tmpstring + boardname +"_b.addGrid();";
          else if (el[el[i].Anim[j]].JsxType == 'locus') {
            if (el[el[el[i].Anim[j]].Pos[1]].JsxType == 'point') {tmpstring = tmpstring + elid+el[el[i].Anim[j]].Row+"visible=true;"+elid+"Locus"+el[el[i].Anim[j]].Row+"("+elid+"_el["+el[el[i].Anim[j]].Pos[2]+"],"+elid+"_el["+el[el[i].Anim[j]].Pos[0]+"],"+elid+"_el["+el[el[i].Anim[j]].Pos[1]+"]);";} 
            else tmpstring = tmpstring + elid+"_el["+el[i].Anim[j]+"].setAttribute({visible:true});"; 
          }           
          else
            tmpstring = tmpstring + elid+"_el["+el[i].Anim[j]+"].setAttribute({visible:true});";    
          if (el[i].Pos[2].indexOf("Jäljitä") >= 0 || el[i].Pos[2].indexOf("Trace") >= 0)
            tmpstring = tmpstring + elid+"_el["+el[i].Anim[j]+"].setAttribute({trace:true});";
        }
          evalstring[el[i].Row] = elid+"_el["+el[i].Row+"] = "+boardname+"_b.create('button', ["+el[i].Pos[0]+","+el[i].Pos[1]+", '"+el[i].Pos[2]+"', function() {"+tmpstring+"} ],"+getOptions(el[i])+");";
          el[i].Anim = tmpstring;         
      }
      else if (el[i].JsxType == 'hidebutton') {
        for (var j = 0; j < el[i].Anim.length; j++) {
          if (el[el[i].Anim[j]].CType == 'buttons' || el[el[i].Anim[j]].CType == 'measurements')
            tmpstring = tmpstring + elid+"_el["+el[i].Anim[j]+"].hideElement();";
          else if (el[el[i].Anim[j]].JsxType == 'originandunit')
            tmpstring = tmpstring + boardname +"_b.removeGrids();";
          else if (el[el[i].Anim[j]].JsxType == 'locus') {
            if (el[el[el[i].Anim[j]].Pos[1]].JsxType == 'point') {tmpstring = tmpstring + elid+el[el[i].Anim[j]].Row+"visible=false;"+elid+"Locus"+el[el[i].Anim[j]].Row+"("+elid+"_el["+el[el[i].Anim[j]].Pos[2]+"],"+elid+"_el["+el[el[i].Anim[j]].Pos[0]+"],"+elid+"_el["+el[el[i].Anim[j]].Pos[1]+"]);";} 
            else tmpstring = tmpstring + elid+"_el["+el[i].Anim[j]+"].setAttribute({visible:false});"; 
          }   
          else
            tmpstring = tmpstring + elid+"_el["+el[i].Anim[j]+"].setAttribute({visible:false});";
          if (el[i].Pos[2].indexOf("Lopeta") >= 0 || el[i].Pos[2].indexOf("Stop") >= 0) {
            tmpstring = tmpstring + elid+"_el["+el[i].Anim[j]+"].setAttribute({trace:false});";
            tmpstring = tmpstring + elid+"_el["+el[i].Anim[j]+"].clearTrace();";
          }
        }
          evalstring[el[i].Row] = elid+"_el["+el[i].Row+"] = "+boardname+"_b.create('button', ["+el[i].Pos[0]+","+el[i].Pos[1]+", '"+el[i].Pos[2]+"', function() {"+tmpstring+"} ],"+getOptions(el[i])+");";   
        el[i].Anim = tmpstring;       
      }
      else if (el[i].JsxType == 'animatebutton') { //ANIMBUTTON
        /* AnimateButton 
         * (xpos, ypos, label) (point/path pairs) 
         * (speeds) (once-only flags) (direction flags);
         */ evalstring[el[i].Row] ="";
        for (var j=0; j<el[i].Anim[0].length; j+=2) {
            //tmpstring = tmpstring + elid+"_el["+el[i].Anim[0][j]+"].moveAlong("+getAnimationPath(elid+"_el["+el[i].Anim[0][j+1]+"]", eval(elid+"_el["+el[i].Anim[0][j+1]+"]").getType(), el[i].Anim[3][j])+", "+el[i].Anim[1][j]+");";
          tmpstring = tmpstring + "if (!anim"+el[i].Row+j+") {anim"+el[i].Row+j+"=true; "+elid+"_animOn=true; animateOn"+el[i].Row+j+"();} else {anim"+el[i].Row+j+" = false; "+elid+"_animOn=false; animateOff"+el[i].Row+j+"();}";
            //alert(tmpstring);
        //}
        //evalstring[el[i].Row] = "var "+elid+"_path1"+el[i].Row+" = "+getAnimationPath(elid+"_el["+el[i].Anim[0][j+1]+"]", eval(elid+"_el["+el[i].Anim[0][j+1]+"]").getType(), el[i].Anim[3][j])+"; var "+elid+"_path2"+el[i].Row+"=[];";
        
        //Create anim path (corners of the board, or segment start and end point)
          if (el[i].Anim[3][j] == 0) //If counter clockwise (on circle) or start-end-start-point on segment
            evalstring[el[i].Row] = evalstring[el[i].Row] + "var "+elid+"_path"+el[i].Row+j+"=[];if("+elid+"_el["+el[i].Anim[0][j+1]+"].getType()=='segment'){"+elid+"_path"+el[i].Row+j+"=["+elid+"_el["+el[i].Anim[0][j+1]+"].point1,"+elid+"_el["+el[i].Anim[0][j+1]+"].point2,"+elid+"_el["+el[i].Anim[0][j+1]+"].point1];}else{"+elid+"_path"+el[i].Row+j+"=[["+boardsize[2]+","+boardsize[1]+"],["+boardsize[0]+","+boardsize[1]+"],["+boardsize[0]+","+boardsize[3]+"],["+boardsize[2]+","+boardsize[3]+"],["+boardsize[2]+","+boardsize[1]+"]];}";
          else //if clockwise (on circle) or only on-way movement on segment
            evalstring[el[i].Row] = evalstring[el[i].Row] + "var "+elid+"_path"+el[i].Row+j+"=[];if("+elid+"_el["+el[i].Anim[0][j+1]+"].getType()=='segment'){"+elid+"_path"+el[i].Row+j+"=["+elid+"_el["+el[i].Anim[0][j+1]+"].point1,"+elid+"_el["+el[i].Anim[0][j+1]+"].point2];}else{"+elid+"_path"+el[i].Row+j+"=[["+boardsize[0]+","+boardsize[1]+"],["+boardsize[2]+","+boardsize[1]+"],["+boardsize[2]+","+boardsize[3]+"],["+boardsize[0]+","+boardsize[3]+"],["+boardsize[0]+","+boardsize[1]+"]];}";
        //evalstring[el[i].Row] = evalstring[el[i].Row] +" "+ elid+"_animLoop["+el[i].Row+"] = true; function nextStep"+el[i].Row+"() { var pos"+el[i].Row+"; if ("+elid+"_path1"+el[i].Row+".length > 0 && "+elid+"_animLoop["+el[i].Row+"]) {"+elid+"_path2"+el[i].Row+".push("+elid+"_path1"+el[i].Row+"[0]); pos"+el[i].Row+"="+elid+"_path1"+el[i].Row+".shift(); "+elid+"_el["+el[i].Anim[0][j]+"].moveTo(pos"+el[i].Row+", "+el[i].Anim[1][j]+", {callback: nextStep"+el[i].Row+"}); if ("+elid+"_path1"+el[i].Row+".length == 0) "+elid+"_animLoop["+el[i].Row+"] = false;} else {"+elid+"_path1"+el[i].Row+".push("+elid+"_path2"+el[i].Row+"[0]); pos"+el[i].Row+"="+elid+"_path2"+el[i].Row+".shift(); "+elid+"_el["+el[i].Anim[0][j]+"].moveTo(pos"+el[i].Row+", "+el[i].Anim[1][j]+", {callback: nextStep"+el[i].Row+"}); if ("+elid+"_path1"+el[i].Row+".length == "+getAnimationCPointAmount(eval(elid+"_el["+el[i].Anim[0][j+1]+"]").getType())+") "+elid+"_animLoop["+el[i].Row+"] = true;} } ";
        
        //create variable anim[Row nr][j] and functions needed (animOn, animOff)
          if (el[i].Anim[2][j] == 0) //if run repeatedly
            evalstring[el[i].Row] = evalstring[el[i].Row] + "var anim"+el[i].Row+j+" = false; var antype"+el[i].Row+j+"="+elid+"_el["+el[i].Anim[0][j]+"].getType(); function animateOn"+el[i].Row+j+"() {"+elid+"_el["+el[i].Anim[0][j]+"].makeGlider("+elid+"_el["+el[i].Anim[0][j+1]+"]); "+elid+"_el["+el[i].Anim[0][j]+"].moveAlong("+elid+"_path"+el[i].Row+j+", "+el[i].Anim[1][j]+", {callback: animateOn"+el[i].Row+j+"});}; function animateOff"+el[i].Row+j+"() {"+elid+"_el["+el[i].Anim[0][j]+"].visit([0,0], 1); if (antype"+el[i].Row+j+" == 'point')"+elid+"_el["+el[i].Anim[0][j]+"].free(); }; ";
          else  //if run only once
            evalstring[el[i].Row] = evalstring[el[i].Row] + "var anim"+el[i].Row+j+" = false; var antype"+el[i].Row+j+"="+elid+"_el["+el[i].Anim[0][j]+"].getType(); function animateOn"+el[i].Row+j+"() {"+elid+"_el["+el[i].Anim[0][j]+"].makeGlider("+elid+"_el["+el[i].Anim[0][j+1]+"]); "+elid+"_el["+el[i].Anim[0][j]+"].moveAlong("+elid+"_path"+el[i].Row+j+", "+el[i].Anim[1][j]+");}; function animateOff"+el[i].Row+j+"() {"+elid+"_el["+el[i].Anim[0][j]+"].visit([0,0], 1); if (antype"+el[i].Row+j+" == 'point')"+elid+"_el["+el[i].Anim[0][j]+"].free(); }; ";

        } //alert(evalstring[el[i].Row]);//if (el[i].Att.Visible) {
          //if (animtype.indexOf("animtype1")>=0) evalstring[el[i].Row] = elid+"_el["+el[i].Row+"] = "+boardname+"_b.create('button', ["+el[i].Pos[0]+","+el[i].Pos[1]+", '"+el[i].Pos[2]+"', function() {"+tmpstring+"}], {fixed:true, showInfoBox:"+el[i].Att.Infobox+"} );"; 
          
          // if user selected 'animtype1' create button activating function 'click[row][j]()' (move along animation created)
          if (animtype.indexOf("animtype1")>=0) evalstring[el[i].Row] = evalstring[el[i].Row] + "function click"+el[i].Row+"() {"+tmpstring+"} "+elid+"_el["+el[i].Row+"] = "+boardname+"_b.create('button', ["+el[i].Pos[0]+","+el[i].Pos[1]+", '"+el[i].Pos[2]+"', function() { click"+el[i].Row+"();}], {fixed:true} );"; 
          
          //if user selected 'animtype2' the this
          else {
            evalstring[el[i].Row] = evalstring[el[i].Row] + elid+"_el["+el[i].Row+"] = "+boardname+"_b.create('button', ["+el[i].Pos[0]+","+el[i].Pos[1]+", '"+el[i].Pos[2]+"', function() {if ("+elid+"_animOn){"+elid+"_el["+el[i].Anim[0][0]+"].stopAnimation(); "+elid+"_animOn=false;} else{"+elid+"_el["+el[i].Anim[0][0]+"].startAnimation(1,"+animticks+"); "+elid+"_animOn=true;}}], {fixed:true, showInfoBox:"+el[i].Att.Infobox+"});"; 
            if (eval(elid+"_el["+el[i].Anim[0][0]+"]").getType()!="glider")
              errors = errors + "Error on line ["+el[i].Row+"]: You can't use animation2 for other objects than 'Point on object'. <br>Some animation may not work properly.<br><br>";
          }
        //} else {
          //if (animtype.indexOf("animtype1")>=0) evalstring[el[i].Row] = elid+"_el["+el[i].Row+"] = "+boardname+"_b.create('button', ["+1.3*unitx+","+1.3*unity+", '<font size=1.5>"+el[i].Pos[2]+"</font>', function() {"+tmpstring+"}], {fixed:true, showInfoBox:"+el[i].Att.Infobox+"} );";   
          //else {
            //evalstring[el[i].Row] = elid+"_el["+el[i].Row+"] = "+boardname+"_b.create('button', ["+1.3*unitx+","+1.3*unity+", '"+el[i].Pos[2]+"', function() {if ("+elid+"_animOn){"+elid+"_el["+el[i].Anim[0][0]+"].stopAnimation(); "+elid+"_animOn=false;} else{"+elid+"_el["+el[i].Anim[0][0]+"].startAnimation(1,"+animticks+"); "+elid+"_animOn=true;}}], {fixed:true, showInfoBox:"+el[i].Att.Infobox+"});";
            //if (eval(elid+"_el["+el[i].Anim[0][0]+"]").getType()!="glider")
              //errors = errors + "Error on line ["+el[i].Row+"]: You can't use animation2 for other objects than 'Point on object'. <br>Some animation may not work properly.<br><br>";
          //}
        //}
        if (!el[i].Att.Visible)
            evalstring[el[i].Row] = evalstring[el[i].Row] + elid+"_el["+el[i].Row+"].hideElement();";
        el[i].Anim = tmpstring;      
      } //ANIMBUTTON

      else if (el[i].JsxType == 'simultaneousbutton') {
        for (var j = 0; j < el[i].Anim.length; j++) {
            tmpstring = " "+tmpstring + el[el[i].Anim[j]].Anim;
        }
          evalstring[el[i].Row] = elid+"_el["+el[i].Row+"] = "+boardname+"_b.create('button', ["+el[i].Pos[0]+","+el[i].Pos[1]+", '"+el[i].Pos[2]+"', function(){"+tmpstring+"} ],"+getOptions(el[i])+");";
        el[i].Anim = tmpstring;
      }

      // * * * * * * /BUTTONS 

      // COORDINATE SYSTEM *  * * * /

        else if(el[i].JsxType == 'originandunit') {

          evalstring[el[i].Row] = elid+"_el["+el[i].Row+"] = ["+elid+"_el["+el[i].Pos[0]+"],function(){return "+elid+"_el["+el[i].Pos[0]+"].Dist("+elid+"_el["+el[i].Pos[1]+"]);}];" 
          
          evalstring[el[i].Row] = evalstring[el[i].Row] + boardname+'_b.moveOrigin('+scalex * getOrigin(sketch).slice(0,getOrigin(sketch).indexOf(','))+','+scaley * getOrigin(sketch).slice(getOrigin(sketch).indexOf(',')+1,getOrigin(sketch).length)+');';
          
        }
        else if(el[i].JsxType == 'coordinates') {
          /*Coordinates(obj1, obj2, numX, numY, string);
            Constructs a measurement of the ordered pair of coordinates representing point obj1's location with respect to the coordinate system obj2.
            https://www.math.uni-bielefeld.de/~lisken/cgi-bin/jsp_qref?5.7.11+5.9*+5.7
            */
          calc[el[i].Row] = ["function(){return "+elid+"_el["+el[i].Pos[0]+"].X();}", "function(){return "+elid+"_el["+el[i].Pos[0]+"].Y();}"];
          evalstring[el[i].Row] = elid+"_el["+el[i].Row+"] = "+boardname+"_b.create('text', ["+el[i].Pos[2]+","+el[i].Pos[3]+",function(){return '"+el[i].Pos[4]+" ('+ Math.round("+elid+"_el["+el[i].Pos[0]+"].X()*"+mesaccu+")/"+mesaccu+" +','+ Math.round("+elid+"_el["+el[i].Pos[0]+"].Y()*"+mesaccu+")/"+mesaccu+" +')';}], {name:'"+el[i].Att.Name+"',color:'"+el[i].Att.Color+"', visible:"+el[i].Att.Visible+", anchorX:'"+el[i].Att.AnchorX+"', fixed:"+el[i].Att.Fixed+", showInfoBox:"+el[i].Att.Infobox+", anchorX:'left'} );";

        }
        // * * * * * /COORDINATE SYSTEM /


        // LOCUS * * * * * * /
        else if (el[i].JsxType == 'locus') {
          // JSP description: Locus(obj1, obj2, obj3, num);
            //Constructs the locus of obj1 as point obj2 moves along the path determined by obj3. 
            //JavaSketchpad devotes num samples to the representation of the locus--higher values of 
            //num correspond to more accurate approximations of the locus, but take more time and computer memory to process. */
          var usertick = 20; //set user ticks here
          if (el[i].Opts.indexOf('ticks(')> 0) usertick = eval(el[i].Opts.slice(el[i].Opts.indexOf('ticks(')+6, el[i].Opts.indexOf(')',el[i].Opts.indexOf('ticks(')+6)));
          usertick = 1/usertick;

          if (eval(elid+"_el["+el[i].Pos[1]+"]").getType() == 'glider')
            evalstring[el[i].Row] = elid+"_el["+el[i].Row+"] = "+boardname+"_b.create('tracecurve', ["+elid+"_el["+el[i].Pos[1]+"],"+elid+"_el["+el[i].Pos[0]+"]], {name:'"+el[i].Att.Name+"', strokeColor:'"+el[i].Att.Color+"', visible:"+el[i].Att.Visible+", numberPoints:"+el[i].Pos[3]+"} );";
          else if (eval(elid+"_el["+el[i].Pos[1]+"]").getType() == 'point') {
            if (el[el[i].Pos[2]].JsxType == 'circle') {
              evalstring[el[i].Row] = "var "+elid+el[i].Row+"visible="+el[i].Att.Visible+";"+ elid+"_el["+el[i].Row+"]=[]; function "+elid+"Locus"+el[i].Row+"(obj1,obj2,obj3){var objstart=[obj3.X(),obj3.Y()];var locuspath=[];var tick=0;obj3.makeGlider(obj1);while(tick<=1.02){obj3.setGliderPosition(tick); locuspath.push([obj2.X(),obj2.Y()]); tick=tick+"+usertick+";} for(var i=0; i<locuspath.length; i++){"+boardname+"_b.removeObject("+elid+"_el["+el[i].Row+"][i]); if(i==0)"+elid+"_el["+el[i].Row+"][i]="+boardname+"_b.create('segment',[locuspath[i],locuspath[locuspath.length-1]],{strokeWidth:1,fixed:true,visible:"+elid+el[i].Row+"visible}); else "+elid+"_el["+el[i].Row+"][i]="+boardname+"_b.create('segment',[locuspath[i-1],locuspath[i]],{strokeWidth:1,fixed:true, visible:"+elid+el[i].Row+"visible}); } if(!"+elid+"_animOn){obj3.free(); obj3.setPosition(JXG.COORDS_BY_USER, objstart); "+boardname+"_b.update();} return locuspath; }"; 
              evalstring[el[i].Row] = evalstring[el[i].Row] + elid+"Locus"+el[i].Row+"("+elid+"_el["+el[i].Pos[2]+"],"+elid+"_el["+el[i].Pos[0]+"],"+elid+"_el["+el[i].Pos[1]+"]);";
              evalstring[el[i].Row] = evalstring[el[i].Row] + elid+"_el["+el[i].Pos[2]+"].on('mouseup', function() {"+ elid+"Locus"+el[i].Row+"("+elid+"_el["+el[i].Pos[2]+"],"+elid+"_el["+el[i].Pos[0]+"],"+elid+"_el["+el[i].Pos[1]+"]);});"+elid+"_el["+el[i].Pos[2]+"].center.on('mouseup', function() {"+ elid+"Locus"+el[i].Row+"("+elid+"_el["+el[i].Pos[2]+"],"+elid+"_el["+el[i].Pos[0]+"],"+elid+"_el["+el[i].Pos[1]+"]);});";
            }
            else if (el[el[i].Pos[2]].JsxType == 'segment') {
              evalstring[el[i].Row] = "var "+elid+el[i].Row+"visible="+el[i].Att.Visible+";"+ elid+"_el["+el[i].Row+"]=[]; function "+elid+"Locus"+el[i].Row+"(obj1,obj2,obj3){var objstart=[obj3.X(),obj3.Y()];var locuspath=[];var tick=0;obj3.makeGlider(obj1);while(tick<=1.2){obj3.setGliderPosition(tick); locuspath.push([obj2.X(),obj2.Y()]); tick=tick+"+usertick+";} for(var i=0; i<locuspath.length; i++){"+boardname+"_b.removeObject("+elid+"_el["+el[i].Row+"][i]); if(i==0)"+elid+"_el["+el[i].Row+"][i]="+boardname+"_b.create('segment',[locuspath[i],locuspath[i]],{strokeWidth:1,fixed:true,visible:"+elid+el[i].Row+"visible}); else "+elid+"_el["+el[i].Row+"][i]="+boardname+"_b.create('segment',[locuspath[i-1],locuspath[i]],{strokeWidth:1,fixed:true, visible:"+elid+el[i].Row+"visible}); } if(!"+elid+"_animOn){obj3.free(); obj3.setPosition(JXG.COORDS_BY_USER, objstart); "+boardname+"_b.update();} return locuspath; }"; 
              evalstring[el[i].Row] = evalstring[el[i].Row] + elid+"Locus"+el[i].Row+"("+elid+"_el["+el[i].Pos[2]+"],"+elid+"_el["+el[i].Pos[0]+"],"+elid+"_el["+el[i].Pos[1]+"]);";
              evalstring[el[i].Row] = evalstring[el[i].Row] + elid+"_el["+el[i].Pos[2]+"].on('mouseup', function() {"+ elid+"Locus"+el[i].Row+"("+elid+"_el["+el[i].Pos[2]+"],"+elid+"_el["+el[i].Pos[0]+"],"+elid+"_el["+el[i].Pos[1]+"]);});"+ elid+"_el["+el[i].Pos[2]+"].point1.on('mouseup', function() {"+ elid+"Locus"+el[i].Row+"("+elid+"_el["+el[i].Pos[2]+"],"+elid+"_el["+el[i].Pos[0]+"],"+elid+"_el["+el[i].Pos[1]+"]);});"+ elid+"_el["+el[i].Pos[2]+"].point2.on('mouseup', function() {"+ elid+"Locus"+el[i].Row+"("+elid+"_el["+el[i].Pos[2]+"],"+elid+"_el["+el[i].Pos[0]+"],"+elid+"_el["+el[i].Pos[1]+"]);});";
            }
            else errors = errors + "Traced point [line:"+el[i].Pos[1]+"] is not a type 'Point on object' [type is "+el[el[i].Pos[1]].Type+"].<br> 'Locus' can be constructed for a 'Point'-element only if path [line:"+el[i].Pos[2]+"] in 'Circle' or 'Segment'.<br>Locus [line:"+el[i].Row+"] was not constructed!<br><br>";
          }
          else 
            //evalstring[el[i].Row] = elid+"_el["+el[i].Row+"] = "+boardname+"_b.create('locus', ["+elid+"_el["+el[i].Pos[0]+"]], {name:'"+el[i].Att.Name+"', strokeColor:'"+el[i].Att.Color+"', visible:"+el[i].Att.Visible+"} );";
            errors = errors + "Error on line ["+el[i].Row+"]: Traced point on line ["+el[i].Pos[1]+"] is not a type 'Point on object'.<br> This locus may not work properly. <br><br>";
        }
        else {
          errors = errors + "Operator '"+el[i].Type+"' is unknown or is not supported yet.<br> Converting stopped on line ["+el[i].Row+"]. <br><br>";
          break;
        }

        // * * * * * /LOCUS /

        //Hide buttons and measurements if they are 'hidden' in options field
        if (!el[i].Att.Visible && (el[i].CType == 'measurements' || el[i].CType == 'buttons') ) {evalstring[el[i].Row] = evalstring[el[i].Row] + elid+"_el["+el[i].Row+"].hideElement();";}        

    }
    //if (!isFullPageConvert)      
      eval(evalstring[el[i].Row]); 
    tmpstring = "";
    if (document.getElementById('originalcode').value == 'Comment' && !isFullPageConvert)
      codestring = codestring + "&#13;&#10; <!-- -- " +sketchrows_comment[i]+ " -->&#13;&#10;";
    
    //if (evalstring[el[i].Row].indexOf('&#70;') > 0) {evalstring[el[i].Row] = evalstring[el[i].Row].replace('&#70;', '&#70;'); alert(evalstring[el[i].Row]);}
    //if (el[i].hasComment)
      codestring = codestring +el[i].comment+ evalstring[el[i].Row] + "&#13;&#10;";
    //else
      //codestring = codestring + evalstring[el[i].Row];


    if (!isFullPageConvert){
      codestring = codestring+"&#13;&#10;";
    }
  }
  codestring = codestring + "<"+"/"+"script"+">";

  if (isFullPageConvert) {
    document.getElementById('jsxgimage').innerHTML = "";
    if (errors.length > 30) document.getElementById('errormessages').innerHTML = "<font color='red'><b>Convertion done, but some errors occurred.<br><br></b></font>"+errors;
    else document.getElementById('errormessages').innerHTML = "<font color='green'><b>Convertion done, no errors.</b></font>";
    return codestring;
  }
  else {
    codestring = "<table style='borders:1; width:80%;' cellpadding='3'><tr><td><font size='4'><b><u>JSXGraph code:</u></b></font> </td><td><input onclick='downloadJSX()' value='Save JSX/HTML' type='button' class='browseButton'></td><td><input onclick='copyToClipboard()' value='Copy JSX code to clipboard' type='button' class='browseButton'></td></tr><tr><td colspan='3'><textarea id ='jsxcode' cols='120' rows='30' value="+codestring+" </textarea></td></tr></table>";
    document.getElementById("jsxgcode").innerHTML = codestring;
    if (errors.length > 30) document.getElementById('errormessages').innerHTML = "<font color='red'><b>Convertion done, but some errors occurred.<br><br></b></font>"+errors;
    else document.getElementById('errormessages').innerHTML = "<font color='green'><b>Convertion done, no errors.</b></font>";
    return codestring;
  }
}