Skip to content
Snippets Groups Projects
Commit 2522fde8 authored by Vincent Nivoliers's avatar Vincent Nivoliers
Browse files

update a_propos and help, added pgm logging

parent 4191a1f0
No related branches found
No related tags found
No related merge requests found
......@@ -41,14 +41,19 @@
<h2>Cadre</h2>
<p class=text-justify>
Cette page a été créée par Vincent Nivoliers (l'auteur de ces mots),
doctorant en informatique au LORIA (Nancy) à l'époque. Elle a été
utilisée dans le cadre d'un atelier <a
Cette page a été créée par Vincent Nivoliers,
doctorant en informatique au <a href="http://www.loria.fr">LORIA</a>
(Nancy) à l'époque. Elle a été utilisée dans le cadre d'un atelier <a
href="http://www.mathenjeans.fr">MAth.en.JEANS</a> avec des élèves de la
sixième à la quatrième du <a
href="http://www.ac-nancy-metz.fr/pres-etab/collchepfervillers/">
Collège George Chepfer</a> encadrés par Louisette Hiriart et Christelle
Kunc pendant l'année scolaire 2011-2012. Le but de ces ateliers consiste
Kunc pendant l'année scolaire 2011-2012. Elle a ensuite été mise à jour
depuis le <a href="http://liris.cnrs.fr">LIRIS</a> et <a
href="http://www.univ-lyon1.fr">l'université de Lyon</a> en 2016 et dotée
d'outils de programmation pour un second atelier au
<a href="http://www.lamartinierediderot.fr/">Lycée Lamartinière Diderot
</a> à Lyon encadré par Éric Koubi. Le but de ces ateliers consiste
à faire découvrir les mathématiques (et l'informatique) différemment, en
mettant les élèves en situation de recherche. Le sujet que j'ai proposé
aux élèves est fourni sur la page d'accueil. Les élèves et leurs
......@@ -56,7 +61,7 @@
href=http://www.mathenjeans.fr/content/article-explosurf-collège-chepfer-villers-lès-nancy
>sur le site de l'association</a>. La liste des élèves impliqués dans le
projet est fournie dans l'article. Je tiens à les remercier, ainsi que
leurs enseignantes, pour m'avoir invité dans leur classe, et pour leur
leurs enseignant.e.s, pour m'avoir invité dans leur classe, et pour leur
motivation sans faille tout au long de l'année.
</p>
......@@ -75,7 +80,7 @@
<li>une première case ;</li>
<li>quel bord de la première case ;</li>
<li>une seconde case ;</li>
<li>quel bords de la seconde case ;</li>
<li>quel bord de la seconde case ;</li>
<li>orientation de la connexion.</li>
</ul>
L'orientation de la connexion indique en quelque sorte si la boussole
......@@ -111,7 +116,7 @@
utiliser pour la description de la planète correspondante. Ce fichier
est nommé «&nbsp;explorer.php&nbsp;» dans l'<a
href=explosurf_ressources.tar.gz>archive</a> fournie. Dans le dossier
de la planète, un fichier «&nbsp;extra.html&nbsp;» peut être ajouté pour
de la planète, un fichier «&nbsp;extra.php&nbsp;» peut être ajouté pour
rajouter une information supplémentaire en dessous du bloc de navigation
de la planète. C'est par ce biais que la mission sur la planète Dédale a
été ajoutée.
......@@ -119,21 +124,55 @@
<p class=text-justify>
Pour ne pas avoir à gérer de base de données, de comptes utilisateur, et
pour pouvoir laisser sans risque le site ouvert à tous, le parcours de
la planète et les notes sont entièrement gérées côté client via du
javascript. Le code réalisant ce parcours est regroupé dans le fichier
«&nbsp;explorer.js&nbsp;». Ce choix de tout déléguer côté client a des
désavantages, en particulier celui de ne stocker les notes que via le
navigateur, il est donc presque impossible de transférer ses notes d'une
machine à l'autre et, selon la politique de vie privée du navigateur,
les notes peuvent être perdues lorsque le site est fermé. Ce choix
signifie également que le fichier XML décrivant la planète est lisible
par l'utilisateur et qu'il peut y accéder directement plutôt que de
parcourir la planète «&nbsp;à pieds&nbsp;». Il est également possible de
sauter à la case voulue en exécutant du code javascript supplémentaire.
Ces deux derniers défauts n'en sont cependant pas réellement à mon sens,
car je serais ravi de voir les enfants acquérir les connaissances
nécessaires à leur exploitation.
pour pouvoir laisser sans risque le site ouvert à tous, les données
d'utilisation (notes, programme) sont entièrement gérées côté client via
du javascript et le stockage local. Il est également possible de
sauvegardes ses données dans un fichier pour les transférer d'un poste à
un autre. Ces choix signifient également que le fichier XML décrivant la
planète est lisible par l'utilisateur et qu'il peut y accéder
directement plutôt que de parcourir la planète «&nbsp;à pieds&nbsp;». Il
est également possible de sauter à la case voulue en exécutant du code
javascript supplémentaire. Ces deux derniers défauts n'en sont
cependant pas réellement à mon sens, car je serais ravi de voir les
enfants acquérir les connaissances nécessaires à leur exploitation. Le
code réalisé est séparé en quatre fichiers :
<ul>
<li>
<code>explorer.js</code>
pour la gestion des planètes et la navigation
</li>
<li>
<code>notes.js</code>
pour la gestion des notes et des variables du programme
</li>
<li>
<code>pgm_construction.js</code>
pour l'interface de programmation
</li>
<li>
<code>pgm_compile.js</code>
pour l'interprétation des programmes et leur exécution
</li>
</ul>
</p>
<p class=text-justify>
La conception du site a bénéficié d'outils ouverts pour la mise en page
et la gestion de certains aspects compliqués :
<ul>
<li>
<a href="http://getbootstrap.com">bootstrap</a>
pour la mise en page
</li>
<li>
<a href="http://thednp.github.io/bootstrap.native">bootstrap-native</a>
également pour la mise en page
</li>
<li>
<a href="http://rubaxa.github.io/Sortable">sortable</a>
pour la gestion du glisser / déposer dans le programme
</li>
</ul>
</p>
<h3>Description XML des planètes</h3>
......
......@@ -250,6 +250,17 @@
coller&nbsp;<span class="glyphicon glyphicon-paste"></span>.
</p>
<h4>Sauvegarde</h4>
<p>
Les boutons
sauvegarde&nbsp;<span class="glyphicon glyphicon-floppy-save"></span>
et
chargement&nbsp;<span class="glyphicon glyphicon-floppy-open"></span>
du panneau programme vous permettent de sauver vos programmes sous
différents noms et de les charger. Les programmes sauvegardés sont
disponibles sur toutes les planètes.
</p>
<h4>Bibliothèque</h4>
<p>
......@@ -275,10 +286,63 @@
globales. Vous pouvez écrire&nbsp;&larr;, lire&nbsp;<span class="
glyphicon glyphicon-search"></span> ou supprimer&nbsp;<span class="
glyphicon glyphicon-trash"></span> des variables. Une variable
apparaîtra sous la forme <code>[ nom = valeur ]</code> dans les notes.
apparaîtra sous la forme <code>[ nom = valeur ]</code> dans les
notes. L'action de lire une variable peut être placée quasiment
partout, si la variable contient le bon type de données. Si une
variable contient une direction ou une couleur, la lire permet
de réaliser le déplacement. Si elle contient un nombre ou un
test, vous pouvez lire le contenu d'une variable dans un
emplacement réclamant un entier ou un test.
</li>
<li>
<span class="glyphicon glyphicon-random"></span>
La catégorie <strong>contrôle</strong> vous permet de modifier
le comportement de votre programme en fonction de tests. Vous
pouvez également trouver des <em>boucles</em> qui vous
permettent de répéter plusieurs fois une partie des
instructions.
</li>
<li>
<span class="glyphicon glyphicon-ok"></span>
La catégorie <strong>tests</strong> vous permet de réaliser des
tests : vérifier si deux valeurs sont identiques, les comparer,
vérifier l'existence de variables, ou le fait qu'une case est au
bord de la planète. Ces tests peuvent être fournis aux blocs de
la catégorie contrôle, ou enregistrés dans des variables.
</li>
<li>
<span class="glyphicon glyphicon-plus"></span>
La catégorie <strong>arithmétique</strong> permet de réaliser
des opérations sur des nombres entiers : addition, soustraction,
multiplication et division. Attention, la division est entière :
elle vous donne le quotient de la division euclidienne.
</li>
<li>
<span class="glyphicon glyphicon-font"></span>
La catégorie <strong>texte</strong> permet de manipuler du texte.
Le trombone&nbsp;<span class="glyphicon glyphicon-paperclip"></span>
vous permet d'accoler deux mots en un seul. Vous pouvez en
particulier vous en servir pour créer des noms de variables du
type <code>voisin_droite</code> en accolant la chaîne
<code>voisin_</code> et la valeur d'une variable contenant une
direction.
Le haut-parleur&nbsp;<span class="glyphicon glyphicon-bullhorn"></span>
permet au programme de vous afficher des messages d'information,
utiles pour étudier le comportement de votre programme.
</li>
</ul>
</p>
<h3>Sauvegarde de toutes les données</h3>
<p>
Si vous utilisez toujours le même navigateur sur le même appareil
pour accéder à Explosurf, vous retrouverez vos données. Vous pouvez
également sauvegarder et recharger l'ensemble de vos données (les
programmes et les notes en cours sur toutes les planètes ainsi que
les programmes sauvegardés) en utilisant les boutons correspondants
sur la barre de menu tout en haut.
</p>
</div>
</div>
......@@ -431,14 +495,24 @@
</div>
</div>
</div>
<div class="row hidden" id="log-panel">
<div class="col-xs-12">
<div class="alert alert-info" role="alert">
<button type="button" class="close" id="log-close">
<span aria-hidden="true">&times;</span>
</button>
<div id="log-msg"></div>
</div>
</div>
</div>
<div class="row hidden" id="error-panel">
<div class="col-xs-12">
<div class="alert alert-danger">
<div class="alert alert-danger alert-dismissible" role='alert'>
<span class="glyphicon glyphicon-exclamation-sign"></span>
<span id="error-msg"></span>
<button type="button" class="close" id="error-close">
<span aria-hidden="true">&times;</span>
</button>
<span id="error-msg"></span>
</div>
</div>
</div>
......@@ -810,6 +884,12 @@
<li class="field"><input size=8 placeholder="fin" disabled></input> </li>
</ul>
</li>
<li class="list-group-item pgm-command pgm-type-void cmd-str-log">
<span class="glyphicon glyphicon-bullhorn"></span>
<ul class="pgm-recv pgm-recv-msg">
<li class="field"><input size=20 placeholder="message" disabled></input> </li>
</ul>
</li>
</ul>
<!--}}}-->
</div>
......
/*******************************************************************************
* This notice must be untouched at all times.
*
* This javascript library contains helper routines to assist with event
* handling consinstently among browsers
*
* EventHelpers.js v.1.3 available at http://www.useragentman.com/
*
* released under the MIT License:
* http://www.opensource.org/licenses/mit-license.php
*
*******************************************************************************/
var EventHelpers = new function(){
var me = this;
var safariTimer;
var isSafari = /WebKit/i.test(navigator.userAgent);
var globalEvent;
me.init = function () {
if (me.hasPageLoadHappened(arguments)) {
return;
}
if (document.createEventObject){
// dispatch for IE
globalEvent = document.createEventObject();
} else if (document.createEvent) {
globalEvent = document.createEvent("HTMLEvents");
}
me.docIsLoaded = true;
}
/**
* Adds an event to the document. Examples of usage:
* me.addEvent(window, "load", myFunction);
* me.addEvent(docunent, "keydown", keyPressedFunc);
* me.addEvent(document, "keyup", keyPressFunc);
*
* @author Scott Andrew - http://www.scottandrew.com/weblog/articles/cbs-events
* @author John Resig - http://ejohn.org/projects/flexible-javascript-events/
* @param {Object} obj - a javascript object.
* @param {String} evType - an event to attach to the object.
* @param {Function} fn - the function that is attached to the event.
*/
me.addEvent = function(obj, evType, fn){
if (obj.addEventListener) {
obj.addEventListener(evType, fn, false);
} else if (obj.attachEvent) {
obj['e' + evType + fn] = fn;
obj[evType + fn] = function(){
obj["e" + evType + fn](self.event);
}
obj.attachEvent("on" + evType, obj[evType + fn]);
}
}
/**
* Removes an event that is attached to a javascript object.
*
* @author Scott Andrew - http://www.scottandrew.com/weblog/articles/cbs-events
* @author John Resig - http://ejohn.org/projects/flexible-javascript-events/
* @param {Object} obj - a javascript object.
* @param {String} evType - an event attached to the object.
* @param {Function} fn - the function that is called when the event fires.
*/
me.removeEvent = function(obj, evType, fn){
if (obj.removeEventListener) {
obj.removeEventListener(evType, fn, false);
} else if (obj.detachEvent) {
try {
obj.detachEvent("on" + evType, obj[evType + fn]);
obj[evType + fn] = null;
obj["e" + evType + fn] = null;
}
catch (ex) {
// do nothing;
}
}
}
function removeEventAttribute(obj, beginName){
var attributes = obj.attributes;
for (var i = 0; i < attributes.length; i++) {
var attribute = attributes[i]
var name = attribute.name
if (name.indexOf(beginName) == 0) {
//obj.removeAttributeNode(attribute);
attribute.specified = false;
}
}
}
me.addScrollWheelEvent = function(obj, fn){
if (obj.addEventListener) {
/** DOMMouseScroll is for mozilla. */
obj.addEventListener('DOMMouseScroll', fn, true);
}
/** IE/Opera. */
if (obj.attachEvent) {
obj.attachEvent("onmousewheel", fn);
}
}
me.removeScrollWheelEvent = function(obj, fn){
if (obj.removeEventListener) {
/** DOMMouseScroll is for mozilla. */
obj.removeEventListener('DOMMouseScroll', fn, true);
}
/** IE/Opera. */
if (obj.detachEvent) {
obj.detatchEvent("onmousewheel", fn);
}
}
me.getMouseCoords = function (e) {
if (!e) {
return;
}
// IE
if (e.clientX != null) {
return {
x: e.clientX,
y: e.clientY
}
}
// NS4
else if (e.pageX != null) {
return {
x: e.pageX,
y: e.pageY
}
// W3C
} else if (window.event != null && window.event.clientX != null
&& document.body != null &&
document.body.scrollLeft != null) {
return {
x: window.event.clientX + document.body.scrollLeft,
y: window.event.clientY + document.body.scrollTop
}
} else {
return null;
}
}
/**
* Given a mouse event, get the mouse pointer's x-coordinate.
*
* @param {Object} e - a DOM Event object.
* @return {int} - the mouse pointer's x-coordinate.
*/
me.getMouseX = function(e){
if (!e) {
return;
}
// NS4
if (e.pageX != null) {
return e.pageX;
// IE
} else if (window.event != null && window.event.clientX != null &&
document.body != null &&
document.body.scrollLeft != null)
return window.event.clientX + document.body.scrollLeft;
// W3C
else if (e.clientX != null)
return e.clientX;
else
return null;
}
/**
* Given a mouse event, get the mouse pointer's y-coordinate.
* @param {Object} e - a DOM Event Object.
* @return {int} - the mouse pointer's y-coordinate.
*/
me.getMouseY = function(e){
// NS4
if (e.pageY != null)
return e.pageY;
// IE
else if (window.event != null && window.event.clientY != null &&
document.body != null &&
document.body.scrollTop != null)
return window.event.clientY + document.body.scrollTop;
// W3C
else if (e.clientY != null) {
return e.clientY;
}
}
/**
* Given a mouse scroll wheel event, get the "delta" of how fast it moved.
* @param {Object} e - a DOM Event Object.
* @return {int} - the mouse wheel's delta. It is greater than 0, the
* scroll wheel was spun upwards; if less than 0, downwards.
*/
me.getScrollWheelDelta = function(e){
var delta = 0;
if (!e) /* For IE. */
e = window.event;
if (e.wheelDelta) { /* IE/Opera. */
delta = e.wheelDelta / 120;
/** In Opera 9, delta differs in sign as compared to IE.
*/
if (window.opera) {
delta = -delta;
}
} else if (e.detail) { /** Mozilla case. */
/** In Mozilla, sign of delta is different than in IE.
* Also, delta is multiple of 3.
*/
delta = -e.detail / 3;
}
return delta
}
/**
* Sets a mouse move event of a document.
*
* @deprecated - use only if compatibility with IE4 and NS4 is necessary. Otherwise, just
* use EventHelpers.addEvent(window, 'mousemove', func) instead. Cannot be used to add
* multiple mouse move event handlers.
*
* @param {Function} func - the function that you want a mouse event to fire.
*/
me.addMouseEvent = function(func){
if (document.captureEvents) {
document.captureEvents(Event.MOUSEMOVE);
}
document.onmousemove = func;
window.onmousemove = func;
window.onmouseover = func;
}
/**
* Find the HTML object that fired an Event.
*
* @param {Object} e - an HTML object
* @return {Object} - the HTML object that fired the event.
*/
me.getEventTarget = function(e){
// first, IE method for mouse events(also supported by Safari and Opera)
if (e.toElement) {
return e.toElement;
// W3C
} else if (e.currentTarget) {
return e.currentTarget;
// MS way
} else if (e.srcElement) {
return e.srcElement;
} else {
return null;
}
}
/**
* Given an event fired by the keyboard, find the key associated with that event.
*
* @param {Object} e - an event object.
* @return {String} - the ASCII character code representing the key associated with the event.
*/
me.getKey = function(e){
if (e.keyCode) {
return e.keyCode;
} else if (e.event && e.event.keyCode) {
return window.event.keyCode;
} else if (e.which) {
return e.which;
}
}
/**
* Will execute a function when the page's DOM has fully loaded (and before all attached images, iframes,
* etc., are).
*
* Usage:
*
* EventHelpers.addPageLoadEvent('init');
*
* where the function init() has this code at the beginning:
*
* function init() {
*
* if (EventHelpers.hasPageLoadHappened(arguments)) return;
*
* // rest of code
* ....
* }
*
* @author This code is based off of code from http://dean.edwards.name/weblog/2005/09/busted/ by Dean
* Edwards, with a modification by me.
*
* @param {String} funcName - a string containing the function to be called.
*/
me.addPageLoadEvent = function(funcName){
var func = eval(funcName);
// for Internet Explorer (using conditional comments)
/*@cc_on @*/
/*@if (@_win32)
pageLoadEventArray.push(func);
return;
/*@end @*/
if (isSafari) { // sniff
pageLoadEventArray.push(func);
if (!safariTimer) {
safariTimer = setInterval(function(){
if (/loaded|complete/.test(document.readyState)) {
clearInterval(safariTimer);
/*
* call the onload handler
* func();
*/
me.runPageLoadEvents();
return;
}
set = true;
}, 10);
}
/* for Mozilla */
} else if (document.addEventListener) {
var x = document.addEventListener("DOMContentLoaded", func, null);
/* Others */
} else {
me.addEvent(window, 'load', func);
}
}
var pageLoadEventArray = new Array();
me.runPageLoadEvents = function(e){
if (isSafari || e.srcElement.readyState == "complete") {
for (var i = 0; i < pageLoadEventArray.length; i++) {
pageLoadEventArray[i]();
}
}
}
/**
* Determines if either addPageLoadEvent('funcName') or addEvent(window, 'load', funcName)
* has been executed.
*
* @see addPageLoadEvent
* @param {Function} funcArgs - the arguments of the containing. function
*/
me.hasPageLoadHappened = function(funcArgs){
// If the function already been called, return true;
if (funcArgs.callee.done)
return true;
// flag this function so we don't do the same thing twice
funcArgs.callee.done = true;
}
/**
* Used in an event method/function to indicate that the default behaviour of the event
* should *not* happen.
*
* @param {Object} e - an event object.
* @return {Boolean} - always false
*/
me.preventDefault = function(e){
if (e.preventDefault) {
e.preventDefault();
}
try {
e.returnValue = false;
}
catch (ex) {
// do nothing
}
}
me.cancelBubble = function(e){
if (e.stopPropagation) {
e.stopPropagation();
}
try {
e.cancelBubble = true;
}
catch (ex) {
// do nothing
}
}
/*
* Fires an event manually.
* @author Scott Andrew - http://www.scottandrew.com/weblog/articles/cbs-events
* @author John Resig - http://ejohn.org/projects/flexible-javascript-events/ * @param {Object} obj - a javascript object.
* @param {String} evType - an event attached to the object.
* @param {Function} fn - the function that is called when the event fires.
*
*/
me.fireEvent = function (element,event, options){
if(!element) {
return;
}
if (document.createEventObject){
/*
var stack = DebugHelpers.getStackTrace();
var s = stack.toString();
jslog.debug(s);
if (s.indexOf('fireEvent') >= 0) {
return;
}
*/
return element.fireEvent('on' + event, globalEvent)
//jslog.debug('ss');
}
//else{
// // dispatch for firefox + others
// globalEvent.initEvent(event, true, true); // event type,bubbling,cancelable
// return !element.dispatchEvent(globalEvent);
//}
}
/* EventHelpers.init () */
function init(){
// Conditional comment alert: Do not remove comments. Leave intact.
// The detection if the page is secure or not is important. If
// this logic is removed, Internet Explorer will give security
// alerts.
/*@cc_on @*/
/*@if (@_win32)
document.write('<script id="__ie_onload" defer src="' +
((location.protocol == 'https:') ? '//0' : 'javascript:void(0)') + '"><\/script>');
var script = document.getElementById("__ie_onload");
me.addEvent(script, 'readystatechange', me.runPageLoadEvents);
/*@end @*/
}
init();
}
EventHelpers.addPageLoadEvent('EventHelpers.init');
if (!window.localStorage) {
window.localStorage = {
getItem: function (sKey) {
if (!sKey || !this.hasOwnProperty(sKey)) { return null; }
return unescape(document.cookie.replace(new RegExp("(?:^|.*;\\s*)" + escape(sKey).replace(/[\-\.\+\*]/g, "\\$&") + "\\s*\\=\\s*((?:[^;](?!;))*[^;]?).*"), "$1"));
},
key: function (nKeyId) { return unescape(document.cookie.replace(/\s*\=(?:.(?!;))*$/, "").split(/\s*\=(?:[^;](?!;))*[^;]?;\s*/)[nKeyId]); },
setItem: function (sKey, sValue) {
if(!sKey) { return; }
document.cookie = escape(sKey) + "=" + escape(sValue) + "; path=/";
this.length = document.cookie.match(/\=/g).length;
},
length: 0,
removeItem: function (sKey) {
if (!sKey || !this.hasOwnProperty(sKey)) { return; }
var sExpDate = new Date();
sExpDate.setDate(sExpDate.getDate() - 1);
document.cookie = escape(sKey) + "=; expires=" + sExpDate.toGMTString() + "; path=/";
this.length--;
},
hasOwnProperty: function (sKey) { return (new RegExp("(?:^|;\\s*)" + escape(sKey).replace(/[\-\.\+\*]/g, "\\$&") + "\\s*\\=")).test(document.cookie); }
};
window.localStorage.length = (document.cookie.match(/\=/g) || window.localStorage).length;
}
/*
* @licstart
* This program is meant to write a log file in the element with "log" id
*
* Copyright (C) 2011 Vincent Nivoliers
*
* This program is free software: you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later
* version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see http://www.gnu.org/licenses/gpl.html.
* @licend
*/
var Logger = new function () {
var me = this ;
var muted = false ;
var buffer = ""
me.clear_log = function() {
var logger = document.getElementById("log") ;
logger.value = "" ;
}
me.mute = function() {
muted = true ;
}
me.unmute = function() {
muted = false ;
}
me.flush = function() {
var logger = document.getElementById("log") ;
if(logger) {
logger.value += buffer ;
buffer = "" ;
}
}
me.log = function(txt) {
if(!muted) {
buffer += txt ;
buffer += '\n'
}
}
}
......@@ -70,6 +70,18 @@ function get_str(data, error_target) {
}
}
function get_msg(data, error_target) {
var str = typeof data === 'string' ? data : '' + data ;
if(str.match(/^[\w\u00C0-\u02B8\- ]+$/)) {
return str ;
} else {
return pgm_selector_error(
error_target,
"seules les lettre, les chiffres, l'espace et _ sont autorisés : " + str
);
}
}
function receiver_compile(el) {
//type of the receiver
var type = el.className.match(/pgm-recv-(\S+)/)[1] ;
......@@ -95,7 +107,11 @@ function receiver_compile(el) {
var rec_compile = "" ;
if(target.className.match(/field/)) {
var err_target = selector_path_to_root(target.children[0]) ;
rec_compile = '"' + get_str(target.children[0].value, err_target) + '"' ;
if(type === 'str') {
rec_compile = '"' + get_str(target.children[0].value, err_target) + '"' ;
} else {
rec_compile = '"' + get_msg(target.children[0].value, err_target) + '"' ;
}
}
else {
rec_compile = cmd_compile(target) ;
......@@ -106,7 +122,7 @@ function receiver_compile(el) {
return 'get_integer(' + rec_compile + ',' + err_target + ')' ;
} else if (type === 'bool') {
return 'get_boolean(' + rec_compile + ',' + err_target + ')' ;
} else if (type === 'str') {
} else if (type === 'str' || type === 'msg') {
return rec_compile ;
} else if (type === 'direction') {
return 'check_direction(' + rec_compile + ',' + err_target + ')'
......@@ -163,6 +179,23 @@ document.getElementById('error-close').addEventListener(
pgm_clear_error
) ;
var log_elt = document.getElementById('log-msg') ;
var log_panel = document.getElementById('log-panel') ;
function pgm_log(msg) {
log_elt.innerHTML = log_elt.innerHTML + msg + '<br/>' ;
Pgm.removeClass(log_panel, 'hidden') ;
}
function pgm_clear_log() {
log_elt.innerHTML = '' ;
Pgm.addClass(log_panel, 'hidden') ;
}
document.getElementById('log-close').addEventListener(
'click',
pgm_clear_log
) ;
/*}}}*/
/* {{{ Color and direction ================================================== */
......@@ -657,6 +690,13 @@ function command_concat(el) {
pgm_elements['cmd-str-concat'] = command_concat ;
function command_log(el) {
var msg = receiver_compile(el.children[1]) ;
return 'pgm_log(' + msg + ')' ;
}
pgm_elements['cmd-str-log'] = command_log ;
/*}}}*/
/* {{{ Compilation ========================================================== */
......@@ -673,6 +713,7 @@ function hide_progress() {
function run() {
pgm_clear_error() ;
pgm_clear_log() ;
var el = document.getElementById("pgm-main") ;
show_progress() ;
//timeout to allow the browser to update and show the bar
......
......@@ -467,19 +467,19 @@ function deactivate_cloning(el) {
function activate_copy_mode() {
//list blocks and activate them
var pgm_blocks = main.getElementsByClassName('pgm-recv-void') ;
var pgm_blocks = pgm.getElementsByClassName('pgm-recv-void') ;
[].forEach.call(pgm_blocks, activate_cloning) ;
//list receivers and activate them
var pgm_receivers = main.getElementsByClassName('pgm-recv') ;
var pgm_receivers = pgm.getElementsByClassName('pgm-recv') ;
[].forEach.call(pgm_receivers, activate_cloning) ;
}
function deactivate_copy_mode() {
//list blocks and activate them
var pgm_blocks = main.getElementsByClassName('pgm-recv-void') ;
var pgm_blocks = pgm.getElementsByClassName('pgm-recv-void') ;
[].forEach.call(pgm_blocks, deactivate_cloning) ;
//list receivers and activate them
var pgm_receivers = main.getElementsByClassName('pgm-recv') ;
var pgm_receivers = pgm.getElementsByClassName('pgm-recv') ;
[].forEach.call(pgm_receivers, deactivate_cloning) ;
}
......
/*
* @licstart
* This program provides some utilities to hide and show div elements
*
* Copyright (C) 2011 Vincent Nivoliers
*
* This program is free software: you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later
* version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see http://www.gnu.org/licenses/gpl.html.
* @licend
*/
/* {{{ tools*/
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 ;
}
/*}}}*/
/* {{{ copy mode button */
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() ;
}
}
/*}}}*/
/* {{{ mobile ui */
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() ;
}
}
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") ;
}
}
}
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 ;
}
}
}
/*}}}*/
/* {{{ library */
function open_library() {
var elem = document.getElementById("program") ;
addClass(elem, "active") ;
/*
var t = topOffset(document.getElementById("library-open-btn")) + "px" ;
console.log(t) ;
document.getElementById("library").style.top = t ;
*/
}
function close_library() {
var elem = document.getElementById("program") ;
removeClass(elem, "active") ;
}
/*}}}*/
/* {{{ keyboard */
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) ;
/*}}}*/
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment