From 39acbca360e5fe211aac7801ee3512ade5b4ba02 Mon Sep 17 00:00:00 2001
From: Vincent Nivoliers <vincent.nivoliers@univ-lyon1.fr>
Date: Fri, 28 Oct 2016 16:32:07 +0200
Subject: [PATCH] missing image, saving and loading draw-area

---
 Images/bonhomme.png    | Bin 0 -> 5868 bytes
 css/style.css          |  68 +++++++++++++++++++++++++++++----
 explorer.php           |   6 ++-
 js/draw.js             |  85 +++++++++++++++++++++++++++++++++--------
 js/pgm_construction.js |  12 ++++--
 5 files changed, 144 insertions(+), 27 deletions(-)
 create mode 100644 Images/bonhomme.png

diff --git a/Images/bonhomme.png b/Images/bonhomme.png
new file mode 100644
index 0000000000000000000000000000000000000000..ac7efbb02404be874c02f27a2e647c54fdeb187e
GIT binary patch
literal 5868
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
Cd^xxP

literal 0
HcmV?d00001

diff --git a/css/style.css b/css/style.css
index b4c4d84..ed52376 100644
--- a/css/style.css
+++ b/css/style.css
@@ -214,12 +214,30 @@ body {
 #tile_left_container,
 #tile_right_container,
 #tile_bottom_container {
-  -webkit-box-shadow: 0px 0px 10px #000;
-  box-shadow: 0px 0px 10px #000;
+  -webkit-box-shadow: 0px 0px 3px #555;
+  box-shadow: 0px 0px 3px #555;
   background-color: #000 ;
   width : 100% ;
   height : 100% ;
   z-index: 0 ;
+  box-sizing : content-box ;
+  border : 1px solid #555 ;
+}
+
+#tile_top_container {
+  border-bottom : 0 ;
+}
+
+#tile_left_container {
+  border-right : 0 ;
+}
+
+#tile_bottom_container {
+  border-top : 0 ;
+}
+
+#tile_right_container {
+  border-left : 0 ;
 }
 
 #tile_center_container {
@@ -263,7 +281,7 @@ body {
   margin : auto ;
   width: 25% ;
   height: 25% ;
-  box-shadow: 0px 0px 10px #000;
+  box-shadow: 0px 0px 3px #000;
   z-index: 2 ;
   display : inline-block ;
   vertical-align : middle ;
@@ -285,7 +303,7 @@ body {
   border-radius: 50% ;
   width: 100% ;
   padding-bottom : 100% ;
-  box-shadow: 0px 0px 10px #000;
+  box-shadow: 0px 0px 3px #000;
   background-size : contain ;
   vertical-align : middle ;
 }
@@ -460,26 +478,54 @@ body {
   border-bottom : 0 ;
 }
 
-.nav-tabs a {
+.nav-tabs a, .navbar a {
   outline : 0 ;
 }
 
+#tab_mv,
+#tab_var,
+#tab_draw,
+#tab_ctrl,
+#tab_test,
+#tab_arth,
+#tab_str
+{
+  padding-left : 7px ;
+  padding-right : 7px ;
+}
+
+@media(min-width:340px){
+  #tab_mv,
+  #tab_var,
+  #tab_draw,
+  #tab_ctrl,
+  #tab_test,
+  #tab_arth,
+  #tab_str
+  {
+    padding-left : 9px ;
+    padding-right : 9px ;
+  }
+}
+
 @media(min-width:768px){
   #tab_mv,
   #tab_var,
+  #tab_draw,
   #tab_ctrl,
   #tab_test,
   #tab_arth,
   #tab_str
   {
-    padding-left : 10px ;
-    padding-right : 10px ;
+    padding-left : 9px ;
+    padding-right : 9px ;
   }
 }
 
 @media(min-width:992px){
   #tab_mv,
   #tab_var,
+  #tab_draw,
   #tab_ctrl,
   #tab_test,
   #tab_arth,
@@ -493,6 +539,7 @@ body {
 @media(min-width:1200px){
   #tab_mv,
   #tab_var,
+  #tab_draw,
   #tab_ctrl,
   #tab_test,
   #tab_arth,
@@ -503,6 +550,13 @@ body {
   }
 }
 
+.panel {
+  margin-bottom : 15px ;
+}
+
+.navbar {
+  margin-bottom : 15px ;
+}
 
 .no-top-border-lists > .list-group > .list-group-item:first-child {
   border-top : 0 ;
diff --git a/explorer.php b/explorer.php
index 298db62..39ce3b2 100644
--- a/explorer.php
+++ b/explorer.php
@@ -349,7 +349,7 @@
         <!--}}}-->
         <div class="row" id="map">
         <!--{{{ map -->
-          <div class="col-sm-8 col-md-9">
+          <div class="col-sm-12 col-md-9">
             <div class="panel panel-default">
               <ul class="Map">
                 <li>
@@ -446,7 +446,7 @@
           </div>
         <!--}}}-->
         <!--{{{ notes -->
-          <div class="col-sm-4 col-md-3">
+          <div class="col-sm-6 col-md-3">
             <div class="panel panel-default" id="local-notes-panel">
               <div class="panel-heading clearfix">
                 <h3 class="panel-title pull-left">Notes locales</h3>
@@ -462,6 +462,8 @@
                 <textarea class="note" id="local_notes"></textarea>
               </div>
             </div>
+          </div>
+          <div class="col-sm-6 col-md-3">
             <div class="panel panel-default" id="local-notes-panel">
               <div class="panel-heading clearfix">
                 <h3 class="panel-title pull-left">Notes globales</h3>
diff --git a/js/draw.js b/js/draw.js
index 014d8e0..0fe1309 100644
--- a/js/draw.js
+++ b/js/draw.js
@@ -9,10 +9,18 @@
   factory(window["Explosurf"]["draw"]) ;
 })(function(Draw) { //namespace Explosurf.draw
 
+/* local storage prefix */
+var storage_prefix = 'Explosurf:' 
+    + document.getElementById('planet-name').innerHTML.toLowerCase().replace(/\s+/mg, '')
+    + ':draw'
+  ;
+
 var area = document.getElementById("draw-area") ;
 var ctx = area.getContext("2d") ;
 var center_img = document.getElementById("tile_center") ;
 var cursor = document.createElement('img') ;
+cursor.loading = true ;
+cursor.onload = function() {cursor.loading = false ;} ;
 cursor.src = window.location.href.split('/').slice(0, -2).join('/') + '/Images/bonhomme.png' ;
 
 var pad = {
@@ -29,9 +37,53 @@ var pad = {
   },
 }
 
+function local_save() {
+  var data = JSON.stringify(
+      pad, 
+      function(key, value) {
+        if(key === 'tiles') {
+          var paths = {} ;
+          for(var entry in value) {
+            var fname = value[entry].src.split('/').pop() ;
+            paths[entry] = fname ;
+          }
+          return paths ;
+        }
+        return value ;
+      }) ;
+  localStorage.setItem(storage_prefix, data) ;
+}
+
+function loading_image(path) {
+  var img = new Image() ;
+  img.loading = true ;
+  img.onload = function() {img.loading = false ;} ;
+  img.src = path ;
+  return img ;
+}
+
+function local_load() {
+  var data = JSON.parse(
+      localStorage.getItem(storage_prefix),
+      function(key, value) {
+        if(key === 'tiles') {
+          var imgs = {} ;
+          for(var entry in value) {
+            var path = window.location.href + value[entry] ;
+            imgs[entry] = loading_image(path) ;
+          }
+          return imgs ;
+        }
+        return value ;
+      }) ;
+  if(data) {
+    pad = data ;
+  }
+}
+
 function recompute_minmax() {
   var initialized = false ;
-  for(key in pad.tiles) {
+  for(var key in pad.tiles) {
     var pen = JSON.parse(key) ;
     if(! initialized) {
       pad.xmin = pen.x ;
@@ -48,16 +100,19 @@ function recompute_minmax() {
   }
 }
 
-function draw_when_loaded(img, x, y, sx, sy) {
-  if(img.loading) {
-    setTimeout(function() {draw_when_loaded(img, x, y, sx, sy) ;}, 100) ;
+function draw_when_loaded(img, x, y, sx, sy, other) {
+  if(img.loading || (other && other.loading)) {
+    if(other) {
+      setTimeout(function() {draw_when_loaded(img, x, y, sx, sy, other) ;}, 100) ;
+    } else {
+      setTimeout(function() {draw_when_loaded(img, x, y, sx, sy, other) ;}, 50) ;
+    }
   } else {
     ctx.drawImage(img, x, y, sx, sy) ;
   }
 }
 
 function redraw() {
-  console.log('redraw') ;
   ctx.clearRect(0,0,area.width, area.height) ;
 
   var xmin = pad.pen.x < pad.xmin ? pad.pen.x : pad.xmin ;
@@ -77,26 +132,24 @@ function redraw() {
   var ox = Math.floor(area.width / 2 - (xmin + wx / 2)*s)  ;
   var oy = Math.floor(area.height / 2 - (ymin + wy / 2)*s)  ;
 
-  for(key in pad.tiles) {
+  for(var key in pad.tiles) {
     var img = pad.tiles[key] ;
     var pen = JSON.parse(key) ;
     draw_when_loaded(img, ox + pen.x * s, oy + pen.y * s, s, s) ;
   }
   
   var cs = s / 3 ;
-  ctx.drawImage(cursor, ox + pad.pen.x * s + cs, oy + pad.pen.y * s + cs, cs, cs) ;
+  var cursor_tile = pad.tiles[JSON.stringify(pad.pen)] ;
+  draw_when_loaded(cursor, ox + pad.pen.x * s + cs, oy + pad.pen.y * s + cs, cs, cs, cursor_tile) ;
+
+  local_save() ;
 }
 
 Draw.redraw = redraw ;
 
 function stamp() {
   var key = JSON.stringify(pad.pen) ;
-  var src = center_img.src.split('/').pop() ;
-  var img = new Image() ;
-  img.loading = true ;
-  img.onload = function() {img.loading = false ;} ;
-  img.src = center_img.src ;
-  pad.tiles[key] = img ;
+  pad.tiles[key] = loading_image(center_img.src) ;
 
   pad.xmax = pad.xmax < pad.pen.x ? pad.pen.x : pad.xmax ;
   pad.xmin = pad.xmin > pad.pen.x ? pad.pen.x : pad.xmin ;
@@ -170,7 +223,9 @@ document.getElementById('draw-stamp').addEventListener(
     function() {stamp() ; redraw() ;}
     ) ;
 
-
-redraw() ;
+document.addEventListener("DOMContentLoaded", function(event) {
+  local_load() ;
+  redraw() ;
+}) ;
 
 })//end of namespace Explosurf.draw
diff --git a/js/pgm_construction.js b/js/pgm_construction.js
index 8b6607d..625dc87 100644
--- a/js/pgm_construction.js
+++ b/js/pgm_construction.js
@@ -1047,10 +1047,16 @@ function phone_tools_update() {
 }
 
 function phone_tools_fixed_switch() {
-  if(pgm.getBoundingClientRect().top < 10) {
-    addClass(phone_toolbar.children[0], 'fixed-bottom') ;
+  if(phone_toolbar.children[0]) {
+    if(pgm.getBoundingClientRect().top < 10) {
+      addClass(phone_toolbar.children[0], 'fixed-bottom') ;
+    } else {
+      removeClass(phone_toolbar.children[0], 'fixed-bottom') ;
+    }
   } else {
-    removeClass(phone_toolbar.children[0], 'fixed-bottom') ;
+    //defer, because of collapse animation
+    //errors only in browser web dev mode
+    setTimeout(phone_tools_fixed_switch, 100) ;
   }
 }
 
-- 
GitLab