From 225589eb374fbea807c26fe3fa92e521b6d6c03c Mon Sep 17 00:00:00 2001
From: Vincent Nivoliers <vincent.nivoliers@univ-lyon1.fr>
Date: Tue, 13 Sep 2016 16:53:34 +0200
Subject: [PATCH] integrating programming into explorer

---
 css/style.css          |  19 +-
 explorer.php           | 427 +++++++++++++++++++++++++++++++++++++++--
 js/explorer.js         |   8 -
 js/pgm_compiler.js     | 135 ++++++++++---
 js/pgm_construction.js | 242 ++++++++++++++++++++---
 sortable_test.html     |  28 ++-
 6 files changed, 771 insertions(+), 88 deletions(-)

diff --git a/css/style.css b/css/style.css
index 463ffa3..87fcfb3 100644
--- a/css/style.css
+++ b/css/style.css
@@ -371,15 +371,13 @@ script {
   overflow : hidden ;
 }
 
-@media(min-width:768px){
-  #pgm-title {
-    margin-top : 9px ;
-  }
+#pgm-title {
+  margin-top : 9px ;
+  margin-right : 10px ;
 }
 
 #desktop-switches {
-  margin-left : auto ;
-  vertical-align : middle ;
+  margin-right : 10px ;
 }
 
 .pgm-recv {
@@ -425,7 +423,6 @@ script {
   width : 100%
 }
 
-
 .pgm-block.add-target,
 .pgm-command.add-target {
   border-top : 15px solid #337ab7 !important ;
@@ -537,6 +534,14 @@ input.add-target {
   display : block ;
 }
 
+#library {
+  position : relative ;
+}
+
+#library > .panel {
+  /*position : fixed ;*/
+}
+
 @media(max-width:767px){
   .col-xs-12 {
     padding : 0px ;
diff --git a/explorer.php b/explorer.php
index f291c78..a7f827a 100644
--- a/explorer.php
+++ b/explorer.php
@@ -1,6 +1,7 @@
 <!DOCTYPE html>
 <html>
   <head>
+    <!--{{{ header-->
     <title>Explosurf</title>
     <meta name="viewport" content="width=device-width, initial-scale=1">
     <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
@@ -18,23 +19,7 @@
       href="<?php echo $rootpath?>/css/bootstrap.css" />
     <link rel="stylesheet" type="text/css" media="screen" 
       href="<?php echo $rootpath?>/css/style.css" />
-
-    <script type="text/javascript"
-      src="<?php echo $rootpath?>/js/EventHelpers.js">
-    </script>
-    <script type="text/javascript" 
-      src="<?php echo $rootpath?>/js/logger.js">
-    </script>
-    <script type="text/javascript" 
-      src="<?php echo $rootpath?>/js/fakeLocalStorage.js">
-    </script>
-    <script type="text/javascript" 
-      src="<?php echo $rootpath?>/js/explorer.js">
-    </script>
-    <script type="text/javascript" 
-      src="<?php echo $rootpath?>/js/ui.js">
-    </script>
-		
+	<!--}}}-->	
   </head>
   <body onload="javascript:init(
     <?php 
@@ -52,6 +37,7 @@
     onunload="javascript:get_out();"
     >
     <div class="container">
+      <!--{{{ top bar-->
       <div class="navbar navbar-default">
         <div class="container-fluid">
           <div class="navbar-header">
@@ -86,8 +72,10 @@
           </div>
         </div>
       </div>
+      <!--}}}-->
 
       <div class="container-fluid">
+        <!--{{{ help-->
         <div class="panel panel-default collapse" id="help-panel">
           <div class="panel-heading">
             <h2 class="panel-title">Aide</h2>
@@ -198,6 +186,8 @@
             </p>
           </div>
         </div>
+        <!--}}}-->
+        <!--{{{ map and notes-->
         <div class="row">
           <div class="col-md-9">
             <div class="panel panel-default">
@@ -327,6 +317,387 @@
             </div>
           </div>
         </div>
+        <!--}}}-->
+        <!--{{{ programming interface-->
+        <div class="row row-offcanvas row-offcanvas-left" id="program">
+          <!--{{{ commands-->
+          <div class="col-xs-12 col-sm-4 sidebar-offcanvas" id="library">
+            <div class="panel panel-default">
+              <!--{{{ tabs-->
+              <div class="panel-heading tabbed-heading">
+                <ul class="nav nav-tabs">
+                  <li class="active">
+                    <a class="glyphicon glyphicon-move" data-toggle="tab" href=#mv_cmds></a>
+                  </li>
+                  <li>
+                    <a class="glyphicon glyphicon-pencil" data-toggle="tab" href=#var_cmds></a>
+                  </li>
+                  <li>
+                    <a class="glyphicon glyphicon-random" data-toggle="tab" href=#ctrl_cmds></a>
+                  </li>
+                  <li>
+                    <a class="glyphicon glyphicon-ok" data-toggle="tab" href=#test_cmds></a>
+                  </li>
+                  <li>
+                    <a class="glyphicon glyphicon-plus" data-toggle="tab" href=#arth_cmds></a>
+                  </li>
+                  <li>
+                    <a class="glyphicon glyphicon-font" data-toggle="tab" href=#txt_cmds></a>
+                  </li>
+                </ul>
+                <a class="glyphicon glyphicon-remove hidden" 
+                  id="btn-close-library" 
+                ></a>
+              </div>
+              <!--}}}-->
+              <div class="tab-content panel-collapse no-top-border-lists">
+                <!--{{{ movement-->
+                <ul id="mv_cmds" class="list-group tab-pane fade library-group in active">
+                  <li class="list-group-item pgm-command pgm-type-direction cmd-dir-up">
+                    <span class="glyphicon glyphicon-circle-arrow-up"></span>
+                    haut
+                  </li>
+                  <li class="list-group-item pgm-command pgm-type-direction cmd-dir-left">
+                    <span class="glyphicon glyphicon-circle-arrow-left"></span>
+                    gauche 
+                  </li>
+                  <li class="list-group-item pgm-command pgm-type-direction cmd-dir-down">
+                    <span class="glyphicon glyphicon-circle-arrow-down"></span>
+                    bas 
+                  </li>
+                  <li class="list-group-item pgm-command pgm-type-direction cmd-dir-right">
+                    <span class="glyphicon glyphicon-circle-arrow-right"></span>
+                    droite 
+                  </li>
+                  <li class="list-group-item pgm-command pgm-type-color cmd-col-red">
+                    <span class="glyphicon glyphicon-adjust text-danger"></span>
+                    rouge 
+                  </li>
+                  <li class="list-group-item pgm-command pgm-type-color cmd-col-yellow">
+                    <span class="glyphicon glyphicon-adjust text-warning"></span>
+                    jaune 
+                  </li>
+                  <li class="list-group-item pgm-command pgm-type-color cmd-col-green">
+                    <span class="glyphicon glyphicon-adjust text-success"></span>
+                    vert 
+                  </li>
+                  <li class="list-group-item pgm-command pgm-type-color cmd-col-blue">
+                    <span class="glyphicon glyphicon-adjust text-primary"></span>
+                    bleu 
+                  </li>
+                  <li class="list-group-item pgm-command pgm-type-color cmd-col-of">
+                    <span class="glyphicon glyphicon-transfer"></span>
+                    couleur de 
+                    <div class="pgm-recv pgm-recv-direction">
+                      <div class="placeholder">direction</div>
+                    </div>
+                  </li>
+                  <li class="list-group-item pgm-command pgm-type-direction cmd-dir-of">
+                    <span class="glyphicon glyphicon-transfer"></span>
+                    direction de 
+                    <div class="pgm-recv pgm-recv-color">
+                      <div class="placeholder">couleur</div>
+                    </div>
+                  </li>
+                  <li class="list-group-item pgm-command pgm-type-direction cmd-next-dir">
+                    <span class="glyphicon glyphicon-refresh"></span>
+                    direction suivante de 
+                    <div class="pgm-recv pgm-recv-direction">
+                      <div class="placeholder">direction</div>
+                    </div>
+                  </li>
+                  <li class="list-group-item pgm-command pgm-type-color cmd-next-col">
+                    <span class="glyphicon glyphicon-refresh"></span>
+                    couleur suivante de 
+                    <div class="pgm-recv pgm-recv-color">
+                      <div class="placeholder">couleur</div>
+                    </div>
+                  </li>
+                </ul>
+                <!--}}}-->
+                <!--{{{ vaiables-->
+                <ul id="var_cmds" class="list-group tab-pane fade library-group">
+                  <li class="list-group-item pgm-command pgm-type-void cmd-var-local-set">
+                    <span class="glyphicon glyphicon-map-marker"></span>
+                    <div class="pgm-recv pgm-recv-str">
+                      <input size=8 placeholder="variable" disabled></input> 
+                    </div>
+                    &larr;
+                    <div class="pgm-recv pgm-recv-str">
+                      <input size=8 placeholder="valeur" disabled></input> 
+                    </div>
+                  </li>
+                  <li class="list-group-item pgm-command pgm-type-read cmd-var-local-read">
+                    <span class="glyphicon glyphicon-map-marker"></span>
+                    <span class="glyphicon glyphicon-search"></span>
+                    <div class="pgm-recv pgm-recv-str">
+                      <input size=8 placeholder="variable" disabled></input> 
+                    </div>
+                  </li>
+                  <li class="list-group-item pgm-command pgm-type-void cmd-var-local-delete-var">
+                    <span class="glyphicon glyphicon-map-marker"></span>
+                    <span class="glyphicon glyphicon-trash"></span>
+                    <div class="pgm-recv pgm-recv-str">
+                      <input size=8 placeholder="variable" disabled></input> 
+                    </div>
+                  </li>
+                  <li class="list-group-item pgm-command pgm-type-void cmd-var-local-delete-tile">
+                    <span class="glyphicon glyphicon-map-marker"></span>
+                    <span class="glyphicon glyphicon-trash"></span>
+                    tout sur la case
+                  </li>
+                  <li class="list-group-item pgm-command pgm-type-void cmd-var-local-delete-world">
+                    <span class="glyphicon glyphicon-map-marker"></span>
+                    <span class="glyphicon glyphicon-trash"></span>
+                    tout sur toutes les cases
+                  </li>
+                  <li class="list-group-item pgm-command pgm-type-void cmd-var-global-set">
+                    <span class="glyphicon glyphicon-globe"></span>
+                    <div class="pgm-recv pgm-recv-str">
+                      <input size=8 placeholder="variable" disabled></input> 
+                    </div>
+                    &larr;
+                    <div class="pgm-recv pgm-recv-str">
+                      <input size=8 placeholder="valeur" disabled></input> 
+                    </div>
+                  </li>
+                  <li class="list-group-item pgm-command pgm-type-read cmd-var-global-read">
+                    <span class="glyphicon glyphicon-globe"></span>
+                    <span class="glyphicon glyphicon-search"></span>
+                    <div class="pgm-recv pgm-recv-str">
+                      <input size=8 placeholder="variable" disabled></input> 
+                    </div>
+                  </li>
+                  <li class="list-group-item pgm-command pgm-type-void cmd-var-global-delete-var">
+                    <span class="glyphicon glyphicon-globe"></span>
+                    <span class="glyphicon glyphicon-trash"></span>
+                    <div class="pgm-recv pgm-recv-str">
+                      <input size=8 placeholder="variable" disabled></input> 
+                    </div>
+                  </li>
+                  <li class="list-group-item pgm-command pgm-type-void cmd-var-global-delete-all">
+                    <span class="glyphicon glyphicon-globe"></span>
+                    <span class="glyphicon glyphicon-trash"></span>
+                    tout
+                  </li>
+                </ul>
+                <!--}}}-->
+                <!--{{{ control-->
+                <ul id="ctrl_cmds" class="list-group tab-pane fade library-group">
+                  <li class="list-group-item panel panel-default pgm-block pgm-type-void cmd-block-if">
+                    <div class="panel-heading">
+                      Si
+                      <div class="pgm-recv pgm-recv-bool">
+                        <div class="placeholder">test</div>
+                      </div>
+                    </div>
+                    <ul class="list-group pgm-recv-void">
+                      <li class="list-group-item pgm-command block-add no-sort hidden">
+                        <span class="glyphicon glyphicon-plus"></span>
+                      </li>
+                    </ul>
+                  </li>
+                  <li class="list-group-item panel panel-default pgm-block pgm-type-void cmd-block-if-else">
+                    <div class="panel-heading">
+                      Si
+                      <div class="pgm-recv pgm-recv-bool">
+                        <div class="placeholder">test</div>
+                      </div>
+                    </div>
+                    <ul class="list-group pgm-recv-void">
+                      <li class="list-group-item pgm-command block-add no-sort hidden">
+                        <span class="glyphicon glyphicon-plus"></span>
+                      </li>
+                    </ul>
+                    <div class="panel-heading">
+                      Sinon
+                    </div>
+                    <ul class="list-group pgm-recv-void">
+                      <li class="list-group-item pgm-command block-add no-sort hidden">
+                        <span class="glyphicon glyphicon-plus"></span>
+                      </li>
+                    </ul>
+                  </li>
+                  <li class="list-group-item panel panel-default pgm-block pgm-type-void cmd-block-while">
+                    <div class="panel-heading">
+                      Tant que
+                      <div class="pgm-recv pgm-recv-bool">
+                        <div class="placeholder">test</div>
+                      </div>
+                    </div>
+                    <ul class="list-group pgm-recv-void">
+                      <li class="list-group-item pgm-command block-add no-sort hidden">
+                        <span class="glyphicon glyphicon-plus"></span>
+                      </li>
+                    </ul>
+                  </li>
+                </ul>
+                <!--}}}-->
+                <!--{{{ tests-->
+                <ul id="test_cmds" class="list-group tab-pane fade library-group">
+                  <li class="list-group-item pgm-command pgm-type-bool cmd-test-equal">
+                    <div class="pgm-recv pgm-recv-str">
+                      <input size=8 placeholder="valeur" disabled></input> 
+                    </div>
+                    =
+                    <div class="pgm-recv pgm-recv-str">
+                      <input size=8 placeholder="valeur" disabled></input> 
+                    </div>
+                  </li>
+                  <li class="list-group-item pgm-command pgm-type-bool cmd-test-gt">
+                    <div class="pgm-recv pgm-recv-int">
+                      <input size=8 placeholder="valeur" disabled></input> 
+                    </div>
+                    &gt;
+                    <div class="pgm-recv pgm-recv-int">
+                      <input size=8 placeholder="valeur" disabled></input> 
+                    </div>
+                  </li>
+                  <li class="list-group-item pgm-command pgm-type-bool cmd-test-ge">
+                    <div class="pgm-recv pgm-recv-int">
+                      <input size=8 placeholder="valeur" disabled></input> 
+                    </div>
+                    &ge;
+                    <div class="pgm-recv pgm-recv-int">
+                      <input size=8 placeholder="valeur" disabled></input> 
+                    </div>
+                  </li>
+                  <li class="list-group-item pgm-command pgm-type-bool cmd-test-not">
+                    non
+                    <div class="pgm-recv pgm-recv-bool">
+                      <div class="placeholder">test</div>
+                    </div>
+                  </li>
+                  <li class="list-group-item pgm-command pgm-type-bool cmd-test-or">
+                    <div class="pgm-recv pgm-recv-bool">
+                      <div class="placeholder">test</div>
+                    </div>
+                    ou
+                    <div class="pgm-recv pgm-recv-bool">
+                      <div class="placeholder">test</div>
+                    </div>
+                  </li>
+                  <li class="list-group-item pgm-command pgm-type-bool cmd-test-and">
+                    <div class="pgm-recv pgm-recv-bool">
+                      <div class="placeholder">test</div>
+                    </div>
+                    et
+                    <div class="pgm-recv pgm-recv-bool">
+                      <div class="placeholder">test</div>
+                    </div>
+                  </li>
+                  <li class="list-group-item pgm-command pgm-type-bool cmd-test-var-exists-local">
+                    <span class="glyphicon glyphicon-map-marker"></span>
+                    <div class="pgm-recv pgm-recv-str">
+                      <input size=8 placeholder="variable" disabled></input> 
+                    </div>
+                    existe
+                  </li>
+                  <li class="list-group-item pgm-command pgm-type-bool cmd-test-var-exists-global">
+                    <span class="glyphicon glyphicon-globe"></span>
+                    <div class="pgm-recv pgm-recv-str">
+                      <input size=8 placeholder="variable" disabled></input> 
+                    </div>
+                    existe
+                  </li>
+                </ul>
+                <!--}}}-->
+                <!--{{{ arithmetics-->
+                <ul id="arth_cmds" class="list-group tab-pane fade library-group">
+                  <li class="list-group-item pgm-command pgm-type-int cmd-arith-plus">
+                    (
+                    <div class="pgm-recv pgm-recv-int">
+                      <input size=8 placeholder="entier" disabled></input> 
+                    </div>
+                    +
+                    <div class="pgm-recv pgm-recv-int">
+                      <input size=8 placeholder="entier" disabled></input> 
+                    </div>
+                    )
+                  </li>
+                  <li class="list-group-item pgm-command pgm-type-int cmd-arith-minus">
+                    (
+                    <div class="pgm-recv pgm-recv-int">
+                      <input size=8 placeholder="entier" disabled></input> 
+                    </div>
+                    -
+                    <div class="pgm-recv pgm-recv-int">
+                      <input size=8 placeholder="entier" disabled></input> 
+                    </div>
+                    )
+                  </li>
+                  <li class="list-group-item pgm-command pgm-type-int cmd-arith-mult">
+                    (
+                    <div class="pgm-recv pgm-recv-int">
+                      <input size=8 placeholder="entier" disabled></input> 
+                    </div>
+                    &times;
+                    <div class="pgm-recv pgm-recv-int">
+                      <input size=8 placeholder="entier" disabled></input> 
+                    </div>
+                    )
+                  </li>
+                  <li class="list-group-item pgm-command pgm-type-int cmd-arith-div">
+                    (
+                    <div class="pgm-recv pgm-recv-int">
+                      <input size=8 placeholder="entier" disabled></input> 
+                    </div>
+                    &divide;
+                    <div class="pgm-recv pgm-recv-int">
+                      <input size=8 placeholder="entier" disabled></input> 
+                    </div>
+                    )
+                  </li>
+                </ul>
+                <!--}}}-->
+                <!--{{{ strings-->
+                <ul id="txt_cmds" class="list-group tab-pane fade library-group">
+                  <li class="list-group-item pgm-command pgm-type-str cmd-str-concat">
+                    <span class="glyphicon glyphicon-paperclip"></span>
+                    <div class="pgm-recv pgm-recv-str">
+                      <input size=8 placeholder="debut" disabled></input> 
+                    </div>
+                    <div class="pgm-recv pgm-recv-str">
+                      <input size=8 placeholder="fin" disabled></input> 
+                    </div>
+                  </li>
+                </ul>
+                <!--}}}-->
+              </div>
+            </div>
+          </div>
+          <!---}}}-->
+          <!--{{{ program-->
+          <div class="col-xs-12 col-sm-8">
+            <div class="panel panel-default pgm" id="pgm">
+              <div class="panel-heading">
+                <h3 class="panel-title pull-left" id="pgm-title">Programme</h3>
+                <div class="btn-group pull-right" role="group">
+                  <button class="btn btn-default" type="button" id="pgm-run"
+                    onclick="javascript:Explosurf.pgm.run();"
+                  >
+                    <span class="glyphicon glyphicon-play"></span>
+                  </button>
+                </div>
+                <div class="btn-group pull-right hidden-xs" role="group" id="desktop-switches">
+                  <button class="btn btn-default" type="button" id="desktop-ui-phone">
+                    <span class="glyphicon glyphicon-phone"></span>
+                  </button>
+                  <button class="btn btn-default" type="button" id="desktop-ui-copy">
+                    <span class="glyphicon glyphicon-copy"></span>
+                  </button>
+                </div>
+              </div>
+              <ul class="list-group pgm-recv-void" id="pgm-main">
+                <li class="list-group-item pgm-command block-add no-sort hidden">
+                  <span class="glyphicon glyphicon-plus"></span>
+                </li>
+              </ul>
+            </div>
+          </div>
+          <!--}}}-->
+        </div>
+        <!--}}}-->
         <?php 
           // get the XML planet descriptor
           if(file_exists('extra.php')) {
@@ -336,8 +707,30 @@
           }
         ?>
     </div>
+    <!--{{{ mobile toolbar-->
+    <div class="btn-toolbar hidden" role="toolbar" id="phone-toolbar">
+      <div class="btn-group" role="group">
+        <button class="btn btn-default active" autofocus type="button" id="phone-tool-add">
+          <span class="glyphicon glyphicon-plus"></span>
+        </button>
+        <button class="btn btn-default" type="button" id="phone-tool-cut">
+          <span class="glyphicon glyphicon-scissors"></span>
+        </button>
+        <button class="btn btn-default" type="button" id="phone-tool-copy">
+          <span class="glyphicon glyphicon-copy"></span>
+        </button>
+        <button class="btn btn-default" type="button" id="phone-tool-paste">
+          <span class="glyphicon glyphicon-paste"></span>
+        </button>
+      </div>
+    </div>
+    <!--}}}-->
     <script type="text/javascript" src="<?php echo $rootpath?>/js/bootstrap-native.js"></script>
+    <script type="text/javascript" src="<?php echo $rootpath?>/js/sortable.js"></script>
+    <script type="text/javascript" src="<?php echo $rootpath?>/js/pgm_construction.js"></script>
     <script type="text/javascript" src="<?php echo $rootpath?>/js/pgm_compiler.js"></script>
     <script type="text/javascript" src="<?php echo $rootpath?>/js/notes.js"></script>
+    <script type="text/javascript" src="<?php echo $rootpath?>/js/explorer.js"></script>
+    <div class="visible-xs-block" id="mobile-tester"></div>
   </body>
 </html>
diff --git a/js/explorer.js b/js/explorer.js
index 564f823..b75e8eb 100644
--- a/js/explorer.js
+++ b/js/explorer.js
@@ -26,27 +26,21 @@ function Tile(XmlElement) {
   this.neighbour_edges = new Array(null,null,null,null) ;
   this.orientations = new Array(null,null,null,null) ;
   this.image = null ;
-  Logger.log("Parsing tile " + this.name) ;
   
   var children = XmlElement.childNodes ;
   for(var i=0; i<children.length; i++) {
     var child = children[i] ;
     if(child.nodeName == 'image') {
       this.image = child.getAttribute('name') ;
-      Logger.log("  Found image " + this.image) ;
     } else if (child.nodeName == 'edge') {
       var index = parseInt(child.getAttribute('origin_index')) ;
-      Logger.log("  Found edge " + index) ;
       var neighbour = child.getAttribute('neighbour') ;
       if(neighbour != '') {
         this.neighbours[index] = neighbour ;
-        Logger.log("    Neighbour is " + neighbour) ;
         var neighbour_edge = parseInt(child.getAttribute('opposite_index')) ;
         this.neighbour_edges[index] = neighbour_edge ;
-        Logger.log("    Neighbour edge  is " + neighbour_edge) ;
         var orientation = child.getAttribute('orientation') ;
         this.orientations[index] = (orientation != "switch") ;
-        Logger.log("    Orientation is " + orientation) ;
       }
     }
   }
@@ -112,7 +106,6 @@ Map.prototype.toString = function() {
 }
 
 handle_request_error = function(evt) {
-  Logger.log("Error getting XML file") ;
 }
 
 function openXML(filename) {
@@ -195,7 +188,6 @@ function PlanetExplorer(filename) {
       }
     }
   }
-  //Logger.unmute() ;
 
   if(localStorage.getItem(this.prefix+"explorer:position")) {
     this.load_state() ;
diff --git a/js/pgm_compiler.js b/js/pgm_compiler.js
index a564ae9..10f024d 100644
--- a/js/pgm_compiler.js
+++ b/js/pgm_compiler.js
@@ -26,6 +26,7 @@ function block_compile(el) {
       res += ';' ;
     }
   }
+  return res ;
 }
 
 function get_integer(str, error_target) {
@@ -73,7 +74,7 @@ function get_str(str, error_target) {
 
 function receiver_compile(el) {
   //type of the receiver
-  var type = el.className.match(/pgm-type-(\S+)/)[1] ;
+  var type = el.className.match(/pgm-recv-(\S+)/)[1] ;
   //search for the child to compile
   var target = null ;
   for(var i = 0; i < el.children.length; ++i) {
@@ -95,10 +96,10 @@ function receiver_compile(el) {
   //compile child
   var rec_compile = "" ;
   if(target.tagName === "INPUT") {
-    rec_compile = target.value ;
+    rec_compile = '"' + target.value + '"' ;
   }
   else {
-    rec_compile = compile(target) ;
+    rec_compile = cmd_compile(target) ;
   }
   //handle runtime type errors
   var err_target = '"' + selector_path_to_root(target) + '"' ;
@@ -125,7 +126,7 @@ function selector_path_to_root(el) {
   } else {
     var p = el.parentElement ;
     var i = [].indexOf.call(p.children, el) + 1 ;
-    return path_to_root(p) + ' ' 
+    return selector_path_to_root(p) + ' ' 
       + el.tagName.toLowerCase() 
       + ':nth-child(' + i + ')' ;
   }
@@ -255,7 +256,7 @@ function command_dir_up(el) {
   if(el.parentElement.className.match(/pgm-recv-void/)) {
     return 'explorer.go(2)' ;
   } else {
-    return "haut" ;
+    return '"haut"' ;
   }
 }
 
@@ -265,7 +266,7 @@ function command_dir_left(el) {
   if(el.parentElement.className.match(/pgm-recv-void/)) {
     return 'explorer.go(3)' ;
   } else {
-    return "gauche" ;
+    return '"gauche"' ;
   }
 }
 
@@ -275,16 +276,16 @@ function command_dir_down(el) {
   if(el.parentElement.className.match(/pgm-recv-void/)) {
     return 'explorer.go(0)' ;
   } else {
-    return "bas" ;
+    return '"bas"' ;
   }
 }
 pgm_elements['cmd-dir-down'] = command_dir_down ;
 
-function pgm_command_dir_right(el) {
+function command_dir_right(el) {
   if(el.parentElement.className.match(/pgm-recv-void/)) {
     return 'explorer.go(1)' ;
   } else {
-    return "droite" ;
+    return '"droite"' ;
   }
 }
 
@@ -292,40 +293,46 @@ pgm_elements['cmd-dir-right'] = command_dir_right ;
 
 function command_col_red(el) {
   if(el.parentElement.className.match(/pgm-recv-void/)) {
-    return 'explorer.go(color_to_number("rouge"));' ;
+    return 'explorer.go(color_to_number("rouge"))' ;
   } else {
-    return "rouge" ;
+    return '"rouge"' ;
   }
 }
 
-pgm_elements['cmd-dir-up'] = command_dir_up ;
+pgm_elements['cmd-col-red'] = command_col_red ;
 
 function command_col_yellow(el) {
   if(el.parentElement.className.match(/pgm-recv-void/)) {
-    return 'explorer.go(color_to_number("yellow"));' ;
+    return 'explorer.go(color_to_number("yellow"))' ;
   } else {
-    return "jaune" ;
+    return '"jaune"' ;
   }
 }
 
+pgm_elements['cmd-col-yellow'] = command_col_yellow ;
+
 function command_col_green(el) {
   if(el.parentElement.className.match(/pgm-recv-void/)) {
-    return 'explorer.go(color_to_number("vert"));' ;
+    return 'explorer.go(color_to_number("vert"))' ;
   } else {
-    return "vert" ;
+    return '"vert"' ;
   }
 }
 
+pgm_elements['cmd-col-green'] = command_col_green ;
+
 function command_col_blue(el) {
   if(el.parentElement.className.match(/pgm-recv-void/)) {
-    return 'explorer.go(color_to_number("bleu"));' ;
+    return 'explorer.go(color_to_number("bleu"))' ;
   } else {
-    return "bleu" ;
+    return '"bleu"' ;
   }
 }
 
+pgm_elements['cmd-col-blue'] = command_col_blue ;
+
 function command_col_of(el) {
-  var receiver = el.children[2] ;
+  var receiver = el.children[1] ;
   var dir = receiver_compile(receiver) ;
   if(el.parentElement.className.match(/pgm-recv-void/)) {
     return 'explorer.go(direction_to_number(' + dir + '))' ;
@@ -334,8 +341,10 @@ function command_col_of(el) {
   }
 }
 
+pgm_elements['cmd-col-of'] = command_col_of ;
+
 function command_dir_of(el) {
-  var receiver = el.children[2] ;
+  var receiver = el.children[1] ;
   var col = receiver_compile(receiver) ;
   if(el.parentElement.className.match(/pgm-recv-void/)) {
     return 'explorer.go(color_to_number(' + col + '))' ;
@@ -344,8 +353,11 @@ function command_dir_of(el) {
   }
 }
 
+pgm_elements['cmd-dir-of'] = command_dir_of ;
+
+
 function command_next_col(el) {
-  var receiver = el.children[2] ;
+  var receiver = el.children[1] ;
   var col = receiver_compile(receiver) ;
   if(el.parentElement.className.match(/pgm-recv-void/)) {
     return 'explorer.go((color_to_number(' + col + ') + 1)%4)' ;
@@ -354,8 +366,10 @@ function command_next_col(el) {
   }
 }
 
+pgm_elements['cmd-next-col'] = command_next_col ;
+
 function command_next_dir(el) {
-  var receiver = el.children[2] ;
+  var receiver = el.children[1] ;
   var dir = receiver_compile(receiver) ;
   if(el.parentElement.className.match(/pgm-recv-void/)) {
     return 'explorer.go((direction_to_number(' + dir + ') + 1)%4)' ;
@@ -364,6 +378,8 @@ function command_next_dir(el) {
   }
 }
 
+pgm_elements['cmd-next-dir'] = command_next_dir ;
+
 /*}}}*/
 
 /* {{{ Variable management ================================================== */
@@ -374,8 +390,10 @@ function command_write_local(el) {
   return 'Explosurf.notes.set_variable(' + name + ', ' + value + ');' ;
 }
 
+pgm_elements['cmd-var-local-set'] = command_write_local ;
+
 function command_read_local(el) {
-  var name = receiver_compile(el.children[1]) ;
+  var name = receiver_compile(el.children[2]) ;
   if(el.parentElement.className.match(/pgm-recv-void/)) {
     var err_target = '"' + selector_path_to_root(el.children[2]) + '"' ;
     return 'explorer.go(get_movement(Explosurf.notes.get_variable(' + name + '), ' + err_target + '));' ;
@@ -384,27 +402,37 @@ function command_read_local(el) {
   }
 }
 
+pgm_elements['cmd-var-local-read'] = command_read_local ;
+
 function command_delete_local(el) {
-  var name = receiver_compile(el.children[1]) ;
+  var name = receiver_compile(el.children[2]) ;
   return 'Explosurf.notes.clear_variable(' + name + ');' ;
 }
 
+pgm_elements['cmd-var-local-delete-var'] = command_delete_local ;
+
 function command_delete_tile_local(el) {
   return 'Explosurf.notes.clear_variable(".*");' ;
 }
 
+pgm_elements['cmd-var-local-delete-tile'] = command_delete_tile_local ;
+
 function command_delete_all_local(el) {
   return 'Explosurf.notes.clear_local_variables(".*");' ;
 }
 
-function command_write_local(el) {
+pgm_elements['cmd-var-local-delete-world'] = command_delete_all_local ;
+
+function command_write_global(el) {
   var name = receiver_compile(el.children[1]) ;
   var value = receiver_compile(el.children[2]) ;
-  return 'Explosurf.notes.set_variable(' + name + ', ' + value + ');' ;
+  return 'Explosurf.notes.set_variable(' + name + ', ' + value + ', true);' ;
 }
 
+pgm_elements['cmd-var-global-set'] = command_write_global ;
+
 function command_read_global(el) {
-  var name = receiver_compile(el.children[1]) ;
+  var name = receiver_compile(el.children[2]) ;
   if(el.parentElement.className.match(/pgm-recv-void/)) {
     var err_target = '"' + selector_path_to_root(el.children[2]) + '"' ;
     return 'explorer.go(get_movement(Explosurf.notes.get_variable(' + name + ', true), ' + err_target + '));' ;
@@ -413,15 +441,21 @@ function command_read_global(el) {
   }
 }
 
+pgm_elements['cmd-var-global-read'] = command_read_global ;
+
 function command_delete_global(el) {
-  var name = receiver_compile(el.children[1]) ;
+  var name = receiver_compile(el.children[2]) ;
   return 'Explosurf.notes.clear_variable(' + name + ', true);' ;
 }
 
+pgm_elements['cmd-var-global-delete-var'] = command_delete_global ;
+
 function command_delete_all_global(el) {
   return 'Explosurf.notes.clear_variable(".*", true);' ;
 }
 
+pgm_elements['cmd-var-global-delete-all'] = command_delete_all_global ;
+
 /*}}}*/
 
 /* {{{ Branching ============================================================ */
@@ -432,6 +466,8 @@ function block_if(el) {
   return 'if(' + test + '){' + block + '}' ;
 }
 
+pgm_elements['cmd-block-if'] = block_if ;
+
 function block_if_else(el) {
   var test = receiver_compile(el.children[0].children[0]) ;
   var blockif = block_compile(el.children[1]) ;
@@ -439,12 +475,16 @@ function block_if_else(el) {
   return 'if(' + test + '){' + blockif + '} else {' + blockelse + '}' ;
 }
 
+pgm_elements['cmd-block-if-else'] = block_if_else ;
+
 function block_while(el) {
   var test = receiver_compile(el.children[0].children[0]) ;
   var block = block_compile(el.children[1]) ;
   return 'while(' + test + '){' + block + '}' ;
 }
 
+pgm_elements['cmd-block-while'] = block_while ;
+
 /*}}}*/
 
 /* {{{ Boolean expressions ================================================== */
@@ -455,45 +495,61 @@ function command_equals(el) {
   return '(' + lhs + ' == ' + rhs + ')' ;
 }
 
+pgm_elements['cmd-test-equal'] = command_equals ;
+
 function command_gt(el) {
   var lhs = receiver_compile(el.children[0]) ;
   var rhs = receiver_compile(el.children[1]) ;
   return '(' + lhs + ' > ' + rhs + ')' ;
 }
 
+pgm_elements['cmd-test-gt'] = command_gt ;
+
 function command_ge(el) {
   var lhs = receiver_compile(el.children[0]) ;
   var rhs = receiver_compile(el.children[1]) ;
   return '(' + lhs + ' >= ' + rhs + ')' ;
 }
 
+pgm_elements['cmd-test-ge'] = command_ge ;
+
 function command_not(el) {
   var test = receiver_compile(el.children[0]) ;
   return '(! ' + test + ')' ;
 }
 
+pgm_elements['cmd-test-not'] = command_not ;
+
 function command_or(el) {
   var lhs = receiver_compile(el.children[0]) ;
   var rhs = receiver_compile(el.children[1]) ;
   return '(' + lhs + ' || ' + rhs + ')' ;
 }
 
+pgm_elements['cmd-test-or'] = command_or ;
+
 function command_and(el) {
   var lhs = receiver_compile(el.children[0]) ;
   var rhs = receiver_compile(el.children[1]) ;
   return '(' + lhs + ' && ' + rhs + ')' ;
 }
 
+pgm_elements['cmd-test-and'] = command_and ;
+
 function command_exists_local(el) {
   var name = receiver_compile(el.children[0]) ;
   return 'Explosurf.notes.check_variable(' + name + ')' ;
 }
 
+pgm_elements['cmd-test-var-exists-local'] = command_exists_local ;
+
 function command_exists_global(el) {
   var name = receiver_compile(el.children[0]) ;
   return 'Explosurf.notes.check_variable(' + name + ', true)' ;
 }
 
+pgm_elements['cmd-test-var-exists-global'] = command_exists_global ;
+
 /*}}}*/
 
 /* {{{ Arithmetics ========================================================== */
@@ -504,18 +560,32 @@ function command_add(el) {
   return '(' + lhs + ' + ' + rhs + ')' ;
 }
 
+pgm_elements['cmd-arith-plus'] = command_add ;
+
+function command_sub(el) {
+  var lhs = receiver_compile(el.children[0]) ;
+  var rhs = receiver_compile(el.children[1]) ;
+  return '(' + lhs + ' - ' + rhs + ')' ;
+}
+
+pgm_elements['cmd-arith-minus'] = command_sub ;
+
 function command_mult(el) {
   var lhs = receiver_compile(el.children[0]) ;
   var rhs = receiver_compile(el.children[1]) ;
   return '(' + lhs + ' * ' + rhs + ')' ;
 }
 
+pgm_elements['cmd-arith-mult'] = command_mult ;
+
 function command_div(el) {
   var lhs = receiver_compile(el.children[0]) ;
   var rhs = receiver_compile(el.children[1]) ;
   return '(' + lhs + ' / ' + rhs + ')' ;
 }
 
+pgm_elements['cmd-arith-div'] = command_div ;
+
 /*}}}*/
 
 /* {{{ Strings ============================================================== */
@@ -526,10 +596,19 @@ function command_concat(el) {
   return lhs + ' + ' + rhs ;
 }
 
+pgm_elements['cmd-str-concat'] = command_concat ;
+
 /*}}}*/
 
 /* {{{ Compilation ========================================================== */
 
+Pgm.run = function() {
+  var el = document.getElementById("pgm-main") ;
+  var program = block_compile(el) ;
+  console.log(program) ;
+  eval(program) ;
+}
+
 /*}}}*/
 
 }) //end of namespace
diff --git a/js/pgm_construction.js b/js/pgm_construction.js
index c3089ed..6be04f2 100644
--- a/js/pgm_construction.js
+++ b/js/pgm_construction.js
@@ -1,4 +1,42 @@
-/********************** Desktop interface **********************/
+(function(factory) {
+  //namespacing
+  if(!window["Explosurf"]) {
+    window["Explosurf"] = {} ;
+  }
+  if(!window["Explosurf"]["pgm"]) {
+    window["Explosurf"]["pgm"] = {} ;
+  }
+  factory(window["Explosurf"]["pgm"]) ;
+})(function(Pgm) { //namespace Explosurf.pgm
+
+/* {{{ General tools ======================================================== */
+
+/* {{{ Class management */
+
+function addClass(el,c) {
+  var re = new RegExp("(?:^|\\s)" + c + "(?!\\S)") ;
+  if(!el.className.match(re)) { 
+    el.className += ' ' + c ; 
+  }
+}
+
+function removeClass(el,c) {
+  var re = new RegExp("(?:^|\\s)" + c + "(?!\\S)") ;
+  el.className = el.className.replace( re , '' ) ;
+}
+
+/*}}}*/
+
+function topOffset(el) {
+  return el.getBoundingClientRect().top 
+    + window.pageYOffset 
+    - el.ownerDocument.documentElement.clientTop ;
+}
+
+/*}}}*/
+
+
+/* {{{ Desktop interface ==================================================== */
 
 /* On desktop browser the program construction is handled using drag and drop.
  * */
@@ -60,7 +98,7 @@ function enable_input(el) {
   //remove the disabled attribute from the html element
   el.removeAttribute("disabled") ;
   //fix because inputs in draggables are hardly focusable
-  Sortable.utils.on(el, "mousedown", function(evt) { evt.target.focus() ;}) ;
+  el.addEventListener("mousedown", function(evt) { evt.target.focus() ;}) ;
 }
 
 /* a receiver is inline in a command. It is generally a string for variable
@@ -208,6 +246,36 @@ function deactivate_copy_mode() {
   [].forEach.call(pgm_receivers, deactivate_cloning) ;
 }
 
+function toggle_copy() {
+  var copy_switch = document.getElementById("desktop-ui-copy") ;
+  if(copy_switch.className.match(/active/)) {
+    removeClass(copy_switch, "active") ;
+    deactivate_copy_mode() ;
+  } else {
+    addClass(copy_switch, "active") ;
+    activate_copy_mode() ;
+  }
+}
+
+document.getElementById("desktop-ui-copy").addEventListener(
+  'click',
+  function(evt) {
+    toggle_copy() ;
+  }
+) ;
+
+function copy_detect(evt){
+  if(document.getElementsByClassName("sortable-ghost").length == 0) {
+    var evtobj=window.event? event : evt
+    if(evtobj.key === "Control") {
+      toggle_copy() ;
+    }
+  }
+}
+
+document.addEventListener("keydown", copy_detect) ;
+document.addEventListener("keyup", copy_detect) ;
+
 function activate_sortables_callback(evt) {
   var el = evt.item ;
   activate_sortables(el) ;
@@ -309,7 +377,9 @@ function desktop_deactivate() {
   desktop_deactivate_library() ;
 }
 
-/********************** Mobile interface **********************/
+/*}}}*/
+
+/* {{{ Mobile interface ===================================================== */
 
 /* On mobile devices, drag and drop is difficult, so the program construction is
  * handled via clicks, a global context and various states
@@ -363,10 +433,10 @@ function mobile_pgm_click(evt) {
   pgm_context.active_input = undefined ;
   //check tool and redirect accordingly
   var state = phone_tools_get() ;
-  if(state === 'tool-cut') return pgm_cut(evt) ;
-  if(state === 'tool-add') return pgm_add(evt) ;
-  if(state === 'tool-copy') return pgm_copy(evt) ;
-  if(state === 'tool-paste') return pgm_paste(evt) ;
+  if(state === 'phone-tool-cut') return pgm_cut(evt) ;
+  if(state === 'phone-tool-add') return pgm_add(evt) ;
+  if(state === 'phone-tool-copy') return pgm_copy(evt) ;
+  if(state === 'phone-tool-paste') return pgm_paste(evt) ;
 }
 
 /* addition : mark the element as target, open and filter the library */
@@ -449,7 +519,7 @@ function pgm_paste(evt) {
     //insert it in the container
     before_elt.parentElement.insertBefore(clone_elt, before_elt) ;
     //configure it to receive clicks
-    Sortable.utils.on(clone_elt, "click", mobile_pgm_click) ;
+    clone_elt.addEventListener("click", mobile_pgm_click) ;
     mobile_activate_blocks(clone_elt) ;
     //switch to add
     phone_tools_set("tool-add") ;
@@ -480,6 +550,13 @@ function mobile_context_reset() {
   close_library() ;
 }
 
+document.getElementById('btn-close-library').addEventListener(
+  'click', 
+  function(evt) {
+    mobile_context_reset() ;
+  }
+) ;
+
 /* Insert the chosen element and activate its events */
 function insert_chosen(evt) {
   //check whether an addition is ongoing
@@ -491,7 +568,7 @@ function insert_chosen(evt) {
     //insert it
     pgm_context.container.insertBefore(clone_elt, pgm_context.element) ;
     //activate it
-    Sortable.utils.on(clone_elt, "click", mobile_pgm_click) ;
+    clone_elt.addEventListener("click", mobile_pgm_click) ;
     mobile_activate_blocks(clone_elt) ;
     //reset the context (remove addition styling)
     mobile_context_reset() ;
@@ -505,12 +582,12 @@ function mobile_activate_library() {
   //the commands are clickable for addition
   var library_cmds = library.getElementsByClassName("pgm-command") ;
   for(var i = 0; i < library_cmds.length; ++i) {
-    Sortable.utils.on(library_cmds[i], "click", insert_chosen) ;
+    library_cmds[i].addEventListener("click", insert_chosen) ;
   }
   //the blocks are clickable for addition
   var library_blocks = library.getElementsByClassName("pgm-block") ;
   for(var i = 0; i < library_blocks.length; ++i) {
-    Sortable.utils.on(library_blocks[i], "click", insert_chosen) ;
+    library_blocks[i].addEventListener("click", insert_chosen) ;
   }
 }
 
@@ -520,12 +597,12 @@ function mobile_deactivate_library() {
   //deactivate the commands
   var library_cmds = library.getElementsByClassName("pgm-command") ;
   for(var i = 0; i < library_cmds.length; ++i) {
-    Sortable.utils.off(library_cmds[i], "click", insert_chosen) ;
+    library_cmds[i].removeEventListener("click", insert_chosen) ;
   }
   //deactivate the blocks
   var library_blocks = library.getElementsByClassName("pgm-block") ;
   for(var i = 0; i < library_blocks.length; ++i) {
-    Sortable.utils.off(library_blocks[i], "click", insert_chosen) ;
+    library_blocks[i].removeEventListener("click", insert_chosen) ;
   }
 }
 
@@ -550,26 +627,26 @@ function mobile_activate_blocks(el) {
   //list pgm-blocks and activate them
   var pgm_blocks = el.getElementsByClassName("pgm-block") ;
   for(var i = 0; i < pgm_blocks.length; ++i) {
-    Sortable.utils.on(pgm_blocks[i], "click", mobile_pgm_click) ;
+    pgm_blocks[i].addEventListener("click", mobile_pgm_click) ;
   }
   //list pgm-commands and activate them
   var pgm_commands = el.getElementsByClassName('pgm-command') ;
   for(var i = 0; i < pgm_commands.length; ++i) {
     //commands inside receivers are not to be activated
     if(pgm_commands[i].parentElement.className.match(/pgm-recv-void/)) {
-      Sortable.utils.on(pgm_commands[i], "click", mobile_pgm_click) ;
+      pgm_commands[i].addEventListener("click", mobile_pgm_click) ;
     }
   }
   //list the inputs in the element (normally only one) and activate them
   var pgm_inputs = el.getElementsByTagName('input') ;
   for(var i = 0; i < pgm_inputs.length; ++i) {
     pgm_inputs[i].removeAttribute("disabled") ;
-    Sortable.utils.on(pgm_inputs[i], "click", input_click) ;
+    pgm_inputs[i].addEventListener("click", input_click) ;
   }
   //list the placeholders in the element (normally only one) and activate them
   var pgm_placeholders = el.getElementsByClassName('placeholder') ;
   for(var i = 0; i < pgm_placeholders.length; ++i) {
-    Sortable.utils.on(pgm_placeholders[i], "click", mobile_pgm_click) ;
+    pgm_placeholders[i].addEventListener("click", mobile_pgm_click) ;
   }
 }
 
@@ -577,26 +654,141 @@ function mobile_deactivate_blocks(el) {
   var pgm_blocks = el.getElementsByClassName("pgm-block") ;
   //list pgm-blocks and deactivate them
   for(var i = 0; i < pgm_blocks.length; ++i) {
-    Sortable.utils.off(pgm_blocks[i], "click", mobile_pgm_click) ;
+    pgm_blocks[i].removeEventListener("click", mobile_pgm_click) ;
   }
   //list pgm-commands and deactivate them
   var pgm_commands = el.getElementsByClassName('pgm-command') ;
   for(var i = 0; i < pgm_commands.length; ++i) {
     //commands inside receivers are not to be deactivated
     if(pgm_commands[i].parentElement.className.match(/pgm-recv-void/)) {
-      Sortable.utils.off(pgm_commands[i], "click", mobile_pgm_click) ;
+      pgm_commands[i].removeEventListener("click", mobile_pgm_click) ;
     }
   }
   //list the inputs in the element (normally only one) and activate them
   var pgm_inputs = el.getElementsByTagName('input') ;
   for(var i = 0; i < pgm_inputs.length; ++i) {
-    Sortable.utils.off(pgm_inputs[i], "click", input_click) ;
+    pgm_inputs[i].removeEventListener("click", input_click) ;
   }
   //list the placeholders in the element (normally only one) and activate them
   var pgm_placeholders = el.getElementsByClassName('placeholder') ;
   for(var i = 0; i < pgm_placeholders.length; ++i) {
-    Sortable.utils.off(pgm_placeholders[i], "click", mobile_pgm_click) ;
+    pgm_placeholders[i].removeEventListener("click", mobile_pgm_click) ;
+  }
+}
+
+function show_mobile_ui() {
+  var phone_toolbar = document.getElementById("phone-toolbar") ;
+  removeClass(phone_toolbar, "hidden") ;
+  var library_close = document.getElementById("btn-close-library") ;
+  removeClass(library_close, "hidden") ;
+  var block_adders_collection = document.getElementsByClassName('block-add') ;
+  //necessary, since it seems like appendChild messes with HTMLCollection
+  var block_adders = [].slice.call(block_adders_collection) ;
+  for(var i = 0; i < block_adders.length; ++i) {
+    var el = block_adders[i] ;
+    var el_parent = el.parentElement ;
+    removeClass(el, "hidden") ;
+    //replace adder at the end of the list
+    el_parent.appendChild(el) ;
+  } ;
+}
+
+function hide_mobile_ui() {
+  var phone_toolbar = document.getElementById("phone-toolbar") ;
+  addClass(phone_toolbar, "hidden") ;
+  var library_close = document.getElementById("btn-close-library") ;
+  addClass(library_close, "hidden") ;
+  var block_adders = document.getElementsByClassName('block-add') ;
+  [].forEach.call(block_adders, function(el) {
+    addClass(el, "hidden") ;
+  }) ;
+}
+
+function toggle_mobile() {
+  var mobile_switch = document.getElementById("desktop-ui-phone") ;
+  if(mobile_switch.className.match(/active/)) {
+    removeClass(mobile_switch, "active") ;
+    update_pgm_ui() ;
+  } else {
+    addClass(mobile_switch, "active") ;
+    update_pgm_ui() ;
+  }
+}
+
+document.getElementById("desktop-ui-phone").addEventListener(
+  'click',
+  function(evt) {
+    toggle_mobile() ;
+  }
+) ;
+
+function is_mobile() {
+  var mobile_switch = document.getElementById("desktop-ui-phone") ;
+  if(mobile_switch.className.match(/active/)) {
+    return true ;
   }
+  var test_el = document.getElementById("mobile-tester") ;
+  return getComputedStyle(test_el ,null).display !== "none" ;
+}
+
+function phone_tools_set(id) {
+  var phone_toolbar = document.getElementById("phone-toolbar") ;
+  var btns = phone_toolbar.getElementsByTagName("button") ;
+  for(var i = 0; i < btns.length; ++i) {
+    if(btns[i].id == id) {
+      addClass(btns[i], "active") ;
+    } else {
+      removeClass(btns[i], "active") ;
+    }
+  }
+}
+
+document.getElementById('phone-tool-add').addEventListener(
+  'click',
+  function(evt) {
+    phone_tools_set('phone-tool-add') ;
+  }
+) ;
+
+document.getElementById('phone-tool-cut').addEventListener(
+  'click',
+  function(evt) {
+    phone_tools_set('phone-tool-cut') ;
+  }
+) ;
+
+document.getElementById('phone-tool-copy').addEventListener(
+  'click',
+  function(evt) {
+    phone_tools_set('phone-tool-copy') ;
+  }
+) ;
+
+document.getElementById('phone-tool-paste').addEventListener(
+  'click',
+  function(evt) {
+    phone_tools_set('phone-tool-paste') ;
+  }
+) ;
+
+function phone_tools_get() {
+  var phone_toolbar = document.getElementById("phone-toolbar") ;
+  var btns = phone_toolbar.getElementsByTagName("button") ;
+  for(var i = 0; i < btns.length; ++i) {
+    if(btns[i].className.match(/active/)) {
+      return btns[i].id ;
+    }
+  }
+}
+
+function open_library() {
+  var elem = document.getElementById("program") ;
+  addClass(elem, "active") ;
+}
+
+function close_library() {
+  var elem = document.getElementById("program") ;
+  removeClass(elem, "active") ;
 }
 
 function mobile_activate_program() {
@@ -622,7 +814,9 @@ function mobile_deactivate() {
   hide_mobile_ui() ;
 }
 
-/************************* Activation *************************/
+/*}}}*/
+
+/* {{{ Activation =========================================================== */
 
 function update_pgm_ui() {
   //check the display type : mobile or desktop
@@ -644,3 +838,7 @@ document.addEventListener("DOMContentLoaded", function(event) {
 window.addEventListener("resize", function(event) {
   update_pgm_ui() ;
 });
+
+/*}}}*/
+
+});
diff --git a/sortable_test.html b/sortable_test.html
index 6be9d0a..16c2f5b 100644
--- a/sortable_test.html
+++ b/sortable_test.html
@@ -10,6 +10,7 @@
     <script type="text/javascript" src="js/ui.js"></script>
   </head>
   <body>
+  <!--{{{ programming interface-->
     <div class="container" id="root-container">
       <!--{{{ navigation-->
       <nav class="navbar navbar-default">
@@ -42,9 +43,10 @@
 
       <div class="container-fluid" id="pgm-container">
         <div class="row row-offcanvas row-offcanvas-left" id="program">
-          <!---{{{ commands-->
+          <!--{{{ commands-->
           <div class="col-xs-12 col-sm-4 sidebar-offcanvas" id="library">
             <div class="panel panel-default">
+              <!--{{{ tabs-->
               <div class="panel-heading tabbed-heading">
                 <ul class="nav nav-tabs">
                   <li class="active">
@@ -71,7 +73,9 @@
                   href="javascript:mobile_context_reset();"
                 ></a>
               </div>
+              <!--}}}-->
               <div class="tab-content panel-collapse no-top-border-lists">
+                <!--{{{ movement-->
                 <ul id="mv_cmds" class="list-group tab-pane fade library-group in active">
                   <li class="list-group-item pgm-command pgm-type-direction cmd-dir-up">
                     <span class="glyphicon glyphicon-circle-arrow-up"></span>
@@ -134,6 +138,8 @@
                     </div>
                   </li>
                 </ul>
+                <!--}}}-->
+                <!--{{{ vaiables-->
                 <ul id="var_cmds" class="list-group tab-pane fade library-group">
                   <li class="list-group-item pgm-command pgm-type-void cmd-var-local-set">
                     <span class="glyphicon glyphicon-map-marker"></span>
@@ -199,6 +205,8 @@
                     tout
                   </li>
                 </ul>
+                <!--}}}-->
+                <!--{{{ control-->
                 <ul id="ctrl_cmds" class="list-group tab-pane fade library-group">
                   <li class="list-group-item panel panel-default pgm-block pgm-type-void cmd-block-if">
                     <div class="panel-heading">
@@ -248,6 +256,8 @@
                     </ul>
                   </li>
                 </ul>
+                <!--}}}-->
+                <!--{{{ tests-->
                 <ul id="test_cmds" class="list-group tab-pane fade library-group">
                   <li class="list-group-item pgm-command pgm-type-bool cmd-test-equal">
                     <div class="pgm-recv pgm-recv-str">
@@ -267,7 +277,7 @@
                       <input size=8 placeholder="valeur" disabled></input> 
                     </div>
                   </li>
-                  <li class="list-group-item pgm-command pgm-type-bool cmd-test-gte">
+                  <li class="list-group-item pgm-command pgm-type-bool cmd-test-ge">
                     <div class="pgm-recv pgm-recv-int">
                       <input size=8 placeholder="valeur" disabled></input> 
                     </div>
@@ -315,6 +325,8 @@
                     existe
                   </li>
                 </ul>
+                <!--}}}-->
+                <!--{{{ arithmetics-->
                 <ul id="arth_cmds" class="list-group tab-pane fade library-group">
                   <li class="list-group-item pgm-command pgm-type-int cmd-arith-plus">
                     (
@@ -361,6 +373,8 @@
                     )
                   </li>
                 </ul>
+                <!--}}}-->
+                <!--{{{ strings-->
                 <ul id="txt_cmds" class="list-group tab-pane fade library-group">
                   <li class="list-group-item pgm-command pgm-type-str cmd-str-concat">
                     <span class="glyphicon glyphicon-paperclip"></span>
@@ -372,11 +386,12 @@
                     </div>
                   </li>
                 </ul>
+                <!--}}}-->
               </div>
             </div>
           </div>
           <!---}}}-->
-          <!---{{{ program-->
+          <!--{{{ program-->
           <div class="col-xs-12 col-sm-8">
             <div class="panel panel-default pgm">
               <div class="panel-heading">
@@ -401,11 +416,11 @@
               </ul>
             </div>
           </div>
-          <!---}}}-->
+          <!--}}}-->
         </div>
       </div>
     </div>
-    <!---{{{ mobile toolbar-->
+    <!--{{{ mobile toolbar-->
     <div class="btn-toolbar hidden" role="toolbar" id="phone-toolbar">
       <div class="btn-group" role="group">
         <button class="btn btn-default active" autofocus type="button" id="tool-add"
@@ -430,7 +445,8 @@
         </button>
       </div>
     </div>
-    <!---}}}-->
+    <!--}}}-->
+    <!--}}}-->
     <script type="text/javascript" src="js/bootstrap-native.js"></script>
     <script type="text/javascript" src="js/pgm_construction.js"></script>
     <script type="text/javascript" src="js/pgm_compiler.js"></script>
-- 
GitLab