text: /**
   * Execute the user's code.
   * Just a quick and dirty eval.  No checks for infinite loops, etc.
   */
  function runJS() {
    var code = Blockly.Generator.workspaceToCode('JavaScript');
    try {
      eval(code);
    } catch (e) {
      alert('Program error:\n' + e);
    }
  }
  
  /**
   * Backup code blocks to localStorage.
   */
  function backup_blocks() {
    if ('localStorage' in window) {
       
      var xml = Blockly.Xml.workspaceToDom(Blockly.mainWorkspace);
      window.localStorage.setItem('arduino', Blockly.Xml.domToText(xml));
    }
  }
  
  /**
   * Restore code blocks from localStorage.
   */
  function restore_blocks() {
  
    if ('localStorage' in window && window.localStorage.arduino) {
      var xml = Blockly.Xml.textToDom(window.localStorage.arduino);
      Blockly.Xml.domToWorkspace(Blockly.mainWorkspace, xml);
    }
  }
  
  /**
  * Save Arduino generated code to local file.
  */
  function saveCode() {
      
   //ADEL
   var badBlock = Blockly.Arduino.getUnconnectedBlock();
      //alert(badBlock);
      if (badBlock) {
        warningText = MSG['warningBadBlock'];
        
      } else {
        badBlock = Blockly.Arduino.getBlockWithWarning();
        if (badBlock) {
         warningText = MSG['warningPleaseFix'];
        }
     }
     
  
      if (badBlock) {
        // Go to blocks pane.
        //Code.displayTab('tab_blocks');
        
        Code.selected = 'blocks';
        clickedName = 'blocks';
        
        // Pop up warning dialog, making an offending block blink.
        // If they close the dialog with "OK", they remain in the blocks pane.
        // If they choose the other option ("generate Lua anyway"), the fake
        // tab "tab_lua!" is selected, and this validation will get skipped.
        var style = {
          left: '25%',
          top: '5em'
        };
        
        document.getElementById('badBlockMsg').innerHTML = warningText;
        BlocklyApps.showDialog(document.getElementById('badBlockDiv'), null,
                               false, true, style, BlocklyApps.stopDialogKeyDown);
        BlocklyApps.startDialogKeyDown();
       
        var blink = function() {
          badBlock.select();
          if (BlocklyApps.isDialogVisible_) {
            window.setTimeout(function() {badBlock.unselect();}, 150);
            window.setTimeout(blink, 300);
          }
        };
        blink();
        return;
      
      }
   //
      var d = new Date();
    var fileName = window.prompt('What would you like to name your file?', 'BlocklyDuinoEnhanced_'+'_'+d.getMinutes()+d.getMilliseconds())
    //doesn't save if the user quits the save prompt
    if(fileName){
      var blob = new Blob([Blockly.Arduino.workspaceToCode()], {type: 'text/ino;charset=utf-8'});
      saveAs(blob, fileName + '.ino');
    }
  }
  
  /**
   * Save blocks to local file.
   * better include Blob and FileSaver for browser compatibility
   */
  function save() {
    var xml = Blockly.Xml.workspaceToDom(Blockly.mainWorkspace);
    var data = Blockly.Xml.domToText(xml);
    var fileName = window.prompt('What would you like to name your file?', 'BlocklyDuino');
    // Store data in blob.
    // var builder = new BlobBuilder();
    // builder.append(data);
    // saveAs(builder.getBlob('text/plain;charset=utf-8'), 'blockduino.xml');
    if(fileName){
      var blob = new Blob([data], {type: 'text/xml'});
      saveAs(blob, fileName + ".xml");
    } 
  }
  
  /**
   * Load blocks from local file.
   * 
   * 
   */
  
  
  function load(event) {
      //ADDEL
      //var fileName = window.prompt('§PPPP?', 'BlocklyDuino');
     
    var files = event.target.files;
  
    // Only allow uploading one file.
    if (files.length != 1) {
      return;
    }
  
    // FileReader
    var reader = new FileReader();
    reader.onloadend = function(event) {
      var target = event.target;
      // 2 == FileReader.DONE
      if (target.readyState == 2) {
        try {
          var xml = Blockly.Xml.textToDom(target.result);
        } catch (e) {
          alert('Error parsing XML:\n' + e);
          return;
        }
        var count = Blockly.mainWorkspace.getAllBlocks().length;
        if (count && confirm('Replace existing blocks?\n"Cancel" will merge.')) {
          Blockly.mainWorkspace.clear();
        }
        Blockly.Xml.domToWorkspace(Blockly.mainWorkspace, xml);
      }
      // Reset value of input after loading because Chrome will not fire
      // a 'change' event if the same file is loaded again.
      document.getElementById('load').value = '';
    };
    reader.readAsText(files[0]);
  }
  
  /**
   * Discard all blocks from the workspace.
   */
  function discard() {
    var count = Blockly.mainWorkspace.getAllBlocks().length;
    if (count < 2 || window.confirm('Delete all ' + count + ' blocks?')) {
      Blockly.mainWorkspace.clear();
      renderContent();
    }
  }
  
  /*
   * auto save and restore blocks
   */
  function auto_save_and_restore_blocks() {
    // Restore saved blocks in a separate thread so that subsequent
    // initialization is not affected from a failed load.
    window.setTimeout(restore_blocks, 0);
    // Hook a save function onto unload.
    bindEvent(window, 'unload', backup_blocks);
    Code.tabClick(selected);
  
    // Init load event.
    var loadInput = document.getElementById('load');
    loadInput.addEventListener('change', load, false);
    document.getElementById('fakeload').onclick = function() {
      loadInput.click();
    };
  }
  
  /**
   * Bind an event to a function call.
   * @param {!Element} element Element upon which to listen.
   * @param {string} name Event name to listen to (e.g. 'mousedown').
   * @param {!Function} func Function to call when event is triggered.
   *     W3 browsers will call the function with the event object as a parameter,
   *     MSIE will not.
   */
  function bindEvent(element, name, func) {
    if (element.addEventListener) {  // W3C
      element.addEventListener(name, func, false);
    } else if (element.attachEvent) {  // IE
      element.attachEvent('on' + name, func);
    }
  }
  
  //loading examples via ajax
  var ajax;
  function createAJAX() {
    if (window.ActiveXObject) { //IE
      try {
        return new ActiveXObject("Msxml2.XMLHTTP");
      } catch (e) {
        try {
          return new ActiveXObject("Microsoft.XMLHTTP");
        } catch (e2) {
          return null;
        }
      }
    } else if (window.XMLHttpRequest) {
      return new XMLHttpRequest();
    } else {
      return null;
    }
  }
  
  function onSuccess() {
    if (ajax.readyState == 4) {
      if (ajax.status == 200) {
        try {
        var xml = Blockly.Xml.textToDom(ajax.responseText);
        } catch (e) {
          alert('Error parsing XML:\n' + e);
          return;
        }
        var count = Blockly.mainWorkspace.getAllBlocks().length;
        if (count && confirm('Replace existing blocks?\n"Cancel" will merge.')) {
          Blockly.mainWorkspace.clear();
        }
        Blockly.Xml.domToWorkspace(Blockly.mainWorkspace, xml);
      } else {
        alert("Server error");
      }
    }
  }
  
  function load_by_url(uri) {
    ajax = createAJAX();
    if (!ajax) {
  　　   alert ('Not compatible with XMLHttpRequest');
  　　   return 0;
  　  }
    if (ajax.overrideMimeType) {
      ajax.overrideMimeType('text/xml');
    }
  
  　　ajax.onreadystatechange = onSuccess;
  　　ajax.open ("GET", uri, true);
  　　ajax.send ("");
  }
  
  function uploadCode(code, callback) {
      var target = document.getElementById('content_arduino');
      var spinner = new Spinner().spin(target);
  
      var url = "http://127.0.0.1:8080/";
      var method = "POST";
  
      // You REALLY want async = true.
      // Otherwise, it'll block ALL execution waiting for server response.
      var async = true;
  
      var request = new XMLHttpRequest();
      
      request.onreadystatechange = function() {
          if (request.readyState != 4) { 
              return; 
          }
          
          spinner.stop();
          
          var status = parseInt(request.status); // HTTP response status, e.g., 200 for "200 OK"
          var errorInfo = null;
          switch (status) {
          case 200:
              break;
          case 0:
              errorInfo = "code 0\n\nCould not connect to server at " + url + ".  Is the local web server running?";
              break;
          case 400:
              errorInfo = "code 400\n\nBuild failed - probably due to invalid source code.  Make sure that there are no missing connections in the blocks.";
              break;
          case 500:
              errorInfo = "code 500\n\nUpload failed.  Is the Arduino connected to USB port?";
              break;
          case 501:
              errorInfo = "code 501\n\nUpload failed.  Is 'ino' installed and in your path?  This only works on Mac OS X and Linux at this time.";
              break;
          default:
              errorInfo = "code " + status + "\n\nUnknown error.";
              break;
          };
          
          callback(status, errorInfo);
      };
  
      request.open(method, url, async);
      request.setRequestHeader("Content-Type", "text/plain;charset=UTF-8");
      request.send(code);	     
  }
  
  function uploadClick() {
      var code = document.getElementById('content_arduino').value;
  
      alert("Ready to upload to Arduino.");
      
      uploadCode(code, function(status, errorInfo) {
          if (status == 200) {
              alert("Program uploaded ok");
          } else {
              alert("Error uploading program: " + errorInfo);
          }
      });
  }
  
  function resetClick() {
      var code = "void setup() {} void loop() {}";
  
      uploadCode(code, function(status, errorInfo) {
          if (status != 200) {
              alert("Error resetting program: " + errorInfo);
          }
      });
  }
  