<commit_before>var Game, evaluators, keyPegs, randomizers;

randomizers = {
  mathRandom: function(colors) {
    return Math.floor(Math.random() * colors);
  },
  constantZero: function(colors) {
    return 0;
  }
};

keyPegs = {
  white: 'white',
  black: 'black'
};

evaluators = {
  original: function(solution, guess) {
    var color, guessPos, ret, solutionPos, _len, _len2;
    ret = {};
    ret[keyPegs.white] = 0;
    ret[keyPegs.black] = 0;
    console.log(solution, guess);
    for (solutionPos = 0, _len = solution.length; solutionPos < _len; solutionPos++) {
      color = solution[solutionPos];
      if (guess[solutionPos] === color) {
        ret[keyPegs.black] += 1;
        guess[solutionPos] = solution[solutionPos] = -1;
      }
    }
    console.log(solution, guess);
    for (solutionPos = 0, _len2 = solution.length; solutionPos < _len2; solutionPos++) {
      color = solution[solutionPos];
      if (color === -1) continue;
      if ((guessPos = guess.indexOf(color)) !== -1) {
        ret[keyPegs.white] += 1;
        guess[guessPos] = -1;
      }
    }
    console.log(solution, guess);
    ret.solved = ret[keyPegs.black] === solution.length;
    return ret;
  }
};

Game = (function() {

  Game.states = {
    initial: 'initial',
    playing: 'playiing',
    won: 'won',
    lost: 'lost'
  };

  function Game(opts) {
    var _ref, _ref2, _ref3, _ref4, _ref5;
    this.colors = (_ref = opts.colors) != null ? _ref : 6;
    this.rows = (_ref2 = opts.rows) != null ? _ref2 : 10;
    this.holes = (_ref3 = opts.holes) != null ? _ref3 : 4;
    this.state = Game.states.initial;
    this.randomizer = (_ref4 = opts.randomizer) != null ? _ref4 : randomizers.mathRandom;
    this.evaluator = (_ref5 = opts.evaluator) != null ? _ref5 : evaluators.original;
  }

  Game.prototype.makeCode = function() {
    var hole;
    if (this.state !== Game.states.initial) {
      throw 'makeCode must be called in "initial" state';
    }
    this.code = (function() {
      var _ref, _results;
      _results = [];
      for (hole = 0, _ref = this.holes; 0 <= _ref ? hole < _ref : hole > _ref; 0 <= _ref ? hole++ : hole--) {
        _results.push(this.randomizer(this.colors));
      }
      return _results;
    }).call(this);
    this.guesses = 0;
    return this.state = Game.states.playing;
  };

  Game.prototype.guess = function(guess) {
    var result;
    if (this.state !== Game.states.playing) {
      throw 'The game is over, you can\'t make any more guesses.';
    }
    if (guess.length !== this.holes) {
      throw 'All holes must be filled in the guess.';
    }
    result = this.evaluator(this.code.slice(0, this.code.length), guess.slice(0, guess.length));
    this.guesses += 1;
    if (result.solved) {
      this.state = Game.states.won;
    } else if (this.guesses === this.rows) {
      this.state = Game.states.lost;
    }
    return result;
  };

  return Game;

})();
<commit_msg>Regenerate model.js without console.log calls<commit_after>var Game, evaluators, keyPegs, randomizers;

randomizers = {
  mathRandom: function(colors) {
    return Math.floor(Math.random() * colors);
  },
  constantZero: function(colors) {
    return 0;
  }
};

keyPegs = {
  white: 'white',
  black: 'black'
};

evaluators = {
  original: function(solution, guess) {
    var color, guessPos, ret, solutionPos, _len, _len2;
    ret = {};
    ret[keyPegs.white] = 0;
    ret[keyPegs.black] = 0;
    for (solutionPos = 0, _len = solution.length; solutionPos < _len; solutionPos++) {
      color = solution[solutionPos];
      if (guess[solutionPos] === color) {
        ret[keyPegs.black] += 1;
        guess[solutionPos] = solution[solutionPos] = -1;
      }
    }
    for (solutionPos = 0, _len2 = solution.length; solutionPos < _len2; solutionPos++) {
      color = solution[solutionPos];
      if (color === -1) continue;
      if ((guessPos = guess.indexOf(color)) !== -1) {
        ret[keyPegs.white] += 1;
        guess[guessPos] = -1;
      }
    }
    ret.solved = ret[keyPegs.black] === solution.length;
    return ret;
  }
};

Game = (function() {

  Game.states = {
    initial: 'initial',
    playing: 'playiing',
    won: 'won',
    lost: 'lost'
  };

  function Game(opts) {
    var _ref, _ref2, _ref3, _ref4, _ref5;
    this.colors = (_ref = opts.colors) != null ? _ref : 6;
    this.rows = (_ref2 = opts.rows) != null ? _ref2 : 10;
    this.holes = (_ref3 = opts.holes) != null ? _ref3 : 4;
    this.state = Game.states.initial;
    this.randomizer = (_ref4 = opts.randomizer) != null ? _ref4 : randomizers.mathRandom;
    this.evaluator = (_ref5 = opts.evaluator) != null ? _ref5 : evaluators.original;
  }

  Game.prototype.makeCode = function() {
    var hole;
    if (this.state !== Game.states.initial) {
      throw 'makeCode must be called in "initial" state';
    }
    this.code = (function() {
      var _ref, _results;
      _results = [];
      for (hole = 0, _ref = this.holes; 0 <= _ref ? hole < _ref : hole > _ref; 0 <= _ref ? hole++ : hole--) {
        _results.push(this.randomizer(this.colors));
      }
      return _results;
    }).call(this);
    this.guesses = 0;
    return this.state = Game.states.playing;
  };

  Game.prototype.guess = function(guess) {
    var result;
    if (this.state !== Game.states.playing) {
      throw 'The game is over, you can\'t make any more guesses.';
    }
    if (guess.length !== this.holes) {
      throw 'All holes must be filled in the guess.';
    }
    result = this.evaluator(this.code.slice(0, this.code.length), guess.slice(0, guess.length));
    this.guesses += 1;
    if (result.solved) {
      this.state = Game.states.won;
    } else if (this.guesses === this.rows) {
      this.state = Game.states.lost;
    }
    return result;
  };

  return Game;

})();
<|endoftext|>


<commit_before>webix.ready(function(){
   //webix.ui.fullScreen(); //for fullscreen on mobile devices

var uploadControls =
   {header:"Import Compounds", maxWidth:250, gravity:2, collapsed:false, body:
      {rows:[ //removed view:'form' to make this take up the whole width
         {
            id:'process', view:'button', value:'Process Docking Ouput', type:'form',
            labelWidth:120, click:function(){$$('processorWin').show();},
         },
         { //Uploader element
            id:"hydraUploader", view:"uploader",
            value:"Upload Files",
            multiple:true, autosend:false,
         },
         { //Table showing uploaded files
            id:"uploadTable", view:"datatable",
            select:true, multiselect:true, //ctrl+click & shift+click work
            drag:true, //NEED TO MAKE THIS SYNC WITH COMPOUND LIST
            editable:true, editaction:"dblclick",
            minHeight:160,
            leftSplit:2, //so left 2 col's won't scroll horizontally
            columns:[
               {id:"col", header:"Col", width:40, editor:"text"},
               {id:"oCol", header:"origCol", hidden:true},
               {id:"row", header:"Row", width:45, editor:"text"},
               {id:"oRow", header:"origRow", hidden:true},
               {id:"fileName", header:"File Name", width:200},
               {id:"fileData", header:"Data", hidden:true},
            ],
         },
         {
            cols:[
               {
                  view:"button",id:"load_click",value:"Update Data",type:"form",
                  click:load_fxn
               },
               {
                  view:"button",id:"clear_click",value:"Delete Data",type:"danger",
                  click:clear_fxn
               }
            ]
         }
      ]}
   };

var gridControls =
   {header:"Grid Size", maxWidth:250, gravity:1, collapsed:false, body:
      {view:"form", id:"grid_dim", elements:[
         //{view:"text",value:"blarg",label:"test",name:"mg"},
         {
            view:"text",value:"1",label:"Columns:",name:"numCol",//specifies cols count
         },
         {
            view:"text",value:"1",label:"Rows:",name:"numRow",//specifies rows count
         },
         {
            view:"button",id:"update_grid",value:"Update Grid",inputWidth:"150",align:"center",
            on:{
               'onItemClick': updategridfxn
            }
         }
      ]}
   };

//Note that the following compound controls pass in an index into each display-setting fxn
//0 = main compound; 1 = ligand
var mainControls =
   {header:"Main Compound", maxWidth:250, collapsed:false, body:
      {rows:[
         //Hidden element which keeps track of the active viewer. Avoids making global var
         {id:'activeCoord', view:'text', hidden:true},
         {id:'mStructType', view:'richselect', label:'Display as', options:[
            {id:'structCartoon', value:'Cartoon'},
            {id:'structSphere', value:'Sphere'},
            {id:'structStick', value:'Stick'},
            {id:'structLine', value:'Line'},
            {id:'structCross', value:'Cross'},
            ],
            on:{
               'onChange': function(){
                  var coord = $$('activeCoord').getValue();

                  if (coord) {
                     console.log('repainting structure');
                     setStruct(coord,this,0);
                  }
               }
            }
         },
         {id:'mSurfType', view:'richselect', label:'Surface', options:[
            {id:'surfNone', value:'None'},
            {id:'surfVDW', value:'Van der Waals'},
            {id:'surfMS', value:'Molecular'},
            {id:'surfSAS', value:'Solvent Accessible'},
            {id:'surfSES', value:'Solvent Excluded'},
            ],
            value:'surfNone',
            on:{
               onChange: function(){
                  var coord = $$('activeCoord').getValue();
                  var surfID = this.getValue();

                  if (coord && surfID!=$$('viewer'+coord).getWindow().surfType[0]){
                     var opacSet = $$('mSurfOpacity').getValue()/100;
                     console.log('change in surf type detected');
                     setSurface(coord,surfID,0,opacSet);
                  }
               }
            }
         },

         //if time permits: add color setting option for surface and for actual model
         //https://github.com/dkoes/3Dmol.js/issues/88 &
         //https://github.com/dkoes/3Dmol.js/commit/2973a4eebf4ee32972fc13a19d9c0188a89e9efc
         /*{id:'mSurfColor', view:'richselect', label:'Surface Color', options:[
            {id:'mSElement', value:'By Element'},
            {id:'mSCharge', value:'By Charge'}
         ]},*/

         {id:'mSurfOpacity', view:'slider', level:'Opacity', label:'Opacity',
            value:'50', min:0, max:100,
            //Gives opacity in percentage
            //3Dmol requires decimal -> use this.getValue()/100
            on:{
               onChange: function(){
                  var coord = $$('activeCoord').getValue();
                  var itemVal = this.getValue();

                  if (coord && itemVal!=$$('viewer'+coord).getWindow().surfOpacity[0]) {
                     var opacSet = itemVal/100;
                     console.log('change detected in surfOpac');
                     setSurface(coord,$$('mSurfType').getValue(),0,opacSet);
                  }
               }
            }
         },

         {} //Blank view needed to fix a related resizing issue
         //Webix thread: http://forum.webix.com/discussion/comment/4771
      ]}
   };

var ligandControls =
   {header:'Ligand', maxWidth:250, collapsed:false, body:
      {rows:[
         {id:'lStructType', view:'richselect', label:'Display as', options:[
            //Note: 'cartoon 'isn't meant to be used like this, but it does hide HETATMS
            {id:'structCartoon', value:'Hide'},
            {id:'structSphere', value:'Sphere'},
            {id:'structStick', value:'Stick'},
            {id:'structLine', value:'Line'},
            {id:'structCross', value:'Cross'},
            ],
            on:{
               'onChange': function(){
                  var coord = $$('activeCoord').getValue();

                  if (coord) {
                     setStruct(coord,this,1);
                  }
               }
            }

         },
         {id:'lSurfType', view:'richselect', label:'Surface', options:[
            {id:'surfNone', value:'None'},
            {id:'surfVDW', value:'Van der Waals'},
            {id:'surfMS', value:'Molecular'},
            {id:'surfSAS', value:'Solvent Accessible'},
            {id:'surfSES', value:'Solvent Excluded'},
            ],
            value:'surfNone',
            on:{
               onChange: function(){
                  var coord = $$('activeCoord').getValue();
                  var surfID = this.getValue();

                  if (coord && surfID!=$$('viewer'+coord).getWindow().surfType[1]){
                     var opacSet = $$('lSurfOpacity').getValue()/100;

                     setSurface(coord,surfID,1,opacSet);
                  }
               }
            }
         },

         //again, add color settings if time permits

         {id:'lSurfOpacity', view:'slider', level:'Opacity', label:'Opacity',
            value:'50', min:0, max:100,
            //Gives opacity in percentage
            //3Dmol requires decimal -> use this.getValue()/100
            on:{
               onChange: function(){
                  var coord = $$('activeCoord').getValue();
                  var itemVal = this.getValue();

                  if (coord && itemVal!=$$('viewer'+coord).getWindow().surfOpacity[1]) {
                     var opacSet = itemVal/100;

                     setSurface(coord,$$('lSurfType').getValue(),1,opacSet);
                  }
               }
            }
         },

         {} //Blank view needed to fix a related resizing
      ]}
   };

hydraUI = webix.ui({
   container:"masterarea",
   type:"line",
   responsive:"true",

    rows:[
      // first row is a title header for app, maybe put more stuff here later?
      {template:"html->titlebar", height:1 },

      // second row, main content of app goes here
      {cols:[
      //Left column is a sliding pane: [upload controls, grid controls], [model controls]
      {id:'leftCol',
         cells:[
            {id:'files&grid', view:"scrollview",
               scroll:"y",
               body:
               {rows:[

                  // Upload compound list / DOCK data
                  uploadControls,
                  {view:'resizer'},

                  //Webix bug: section below resizer expands when resizer moved up
                  //TEMP FIX: Need to nest the below sections in one row
                  {rows:[
                  // "Grid Controls" - controls for resizing the grid
                     gridControls,
                     {}
                  ]},

                  {
                     view:"button", id:"toVC", type:"next", label:'To Compound Controls',
                     click:function(){$$('compoundCtrls').show();}
                  }
               ]}
            },
            {id:'compoundCtrls', view:'scrollview', scroll:'y', body:
               {rows:[
                  mainControls,
                  ligandControls,
                  {},
                  //checkbox for setting whether or not to sync compound rotation across viewers
                  //unchecked -> 0; checked -> 1
                  //Needed to do an ungly workaround to get the label on the right
                  {cols:[
                     {
                        id:'syncMove', view:'checkbox', value:0,
                     },
                     {
                        view:'label', label:'Sync movements', align:'left', width:210
                     }
                  ]},
                  {
                     id:"toF&G",  view:"button", type:"prev", label:'To File & Grid Controls',
                     click:function(){$$('files&grid').show();}
                  },
               ]}
            }
         ]
      },

      // middle column contains central workspace with all of the visualization objects
      {id:"workspace", view:"scrollview", container:"central_workspace",type:"clean",
         scroll:"xy", //Enables horizontal (x) and vertical (y) scrolling

         //Framework for a resizable grid of GLmol instances
         //Viewers start at index of 1 with coordinates (x,y)
         //Eg "viewer2,1" is in the first row, second column from the left
         body:{id:"workLayout", type:'clean', borderless:true, rows:[{
            id:"workRow"+"1", type:'clean', borderless:true, css:'inactiveViewer', cols:[{
               view:"iframe",
               id:"viewer"+"1"+","+"1",
               src:"3Dmol frame.html",
               minWidth:250,minHeight:250,
               on:{
                  'onAfterLoad':function(){
                     this.getWindow().setGridCoordinates('1,1');
                  }
               }
            }]
         }]}
      },

      // right column has compounds list, details are accordioned components
      {view:"scrollview",scroll:"y",body:
      {
         multi:true, view:"accordion", type:"line",
         rows:[

         // Compound list showing cat,name from uploaded file
         {header:"Compound List", height:300, collapsed:false, body:
            {
               id:"comp_table",
               view:"datatable",
               select:true,
               columns:[
                  // { id:"idNum", header:"ID", width:50},
                  { id:"zincId", header:"Compound Name", width:135 }, //The ZINC ID
                  { id:'numAtoms', hidden:true},
                  { id:'numBonds', hidden:true},
                  { id:'techName', hidden:true}
               ],
               data:'',
               minWidth:250,

            on:{
               onBeforeLoad:function(){
                  this.showOverlay("Loading...");
               },
               onAfterLoad:function(){
                  this.hideOverlay();
               }
            },
            }
         },
         {view:"resizer"},
         // Details of selected compound not shown in list, such as scores
         {rows:[
            {header:"Compound Details", collapsed:false, body:
               {view:"form", id:"comp_det", maxWidth:250, rows:[
                  { view:"text",name:"zincId",label:"ZINC ID" },
                  { view:"text",name:"techName",label:"Name" },
                  { view:"text",name:"numAtoms",label:"# Atoms" },
                  { view:"text",name:"numBonds",label:"# Bonds" },
               ]}
            },

            {view:"resizer",
               container:"vendorDiv",
               scroll: 'xy',
               id:"all_vendors"},

            // Details of selected compound not shown in list, such as scores
            {header:"Vendor List", collapsed:false, body:
               { view:"datatable",
               id:"vendors",
               select:true,
               multiselect:true,
               drag:true,
               maxWidth:250,
               columns:[
                  {  template: "#compound# #vendor#",
                     header:"Zinc ID : Vendor",
                     width:250,
                     height: 350,
                     editor:"text",
                  }
               ],
               data:'',
               on:{
                  onItemDblClick:function(id){
                     alert(
                        "Compound: " + this.getItem(id).compound + "\n" +
                        "Website: " + this.getItem(id).website + "\n" +
                        "Phone #: " + this.getItem(id).phone + "\n" +
                        "Fax #: " + this.getItem(id).fax + "\n" +
                        "Contact Email: " + this.getItem(id).email + "\n" +
                        "Directly order: " + this.getItem(id).orderurl + "\n"
                     );
                  }
               }
               },
            },
         ]},
         //For debugging: Textarea to display contents of files
         /*{header:"File Value", collapsed:false, body:
            {view:"textarea", id:"file_dump", maxWidth:300}
         },*/

      ]},
      },
      ]}
   ]
});

/* Called after a file is added to the view:uploader. Called successively for each file
 * if multiple files are sent at once.
 * Takes data from the first file in "hydraUploader" and puts it in the "uploadTable"
 * view:datatable.  Object is then removed so more items may be read successfully.
 */
$$("hydraUploader").attachEvent("onAfterFileAdd",function(){

   var reader = new FileReader();

   var fID, fName, fData;

   fID = $$('hydraUploader').files.getFirstId();

   fName = $$("hydraUploader").files.getItem(fID).name;
   fData = $$("hydraUploader").files.getItem(fID).file;

   reader.onload = function(e) {
      //CHANGE THIS SO THAT THE FILES GET ADDED TO THE PROCESSOR WINDOW IF PROCESS == 1
      $$('uploadTable').add({col:0, oCol:0, row:0, oRow:0,
                            fileName:fName, fileData:reader.result});
      //Add the parsed file data to 'uploadTable" w/ default coordinates 0,0
      //Added as a string rather than an actual file object

      parseForZinc(reader.result);
      parseLigInfo(reader.result);
   };
   reader.onerror = function(e) {
      console.error("File could not be read. Code: "+e.target.error.code);
      alert("error");
   };

   reader.readAsText(fData);

   $$('hydraUploader').files.remove(fID);
});

// binds selected compound detail panel with selection in compounds list, default selection is first
$$('comp_det').bind($$('comp_table'));
$$("comp_table").select(1);

});

//Resizes GUI dynamically with the window size
webix.event(window,"resize", function(){hydraUI.adjust();});<commit_msg>'comp_det' fields made read only<commit_after>webix.ready(function(){
   //webix.ui.fullScreen(); //for fullscreen on mobile devices

var uploadControls =
   {header:"Import Compounds", maxWidth:250, gravity:2, collapsed:false, body:
      {rows:[ //removed view:'form' to make this take up the whole width
         {
            id:'process', view:'button', value:'Process Docking Ouput', type:'form',
            labelWidth:120, click:function(){$$('processorWin').show();},
         },
         { //Uploader element
            id:"hydraUploader", view:"uploader",
            value:"Upload Files",
            multiple:true, autosend:false,
         },
         { //Table showing uploaded files
            id:"uploadTable", view:"datatable",
            select:true, multiselect:true, //ctrl+click & shift+click work
            drag:true, //NEED TO MAKE THIS SYNC WITH COMPOUND LIST
            editable:true, editaction:"dblclick",
            minHeight:160,
            leftSplit:2, //so left 2 col's won't scroll horizontally
            columns:[
               {id:"col", header:"Col", width:40, editor:"text"},
               {id:"oCol", header:"origCol", hidden:true},
               {id:"row", header:"Row", width:45, editor:"text"},
               {id:"oRow", header:"origRow", hidden:true},
               {id:"fileName", header:"File Name", width:200},
               {id:"fileData", header:"Data", hidden:true},
            ],
         },
         {
            cols:[
               {
                  view:"button",id:"load_click",value:"Update Data",type:"form",
                  click:load_fxn
               },
               {
                  view:"button",id:"clear_click",value:"Delete Data",type:"danger",
                  click:clear_fxn
               }
            ]
         }
      ]}
   };

var gridControls =
   {header:"Grid Size", maxWidth:250, gravity:1, collapsed:false, body:
      {view:"form", id:"grid_dim", elements:[
         //{view:"text",value:"blarg",label:"test",name:"mg"},
         {
            view:"text",value:"1",label:"Columns:",name:"numCol",//specifies cols count
         },
         {
            view:"text",value:"1",label:"Rows:",name:"numRow",//specifies rows count
         },
         {
            view:"button",id:"update_grid",value:"Update Grid",inputWidth:"150",align:"center",
            on:{
               'onItemClick': updategridfxn
            }
         }
      ]}
   };

//Note that the following compound controls pass in an index into each display-setting fxn
//0 = main compound; 1 = ligand
var mainControls =
   {header:"Main Compound", maxWidth:250, collapsed:false, body:
      {rows:[
         //Hidden element which keeps track of the active viewer. Avoids making global var
         {id:'activeCoord', view:'text', hidden:true},
         {id:'mStructType', view:'richselect', label:'Display as', options:[
            {id:'structCartoon', value:'Cartoon'},
            {id:'structSphere', value:'Sphere'},
            {id:'structStick', value:'Stick'},
            {id:'structLine', value:'Line'},
            {id:'structCross', value:'Cross'},
            ],
            on:{
               'onChange': function(){
                  var coord = $$('activeCoord').getValue();

                  if (coord) {
                     console.log('repainting structure');
                     setStruct(coord,this,0);
                  }
               }
            }
         },
         {id:'mSurfType', view:'richselect', label:'Surface', options:[
            {id:'surfNone', value:'None'},
            {id:'surfVDW', value:'Van der Waals'},
            {id:'surfMS', value:'Molecular'},
            {id:'surfSAS', value:'Solvent Accessible'},
            {id:'surfSES', value:'Solvent Excluded'},
            ],
            value:'surfNone',
            on:{
               onChange: function(){
                  var coord = $$('activeCoord').getValue();
                  var surfID = this.getValue();

                  if (coord && surfID!=$$('viewer'+coord).getWindow().surfType[0]){
                     var opacSet = $$('mSurfOpacity').getValue()/100;
                     console.log('change in surf type detected');
                     setSurface(coord,surfID,0,opacSet);
                  }
               }
            }
         },

         //if time permits: add color setting option for surface and for actual model
         //https://github.com/dkoes/3Dmol.js/issues/88 &
         //https://github.com/dkoes/3Dmol.js/commit/2973a4eebf4ee32972fc13a19d9c0188a89e9efc
         /*{id:'mSurfColor', view:'richselect', label:'Surface Color', options:[
            {id:'mSElement', value:'By Element'},
            {id:'mSCharge', value:'By Charge'}
         ]},*/

         {id:'mSurfOpacity', view:'slider', level:'Opacity', label:'Opacity',
            value:'50', min:0, max:100,
            //Gives opacity in percentage
            //3Dmol requires decimal -> use this.getValue()/100
            on:{
               onChange: function(){
                  var coord = $$('activeCoord').getValue();
                  var itemVal = this.getValue();

                  if (coord && itemVal!=$$('viewer'+coord).getWindow().surfOpacity[0]) {
                     var opacSet = itemVal/100;
                     console.log('change detected in surfOpac');
                     setSurface(coord,$$('mSurfType').getValue(),0,opacSet);
                  }
               }
            }
         },

         {} //Blank view needed to fix a related resizing issue
         //Webix thread: http://forum.webix.com/discussion/comment/4771
      ]}
   };

var ligandControls =
   {header:'Ligand', maxWidth:250, collapsed:false, body:
      {rows:[
         {id:'lStructType', view:'richselect', label:'Display as', options:[
            //Note: 'cartoon 'isn't meant to be used like this, but it does hide HETATMS
            {id:'structCartoon', value:'Hide'},
            {id:'structSphere', value:'Sphere'},
            {id:'structStick', value:'Stick'},
            {id:'structLine', value:'Line'},
            {id:'structCross', value:'Cross'},
            ],
            on:{
               'onChange': function(){
                  var coord = $$('activeCoord').getValue();

                  if (coord) {
                     setStruct(coord,this,1);
                  }
               }
            }

         },
         {id:'lSurfType', view:'richselect', label:'Surface', options:[
            {id:'surfNone', value:'None'},
            {id:'surfVDW', value:'Van der Waals'},
            {id:'surfMS', value:'Molecular'},
            {id:'surfSAS', value:'Solvent Accessible'},
            {id:'surfSES', value:'Solvent Excluded'},
            ],
            value:'surfNone',
            on:{
               onChange: function(){
                  var coord = $$('activeCoord').getValue();
                  var surfID = this.getValue();

                  if (coord && surfID!=$$('viewer'+coord).getWindow().surfType[1]){
                     var opacSet = $$('lSurfOpacity').getValue()/100;

                     setSurface(coord,surfID,1,opacSet);
                  }
               }
            }
         },

         //again, add color settings if time permits

         {id:'lSurfOpacity', view:'slider', level:'Opacity', label:'Opacity',
            value:'50', min:0, max:100,
            //Gives opacity in percentage
            //3Dmol requires decimal -> use this.getValue()/100
            on:{
               onChange: function(){
                  var coord = $$('activeCoord').getValue();
                  var itemVal = this.getValue();

                  if (coord && itemVal!=$$('viewer'+coord).getWindow().surfOpacity[1]) {
                     var opacSet = itemVal/100;

                     setSurface(coord,$$('lSurfType').getValue(),1,opacSet);
                  }
               }
            }
         },

         {} //Blank view needed to fix a related resizing
      ]}
   };

hydraUI = webix.ui({
   container:"masterarea",
   type:"line",
   responsive:"true",

    rows:[
      // first row is a title header for app, maybe put more stuff here later?
      {template:"html->titlebar", height:1 },

      // second row, main content of app goes here
      {cols:[
      //Left column is a sliding pane: [upload controls, grid controls], [model controls]
      {id:'leftCol',
         cells:[
            {id:'files&grid', view:"scrollview",
               scroll:"y",
               body:
               {rows:[

                  // Upload compound list / DOCK data
                  uploadControls,
                  {view:'resizer'},

                  //Webix bug: section below resizer expands when resizer moved up
                  //TEMP FIX: Need to nest the below sections in one row
                  {rows:[
                  // "Grid Controls" - controls for resizing the grid
                     gridControls,
                     {}
                  ]},

                  {
                     view:"button", id:"toVC", type:"next", label:'To Compound Controls',
                     click:function(){$$('compoundCtrls').show();}
                  }
               ]}
            },
            {id:'compoundCtrls', view:'scrollview', scroll:'y', body:
               {rows:[
                  mainControls,
                  ligandControls,
                  {},
                  //checkbox for setting whether or not to sync compound rotation across viewers
                  //unchecked -> 0; checked -> 1
                  //Needed to do an ungly workaround to get the label on the right
                  {cols:[
                     {
                        id:'syncMove', view:'checkbox', value:0,
                     },
                     {
                        view:'label', label:'Sync movements', align:'left', width:210
                     }
                  ]},
                  {
                     id:"toF&G",  view:"button", type:"prev", label:'To File & Grid Controls',
                     click:function(){$$('files&grid').show();}
                  },
               ]}
            }
         ]
      },

      // middle column contains central workspace with all of the visualization objects
      {id:"workspace", view:"scrollview", container:"central_workspace",type:"clean",
         scroll:"xy", //Enables horizontal (x) and vertical (y) scrolling

         //Framework for a resizable grid of GLmol instances
         //Viewers start at index of 1 with coordinates (x,y)
         //Eg "viewer2,1" is in the first row, second column from the left
         body:{id:"workLayout", type:'clean', borderless:true, rows:[{
            id:"workRow"+"1", type:'clean', borderless:true, css:'inactiveViewer', cols:[{
               view:"iframe",
               id:"viewer"+"1"+","+"1",
               src:"3Dmol frame.html",
               minWidth:250,minHeight:250,
               on:{
                  'onAfterLoad':function(){
                     this.getWindow().setGridCoordinates('1,1');
                  }
               }
            }]
         }]}
      },

      // right column has compounds list, details are accordioned components
      {view:"scrollview",scroll:"y",body:
      {
         multi:true, view:"accordion", type:"line",
         rows:[

         // Compound list showing cat,name from uploaded file
         {header:"Compound List", height:300, collapsed:false, body:
            {
               id:"comp_table",
               view:"datatable",
               select:true,
               columns:[
                  // { id:"idNum", header:"ID", width:50},
                  { id:"zincId", header:"Compound Name", width:135 }, //The ZINC ID
                  { id:'numAtoms', hidden:true},
                  { id:'numBonds', hidden:true},
                  { id:'techName', hidden:true}
               ],
               data:'',
               minWidth:250,

            on:{
               onBeforeLoad:function(){
                  this.showOverlay("Loading...");
               },
               onAfterLoad:function(){
                  this.hideOverlay();
               }
            },
            }
         },
         {view:"resizer"},
         // Details of selected compound not shown in list, such as scores
         {rows:[
            {header:"Compound Details", collapsed:false, body:
               {view:"form", id:"comp_det", maxWidth:250, rows:[
                  { view:"text",name:"zincId",label:"ZINC ID", readonly:true },
                  { view:"text",name:"techName",label:"Name", readonly:true },
                  { view:"text",name:"numAtoms",label:"# Atoms", readonly:true },
                  { view:"text",name:"numBonds",label:"# Bonds", readonly:true },
               ]}
            },

            {view:"resizer",
               container:"vendorDiv",
               scroll: 'xy',
               id:"all_vendors"},

            // Details of selected compound not shown in list, such as scores
            {header:"Vendor List", collapsed:false, body:
               { view:"datatable",
               id:"vendors",
               select:true,
               multiselect:true,
               drag:true,
               maxWidth:250,
               columns:[
                  {  template: "#compound# #vendor#",
                     header:"Zinc ID : Vendor",
                     width:250,
                     height: 350,
                     editor:"text",
                  }
               ],
               data:'',
               on:{
                  onItemDblClick:function(id){
                     alert(
                        "Compound: " + this.getItem(id).compound + "\n" +
                        "Website: " + this.getItem(id).website + "\n" +
                        "Phone #: " + this.getItem(id).phone + "\n" +
                        "Fax #: " + this.getItem(id).fax + "\n" +
                        "Contact Email: " + this.getItem(id).email + "\n" +
                        "Directly order: " + this.getItem(id).orderurl + "\n"
                     );
                  }
               }
               },
            },
         ]},
         //For debugging: Textarea to display contents of files
         /*{header:"File Value", collapsed:false, body:
            {view:"textarea", id:"file_dump", maxWidth:300}
         },*/

      ]},
      },
      ]}
   ]
});

/* Called after a file is added to the view:uploader. Called successively for each file
 * if multiple files are sent at once.
 * Takes data from the first file in "hydraUploader" and puts it in the "uploadTable"
 * view:datatable.  Object is then removed so more items may be read successfully.
 */
$$("hydraUploader").attachEvent("onAfterFileAdd",function(){

   var reader = new FileReader();

   var fID, fName, fData;

   fID = $$('hydraUploader').files.getFirstId();

   fName = $$("hydraUploader").files.getItem(fID).name;
   fData = $$("hydraUploader").files.getItem(fID).file;

   reader.onload = function(e) {
      //CHANGE THIS SO THAT THE FILES GET ADDED TO THE PROCESSOR WINDOW IF PROCESS == 1
      $$('uploadTable').add({col:0, oCol:0, row:0, oRow:0,
                            fileName:fName, fileData:reader.result});
      //Add the parsed file data to 'uploadTable" w/ default coordinates 0,0
      //Added as a string rather than an actual file object

      parseForZinc(reader.result);
      parseLigInfo(reader.result);
   };
   reader.onerror = function(e) {
      console.error("File could not be read. Code: "+e.target.error.code);
      alert("error");
   };

   reader.readAsText(fData);

   $$('hydraUploader').files.remove(fID);
});

// binds selected compound detail panel with selection in compounds list, default selection is first
$$('comp_det').bind($$('comp_table'));
$$("comp_table").select(1);

});

//Resizes GUI dynamically with the window size
webix.event(window,"resize", function(){hydraUI.adjust();});<|endoftext|>


<commit_before>/**
 * Created by Pavel on 02.12.2016.
 */

function prepareNoteFormAndFillNotes(place_name) {
    checkIfPlaceIsInUserPlaces(place_name, function (place_id) {
        if(place_id != null && place_id != undefined){
            document.getElementById('addNote').addEventListener("click", function () {
                var addNoteDiv = document.getElementById("addNoteDiv");
                addNoteDiv.style = "display: block; text-align: center;";
                addNoteDiv.innerHTML =
                    "
Nová poznámka
"+
                    "Název" +
                    "<input id='note_name' type='text' class='form-control'>
" +
                    "Obsah" +
                    "<textarea id='note_content' class='form-control' rows='5'></textarea>
" +
                    "<button class='btn btn-primary' id='add-note-submit-btn'>Přidat</button>";
                document.getElementById("add-note-submit-btn").addEventListener("click", function () {
                    var noteObj = {name: document.getElementById("note_name").value, content: document.getElementById("note_content").value}
                    console.log(noteObj);
                    addNoteToPlace(place_id, noteObj);
                    //clear form
                    document.getElementById("note_name").value = "";
                    document.getElementById("note_content").value = "";
                })
                document.getElementById("note_name").focus();
            })
            getAndShowNotesForPlace(place_id);
        }
    });
}

function addNoteToPlace(place_id, note) {
    var data = "name="+note.name+"&content="+note.content;
    var user_id = localStorage.getItem("id");
    var url = "https://ivebeenthereapi-matyapav.rhcloud.com/notesForPlace/"+place_id+"/user/"+user_id;
    makeCorsRequest("POST", url, data, function (response) {
        console.log(response);
        getAndShowNotesForPlace(place_id);//refresh notes
    })
}

function removeNote(note_id, place_id) {
    if(confirm("Do you really want to delete this note?")) {
        var user_id = localStorage.getItem("id");
        var url = "https://ivebeenthereapi-matyapav.rhcloud.com/notes/" + note_id + "/user/" + user_id;
        makeCorsRequest("DELETE", url, null, function (response) {
            console.log(response);
            getAndShowNotesForPlace(place_id);//refresh notes
        })
    }
}

function getAndShowNotesForPlace(place_id) {
    var user_id = localStorage.getItem("id");
    var url = "https://ivebeenthereapi-matyapav.rhcloud.com/notesForPlace/"+place_id+"/user/"+user_id;
    makeCorsRequest("GET", url, null, function (response) {
        console.log(response);
        var notes = JSON.parse(response);
        var notesElement = document.getElementById('myNotes');
        notesElement.innerHTML =
            "
Moje poznámky
"+
            "
"+
            "
" +
            "
" +
            "Název	" +
            "Obsah	" +
            "Akce	" +
            "
" +
            "
" +
            "
"+
            "

";
        var index = 0;

        var tableRef = document.getElementById('myNotesTable').getElementsByTagName('tbody')[0];
        notes.forEach(function (note) {
            // Insert a row in the table at row index 0
            var newRow   = tableRef.insertRow(tableRef.rows.length);
            var nameCell  = newRow.insertCell(0);
            var nameText  = document.createTextNode(note.name);
            var contentCell  = newRow.insertCell(1);
            var contentText  = document.createTextNode(note.content);
            var actionsCell  = newRow.insertCell(2);
            var deleteLink = document.createElement('a');
            deleteLink.setAttribute("id", "deleteNote"+index);
            deleteLink.setAttribute("style", "cursor: pointer");
            var actionsText  = "Smazat"
            nameCell.appendChild(nameText);
            contentCell.appendChild(contentText);
            deleteLink.appendChild(actionsText);
            actionsCell.appendChild(deleteLink);
            document.getElementById("deleteNote"+index).addEventListener("click", function () {
                removeNote(note._id, place_id);
            });
            index++;
        })
    })
}
<commit_msg>My notes table insertion<commit_after>/**
 * Created by Pavel on 02.12.2016.
 */

function prepareNoteFormAndFillNotes(place_name) {
    checkIfPlaceIsInUserPlaces(place_name, function (place_id) {
        if(place_id != null && place_id != undefined){
            document.getElementById('addNote').addEventListener("click", function () {
                var addNoteDiv = document.getElementById("addNoteDiv");
                addNoteDiv.style = "display: block; text-align: center;";
                addNoteDiv.innerHTML =
                    "
Nová poznámka
"+
                    "Název" +
                    "<input id='note_name' type='text' class='form-control'>
" +
                    "Obsah" +
                    "<textarea id='note_content' class='form-control' rows='5'></textarea>
" +
                    "<button class='btn btn-primary' id='add-note-submit-btn'>Přidat</button>";
                document.getElementById("add-note-submit-btn").addEventListener("click", function () {
                    var noteObj = {name: document.getElementById("note_name").value, content: document.getElementById("note_content").value}
                    console.log(noteObj);
                    addNoteToPlace(place_id, noteObj);
                    //clear form
                    document.getElementById("note_name").value = "";
                    document.getElementById("note_content").value = "";
                })
                document.getElementById("note_name").focus();
            })
            getAndShowNotesForPlace(place_id);
        }
    });
}

function addNoteToPlace(place_id, note) {
    var data = "name="+note.name+"&content="+note.content;
    var user_id = localStorage.getItem("id");
    var url = "https://ivebeenthereapi-matyapav.rhcloud.com/notesForPlace/"+place_id+"/user/"+user_id;
    makeCorsRequest("POST", url, data, function (response) {
        console.log(response);
        getAndShowNotesForPlace(place_id);//refresh notes
    })
}

function removeNote(note_id, place_id) {
    if(confirm("Do you really want to delete this note?")) {
        var user_id = localStorage.getItem("id");
        var url = "https://ivebeenthereapi-matyapav.rhcloud.com/notes/" + note_id + "/user/" + user_id;
        makeCorsRequest("DELETE", url, null, function (response) {
            console.log(response);
            getAndShowNotesForPlace(place_id);//refresh notes
        })
    }
}

function getAndShowNotesForPlace(place_id) {
    var user_id = localStorage.getItem("id");
    var url = "https://ivebeenthereapi-matyapav.rhcloud.com/notesForPlace/"+place_id+"/user/"+user_id;
    makeCorsRequest("GET", url, null, function (response) {
        console.log(response);
        var notes = JSON.parse(response);
        var notesElement = document.getElementById('myNotes');
        notesElement.innerHTML =
            "
Moje poznámky
"+
            "
"+
            "
" +
            "
" +
            "Název	" +
            "Obsah	" +
            "Akce	" +
            "
" +
            "
" +
            "
"+
            "

";
        var index = 0;

        var tableRef = document.getElementById('myNotesTable').getElementsByTagName('tbody')[0];
        notes.forEach(function (note) {
            // Insert a row in the table at row index 0
            var newRow   = tableRef.insertRow(tableRef.rows.length);
            var nameCell  = newRow.insertCell(0);
            var nameText  = document.createTextNode(note.name);
            var contentCell  = newRow.insertCell(1);
            var contentText  = document.createTextNode(note.content);
            var actionsCell  = newRow.insertCell(2);
            var deleteLink = document.createElement('a');
            deleteLink.setAttribute("id", "deleteNote"+index);
            deleteLink.setAttribute("style", "cursor: pointer");
            var actionsText  = document.createTextNode("Smazat");
            nameCell.appendChild(nameText);
            contentCell.appendChild(contentText);
            deleteLink.appendChild(actionsText);
            actionsCell.appendChild(deleteLink);
            document.getElementById("deleteNote"+index).addEventListener("click", function () {
                removeNote(note._id, place_id);
            });
            index++;
        })
    })
}
<|endoftext|>


<commit_before>function myFunction() {
    document.getElementsByClassName("navbar")[0].classList.toggle("responsive");
}

function myFunction(social_media_image) {
    var new_src = "icons/" + social_media_image.id + "_clicked.png";
    window.alert(new_src);
    social_media_image.src = new_src;
}

function mouseaway(my_image) {

    my_image.src = "icons/" + my_image.id + ".png";

}

// $("#project1").hover(
//   function() {
//     $(this).attr("src", "http://cdn-6.dooziedog.com/dog_breeds/beagle/images/full/Beagle-Puppy.jpg");
//   },
//     function() {
//       $(this).attr("src", "http://i.imgur.com/Flk3FcN.png");
//   });
<commit_msg>javascript<commit_after>function myFunction() {
    document.getElementsByClassName("navbar")[0].classList.toggle("responsive");
}

function myFunction(social_media_image) {
    var id = social_media_image.id;
    window.alert(id);
    var new_src = "icons/" + id + "_clicked.png";
    window.alert(new_src);
    social_media_image.src = new_src;
}

function mouseaway(my_image) {
    var id = my_image.id;
    my_image.src = "icons/" + id + ".png";

}

// $("#project1").hover(
//   function() {
//     $(this).attr("src", "http://cdn-6.dooziedog.com/dog_breeds/beagle/images/full/Beagle-Puppy.jpg");
//   },
//     function() {
//       $(this).attr("src", "http://i.imgur.com/Flk3FcN.png");
//   });
<|endoftext|>


<commit_before>//get dom elements buttons and screen
var zero = document.getElementById("zero");
var one = document.getElementById("one");
var two = document.getElementById("two");
var three = document.getElementById("three");
var four = document.getElementById("four");
var five = document.getElementById("five");
var six = document.getElementById("six");
var seven = document.getElementById("seven");
var eight = document.getElementById("eight");
var nine = document.getElementById("nine");
var point = document.getElementById("point");
var equal = document.getElementById("equal");
var plus = document.getElementById("plus");
var minus = document.getElementById("minus");
var mult = document.getElementById("mult");
var divide = document.getElementById("divide");
var percent = document.getElementById("percent");
var reverse = document.getElementById("reverse");
var ac = document.getElementById("ac");
var screen = document.getElementById("screen");

//declare variables for calculations
var val = "0";
var floating = false;
var memVal = 0;
var operator;
var operatorPressed = false;
var firstDigitAfterOperator = false;
var isFirstZero = true;
var isResult = false;

function display() {

  if (val.length < 9) {
    screen.className = "";
    screen.innerHTML = val;
  } else {
    if (val.length < 12) {
      screen.className = "small";
      screen.innerHTML = val;
    } else {
      if (val.length < 17) {
        screen.className = "smaller";
        screen.innerHTML = val;
      } else {
        if (val.length < 25) {
          screen.className = "smallest";
          screen.innerHTML = val;
        } else {
          screen.innerHTML = "Number too large";
          val = "0";
        }
      }
    }
  }

}

function screenFlash() {
  screen.style.display = "none";
  setTimeout(function () {
    screen.style.display = "inherit";
  }, 50);
}

function clear() {
  val = "0";
  memVal = "0";
  firstDigitAfterOperator = false;
  operatorPressed = false;
  isFirstZero = true;
  isResult = false;
  floating = "false";
  screen.className = "";
  display();
}

function reverseNum() {
  if (val != "0") {
    if (val.startsWith("-")) {
      val = val.replace("-", "");
    } else {
      val = "-" + val;
    }
    display();
  }
}

function decimal() {
  if (!floating) {
    val += ".";
    floating = true;
  }
  display();
}

function add() {
  firstDigitAfterOperator = true;

  if (operatorPressed) {
    calculate();
    memVal = parseFloat(val);
  } else {
    memVal = parseFloat(val);
    //css border plus
  }
  screenFlash();
  operator = "plus";
  isResult = false;
}

function substract() {
  memVal = parseFloat(val);
  operator = "minus";
  isResult = false;
  clear();
}

function multiply() {
  memVal = parseFloat(val);
  operator = "times";
  isResult = false;
  clear();
}

function division() {
  memVal = parseFloat(val);
  operator = "division";
  isResult = false;
  clear();
}

function percentage() {
  val = parseFloat(val) / 100;
  val = val.toString();
  display();
}

function calculate() {
  var temp = 0;
  switch (operator) {
    case "plus":
      if (isResult) {
        val = memVal + parseFloat(val);
        val = val.toString();
      } else {
        temp = parseFloat(val);
        val = memVal + temp;
        memVal = temp;
        val = val.toString();
        isResult = true;
      }
      break;
    case "minus":
      if (isResult) {
        val = parseFloat(val) - memVal;
        val = val.toString();
      } else {
        temp = parseFloat(val);
        val = memVal - temp;
        memVal = temp;
        val = val.toString();
        isResult = true;
      }
      break;
    case "times":
      if (isResult) {
        val = memVal * parseFloat(val);
        val = val.toString();
      } else {
        temp = parseFloat(val);
        val = memVal * temp;
        memVal = temp;
        val = val.toString();
        isResult = true;
      }
      break;
    case "division":
      if (isResult) {
        val = parseFloat(val) / memVal;
        val = val.toString();
      } else {
        temp = parseFloat(val);
        val = memVal / temp;
        memVal = temp;
        val = val.toString();
        isResult = true;
      }
      break;
  }
  display();
}

function pressNum(num) {
  if (firstDigitAfterOperator) {
    val = num;
    firstDigitAfterOperator = false;
    operatorPressed = true;
  } else {
    if (isFirstZero) {
      val = num;
      isFirstZero = false;
    } else {
      val += num;
    }
  }

  display();
}

//declare event listeners
ac.addEventListener("click", clear);
reverse.addEventListener("click", reverseNum);
point.addEventListener("click", decimal);
plus.addEventListener("click", add);
minus.addEventListener("click", substract);
mult.addEventListener("click", multiply);
divide.addEventListener("click", division);
percent.addEventListener("click", percentage);
equal.addEventListener("click", calculate);
zero.addEventListener("click", function () {
  pressNum('0')
});
one.addEventListener("click", function () {
  pressNum('1')
});
two.addEventListener("click", function () {
  pressNum('2')
});
three.addEventListener("click", function () {
  pressNum('3')
});
four.addEventListener("click", function () {
  pressNum('4')
});
five.addEventListener("click", function () {
  pressNum('5')
});
six.addEventListener("click", function () {
  pressNum('6')
});
seven.addEventListener("click", function () {
  pressNum('7')
});
eight.addEventListener("click", function () {
  pressNum('8')
});
nine.addEventListener("click", function () {
  pressNum('9')
});

//keyboard event listener using keyCode because replacements are not yet supported
//by all browsers
document.addEventListener("keypress", function (e) {
  console.log(e.keyCode);
  switch (e.keyCode) {
    case 48:
      pressNum('0');
      break;

    case 49:
      pressNum('1');
      break;

    case 50:
      pressNum('2');
      break;

    case 51:
      pressNum('3');
      break;

    case 52:
      pressNum('4');
      break;

    case 53:
      pressNum('5');
      break;

    case 54:
      pressNum('6');
      break;

    case (55):
      pressNum('7');
      break;

    case 56:
      pressNum('8');
      break;

    case 57:
      pressNum('9');
      break;

    case 44:
    case 46:
      decimal();
      break;

    case 61:
    case 13:
      calculate();
      break;

    case 43:
      add();
      break;

    case 45:
      substract();
      break;

    case 42:
      multiply();
      break;

    case 47:
      division();
      break;

    case 37:
      percentage();
      break;

    case 177:
      reverseNum();
      break;

    case 67:
    case 99:
      clear();
      break;
  }
})<commit_msg>Change substract() to allow operation chaining<commit_after>//get dom elements buttons and screen
var zero = document.getElementById("zero");
var one = document.getElementById("one");
var two = document.getElementById("two");
var three = document.getElementById("three");
var four = document.getElementById("four");
var five = document.getElementById("five");
var six = document.getElementById("six");
var seven = document.getElementById("seven");
var eight = document.getElementById("eight");
var nine = document.getElementById("nine");
var point = document.getElementById("point");
var equal = document.getElementById("equal");
var plus = document.getElementById("plus");
var minus = document.getElementById("minus");
var mult = document.getElementById("mult");
var divide = document.getElementById("divide");
var percent = document.getElementById("percent");
var reverse = document.getElementById("reverse");
var ac = document.getElementById("ac");
var screen = document.getElementById("screen");

//declare variables for calculations
var val = "0";
var floating = false;
var memVal = 0;
var operator;
var operatorPressed = false;
var firstDigitAfterOperator = false;
var isFirstZero = true;
var isResult = false;

function display() {

  if (val.length < 9) {
    screen.className = "";
    screen.innerHTML = val;
  } else {
    if (val.length < 12) {
      screen.className = "small";
      screen.innerHTML = val;
    } else {
      if (val.length < 17) {
        screen.className = "smaller";
        screen.innerHTML = val;
      } else {
        if (val.length < 25) {
          screen.className = "smallest";
          screen.innerHTML = val;
        } else {
          screen.innerHTML = "Number too large";
          val = "0";
        }
      }
    }
  }

}

function screenFlash() {
  screen.style.display = "none";
  setTimeout(function () {
    screen.style.display = "inherit";
  }, 50);
}

function clear() {
  val = "0";
  memVal = "0";
  firstDigitAfterOperator = false;
  operatorPressed = false;
  isFirstZero = true;
  isResult = false;
  floating = "false";
  screen.className = "";
  display();
}

function reverseNum() {
  if (val != "0") {
    if (val.startsWith("-")) {
      val = val.replace("-", "");
    } else {
      val = "-" + val;
    }
    display();
  }
}

function decimal() {
  if (!floating) {
    val += ".";
    floating = true;
  }
  display();
}

function add() {
  firstDigitAfterOperator = true;

  if (operatorPressed) {
    calculate();
    memVal = parseFloat(val);
  } else {
    memVal = parseFloat(val);
    //css border plus
  }
  screenFlash();
  operator = "plus";
  isResult = false;
}

function substract() {
  firstDigitAfterOperator = true;

  if (operatorPressed) {
    calculate();
    memVal = parseFloat(val);
  } else {
    memVal = parseFloat(val);
    //css border minus
  }
  screenFlash();
  operator = "minus";
  isResult = false;
}

function multiply() {
  memVal = parseFloat(val);
  operator = "times";
  isResult = false;
  clear();
}

function division() {
  memVal = parseFloat(val);
  operator = "division";
  isResult = false;
  clear();
}

function percentage() {
  val = parseFloat(val) / 100;
  val = val.toString();
  display();
}

function calculate() {
  var temp = 0;
  switch (operator) {
    case "plus":
      if (isResult) {
        val = memVal + parseFloat(val);
        val = val.toString();
      } else {
        temp = parseFloat(val);
        val = memVal + temp;
        memVal = temp;
        val = val.toString();
        isResult = true;
      }
      break;
    case "minus":
      if (isResult) {
        val = parseFloat(val) - memVal;
        val = val.toString();
      } else {
        temp = parseFloat(val);
        val = memVal - temp;
        memVal = temp;
        val = val.toString();
        isResult = true;
      }
      break;
    case "times":
      if (isResult) {
        val = memVal * parseFloat(val);
        val = val.toString();
      } else {
        temp = parseFloat(val);
        val = memVal * temp;
        memVal = temp;
        val = val.toString();
        isResult = true;
      }
      break;
    case "division":
      if (isResult) {
        val = parseFloat(val) / memVal;
        val = val.toString();
      } else {
        temp = parseFloat(val);
        val = memVal / temp;
        memVal = temp;
        val = val.toString();
        isResult = true;
      }
      break;
  }
  display();
}

function pressNum(num) {
  if (firstDigitAfterOperator) {
    val = num;
    firstDigitAfterOperator = false;
    operatorPressed = true;
  } else {
    if (isFirstZero) {
      val = num;
      isFirstZero = false;
    } else {
      val += num;
    }
  }

  display();
}

//declare event listeners
ac.addEventListener("click", clear);
reverse.addEventListener("click", reverseNum);
point.addEventListener("click", decimal);
plus.addEventListener("click", add);
minus.addEventListener("click", substract);
mult.addEventListener("click", multiply);
divide.addEventListener("click", division);
percent.addEventListener("click", percentage);
equal.addEventListener("click", calculate);
zero.addEventListener("click", function () {
  pressNum('0')
});
one.addEventListener("click", function () {
  pressNum('1')
});
two.addEventListener("click", function () {
  pressNum('2')
});
three.addEventListener("click", function () {
  pressNum('3')
});
four.addEventListener("click", function () {
  pressNum('4')
});
five.addEventListener("click", function () {
  pressNum('5')
});
six.addEventListener("click", function () {
  pressNum('6')
});
seven.addEventListener("click", function () {
  pressNum('7')
});
eight.addEventListener("click", function () {
  pressNum('8')
});
nine.addEventListener("click", function () {
  pressNum('9')
});

//keyboard event listener using keyCode because replacements are not yet supported
//by all browsers
document.addEventListener("keypress", function (e) {
  console.log(e.keyCode);
  switch (e.keyCode) {
    case 48:
      pressNum('0');
      break;

    case 49:
      pressNum('1');
      break;

    case 50:
      pressNum('2');
      break;

    case 51:
      pressNum('3');
      break;

    case 52:
      pressNum('4');
      break;

    case 53:
      pressNum('5');
      break;

    case 54:
      pressNum('6');
      break;

    case (55):
      pressNum('7');
      break;

    case 56:
      pressNum('8');
      break;

    case 57:
      pressNum('9');
      break;

    case 44:
    case 46:
      decimal();
      break;

    case 61:
    case 13:
      calculate();
      break;

    case 43:
      add();
      break;

    case 45:
      substract();
      break;

    case 42:
      multiply();
      break;

    case 47:
      division();
      break;

    case 37:
      percentage();
      break;

    case 177:
      reverseNum();
      break;

    case 67:
    case 99:
      clear();
      break;
  }
})<|endoftext|>


<commit_before>'use strict';

var os = require('os');
var fs = require('fs');
var path = require('path');

module.exports = {
  fsExistsSync: function(path) {
    try {
      fs.accessSync(path, fs.F_OK);
    } catch (e) {
      return false;
    }

    return true;
  },

  getPngdefryBinPath: function() {
    var binPaths = {
      Darwin: path.join(__dirname, 'pngdefry', 'bin', 'osx', 'pngdefry'),
      Linux: path.join(__dirname, 'pngdefry', 'bin', 'osx', 'pngdefry'),
      Windows_NT: path.join(__dirname, 'pngdefry', 'bin', 'windows', 'pngdefry')
    };

    return binPaths[os.type()];
  }
};
<commit_msg>Fixes linux typo<commit_after>'use strict';

var os = require('os');
var fs = require('fs');
var path = require('path');

module.exports = {
  fsExistsSync: function(path) {
    try {
      fs.accessSync(path, fs.F_OK);
    } catch (e) {
      return false;
    }

    return true;
  },

  getPngdefryBinPath: function() {
    var binPaths = {
      Darwin: path.join(__dirname, 'pngdefry', 'bin', 'osx', 'pngdefry'),
      Linux: path.join(__dirname, 'pngdefry', 'bin', 'linux', 'pngdefry'),
      Windows_NT: path.join(__dirname, 'pngdefry', 'bin', 'windows', 'pngdefry')
    };

    return binPaths[os.type()];
  }
};
<|endoftext|>


<commit_before>/**
 * Copyright (c) Camunda Services GmbH.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

/* global sinon */

import React from 'react';

import { mount } from 'enzyme';

import {
  Cache,
  WithCachedState
} from '../../../cached';

import {
  CmmnEditor
} from '../CmmnEditor';

import CmmnModeler from 'test/mocks/cmmn-js/Modeler';

import {
  getCanvasEntries,
  getCopyCutPasteEntries,
  getDiagramFindEntries,
  getSelectionEntries,
  getToolEntries,
  getUndoRedoEntries
} from '../../getEditMenu';

import diagramXML from './diagram.cmmn';

const { spy } = sinon;

describe('<CmmnEditor>', function() {

  it('should render', function() {
    const {
      instance
    } = renderEditor(diagramXML);

    expect(instance).to.exist;
  });

  describe('caching behavior', function() {

    let createSpy;

    beforeEach(function() {
      createSpy = sinon.spy(CmmnEditor, 'createCachedState');
    });

    afterEach(function() {
      createSpy.restore();
    });

    it('should create modeler if not cached', function() {

      // when
      const {
        instance
      } = renderEditor(diagramXML);

      // then
      const {
        modeler
      } = instance.getCached();

      expect(modeler).to.exist;
      expect(createSpy).to.have.been.calledOnce;
    });

    it('should use cached modeler', function() {

      // given
      const cache = new Cache();

      cache.add('editor', {
        cached: {
          modeler: new CmmnModeler()
        },
        __destroy: () => {}
      });

      // when
      renderEditor(diagramXML, {
        id: 'editor',
        cache
      });

      // then
      expect(createSpy).not.to.have.been.called;
    });

  });

  it('#getModeler', async function() {

    // given
    const { instance } = await renderEditor(diagramXML);

    // when
    const modeler = instance.getModeler();

    // then
    expect(modeler).to.exist;
  });

  it('#getXML', async function() {
    const {
      instance
    } = renderEditor(diagramXML);

    const xml = await instance.getXML();

    expect(xml).to.exist;
    expect(xml).to.eql(diagramXML);
  });

  describe('#exportAs', function() {

    // increase test time-outs, as exporting takes a
    // long certain underpowered CI systems (AppVeyor, wink, wink)
    this.timeout(5000);

    let instance;

    beforeEach(function() {
      instance = renderEditor(diagramXML).instance;
    });

    it('svg', async function() {
      const contents = await instance.exportAs('svg');

      expect(contents).to.exist;
      expect(contents).to.equal('<svg />');
    });

    it('png', async function() {
      const contents = await instance.exportAs('png');

      expect(contents).to.exist;
      expect(contents).to.contain('data:image/png');
    });

    it('jpeg', async function() {
      const contents = await instance.exportAs('jpeg');

      expect(contents).to.exist;
      expect(contents).to.contain('data:image/jpeg');
    });

  });

  describe('#listen', function() {

    function expectHandleChanged(event) {
      return async function() {
        const modeler = new CmmnModeler();

        const cache = new Cache();

        cache.add('editor', {
          cached: {
            modeler
          },
          __destroy: () => {}
        });

        const changedSpy = spy();

        await renderEditor(diagramXML, {
          id: 'editor',
          cache,
          onChanged: changedSpy
        });

        modeler._emit(event);

        expect(changedSpy).to.have.been.called;
      };
    }

    it('import.done', expectHandleChanged('import.done'));

    it('saveXML.done', expectHandleChanged('saveXML.done'));

    it('commandStack.changed', expectHandleChanged('commandStack.changed'));

    it('selection.changed', expectHandleChanged('selection.changed'));

    it('attach', expectHandleChanged('attach'));

    it('propertiesPanel.focusin', expectHandleChanged('propertiesPanel.focusin'));

    it('propertiesPanel.focusout', expectHandleChanged('propertiesPanel.focusout'));

  });

  describe('#handleChanged', function() {

    it('should notify about changes', function() {

      // given
      const changedSpy = sinon.spy();

      const modeler = new CmmnModeler({
        modules: {
          commandStack: {
            canRedo: () => true,
            canUndo: () => true,
            _stackIdx: 1
          },
          selection: {
            get: () => []
          }
        }
      });

      const cache = new Cache();

      cache.add('editor', {
        cached: {
          lastXML: diagramXML,
          modeler,
          stackIdx: 1
        },
        __destroy: () => {}
      });

      const { instance } = renderEditor(diagramXML, {
        id: 'editor',
        cache,
        onChanged: changedSpy
      });

      changedSpy.resetHistory();

      // when
      modeler.get('commandStack')._stackIdx = 5;

      instance.handleChanged();

      expect(changedSpy).to.be.calledOnce;
      expect(changedSpy.firstCall.args[0]).to.include({
        dirty: true,
        editLabel: false,
        find: true,
        globalConnectTool: true,
        handTool: true,
        inputActive: false,
        lassoTool: true,
        moveCanvas: true,
        redo: true,
        removeSelected: false,
        spaceTool: true,
        undo: true
      });
    });

    it('should notify about plugin related changes', async function() {
      // given
      const changedSpy = sinon.spy();

      const { instance } = await renderEditor(diagramXML, {
        id: 'editor',
        onChanged: changedSpy
      });

      changedSpy.resetHistory();

      // when
      instance.handleChanged();

      // then
      expect(changedSpy).to.be.calledOnce;

      const state = changedSpy.firstCall.args[0];

      expect(state).to.have.property('cmmn');
      expect(state).to.have.property('editable');
      expect(state).to.have.property('elementsSelected');
      expect(state).to.have.property('inactiveInput');
    });

    describe('edit menu', function() {

      it('should provide und/redo entries', async function() {

        // given
        const changedSpy = (state) => {

          const editMenuEntries = getUndoRedoEntries(state);

          // then
          expect(state.editMenu).to.deep.include(editMenuEntries);

        };

        const { instance } = await renderEditor(diagramXML, {
          onChanged: changedSpy
        });

        // when
        instance.handleChanged();
      });

      it('should provide copy/paste entries', async function() {

        // given
        const changedSpy = (state) => {

          const editMenuEntries = getCopyCutPasteEntries(state);

          // then
          expect(state.editMenu).to.deep.include(editMenuEntries);

        };

        const { instance } = await renderEditor(diagramXML, {
          onChanged: changedSpy
        });

        // when
        instance.handleChanged();
      });

      it('should provide tool entries', async function() {

        // given
        const changedSpy = (state) => {

          const editMenuEntries = getToolEntries(state);

          // then
          expect(state.editMenu).to.deep.include(editMenuEntries);

        };

        const { instance } = await renderEditor(diagramXML, {
          onChanged: changedSpy
        });

        // when
        instance.handleChanged();
      });

      it('should provide find entries', async function() {

        // given
        const changedSpy = (state) => {

          const editMenuEntries = getDiagramFindEntries(state);

          // then
          expect(state.editMenu).to.deep.include(editMenuEntries);

        };

        const { instance } = await renderEditor(diagramXML, {
          onChanged: changedSpy
        });

        // when
        instance.handleChanged();
      });

      it('should provide selection + canvas entries', async function() {

        // given
        const changedSpy = (state) => {

          const editMenuEntries = [
            ...getCanvasEntries(state),
            ...getSelectionEntries(state)
          ];

          // then
          expect(state.editMenu).to.deep.include(editMenuEntries);

        };

        const { instance } = await renderEditor(diagramXML, {
          onChanged: changedSpy
        });

        // when
        instance.handleChanged();
      });
    });

  });

  describe('layout', function() {

    it('should open properties panel', function() {

      // given
      let layout = {
        propertiesPanel: {
          open: false
        }
      };

      function onLayoutChanged(newLayout) {
        layout = newLayout;
      }

      const {
        wrapper
      } = renderEditor(diagramXML, {
        layout,
        onLayoutChanged
      });

      const toggle = wrapper.find('.toggle');

      // when
      toggle.simulate('click');

      // then
      expect(layout.propertiesPanel.open).to.be.true;
    });

    it('should close properties panel', function() {

      // given
      let layout = {
        propertiesPanel: {
          open: true
        }
      };

      function onLayoutChanged(newLayout) {
        layout = newLayout;
      }

      const {
        wrapper
      } = renderEditor(diagramXML, {
        layout,
        onLayoutChanged
      });

      const toggle = wrapper.find('.toggle');

      // when
      toggle.simulate('click');

      // then
      expect(layout.propertiesPanel.open).to.be.false;
    });

    it('should handle missing layout', function() {

      // given
      let layout = { };

      // then
      renderEditor(diagramXML, {
        layout
      });

    });

  });

  describe('errors', function() {

    it('should handle XML export error', async function() {

      // given
      const errorSpy = spy();

      const {
        instance
      } = renderEditor('export-error', {
        onError: errorSpy
      });

      // make sure editor is dirty
      const commandStack = instance.getModeler().get('commandStack');

      commandStack.execute(1);

      let err;

      // when
      try {
        await instance.getXML();
      } catch (e) {
        err = e;
      }

      // then
      expect(err).to.exist;
      expect(errorSpy).to.have.been.calledOnce;
    });

    it('should handle image export error', async function() {

      // given
      const errorSpy = spy();

      const {
        instance
      } = renderEditor('export-as-error', {
        onError: errorSpy
      });

      let err;

      // when
      try {
        await instance.exportAs('svg');
      } catch (e) {
        err = e;
      }

      // then
      expect(err).to.exist;
      expect(errorSpy).to.have.been.calledOnce;
    });

  });

  describe('import', function() {

    it('should import without errors and warnings', function() {

      // given
      const importSpy = spy();

      // when
      const { instance } = renderEditor(diagramXML, {
        onImport: importSpy
      });

      // then
      const {
        lastXML
      } = instance.getCached();

      expect(importSpy).to.have.been.calledWith(null, []);

      expect(lastXML).to.equal(diagramXML);
    });

    it('should import with warnings', function() {

      // given
      const importSpy = (error, warnings) => {

        // then
        expect(error).not.to.exist;

        expect(warnings).to.exist;
        expect(warnings).to.have.length(1);
        expect(warnings[0]).to.equal('warning');
      };

      // when
      const { instance } = renderEditor('import-warnings', {
        onImport: importSpy
      });

      // then
      const {
        lastXML
      } = instance.getCached();

      expect(lastXML).to.equal('import-warnings');
    });

    it('should import with error', function() {

      // given
      const importSpy = (error, warnings) => {

        // then
        expect(error).to.exist;
        expect(error.message).to.equal('error');

        expect(warnings).to.exist;
        expect(warnings).to.have.length(0);
      };

      // when
      const { instance } = renderEditor('import-error', {
        onImport: importSpy
      });

      // then
      const {
        lastXML
      } = instance.getCached();

      expect(lastXML).not.to.exist;
    });

  });

  describe('dirty state', function() {

    let instance;

    beforeEach(function() {
      instance = renderEditor(diagramXML).instance;
    });

    it('should NOT be dirty initially', function() {

      // then
      const dirty = instance.isDirty();

      expect(dirty).to.be.false;
    });

    it('should be dirty after modeling', function() {

      // given
      const { modeler } = instance.getCached();

      // when
      // execute 1 command
      modeler.get('commandStack').execute(1);

      // then
      const dirty = instance.isDirty();

      expect(dirty).to.be.true;
    });

    it('should NOT be dirty after modeling -> undo', function() {

      // given
      const { modeler } = instance.getCached();

      modeler.get('commandStack').execute(1);

      // when
      modeler.get('commandStack').undo();

      // then
      const dirty = instance.isDirty();

      expect(dirty).to.be.false;
    });

    it('should NOT be dirty after save', async function() {

      // given
      const { modeler } = instance.getCached();

      // execute 1 command
      modeler.get('commandStack').execute(1);

      // when
      await instance.getXML();

      // then
      const dirty = instance.isDirty();

      expect(dirty).to.be.false;
    });

  });

  describe('properties panel actions', function() {

    it('should toggle properties panel', async function() {
      // given
      const onLayoutChangedSpy = sinon.spy();
      const {
        instance
      } = await renderEditor(diagramXML, {
        layout: {
          propertiesPanel: {
            open: false,
          }
        },
        onLayoutChanged: onLayoutChangedSpy
      });

      // when
      instance.triggerAction('toggleProperties');

      // then
      expect(onLayoutChangedSpy).to.be.calledOnceWith({
        propertiesPanel: {
          open: true,
        }
      });
    });

    it('should reset properties panel', async function() {
      // given
      const onLayoutChangedSpy = sinon.spy();
      const {
        instance
      } = await renderEditor(diagramXML, {
        onLayoutChanged: onLayoutChangedSpy
      });

      // when
      instance.triggerAction('resetProperties');

      // then
      expect(onLayoutChangedSpy).to.be.calledOnceWith({
        propertiesPanel: {
          open: true,
          width: 250
        }
      });
    });

  });

  describe('zoom actions', function() {

    let editorActionsStub,
        instance;

    beforeEach(async function() {
      // given
      editorActionsStub = sinon.stub({ trigger() {} });

      const cache = new Cache();

      cache.add('editor', {
        cached: {
          modeler: new CmmnModeler({
            modules: {
              editorActions: editorActionsStub
            }
          })
        }
      });

      instance = (await renderEditor(diagramXML, { cache })).instance;
    });

    afterEach(sinon.restore);

    it('should zoom in', function() {
      // when
      instance.triggerAction('zoomIn');

      // then
      expect(editorActionsStub.trigger).to.be.calledOnceWith('stepZoom', {
        value: 1
      });
    });

    it('should zoom out', function() {
      // when
      instance.triggerAction('zoomOut');

      // then
      expect(editorActionsStub.trigger).to.be.calledOnceWith('stepZoom', {
        value: -1
      });
    });

    it('should zoom to fit diagram', function() {
      // when
      instance.triggerAction('zoomFit');

      // then
      expect(editorActionsStub.trigger).to.be.calledOnceWith('zoom', {
        value: 'fit-viewport'
      });
    });

    it('should reset zoom', async function() {
      // when
      instance.triggerAction('resetZoom');

      // then
      expect(editorActionsStub.trigger).to.be.calledOnceWith('zoom', {
        value: 1
      });
    });

  });

});

// helpers //////////

function noop() {}

const TestEditor = WithCachedState(CmmnEditor);

function renderEditor(xml, options = {}) {
  const {
    layout,
    onChanged,
    onError,
    onImport,
    onLayoutChanged
  } = options;

  const wrapper = mount(
    <TestEditor
      id={ options.id || 'editor' }
      xml={ xml }
      activeSheet={ options.activeSheet || { id: 'cmmn' } }
      onChanged={ onChanged || noop }
      onError={ onError || noop }
      onImport={ onImport || noop }
      onLayoutChanged={ onLayoutChanged || noop }
      cache={ options.cache || new Cache() }
      layout={ layout || {
        minimap: {
          open: false
        },
        propertiesPanel: {
          open: true
        }
      } }
    />
  );

  const instance = wrapper.find(CmmnEditor).instance();

  return {
    instance,
    wrapper
  };
}<commit_msg>test(client/cmmn): fix import related tests<commit_after>/**
 * Copyright (c) Camunda Services GmbH.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

/* global sinon */

import React from 'react';

import { mount } from 'enzyme';

import {
  Cache,
  WithCachedState
} from '../../../cached';

import {
  CmmnEditor
} from '../CmmnEditor';

import CmmnModeler from 'test/mocks/cmmn-js/Modeler';

import {
  getCanvasEntries,
  getCopyCutPasteEntries,
  getDiagramFindEntries,
  getSelectionEntries,
  getToolEntries,
  getUndoRedoEntries
} from '../../getEditMenu';

import diagramXML from './diagram.cmmn';

const { spy } = sinon;

describe('<CmmnEditor>', function() {

  it('should render', function() {
    const {
      instance
    } = renderEditor(diagramXML);

    expect(instance).to.exist;
  });

  describe('caching behavior', function() {

    let createSpy;

    beforeEach(function() {
      createSpy = sinon.spy(CmmnEditor, 'createCachedState');
    });

    afterEach(function() {
      createSpy.restore();
    });

    it('should create modeler if not cached', function() {

      // when
      const {
        instance
      } = renderEditor(diagramXML);

      // then
      const {
        modeler
      } = instance.getCached();

      expect(modeler).to.exist;
      expect(createSpy).to.have.been.calledOnce;
    });

    it('should use cached modeler', function() {

      // given
      const cache = new Cache();

      cache.add('editor', {
        cached: {
          modeler: new CmmnModeler()
        },
        __destroy: () => {}
      });

      // when
      renderEditor(diagramXML, {
        id: 'editor',
        cache
      });

      // then
      expect(createSpy).not.to.have.been.called;
    });

  });

  it('#getModeler', async function() {

    // given
    const { instance } = await renderEditor(diagramXML);

    // when
    const modeler = instance.getModeler();

    // then
    expect(modeler).to.exist;
  });

  it('#getXML', async function() {
    const {
      instance
    } = renderEditor(diagramXML);

    const xml = await instance.getXML();

    expect(xml).to.exist;
    expect(xml).to.eql(diagramXML);
  });

  describe('#exportAs', function() {

    // increase test time-outs, as exporting takes a
    // long certain underpowered CI systems (AppVeyor, wink, wink)
    this.timeout(5000);

    let instance;

    beforeEach(function() {
      instance = renderEditor(diagramXML).instance;
    });

    it('svg', async function() {
      const contents = await instance.exportAs('svg');

      expect(contents).to.exist;
      expect(contents).to.equal('<svg />');
    });

    it('png', async function() {
      const contents = await instance.exportAs('png');

      expect(contents).to.exist;
      expect(contents).to.contain('data:image/png');
    });

    it('jpeg', async function() {
      const contents = await instance.exportAs('jpeg');

      expect(contents).to.exist;
      expect(contents).to.contain('data:image/jpeg');
    });

  });

  describe('#listen', function() {

    function expectHandleChanged(event) {
      return async function() {
        const modeler = new CmmnModeler();

        const cache = new Cache();

        cache.add('editor', {
          cached: {
            modeler
          },
          __destroy: () => {}
        });

        const changedSpy = spy();

        await renderEditor(diagramXML, {
          id: 'editor',
          cache,
          onChanged: changedSpy
        });

        modeler._emit(event);

        expect(changedSpy).to.have.been.called;
      };
    }

    it('import.done', expectHandleChanged('import.done'));

    it('saveXML.done', expectHandleChanged('saveXML.done'));

    it('commandStack.changed', expectHandleChanged('commandStack.changed'));

    it('selection.changed', expectHandleChanged('selection.changed'));

    it('attach', expectHandleChanged('attach'));

    it('propertiesPanel.focusin', expectHandleChanged('propertiesPanel.focusin'));

    it('propertiesPanel.focusout', expectHandleChanged('propertiesPanel.focusout'));

  });

  describe('#handleChanged', function() {

    it('should notify about changes', function() {

      // given
      const changedSpy = sinon.spy();

      const modeler = new CmmnModeler({
        modules: {
          commandStack: {
            canRedo: () => true,
            canUndo: () => true,
            _stackIdx: 1
          },
          selection: {
            get: () => []
          }
        }
      });

      const cache = new Cache();

      cache.add('editor', {
        cached: {
          lastXML: diagramXML,
          modeler,
          stackIdx: 1
        },
        __destroy: () => {}
      });

      const { instance } = renderEditor(diagramXML, {
        id: 'editor',
        cache,
        onChanged: changedSpy
      });

      changedSpy.resetHistory();

      // when
      modeler.get('commandStack')._stackIdx = 5;

      instance.handleChanged();

      expect(changedSpy).to.be.calledOnce;
      expect(changedSpy.firstCall.args[0]).to.include({
        dirty: true,
        editLabel: false,
        find: true,
        globalConnectTool: true,
        handTool: true,
        inputActive: false,
        lassoTool: true,
        moveCanvas: true,
        redo: true,
        removeSelected: false,
        spaceTool: true,
        undo: true
      });
    });

    it('should notify about plugin related changes', async function() {
      // given
      const changedSpy = sinon.spy();

      const { instance } = await renderEditor(diagramXML, {
        id: 'editor',
        onChanged: changedSpy
      });

      changedSpy.resetHistory();

      // when
      instance.handleChanged();

      // then
      expect(changedSpy).to.be.calledOnce;

      const state = changedSpy.firstCall.args[0];

      expect(state).to.have.property('cmmn');
      expect(state).to.have.property('editable');
      expect(state).to.have.property('elementsSelected');
      expect(state).to.have.property('inactiveInput');
    });

    describe('edit menu', function() {

      it('should provide und/redo entries', async function() {

        // given
        const changedSpy = (state) => {

          const editMenuEntries = getUndoRedoEntries(state);

          // then
          expect(state.editMenu).to.deep.include(editMenuEntries);

        };

        const { instance } = await renderEditor(diagramXML, {
          onChanged: changedSpy
        });

        // when
        instance.handleChanged();
      });

      it('should provide copy/paste entries', async function() {

        // given
        const changedSpy = (state) => {

          const editMenuEntries = getCopyCutPasteEntries(state);

          // then
          expect(state.editMenu).to.deep.include(editMenuEntries);

        };

        const { instance } = await renderEditor(diagramXML, {
          onChanged: changedSpy
        });

        // when
        instance.handleChanged();
      });

      it('should provide tool entries', async function() {

        // given
        const changedSpy = (state) => {

          const editMenuEntries = getToolEntries(state);

          // then
          expect(state.editMenu).to.deep.include(editMenuEntries);

        };

        const { instance } = await renderEditor(diagramXML, {
          onChanged: changedSpy
        });

        // when
        instance.handleChanged();
      });

      it('should provide find entries', async function() {

        // given
        const changedSpy = (state) => {

          const editMenuEntries = getDiagramFindEntries(state);

          // then
          expect(state.editMenu).to.deep.include(editMenuEntries);

        };

        const { instance } = await renderEditor(diagramXML, {
          onChanged: changedSpy
        });

        // when
        instance.handleChanged();
      });

      it('should provide selection + canvas entries', async function() {

        // given
        const changedSpy = (state) => {

          const editMenuEntries = [
            ...getCanvasEntries(state),
            ...getSelectionEntries(state)
          ];

          // then
          expect(state.editMenu).to.deep.include(editMenuEntries);

        };

        const { instance } = await renderEditor(diagramXML, {
          onChanged: changedSpy
        });

        // when
        instance.handleChanged();
      });
    });

  });

  describe('layout', function() {

    it('should open properties panel', function() {

      // given
      let layout = {
        propertiesPanel: {
          open: false
        }
      };

      function onLayoutChanged(newLayout) {
        layout = newLayout;
      }

      const {
        wrapper
      } = renderEditor(diagramXML, {
        layout,
        onLayoutChanged
      });

      const toggle = wrapper.find('.toggle');

      // when
      toggle.simulate('click');

      // then
      expect(layout.propertiesPanel.open).to.be.true;
    });

    it('should close properties panel', function() {

      // given
      let layout = {
        propertiesPanel: {
          open: true
        }
      };

      function onLayoutChanged(newLayout) {
        layout = newLayout;
      }

      const {
        wrapper
      } = renderEditor(diagramXML, {
        layout,
        onLayoutChanged
      });

      const toggle = wrapper.find('.toggle');

      // when
      toggle.simulate('click');

      // then
      expect(layout.propertiesPanel.open).to.be.false;
    });

    it('should handle missing layout', function() {

      // given
      let layout = { };

      // then
      renderEditor(diagramXML, {
        layout
      });

    });

  });

  describe('errors', function() {

    it('should handle XML export error', async function() {

      // given
      const errorSpy = spy();

      const {
        instance
      } = renderEditor('export-error', {
        onError: errorSpy
      });

      // make sure editor is dirty
      const commandStack = instance.getModeler().get('commandStack');

      commandStack.execute(1);

      let err;

      // when
      try {
        await instance.getXML();
      } catch (e) {
        err = e;
      }

      // then
      expect(err).to.exist;
      expect(errorSpy).to.have.been.calledOnce;
    });

    it('should handle image export error', async function() {

      // given
      const errorSpy = spy();

      const {
        instance
      } = renderEditor('export-as-error', {
        onError: errorSpy
      });

      let err;

      // when
      try {
        await instance.exportAs('svg');
      } catch (e) {
        err = e;
      }

      // then
      expect(err).to.exist;
      expect(errorSpy).to.have.been.calledOnce;
    });

  });

  describe('import', function() {

    it('should import without errors and warnings', function(done) {

      // when
      renderEditor(diagramXML, {
        onImport
      });

      // then
      function onImport(error, warnings) {
        try {
          expect(error).to.not.exist;
          expect(warnings).to.have.length(0);

          done();
        } catch (error) {
          done(error);
        }
      }
    });

    it('should import with warnings', function(done) {
      // given
      const warningInducingFakeXML = 'import-warnings';

      // when
      renderEditor(warningInducingFakeXML, {
        onImport
      });

      // then
      function onImport(error, warnings) {
        try {
          expect(error).to.not.exist;
          expect(warnings).to.have.length(1);

          done();
        } catch (error) {
          done(error);
        }
      }
    });

    it('should import with error', function(done) {
      // given
      const errorInducingFakeXML = 'import-error';

      // when
      renderEditor(errorInducingFakeXML, {
        onImport
      });

      // then
      function onImport(error, warnings) {
        try {
          expect(error).to.exist;
          expect(warnings).to.have.length(0);

          done();
        } catch (error) {
          done(error);
        }
      }
    });

  });

  describe('dirty state', function() {

    let instance;

    beforeEach(function() {
      instance = renderEditor(diagramXML).instance;
    });

    it('should NOT be dirty initially', function() {

      // then
      const dirty = instance.isDirty();

      expect(dirty).to.be.false;
    });

    it('should be dirty after modeling', function() {

      // given
      const { modeler } = instance.getCached();

      // when
      // execute 1 command
      modeler.get('commandStack').execute(1);

      // then
      const dirty = instance.isDirty();

      expect(dirty).to.be.true;
    });

    it('should NOT be dirty after modeling -> undo', function() {

      // given
      const { modeler } = instance.getCached();

      modeler.get('commandStack').execute(1);

      // when
      modeler.get('commandStack').undo();

      // then
      const dirty = instance.isDirty();

      expect(dirty).to.be.false;
    });

    it('should NOT be dirty after save', async function() {

      // given
      const { modeler } = instance.getCached();

      // execute 1 command
      modeler.get('commandStack').execute(1);

      // when
      await instance.getXML();

      // then
      const dirty = instance.isDirty();

      expect(dirty).to.be.false;
    });

  });

  describe('properties panel actions', function() {

    it('should toggle properties panel', async function() {
      // given
      const onLayoutChangedSpy = sinon.spy();
      const {
        instance
      } = await renderEditor(diagramXML, {
        layout: {
          propertiesPanel: {
            open: false,
          }
        },
        onLayoutChanged: onLayoutChangedSpy
      });

      // when
      instance.triggerAction('toggleProperties');

      // then
      expect(onLayoutChangedSpy).to.be.calledOnceWith({
        propertiesPanel: {
          open: true,
        }
      });
    });

    it('should reset properties panel', async function() {
      // given
      const onLayoutChangedSpy = sinon.spy();
      const {
        instance
      } = await renderEditor(diagramXML, {
        onLayoutChanged: onLayoutChangedSpy
      });

      // when
      instance.triggerAction('resetProperties');

      // then
      expect(onLayoutChangedSpy).to.be.calledOnceWith({
        propertiesPanel: {
          open: true,
          width: 250
        }
      });
    });

  });

  describe('zoom actions', function() {

    let editorActionsStub,
        instance;

    beforeEach(async function() {
      // given
      editorActionsStub = sinon.stub({ trigger() {} });

      const cache = new Cache();

      cache.add('editor', {
        cached: {
          modeler: new CmmnModeler({
            modules: {
              editorActions: editorActionsStub
            }
          })
        }
      });

      instance = (await renderEditor(diagramXML, { cache })).instance;
    });

    afterEach(sinon.restore);

    it('should zoom in', function() {
      // when
      instance.triggerAction('zoomIn');

      // then
      expect(editorActionsStub.trigger).to.be.calledOnceWith('stepZoom', {
        value: 1
      });
    });

    it('should zoom out', function() {
      // when
      instance.triggerAction('zoomOut');

      // then
      expect(editorActionsStub.trigger).to.be.calledOnceWith('stepZoom', {
        value: -1
      });
    });

    it('should zoom to fit diagram', function() {
      // when
      instance.triggerAction('zoomFit');

      // then
      expect(editorActionsStub.trigger).to.be.calledOnceWith('zoom', {
        value: 'fit-viewport'
      });
    });

    it('should reset zoom', async function() {
      // when
      instance.triggerAction('resetZoom');

      // then
      expect(editorActionsStub.trigger).to.be.calledOnceWith('zoom', {
        value: 1
      });
    });

  });

});

// helpers //////////

function noop() {}

const TestEditor = WithCachedState(CmmnEditor);

function renderEditor(xml, options = {}) {
  const {
    layout,
    onChanged,
    onError,
    onImport,
    onLayoutChanged
  } = options;

  const wrapper = mount(
    <TestEditor
      id={ options.id || 'editor' }
      xml={ xml }
      activeSheet={ options.activeSheet || { id: 'cmmn' } }
      onChanged={ onChanged || noop }
      onError={ onError || noop }
      onImport={ onImport || noop }
      onLayoutChanged={ onLayoutChanged || noop }
      cache={ options.cache || new Cache() }
      layout={ layout || {
        minimap: {
          open: false
        },
        propertiesPanel: {
          open: true
        }
      } }
    />
  );

  const instance = wrapper.find(CmmnEditor).instance();

  return {
    instance,
    wrapper
  };
}<|endoftext|>


<commit_before>var _ = exports;

var ver2number = _.ver2number = function(a) {
    var m = /^v?(\d+)(?:\.(\d+))(?:\.(\d+))?.*(\d+)?/i.exec(a);
    if (m) {
        return (m[1] << 21) + (m[2] << 14) + (m[3] || 0) << 7 + (m[4] || 0) << 0;
    } else {
        return 0;
    }
};

_.compareVersion = function (a, b) {
    return ver2number(b) - ver2number(a);
};

_.indexOfArray = function(key, val, list) {
    var found = -1;
    list.every(function(item, index) {
        if (item[key] == val) {
            found = index;
            return false;
        }
        return true;
    });

    return found;
};

_.mixin = function mixin(a, b) {
    if (a && b) {
        for (var key in b) {
            a[key] = b[key];
        }
    }
    return a;
};
<commit_msg>update<commit_after>var _ = exports;

var ver2number = _.ver2number = function(a) {
    var m = /^v?(\d+)(?:\D(\d+))(?:\D(\d+))?(?:\D+(\d+))?/i.exec(a);
    if (m) {
        return parseInt(m[1], 10) * (1 << 10) +
          parseInt(m[2], 10) * (1 << 9) +
          parseInt(m[3] || 0, 10) * (1 << 8) +
          parseInt(m[4] || 0, 10);
    } else {
        return 0;
    }
};

_.compareVersion = function (a, b) {
    return ver2number(b) - ver2number(a);
};

_.indexOfArray = function(key, val, list) {
    var found = -1;
    list.every(function(item, index) {
        if (item[key] == val) {
            found = index;
            return false;
        }
        return true;
    });

    return found;
};

_.mixin = function mixin(a, b) {
    if (a && b) {
        for (var key in b) {
            a[key] = b[key];
        }
    }
    return a;
};
<|endoftext|>