JavascriptProva

martedì 28 febbraio 2012

Ecco il sottomenu che sparisce o ricompare passando il mouse sul menu principale...

Ecco una variante all'esercizio per i menu.
Al passaggio del mouse sull'oggetto principale, appare il sottomenu, mentre quando il mouse viene ritirato il sottomenu scompare.
Esso è creato di default, nella funzione Crea chiamata dalla funzione main, ed è la sua visibilità a variare a seconda che il mouse sia o no sull'oggetto principale.

Il problema è che, se questi oggetti dovranno servire da menu, il mouseout non deve valere nel momento in cui il mouse si sposta fuori dell'oggetto principale per cadere sull'oggetto secondario.
La vedrò poi.

Ecco lo script:
<html>
<head>
<style>
#mainMenu{
 position:absolute;
 width:200px;
 height:300px;
 top:100px;
 left:100px;
 background-color:green;
 border:10px solid brown;
}
.subMenu{
 position:absolute;
 width:100px;
 height:100px;
 top:50px;
 left:20px;
 background-color:cyan;
 border:5px solid yellow;
}
</style>
<script>
function Posizione(obj){
 var curleft=0;
 var curtop=0;
 do {
  curleft+=obj.offsetLeft;
  curtop+=obj.offsetTop;
 } while(obj=obj.offsetParent);
 return {X:curleft, Y:curtop};
}

function main(){
 mainMenu=document.getElementById("mainMenu");
 subMenu=document.getElementById("subMenu");
 Crea();
 mainMenu.onmouseover=function(){Mostra(nuovo)};
 mainMenu.onmouseout=function(){Nascondi(nuovo)};
 
}

function Crea(){
 nuovo=document.createElement("div");
 nuovo.style.left=Posizione(mainMenu).X+mainMenu.offsetWidth;
 nuovo.style.top=Posizione(mainMenu).Y+mainMenu.offsetHeight/3;
 nuovo.className="subMenu";
 nuovo.style.visibility="hidden";
 document.body.appendChild(nuovo);
}
function Mostra(obj){
 obj.style.visibility="visible";
}
function Nascondi(obj){
 obj.style.visibility="hidden";
}
 

window.onload=main;

</script>
</head>
<body>
<div id="mainMenu">
 
</div>

</body>
</html>
Funziona!

Creazione di un embrione di sottomenu con uno script mio

Ufff... Finalmente ci sono riuscito! Come esercizio preparatorio alla creazione di menu, prendendo alcuni spunti da quel terribile script che sto cercando di capire, ho iniziato a esercitarmi nella creazione di nuovi DIV affiancati a DIV già esistenti, nella posizione voluta rispetto a quella di questi ultimi.
Ecco lo script mio:
<html>
<head>
<style>
#mainMenu{
 position:absolute;
 width:200px;
 height:300px;
 top:100px;
 left:100px;
 background-color:green;
 border:10px solid brown;
}
.subMenu{
 position:absolute;
 width:100px;
 height:100px;
 top:50px;
 left:20px;
 background-color:cyan;
 border:5px solid yellow;
}
</style>
<script>
function Posizione(obj){
 var curleft=0;
 var curtop=0;
 do {
  curleft+=obj.offsetLeft;
  curtop+=obj.offsetTop;
 } while(obj=obj.offsetParent);
 return {X:curleft, Y:curtop};
}

function main(){
 mainMenu=document.getElementById("mainMenu");
 subMenu=document.getElementById("subMenu");
 mainMenu.onclick=Crea;
}

function Crea(){
 nuovo=document.createElement("div");
 nuovo.style.left=Posizione(mainMenu).X+mainMenu.offsetWidth;
 nuovo.style.top=Posizione(mainMenu).Y+mainMenu.offsetHeight/3;
 nuovo.className="subMenu";
 document.body.appendChild(nuovo);
}


window.onload=main;

</script>
</head>
<body>
<div id="mainMenu">
 
</div>

</body>
</html>
Notevole la funzione Posizione(obj), che ricava la posizione di un oggetto anche qualora questo sia contenuto in un altro oggetto, sommandone la posizione relativa all'oggetto "genitore" con la posizione dell'oggetto "genitore" stesso e così via via anche qualora l'oggetto sia contenuto in una scatola cinese di altri oggetti.

In questo mio script l'oggetto nuovo viene creato (al click) affiancato al precedente, a un'altezza pari a un terzo di quella dell'oggetto precedente stesso.

Che faticaccia! Però soddisfacente!

lunedì 27 febbraio 2012

Proseguiamo lo studio del diabolico script

var lis = menuObj.getElementsByTagName('A');
 

 
 for(var no=0;no<lis.length;no++){
   

  if(!showSubOnMouseOver)
   lis[no].onmouseover = stopAutoHide;
   

  lis[no].onmouseout = initAutoHide;
    

  lis[no].onmousemove = stopAutoHide;
  
 }
Crea un insieme di tutti gli elementi A del menuObj.
Per tutti gli elementi di questo insieme, se non è vero "showSubOnMouseOver", al mouseover sull'elemento esegui stopAutoHide; al mouseout dall'elemento esegui initAutoHide; al mousemove sull'elemento esegui stopAutoHide;
Non so quali siano queste funzioni. Che faccio, me le analizzo o vado avanti?
Provo ad andare avanti...

 for(var no=0;no<mainMenuItemArray.length;no++){
    

  var sub = mainMenuItemArray[no].getElementsByTagName('UL')[0];
 

            
  if(sub){
    
   mainMenuItemArray[no].id = 'mainMenuItem' + (no+1);
   
   var div = document.createElement('DIV');
    
   div.className='dhtmlgoodies_subMenu';
    
   document.body.appendChild(div);
    
   div.appendChild(sub);
     
   if(slideDirection=='right'){
     
    div.style.left = getLeftPos(mainMenuItemArray[no]) + mainMenuItemArray[no].offsetWidth + xOffsetSubMenu + 'px';
    
   }
   else{
     
    div.style.left = getLeftPos(mainMenuItemArray[no]) + xOffsetSubMenu + 'px';
    
   }
    
   div.style.top = getTopPos(mainMenuItemArray[no]) + 'px';
    
   div.id = 'subMenuDiv' + (no+1);
    
   sub.id = 'submenuUl' + (no+1);
    
   sub.style.position = 'relative'; 

    
   if(navigator.userAgent.indexOf('Opera')>=0){
     
    submenuObjArray[no+1] = new Array();
     
    submenuObjArray[no+1]['parentDiv'] = mainMenuItemArray[no];
     
    submenuObjArray[no+1]['divObj'] = div;
     
    submenuObjArray[no+1]['ulObj'] = sub;
     
    submenuObjArray[no+1]['width'] = sub.offsetWidth;
     
    submenuObjArray[no+1]['left'] = div.style.left.replace(/[^0-9]/g,'');
    
   }
    
   sub.style.left = 1 - sub.offsetWidth + 'px'; 
    
    
   if(document.all)
    div.style.width = '1px'; 
     
    
   if(navigator.userAgent.indexOf('Opera')<0){
     
    submenuObjArray[no+1] = new Array();
     
    submenuObjArray[no+1]['parentDiv'] = mainMenuItemArray[no];
     
    submenuObjArray[no+1]['divObj'] = div;
     
    submenuObjArray[no+1]['ulObj'] = sub;
     
    submenuObjArray[no+1]['width'] = sub.offsetWidth;
     
     
     
     
    submenuObjArray[no+1]['left'] = div.style.left.replace(/[^0-9]/g,'');
     
    if(fixedSubMenuWidth)
     submenuObjArray[no+1]['width'] = fixedSubMenuWidth;
    
   } 

    
   if(!document.all)
    div.style.width = '1px';   
     
   
  }   
  
 }
Questa è colossale: la devo spezzettare un po' altrimenti mi impiccio...

Esegue qualcosa per tutti i mainMenuItem, che erano stati messi tutti nell'array mainMenuItemArray.
Vediamo cosa esegue...

var sub = mainMenuItemArray[no].getElementsByTagName('UL')[0];
chiama sub il primo elemento UL contenuto in un mainMenuItem.
Cioè questo:
 
<li><a href="#">Siti</a>

  <ul>
   
   <li><a href="#">Grafica</a></li> 
   <li><a href="#">CSS</a></li>   
   <li><a href="#">Javascript</a></li>   
   <li><a href="#">Web Design</a></li>
  
  </ul> 
</li>
Quindi se esiste questo sub...
mainMenuItemArray[no].id = 'mainMenuItem' + (no+1);
   
var div = document.createElement('DIV');
    
div.className='dhtmlgoodies_subMenu';
    
document.body.appendChild(div);
    
div.appendChild(sub);
ridenomina il corrispettivo mainMenuItem dell'Array in "mainMenuItem..." + il suo numero progressivo nell'Array; crea un nuovo elemento DIV chiamandolo div; attribuisce a questo elemento la classe "dhtmlgoodies_subMenu"; appende al documento questo div;

Mi sfugge il senso globale di tutte queste cose...
Ecco: il senso di questa è che per ogni mainMenuItem si va a vedere se contengono un sottoelenco: nel caso in cui lo contengano si ridenomina il corrispettivo mainMenuItem e si crea un DIV che viene aggiunto al documento.
Sì, questa ha effettivamente senso!
Ecco: questa analizza se ogni voce del menu principale ha o no dei sottomenu, nel qual caso prepara i sottomenu creando i DIV corrispondenti! Geniale, sì!

Continua la faticosa analisi dello script...

Quindi, a che cosa si riferisce di preciso la variabile mainMenuItem?
Vediamo un po' la struttura della lista.
var mainMenuItem = menuObj.getElementsByTagName('LI')[0];  
Ecco la lista:
<div id="dhtmlgoodies_menu">

<ul>
 
<li><a href="#">Siti</a>

  <ul>
   
<li><a href="#">Grafica</a></li>
   
<li><a href="#">CSS</a></li>   <li><a href="#">Javascript</a></li>   <li><a href="#">Web Design</a></li>
  
</ul> </li>
 
<li><a href="#">Servizi</a>
  
<ul>   <li><a href="#">Download</a></li>
   
<li><a href="#">Webtool</a></li>
   
<li><a href="#">Font.it</a></li>   <li><a href="#">Corsi</a></li>
  
</ul>
 
</li>
 
<li><a href="#">Forum</a>  <ul>
   
<li><a href="#">HTML/XHTML</a></li>
   
<li><a href="#">ASP</a></li>
  
 <li><a href="#">PHP</a></li>
  
</ul>
 
</li>
 
<li><a href="#">Contatti</a></li>

</ul>
La lista contiene un UL che contiene dei LI i quali contengono altri UL che contengono altri LI.
Il punto è: se io faccio riferimento a un insieme di elementi LI del DIV che contiene la lista, faccio riferimento a tutti i LI o solo a quelli del primo livello?
Copio la lista su un altro foglio e ci faccio delle prove...

Ecco il mio codice:
<script>
function funzione(){
 var menuObj = document.getElementById('dhtmlgoodies_menu');
 var Insieme=menuObj.getElementsByTagName("LI")
 for(n=0;n<Insieme.length;n++)
 alert(Insieme[n].innerHTML);
}
window.onload=funzione;
</script>

<body>
<div id="dhtmlgoodies_menu">

<ul>
 
<li><a href="#">Siti</a>

  <ul>
   
<li><a href="#">Grafica</a></li>
   
<li><a href="#">CSS</a></li>   <li><a href="#">Javascript</a></li>   <li><a href="#">Web Design</a></li>
  
</ul> </li>
 
<li><a href="#">Servizi</a>
  
<ul>   <li><a href="#">Download</a></li>
   
<li><a href="#">Webtool</a></li>
   
<li><a href="#">Font.it</a></li>   <li><a href="#">Corsi</a></li>
  
</ul>
 
</li>
 
<li><a href="#">Forum</a>  <ul>
   
<li><a href="#">HTML/XHTML</a></li>
   
<li><a href="#">ASP</a></li>
  
 <li><a href="#">PHP</a></li>
  
</ul>
 
</li>
 
<li><a href="#">Contatti</a></li>

</ul>
</div>
Da questo ottengo che gli elementi compresi nell'insieme sono tutti, non solo quelli del primo livello.

Tornando al codice:
var mainMenuItem = menuObj.getElementsByTagName('LI')[0];   
prende soltanto il primo degli elementi LI, e cioè quello che ha questo contenuto:
<a href="#">Siti</a>

  <ul>
   
<li><a href="#">Grafica</a></li>
   
<li><a href="#">CSS</a></li>   <li><a href="#">Javascript</a></li>   <li><a href="#">Web Design</a></li>
  
</ul> 
...e lo chiama mainMenuItem. Predispone nello stesso tempo un Array di tutti i mainMenuItem:
var mainMenuItemArray = new Array();

Con questa:
while(mainMenuItem){
 
  
  if(mainMenuItem.tagName && mainMenuItem.tagName.toLowerCase()=='li'){
    
   mainMenuItemArray[mainMenuItemArray.length] = mainMenuItem;
    
   var aTag = mainMenuItem.getElementsByTagName('A')[0];
  
 
   if(showSubOnMouseOver)
     
    aTag.onmouseover = showSub; 
    
   else
     
    aTag.onclick = showSub; 
    

  }   
  mainMenuItem = mainMenuItem.nextSibling;
  

 }
...verifica se si tratta di un LI;
Se sì, lo aggiunge all'array mainMenuItemArray;
Prende il primo degli elementi A che sono contenuti nel mainMenuItem di turno e lo chiama aTag;
A seconda dell'impostazione data dalla variabile showSubOnMouseOver, esegue la funzione showSub al passaggio del mouse su questo elemento A o al click del mouse sull'elemento;
Quindi passa al fratello del mainMenuItem. Ora il fratello di mainMenuItem può essere un elemento diverso da un LI, come un textNode, ma in questo caso la verifica non viene superata e si passa al fratello successivo. fratello successivo che non è un LI di un livello inferiore!

In sintesi: questa funzione crea un Array di tutti i mainMenuItem, prende uno per volta tutti i mainMenuItems e attribuisce all'elemento A contenuto in ognuno di essi la risposta a un evento.

domenica 26 febbraio 2012

Studio di uno script un tantino complicato

Sto analizzando uno script preso da questo sito.

Cerco di studiarmelo pezzo-pezzo scrivendo qui gli appunti.
Sono ancora lontano dal leggere gli script come se si trattasse di lingua italiana... Al momento attuale leggo più speditamente l'arabo...

La prima funzione che viene eseguita inizia così:
function initLeftMenu()
{
 var menuObj = document.getElementById('dhtmlgoodies_menu'); 
 var mainMenuItemArray = new Array();
 var mainMenuItem = menuObj.getElementsByTagName('LI')[0];      

 while(mainMenuItem){
 
  if(mainMenuItem.tagName && mainMenuItem.tagName.toLowerCase()=='li'){
    
   mainMenuItemArray[mainMenuItemArray.length] = mainMenuItem;
    
   var aTag = mainMenuItem.getElementsByTagName('A')[0];
  
 
   if(showSubOnMouseOver)
     
    aTag.onmouseover = showSub; 
    
   else
     
    aTag.onclick = showSub; 
  }   
  mainMenuItem = mainMenuItem.nextSibling;
 }
L'HTML è questo:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<title>Menu slide-out</title>
<script type="text/javascript" src="slideout.js"></script>
<link rel="stylesheet" type="text/css" href="slideout.css" />
</head><body>

<div id="dhtmlgoodies_menu">

<ul>
 
<li><a href="#">Siti</a>

  <ul>
   
<li><a href="#">Grafica</a></li>
   
<li><a href="#">CSS</a></li>   <li><a href="#">Javascript</a></li>   <li><a href="#">Web Design</a></li>
  
</ul> </li>
 
<li><a href="#">Servizi</a>
  
<ul>   <li><a href="#">Download</a></li>
   
<li><a href="#">Webtool</a></li>
   
<li><a href="#">Font.it</a></li>   <li><a href="#">Corsi</a></li>
  
</ul>
 
</li>
 
<li><a href="#">Forum</a>  <ul>
   
<li><a href="#">HTML/XHTML</a></li>
   
<li><a href="#">ASP</a></li>
  
 <li><a href="#">PHP</a></li>
  
</ul>
 
</li>
 
<li><a href="#">Contatti</a></li>

</ul>
</div>

</body>

</html>

Cerchiamo di analizzarcelo riga per riga...

function initLeftMenu()
{
 var menuObj = document.getElementById('dhtmlgoodies_menu'); 
La prima funzione ad essere eseguita è initLeftMenu.
All'interno di questa funzione, la variabile menuObj viene usata per denominare l'elemento che ha per id dhtmlgoodies_menu, ossia il seguente:
<div id="dhtmlgoodies_menu">

<ul>
 
<li><a href="#">Siti</a>

  <ul>
   
<li><a href="#">Grafica</a></li>
   
<li><a href="#">CSS</a></li>   <li><a href="#">Javascript</a></li>   <li><a href="#">Web Design</a></li>
  
</ul> </li>
 
<li><a href="#">Servizi</a>
  
<ul>   <li><a href="#">Download</a></li>
   
<li><a href="#">Webtool</a></li>
   
<li><a href="#">Font.it</a></li>   <li><a href="#">Corsi</a></li>
  
</ul>
 
</li>
 
<li><a href="#">Forum</a>  <ul>
   
<li><a href="#">HTML/XHTML</a></li>
   
<li><a href="#">ASP</a></li>
  
 <li><a href="#">PHP</a></li>
  
</ul>
 
</li>
 
<li><a href="#">Contatti</a></li>

</ul>
</div>
...che sarebbe quello che contiene tutta la lista che dovrà formare il menu e i sottomenu.
Quindi, ricordiamo: menuObj è il DIV contenente tutti i menu.

var mainMenuItemArray = new Array();
Viene usata la variabile mainMenuItemArray per creare un Array.
Il nome di questa variabile sarebbe "Array degli elementi del menu principale"... Vedremo...
Per ora teniamo presenti questi due nomi:
  • menuObj
  • che sarebbe il DIV contenente tutti i menu;
  • mainMenuItemArray
  • che sarebbe l'Array degli elementi del menu principale (credo).


var mainMenuItem = menuObj.getElementsByTagName('LI')[0]; 
Ecco un'altra variabile: mainMenuItem, ossia "elemento del menu principale", che prende dall'oggetto menuObj, ossia dal DIV contenente i menu, il primo elemento LI, cioè questo:
<li><a href="#">Siti</a>


...continua...

Eliminare da un testo qualsiasi cosa che non sia...

Vado avanti faticosamente... Ecco un'altra cosa da chiarire:
var numericId = this.parentNode.id.replace(/[^0-9]/g,'');
Che accidentaccio significa quel /[^0-9]/g?

Non so perchè di preciso, ma elimina tutto ciò che non è cifra da una stringa.
Ho appena verificato:
<script>
var string="Ciao ciccio 123 sei un 34 cretino!"
alert(string.replace(/[^0-9]/g,""));
</script>
Restituisce 12334.
Allora adesso voglio eliminare un intervallo di lettere...
<script>
var string="La vispa teresa avea fra l'erbetta a volo sorpreso gentil farfalletta"
alert(string.replace(/[^a-m]/g,""));
</script>
e ottengo: aiaeeaaeafalebeaalegeilfafallea

Interessante!

Ripasso di alcuni metodi dell'oggetto Array

Aggiungere elementi a un Array... vediamo quali sono i metodi di un oggetto Array...

push() e pop() hanno la stessa azione che hanno sullo stack gli stessi comandi in Assembly...

<script>
var Matrice=new Array();
Matrice.push("Mario","Peppe","Gianni","Antonio","Pasquale");
for(n=0;n<Matrice.length;n++)
 alert(Matrice[n]);
</script>
Giusto: il primo elemento è "Mario" e l'ultimo è "Pasquale". Il push ha aggiunto elementi in coda all'Array.
Con questa aggiunta, il metodo push() restituisce anche la lunghezza dell'Array:
<script>
var Matrice=new Array();
var lunghezza=Matrice.push("Mario","Peppe","Gianni","Antonio","Pasquale");
for(n=0;n<Matrice.length;n++)
 alert(Matrice[n]);
alert(lunghezza);
</script>

Aggiunta del metodo pop() che restituisce l'elemento eliminato.
<script>
function elenca(){
 for(n=0;n<Matrice.length;n++)
  alert(Matrice[n]);
}
var Matrice=new Array();
var lunghezza=Matrice.push("Mario","Peppe","Gianni","Antonio","Pasquale");
elenca();
alert(lunghezza);
var elemento=Matrice.pop()
elenca();
alert("Elemento eliminato "+elemento);
</script>

I metodi unshift() e shift() sono speculari a push() e pop() per la parte iniziale anzichè finale dell'Array.
<script>
function elenca(){
 alert("Elenco");
 for(n=0;n<Matrice.length;n++)
  alert(Matrice[n]);
}
var Matrice=new Array();
var lunghezza=Matrice.push("Mario","Peppe","Gianni","Antonio","Pasquale");
elenca();
alert(lunghezza);
elemento=Matrice.shift();
elenca();
alert("elemento rimosso "+elemento);
var lunghezza=Matrice.unshift("Ciccio");

elenca();
alert(lunghezza);
</script>

sabato 25 febbraio 2012

Una tecnica per assegnare una stessa funzione a più elementi.

Dunque... Prendo quattro DIV. Voglio assegnare a ognuno di essi la funzione che al mouseover determina una certa risposta...
Inizio a costruire la pagina.
<html>
<head>
<style>
.elemento {
 background-color:cyan;
 width:300px;
 height:100px;
 border:2px solid black;
 margin:10px;
}
</style>
</head>
<body>
<div class=elemento></div>
<div class=elemento></div>
<div class=elemento></div>
<div class=elemento></div>
</body>
<script>

</script>
</html>
...Ecco...
Ci sono semplicemente quattro elementi DIV celesti uno sopra l'altro.
Aggiungo il codice javascript:
<html>
<head>
<style>
.elemento {
 background-color:cyan;
 width:300px;
 height:100px;
 border:2px solid black;
 margin:10px;
}
</style>
</head>
<body>
<div class=elemento></div>
<div class=elemento></div>
<div class=elemento></div>
<div class=elemento></div>
</body>
<script>
function funzione(){
 alert("toccato");
}
function main(){
 var Elemento=document.getElementsByTagName("div")[0];
 while(Elemento){
  Elemento.onmouseover=funzione;   
  Elemento=Elemento.nextSibling;
 }
}
window.onload=main;
</script>
</html>
...e funziona benissimo!

Suppongo che quando Elemento tenterà di essere uguale al next sibling dell'ultimo elemento, che non esiste, Elemento cesserà di esistere, ponendo fine alla condizione dettata dal while!

venerdì 24 febbraio 2012

Menu popup in Javascript col pulsante destro del mouse.

...per il resto, a parte lo "zittimento" del tasto destro del mouse, la procedura è praticamente uguale a quella che ho ideato io!
Riporto l'indirizzo.

Riscrivo il codice:
<html>
<head>

</head>
<body>
<div id="menu" style="visibility:hidden;position:absolute;left:0px;top:100px">
<a href="pinco">Pinco</a><br>
<a href="pallino">Pallino</a><br>
<a href="gigio">Gigio</a>
</div>

<img src="italia.jpg">
</body>
<script>
function displayMenu(event){
 var menu=document.getElementById("menu");
 if (event.button==2){
  menu.style.left=event.clientX;
  menu.style.top=event.clientY;
  menu.style.visibility="visible";
 }
 else{
  menu.style.visibility="hidden";
 }
}
 
window.onclick=displayMenu;
window.oncontextmenu=function(){return false;}
</script>
</html>
Non proprio uguale... c'è una piccola incongruenza, la vedremo dopo... Comunque il concetto di base è identico!

Zittire il tasto destro del mouse dalla sua risposta di default

Voglio ottenere un effetto con la pressione del tasto destro del mouse.

Per prima cosa bisogna inibire il "menu contestuale", ossia quel menu che appare senza che nessuno l'abbia esplicitamente invitato alla pressione del tasto destro del mouse su una finestra di browser...

Ho trovato il modo:
<html>
<head>
<script>
window.oncontextmenu=function(){return false;}

</script>
</head>
<body>
<img src="italia.jpg">
</body>

</html>
E il bello è che non appare più alcun menu contestuale neanche se si clicca sull'immagine.
E' già un bel passo avanti!

Menu sulle immagini...

Ecco una pagina con un menu che appare cliccando le regioni Abruzzo e Marche, sul quale si possono mettere dei collegamenti ipertestuali (ad es. alle pagine di Wikipedia)
<html>
<head>

</head>
<body>
<img src="italia.jpg" usemap="#mappa">
<map name="mappa">
<area shape="poly" coords="192, 202, 196, 194, 201, 193, 206, 194, 213, 190, 202, 178, 196, 171, 191, 161, 181, 161, 178, 163, 175, 167, 173, 170, 171, 174, 172, 177, 172, 177, 174, 182, 173, 185, 170, 187, 170, 191, 176, 196, 176, 196, 183, 200, 192, 201, 197, 195" onclick="mostra(event,abruzzo)">
<area shape="poly" coords="175, 163, 182, 161, 189, 160, 186, 142, 182, 134, 180, 131, 174, 129, 159, 118, 156, 121, 153, 117, 145, 121, 140, 127, 140, 127, 149, 128, 147, 133, 154, 140, 158, 137, 160, 145, 159, 152, 163, 156, 168, 158, 168, 162, 174, 166, 179, 162, 189, 159" onclick="mostra(event,marche)">
</map>

<div id="menu" style="padding:10px;position:absolute;background:yellow;visibility:hidden" onclick="this.style.visibility='hidden'"></div>
</body>
<script>
var marche="Ancona<br>Pesaro<br>Ascoli Piceno<br>Macerata";
var abruzzo="<a href='http://it.wikipedia.org/wiki/L%27Aquila'>L'Aquila</a><br><a href='http://it.wikipedia.org/wiki/Pescara'>Pescara</a><br><a href='http://it.wikipedia.org/wiki/Chieti'>Chieti</a><br><a href='http://it.wikipedia.org/wiki/Teramo'>Teramo</a>";
function mostra(event,contenuto){
 if (event.button==0){
  document.getElementById("menu").style.left=event.clientX+10;
  document.getElementById("menu").style.top=event.clientY+10;
  document.getElementById("menu").style.visibility="visible";
  document.getElementById("menu").innerHTML=contenuto;
 }
 else{
  document.getElementById("menu").style.visibility="hidden";
 }
} 


 

</script>
</html>
Simpatico!
Ecco la pagina

giovedì 23 febbraio 2012

Un mappatore di immagini costruito da me

Ho riesumato alcune vecchie conoscenze per realizzare un mappatore di immagini, in modo da costruire delle mappe basate su immagini, molto utili a scopi didattici e autodidattici...

Ecco il codice del "mappatore":
<html><head>

</head>
<body>

<img id="immagine" src="italia.jpg" style="position: absolute; left: 100px; top: 10px; border: 2px solid black;">


<div id="legenda" style="position:absolute;left:100px;top:550px;width:1000px;height:150px;border:5px solid blue"></div>


<script>
function clicca(event){
 
 var StyleLeft=this.style.left;
 var StyleTop=this.style.top;
 document.getElementById("legenda").innerHTML+=(event.clientX-Number(StyleLeft.replace("px","")))+", "+(event.clientY-Number(StyleTop.replace("px","")))+", ";
}
document.getElementById("immagine").onclick=clicca;

</script>

</body></html>
In esso ho inserito un'immagine chiamata italia.jpg.

Ecco la pagina.
(l'immagine è presa da questo sito. Nel caso ci siano problemi di copyright la rimuoverò immediatamente, ovvio!) Dovrei superare la limitazione del dover manipolare il codice HTML della pagina per inserire l'immagine...

martedì 21 febbraio 2012

Funzione come risultato di un'altra funzione

Ecco, forse comincio a capire cosa significa quando una funzione è il risultato di un'altra funzione...
<script type="text/javascript">

function funzione(){
 var sottofunzione=function(){
  alert("Stronzo!");
 }
 
 return sottofunzione; 
}

var risultato=funzione();
risultato();

</script> 
<body>

</body>


...invece così non si ottiene niente:
<script type="text/javascript">

function funzione(){
 var sottofunzione=function(){
  alert("Stronzo!");
 }
 
 return sottofunzione; 
}

funzione();

</script> 
<body>

</body>
ecco... trattare il risultato come un'altra funzione, ecco, sì...

domenica 19 febbraio 2012

Una esclusione opinabile di intossicazione da ossido di carbonio

Questo sito fornisce questa immagine:
Curva di saturazione dell'emoglobina.

In ascisse la pO2, in ordinate la percentuale di saturazione dell'emoglobina (Hb).

Se la pO2 diminuisce, ovviamente, diminuisce anche la percentuale di saturazione dell'emoglobina (SaO2), sia pure in modo non lineare in relazione alla strana curva di saturazione (che ha il suo scopo preciso come da progetto del buon Dio).
La quantità totale di ossigeno nell'unità di volume di sangue può essere diminuita, oltre che per ridotta percentuale di saturazione dell'emoglobina, anche per ridotta concentrazione dell'emoglobina stessa...

diminuita pO2 --> diminuita SaO2 + normale concentrazione di Hb --> 
diminuita quantità di O2 nel sangue.
Ma è anche vero che:
normale pO2 --> normale SaO2 + ridotta concentrazione di Hb --> 
diminuita quantità di O2 nel sangue.
Ciò avviene nell'anemia, ovviamente, ma avviene anche in altre situazioni di ridotta concentrazione di Hb nel sangue. Una di queste condizioni è l'intossicazione da ossido di carbonio (CO), in cui una parte dell'emoglobina è resa inefficiente a legare l'ossigeno in quanto legata dal CO.
Quindi l'affermazione del collega, che non si tratta di un'intossicazione da ossido di carbonio perchè la pO2 e la SaO2 sono normali è un'assoluta caproneria.
Nell'emogasanalisi c'è una voce precisa relativa alla carbossiemoglobina.
E' quella che bisogna vedere per avere un'idea precisa della situazione.
Nel caso in questione la percentuale era del 28%, il che significa che quasi un terzo dell'emoglobina era bloccata dall'ossido di carbonio!!!
Dopo diverse ore, nell'emogasanalisi di controllo, era al 5% circa, cosa che mi rassicura: con il respiro di aria ambiente (lo scienziato non ha messo neanche l'ossigeno!) il CO si è pian piano staccato dall'Hb restituendola alla sua normale funzione: a questo punto, la SaO2 attestata sempre su valori normali è reale!!!

Il problema del setInterval con una variabile locale come parametro

Ecco ripassato, con cognizione di causa, il problema che ho avuto in passato con il setInterval.

setInterval è una funzione dell'oggetto window.
Il problema è se io la chiamo da un oggetto diverso fornendole come parametro una variabile dell'oggetto stesso:
<body>
</body>
<script>
function stampa(p){
 document.body.innerHTML+=p;
}
function funzione(){
 this.parola="Ciao, Mondo crudele! ";
 
 setInterval(function(){stampa(this.parola)},2000);
}
f=new funzione();

</script>
Ecco cosa ottengo:
undefinedundefinedundefinedundefinedundefinedundefinedundefinedundefinedundefinedundefinedundefinedundefinedundefinedundefinedundefinedundefinedundefinedundefinedundefinedundefinedundefinedundefinedundefinedundefinedundefinedundefinedundefinedundefinedundefinedundefinedundefined
Perchè?

La spiegazione mi risulta chiara ora che mi sono esercitato un po' sullo scope.
setInterval è una funzione dell'oggetto window. Ora, essendo la proprietà parola non privata, essa è perfettamente visibile dall'oggetto window, ma non viene vista come this. Nel momento in cui la funzione setInterval viene evocata, essa, essendo un metodo dell'oggetto window, riconosce come this l'oggetto window, e non l'oggetto f istanza della funzione funzione.
La soluzione è creare nell'ambito dell'oggetto f una proprietà che detenga il riferimento all'oggetto, da inserire come parametro nella funzione setInterval, in modo che l'oggetto window possa fare il corretto riferimento all'oggetto f e non all'oggetto window.
<body>
</body>
<script>
function stampa(p){
 document.body.innerHTML+=p;
}
function funzione(){
 var questo=this;
 this.parola="Ciao, Mondo crudele! ";
 
 setInterval(function(){stampa(questo.parola)},2000);
}
f=new funzione();

</script>
Il fatto che questo sia una variabile privata non fa nulla perchè essa viene comunque passata nel parametro e quindi resa visibile all'oggetto window.

Ecco:
Ciao, Mondo crudele! Ciao, Mondo crudele! Ciao, Mondo crudele! Ciao, Mondo crudele! Ciao, Mondo crudele! Ciao, Mondo crudele! Ciao, Mondo crudele! Ciao, Mondo crudele! Ciao, Mondo crudele! 
Avevo già affrontato e risolto questo problema in modo un po' empirico-capronesco, ma adesso lo comprendo molto meglio.

E' bello fare le cose con cognizione di causa!

Ancora esercizi sui contesti in Javascript...

Chiamo un metodo di un oggetto da un altro oggetto.
<script>

function funzione(){
 this.dichiara=function(){
   alert(this);
 }
}

function funzione2(){
  this.chiama=function(){
  f1.dichiara(); 
 }
}

f1=new funzione();
f2=new funzione2();
f2.chiama();
</script>
</script>

Ottengo [Object object].

Essendo il metodo della funzione 1 un metodo di un oggetto, il contesto è quello dell'oggetto, non quello della finestra.
Infatti la chiamata viene fatta anteponendo f1, che è l'identificatore dell'oggetto.

Adesso chiamo lo stesso metodo della funzione 1 da un contesto window. Ci provo.
<script>

function funzione(){
 this.dichiara=function(){
   alert(this);
 }
}

function funzione2(){
  this.chiama=function(){
  funzione();
  dichiara(); 
 }
}

f1=new funzione();
f2=new funzione2();
f2.chiama();
</script>

Ottengo [Object Window].

Prima ho dovuto "materializzare" la funzione nel contesto di window, quindi chiamare lo stesso metodo senza farlo precedere dall'identificatore.


Posso chiamare la funzione sia nell'ambito di window sia come oggetto diverso, scegliendo di volta in volta se chiamare da un contesto window o da un contesto oggetto.

Questa chiama la funzione dichiara nell'ambito di un oggetto:
<script>

function funzione(){
 this.dichiara=function(){
   alert(this);
 }
}

function funzione2(){
  this.chiama=function(){
  f1.dichiara(); 
 }
}
funzione();
f1=new funzione();
f2=new funzione2();
f2.chiama();
</script>
e ottengo [object Object]

Questa chiama la funzione dichiara nell'ambito della finestra:
<script>

function funzione(){
 this.dichiara=function(){
   alert(this);
 }
}

function funzione2(){
  this.chiama=function(){
  dichiara(); 
 }
}
funzione();
f1=new funzione();
f2=new funzione2();
f2.chiama();
</script>
e ottengo [object Window].
Spero di essermela spiegata abbastanza bene...

Esercizio sui contesti del Javascript

Eccone un altro.
Materializzo la funzione nell'ambito di window.
Quindi creo oggetti per diverse funzioni.
Dal contesto "oggetti" chiamo il metodo di ogni oggetto che mostra il contesto di esecuzione.
Quindi dal contesto window chiamo il metodo di una di queste funzioni, che mostra il contesto di esecuzione.

Chiamando dal contesto oggetto, ottengo come contesto l'oggetto, mentre chiamando dal contesto window ottengo come contesto window.
<script>
funzione();
function funzione(){
 this.azione=function(){alert(this);} 
}

function funzione2(){
 this.azione=function(){alert(this);} 
}

function funzione3(){
 this.azione=function(){alert(this);} 
}
f=new funzione();
f2=new funzione2();
f3=new funzione3();

f.azione();
f2.azione();
f3.azione();
azione();

</script>
Ottengo per tre volte [object Object], e quindi ottengo [object Window]. L'ultima volta il metodo viene chiamato dal contesto window, e non dal contesto oggetto.

Ancora sugli scope...

Ecco...
Bisognerebbe distinguere l'ambiente dal quale si chiama una funzione...

Vediamo se mi sto costruendo un punto di vista giusto...

<script>

function funzione(){
 this.azione=function(){alert("prima");} 
}

function funzione2(){
 this.azione=function(){alert("seconda");} 
}

function funzione3(){
 this.azione=function(){alert("terza");} 
}

funzione();
funzione2();
funzione3();

azione();
</script>
Ottengo "terza".

I metodi azione di ciascuna funzione sono pubblici, ossia richiamabili dall'ambiente window in cui mi trovo.
Avendo lo stesso nome, viene chiamata l'ultima ad essere stata "materializzata" dalla chiamata delle funzioni.
Se io inverto la chiamata delle funzioni:
funzione();
funzione3();
funzione2();
ottengo "seconda" invece di "terza".

Invece ora "materializzo" un ambiente diverso.
Creo un oggetto di ciascuna funzione.
Il metodo azione può così essere riferito a ognuno dei diversi ambienti.
<script>

function funzione(){
 this.azione=function(){alert("prima");} 
}

function funzione2(){
 this.azione=function(){alert("seconda");} 
}

function funzione3(){
 this.azione=function(){alert("terza");} 
}

f=new funzione();
f2=new funzione2();
f3=new funzione3();
f.azione();
f2.azione();
f3.azione();

</script>
E ottengo nell'ordine "prima", "seconda" e "terza".

Ho chiamato il metodo da un ambito ristretto, ossia dall'interno di ciascun oggetto.

Ora metto insieme la chiamata delle funzioni (da ambiente window) e la creazione di nuovi ambienti (oggetti) da ogni funzione.
<script>
funzione();
funzione3();
funzione2();
function funzione(){
 this.azione=function(){alert("prima");} 
}

function funzione2(){
 this.azione=function(){alert("seconda");} 
}

function funzione3(){
 this.azione=function(){alert("terza");} 
}

f=new funzione();
f2=new funzione2();
f3=new funzione3();
f.azione();
f2.azione();
f3.azione();
azione();
</script>
così facendo, dapprima materializzo le tre funzioni, facendo in modo che il metodo azione venga impostato sulla funzione che mette a video "seconda"; quindi creo i tre oggetti.
Chiamo quindi i tre metodi dall'ambiente di ognuno dei tre oggetti, quindi chiamo il metodo della funzione materializzata nel contesto dell'ambiente window.
Dopo aver ordinatamente agito secondo il metodo azione di ogni oggetto, viene eseguito il metodo azione dell'ultima funzione materializzata nell'ambiente window...

Non so spiegarla compiutamente a parole e forse ho una nomenclatura impropria, ma l'ho capita.

venerdì 17 febbraio 2012

Accessibilità delle funzioni (che poi è la stessa cosa)

Stesso discorso per le funzioni...

<script>
function funzione(){
 funzioneNoVar=function(){
  alert("Funzione senza Var");
 }
 var funzioneVar=function(){
  alert("Funzione con Var");
        }
 this.funzioneThis=function(){
  alert("Funzione con This");
 }
}

funzioneNoVar();
</script>



<script>
function funzione(){
 funzioneNoVar=function(){
  alert("Funzione senza Var");
 }
 var funzioneVar=function(){
  alert("Funzione con Var");
        }
 this.funzioneThis=function(){
  alert("Funzione con This");
 }
}

funzioneVar();
</script>



<script>
function funzione(){
 funzioneNoVar=function(){
  alert("Funzione senza Var");
 }
 var funzioneVar=function(){
  alert("Funzione con Var");
        }
 this.funzioneThis=function(){
  alert("Funzione con This");
 }
}

funzioneThis();
</script>




Questo è sempre perchè non è stata chiamata la funzione.
Chiamiamola...

<script>
function funzione(){
 funzioneNoVar=function(){
  alert("Funzione senza Var");
 }
 var funzioneVar=function(){
  alert("Funzione con Var");
        }
 this.funzioneThis=function(){
  alert("Funzione con This");
 }
}
funzione();
funzioneNoVar();
</script>
Funzione senza Var

<script>
function funzione(){
 funzioneNoVar=function(){
  alert("Funzione senza Var");
 }
 var funzioneVar=function(){
  alert("Funzione con Var");
        }
 this.funzioneThis=function(){
  alert("Funzione con This");
 }
}
funzione();
funzioneVar();
</script>



<script>
function funzione(){
 funzioneNoVar=function(){
  alert("Funzione senza Var");
 }
 var funzioneVar=function(){
  alert("Funzione con Var");
        }
 this.funzioneThis=function(){
  alert("Funzione con This");
 }
}
funzione();
funzioneThis();
</script>
Funzione con This


Anche qui il medesimo discorso: una funzione della funzione (sarà giusta questa denominazione?) viene chiamata dall'esterno, ossia dall'ambiente window, solo se non dichiarata con var, mentre in quest'ultimo caso sarà invisibile.

Accessibilità delle variabili

Non ho capito niente!

Non è molto facile, perlomeno per me adesso, capire bene il gioco della visibilità delle variabili, dello scope e tutto ciò che vi è connesso.

Di tutto quello che ho detto finora in proposito, gran parte, o forse tutto, non è vero.


Procediamo...

Dichiaro tre variabili nell'ambito di una funzione, quindi do il comando di mostrare l'una o l'altra:
<script>
function funzione(){
 variabileNoVar="variabile senza var";
 var variabileVar="variabile con var";
 this.variabileThis="variabile con this"
}

alert(variabileNoVar);
</script>



<script>
function funzione(){
 variabileNoVar="variabile senza var";
 var variabileVar="variabile con var";
 this.variabileThis="variabile con this"
}

alert(variabileVar);
</script>



<script>
function funzione(){
 variabileNoVar="variabile senza var";
 var variabileVar="variabile con var";
 this.variabileThis="variabile con this"
}

alert(variabileThis);
</script>




Bene. In nessun caso di questi ottengo nulla.
Il motivo per cui non ottengo nulla è che non è stata chiamata la funzione nell'ambito della quale vengono dichiarate le variabili.
Allora riscrivo il codice, chiamando la funzione:
<script>
function funzione(){
 variabileNoVar="variabile senza var";
 var variabileVar="variabile con var";
 this.variabileThis="variabile con this"
}
funzione();
alert(variabileNoVar);
</script>
variabile senza var

<script>
function funzione(){
 variabileNoVar="variabile senza var";
 var variabileVar="variabile con var";
 this.variabileThis="variabile con this"
}
funzione();
alert(variabileVar);
</script>



<script>
function funzione(){
 variabileNoVar="variabile senza var";
 var variabileVar="variabile con var";
 this.variabileThis="variabile con this"
}
funzione();
alert(variabileThis);
</script>
variabile con this


Bene.
Queste variabili non esistono finchè non è stata chiamata la funzione. E' la chiamata della funzione a crearle.
Ciononostante, la variabile locale dichiarata con var non è accessibile dall'ambiente window dal quale sto chiamando le variabili. Le altre lo sono.

Ecco un minimo di chiarezza.

martedì 14 febbraio 2012

Partiamo dalle basi sull'ereditarietà in Javascript...

Cerchiamo di fare ordine e capire bene queste maledette ereditarietà...

Cominciamo dal Javascript...

Scrivo questo:
<script>
function funzione(){
 var variabile=0;
}
document.write(funzione.variabile);
</script>
Output:
undefined



Dal di fuori non posso vedere una variabile dichiarata con var all'interno di una funzione.
Scrivo questo:
<script>
function funzione(){
 var variabile=0;
}

var miaFunzione=new funzione();

document.write(miaFunzione.variabile);
</script>
Ottengo sempre:
undefined

ho creato una nuova istanza di funzione ma anche per questa istanza non posso accedere alla variabile dichiarata con var all'interno della funzione.
Se scrivo così:
<script>
function funzione(){
 var variabile=0;
 var dichiara=function(){
  document.write(variabile);
 }
}
funzione.dichiara();
</script>


o così:
<script>
function funzione(){
 var variabile=0;
 var dichiara=function(){
  document.write(variabile);
 }
}
var miaFunzione=new funzione();

miaFunzione.dichiara();
</script>
Output:


...tentando di accedere dall'esterno a un metodo dichiarato con var all'interno della funzione o di una sua istanza, non ottengo niente, in quanto non si può accedere dall'esterno a un metodo privato di una funzione o di una sua istanza.
Queste le premesse prime.

Ora introduciamo il this.
<script>
function funzione(){
 this.variabile=0;
}
document.write(funzione.variabile);
</script>
ottengo:
undefined



Se scrivo questo:
<script>
function funzione(){
 this.variabile=0;
}
var miaFunzione=new funzione();
document.write(miaFunzione.variabile);
</script>
ottengo:
0

Il this non è dunque un modo per rendere pubblici i membri di una funzione.

Proviamo con un metodo:
<script>
function funzione(){
 this.variabile=0;
 this.dichiara=function(){
  document.write(this.variabile);
 }
}
funzione.dichiara();
</script>
Ora creo l'istanza:
<script>
function funzione(){
 this.variabile=0;
 this.dichiara=function(){
  document.write(this.variabile);
 }
}
miaFunzione=new funzione();
miaFunzione.dichiara();
</script>
E ottengo:
0


No, il this non è un modo per rendere pubblici i membri di una funzione...

domenica 12 febbraio 2012

Confronto fra costruttori in Java e Javascript

Cerco di approfondire l'analogia fra i costruttori del Javascript e le classi del Java.
Sicuramente le classi non esistono in Javascript.
Ma in Java posso creare qualcosa di molto simile ai costruttori del Javascript nell'ambito dei costruttori delle classi.
class Persona{
 public Persona(String n, String c,int e){
  String nome=n;
  String cognome=c;
  int eta=e;
  System.out.print(nome);  
 } 
}



public class Main{
 void main(){
 }
 public static void main(String[] args){
  Persona Mario=new Persona("Mario", "Rossi",45);
  
 }
}
Risultato:
C:\Users\Io\Desktop\javascript>javac Main.java

C:\Users\Io\Desktop\javascript>java Main
Mario
C:\Users\Io\Desktop\javascript>


Facciamo l'analogo in Javascript:
<script>
function Persona(n,c,e){
 var nome=n;
 var cognome=c;
 var eta=e;
 document.write(nome);
}
Mario=new Persona("Mario","Rossi",45);
</script>
Risultato:
Mario




La prima differenza è che il Javascript non è tipizzato.

La seconda differenza è che mentre in Java il costruttore deve essere obbligatoriamente inserito in una classe, in Javascript dato che le classi non esistono il costruttore è "libero".

sabato 11 febbraio 2012

Classe in Java e C++

Continuiamo a rivangare un po' di Java...

Ecco:
class Persona{
    String nome;
    String cognome;
    int altezza;     
}

public class Main {
    
    public Main() {
    }
    
    public static void main(String[] args) {
        Persona Mario=new Persona();
        Mario.nome="Mario";
        Mario.cognome="Rossi";
        Mario.altezza=177;       
    }  
}
Ho creato un'istanza della classe Persona, chiamata Mario.
Una volta creata l'istanza, manipolo le sue proprietà.

Adesso ripassiamo la sintassi C++...
Vediamo piano piano come si dichiarano le classi...
class Persona{
public:
 char* nome;
 char* cognome;
 int altezza;
};
void main(){
 Persona Mario;
 Mario.nome="Mario";
 Mario.cognome="Rossi";
 Mario.altezza=176;
 printf(Mario.nome);
 printf(Mario.cognome);
 getchar();
}
Bene.
Confronto:

In Java sembrerebbe che i membri della classe vengano ritenuti di base pubblici, mentre in Cpp verrebbero ritenuti di base privati. Infatti se io faccio questo in Java:
class Persona{
    private String nome;
    String cognome;
    int altezza;    
}

public class Main {
    
   
    public Main() {
    }
    
   
    public static void main(String[] args) {
        Persona Mario=new Persona();
        Mario.nome="Mario";
        Mario.cognome="Rossi";
        Mario.altezza=177;
        
    } 
}
ottengo questo messaggio di errore:
C:\Users\Io\JavaApplication1\src\javaapplication1\Main.java:34: nome has private access in javaapplication1.Persona


In Cpp, invece, se faccio questo:
class Persona{

 char* nome;
public:
 char* cognome;
 int altezza;
};
void main(){
 Persona Mario;
 Mario.nome="Mario";
 Mario.cognome="Rossi";
 Mario.altezza=176;
 printf(Mario.nome);
 printf(Mario.cognome);
 getchar();
}
ottengo questo:
1>c:\users\io\documents\visual studio 2010\projects\progetto\progetto\uno.cpp(12): error C2248: 'Persona::nome': impossibile accedere a private membro dichiarato nella classe 'Persona'
E questa è una delle differenze...
private, in ambedue i linguaggi, significa che il membro può essere visto solo all'interno della classe stessa.
Almeno credo...

Mi esercito a richiamare dalla memoria come si compongono le classi in Java.

Ora, come si aggiungono proprietà e metodi a una classe in Java?

Cerco di tenere sempre un occhio comparativo al Javascript, e magari anche al C++.

Alla classe Java si deve aggiungere un costruttore.
Se ricordo bene, il costruttore senza parametri è di default, e se ci sono costruttori con parametri deve essere dichiarato obbligatoriamente, se lo si vuole, il costruttore senza parametri... Queste sono regole valide con il C++, ma dovrebbero essere valide anche per il Java.

Adesso creo una classe Persona, e ne creo un'istanza con la sintassi adeguata per il Java:
class Persona{
    int nome;
    int cognome;
    int altezza;
    
     
}

public class Main {
    
    /** Creates a new instance of Main */
    public Main() {
    }
    
    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        Persona Mario=new Persona();
    }
    
}
Ecco, con questo NetBeans non mi dà alcun messaggio di errore.
Solo che ho avuto una svista: nome e cognome non sono numeri, quindi non possono essere di tipo int.
La pratica col Javascript mi ha un po' disabituato ai linguaggi fortemente tipizzati!

Riesumando reminiscenze di Java...

NetBeans.
Non mi ricordo quasi più niente di come si programma a oggetti in Java.

Questo è ciò che appare inizialmente in NetBeans:
package javaapplication1;

/**
 *
 * @author Io
 */

public class Main {
    
    /** Creates a new instance of Main */
    public Main() {
    }
    
    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        // TODO code application logic here
    }
    
}


Ora creo un'altra classe nello stesso modulo.
Se ricordo bene, non si possono avere più classi pubbliche nello stesso modulo.
Ecco:
package javaapplication1;

/**
 *
 * @author Io
 */

class Classe{
     
}
public class Main { /** Creates a new instance of Main */ public Main() { } /** * @param args the command line arguments */ public static void main(String[] args) { // TODO code application logic here } }
Ecco, NetBeans non mi segnala errore...

Viceversa, mi segnala errore in questo caso:
package javaapplication1;

/**
 *
 * @author Io
 */

public class Classe{
     
}

public class Main {
    
    /** Creates a new instance of Main */
    public Main() {
    }
    
    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        // TODO code application logic here
    }
    
}
Un errore di questo tipo:
C:\Users\Io\JavaApplication1\src\javaapplication1\Main.java:17: class Classe is public, should be declared in a file named Classe.java
...confermando il mio ricordo che non si può dichiarare più di una classe public in un solo modulo.

venerdì 10 febbraio 2012

Granelli di Glasgow

Captare singoli gesti può essere molto utile...

Il rianimatore ha detto al paziente in coma: "Mostra la lingua".
Quindi lo ha pizzicato osservando che portava la mano del lato non paretico verso la sede del pizzicamento.

Questi sono elementi che fanno parte della valutazione della risposta motoria del GCS, e precisamente dei punteggi 5 e 6
Il grado 5 di risposta motoria è quello messo in luce dall'applicazione di uno stimolo doloroso.
Il grado 6 è quello che sarebbe stato messo in luce se il paziente avesse mostrato la lingua dietro ordine del rianimatore.

Teniamo in conto queste acquisizioni per costruire un modo di procedere spontaneo e ragionato...

Una proprietà unica della classe genitrice per le classi derivate...

Ho un'altra idea per vedere se con classi derivate si può instaurare quel tipo di confusione di cui parla il sito che sto seguendo...
Ci provo.

Inizio con il creare una classe Madre e una classe Figlia.
function Madre(){
 var nome="";
 this.nomina=function(n){
  nome=n;
 }
 this.presentati=function(){
  alert("Mi chiamo "+nome);
 }
} 

function Figlia(){
 var soprannome="";
}


Figlia.prototype=new Madre();
Ora creo due istanze della classe Madre e le nomino. Si dovrebbero presentare ognuna con il suo nome:
Maria=new Madre();
Maria.nomina("Maria");

Lucia=new Madre();
Lucia.nomina("Lucia");

Maria.presentati();
Lucia.presentati();
...e ottengo "Mi chiamo Maria" e "Mi chiamo Lucia". Come previsto.
Ora creo due istanze della classe Figlia...
Barbara=new Figlia();
Barbara.nomina("Barbara");

Giuliana=new Figlia();
Giuliana.nomina("Giuliana");

Barbara.presentati();
Giuliana.presentati();
E cosa ottengo?
Ottengo per due volte "Mi chiamo Giuliana"!

Se inverto le due:
Giuliana=new Figlia();
Giuliana.nomina("Giuliana");

Barbara=new Figlia();
Barbara.nomina("Barbara");


Giuliana.presentati();
Barbara.presentati();
Ottengo per due volte "Mi chiamo Barbara"!

Evidentemente la funzione Madre viene utilizzata da ambedue, e mentre all'inizio il metodo nomina dell'istanza Barbara modifica la variabile nome in "Barbara", successivamente il metodo nomina dell'istanza Giuliana modifica la stessa variabile nome in "Giuliana".
O viceversa.

La soluzione?

<script>

function Madre(){
 var nome="";
 this.nomina=function(n){
  nome=n;
 }
 this.presentati=function(){
  alert("Mi chiamo "+nome);
 }
} 

function Figlia(){
 Madre.call(this);
 var soprannome="";
}

Figlia.prototype=new Madre();


Giuliana=new Figlia();
Giuliana.nomina("Giuliana");

Barbara=new Figlia();
Barbara.nomina("Barbara");


Giuliana.presentati();
Barbara.presentati();

</script>
Il fatto è che le istanze della classe derivata condividono una sola istanza della classe genitrice. Se una variabile in questa non è dichiarata this, si fa riferimento a una sola variabile, che viene modificata ora da una ora dall'altra istanza. Non è molto facile, ma sembra che ci sto cominciando a capire qualcosa, dato che sono riuscito a personalizzare l'esempio del tutorial creandomi, come sempre un esempio tutto mio.

giovedì 9 febbraio 2012

Una proprietà come array di oggetti, e varie implicazioni...

Ecco, sto cercando di riprodurre il discorso che vuole fare il famoso blog di uno molto più bravo di me, a proposito delle implicazioni dell'ereditarietà in Javascript.

Ho creato una classe Veicolo, che carica oggetti anzichè numeri.
Ossia il suo metodo carica() non ha come parametro un numero di passeggeri ma un oggetto passeggero, istanza della classe Persona.
Questa va posta in un Array che è la proprietà passeggeri della classe Veicolo.

Ecco:
<script>
function Persona(nome){
 this.nome=nome;
}
function Veicolo(passeggero){
 this.passeggeri=[]
 this.carica=function(passeggero){
  this.passeggeri.push(passeggero);
 }
}

Auto=new Veicolo();
Mario=new Persona("Mario");
Giuseppe=new Persona("Giuseppe");
Auto.carica(Mario);
Auto.carica(Giuseppe);
for(n=0;n<Auto.passeggeri.length;n++){alert(Auto.passeggeri[n].nome);}

</script>
Ottengo due caselle di testo con i nomi "Mario" e "Giuseppe".


Ora però riprovo l'esperimento che viene suggerito sul blog... ossia faccio caricare a un veicolo Mario e all'altro Giuseppe.
<script>
function Persona(nome){
 this.nome=nome;
}
function Veicolo(passeggero){
 this.passeggeri=[]
 this.carica=function(passeggero){
  this.passeggeri.push(passeggero);
 }
}

Auto1=new Veicolo();
Auto2=new Veicolo();
Mario=new Persona("Mario");
Giuseppe=new Persona("Giuseppe");

Auto1.carica(Mario);
Auto2.carica(Giuseppe);
for(n=0;n<Auto1.passeggeri.length;n++){alert("Sull'Auto1 ci sono "+Auto1.passeggeri[n].nome);}
for(n=0;n<Auto2.passeggeri.length;n++){alert("Sull'Auto2 ci sono "+Auto2.passeggeri[n].nome);}
</script>
...Embeh?

Paradosso! Il codice funziona egregiamente, e mi dice che sull'Auto1 c'è Mario e sull'Auto2 c'è Giuseppe!
Eppure secondo il "maestro" non dovrebbe funzionare, e dovrebbe specificarmi che invece Mario e Giuseppe si troverebbero paradossalmente su tutte e due le auto!

Perchè?

Forse è perchè nell'esempio del sito la proprietà passeggeri non è dichiarata con il this ma con il var.

Proviamo...

Dato che la variabile dichiarata con il var risulta privata, ossia non visibile all'esterno della funzione, devo crearmi un metodo che mi "metta all'esterno" i valori contenuti in essa.
<script>
function Persona(nome){
 this.nome=nome;
}
function Veicolo(passeggero){
 this.passeggeri=[]
 this.carica=function(passeggero){
  this.passeggeri.push(passeggero);
 }
 this.listaPasseggeri=function(){
  for(n=0;n<this.passeggeri.length;n++){alert(this.passeggeri[n].nome);}
 }
}

Auto1=new Veicolo();
Auto2=new Veicolo();
Mario=new Persona("Mario");
Giuseppe=new Persona("Giuseppe");

Auto1.carica(Mario);
Auto2.carica(Giuseppe);

Auto1.listaPasseggeri();
Auto2.listaPasseggeri();
</script>
Ecco: così ottengo DUE caselle di testo con scritto Mario (il passeggero di Auto1) e Giuseppe (il passeggero di Auto2).
Tutto regolare!

E se rendo privata la proprietà passeggeri? Mi sa che non ho capito molto bene la lezione del "maestro"...

Codice e alcuni metodi per gli Array

Ora il discorso si fa un po' difficile...

Sarebbe il caso di affrontare i problemi uno alla volta, altrimenti faccio un casino mentale...

Innanzitutto ho trovato una notazione di tipo [] e dei metodi chiamati push e pop.
Tutto questo mi sa di Array...
Andiamo a vedere le proprietà e i metodi degli Array in Javascript...

Sì, come per i comandi Assembly per lo stack, push e pop aggiungono e tolgono dalla coda dell'Array gli elementi.

Provo a crearmi un codice ad hoc...

<script>

var matrice=[]
function aggiungi(nome){
 matrice.push(nome);
}
function elimina(){
 matrice.pop();
}
aggiungi("mario");
aggiungi("pasquale");
aggiungi("antonio");
aggiungi("nicola");
aggiungi("giorgio");
aggiungi("carletto");
for (n=0;n<matrice.length;n++){alert(matrice[n]);}
elimina();
for (n=0;n<matrice.length;n++){alert(matrice[n]);}
elimina();
for (n=0;n<matrice.length;n++){alert(matrice[n]);}
</script>
Sì, funziona come previsto.
Ma i metodi push e pop restituiscono anche dei valori.
Mi faccio un codice che mi aiuta a capire meglio questo:
<script>

var matrice=[]
//il metodo push restituisce la nuova lunghezza dell'Array
alert(matrice.push("mario"));
alert(matrice.push("pasquale"));

//il metodo pop restituisce il nome dell'elemento eliminato dall'Array
alert(matrice.pop());
</script>
Ecco, come mi aspettavo, ottengo prima 1 e poi 2, quindi ottengo il nome "pasquale", che è appunto quello che era in coda ed è stato eliminato.
Quindi si può dichiarare un Array semplicemente con due parentesi quadre!
Questo non lo sapevo...

Dunque la sintassi matrice=[] equivale a quella che già conosco:
<script>

var matrice=new Array();
//il metodo push restituisce la nuova lunghezza dell'Array
alert(matrice.push("mario"));
alert(matrice.push("pasquale"));

//il metodo pop restituisce il nome dell'elemento eliminato dall'Array
alert(matrice.pop());
</script>
o a questa:
<script>

var matrice=new Array("pippo","ciccio","marco","giovanni");
//il metodo push restituisce la nuova lunghezza dell'Array
alert(matrice.push("mario"));
alert(matrice.push("pasquale"));

//il metodo pop restituisce il nome dell'elemento eliminato dall'Array
alert(matrice.pop());
</script>

Ancora considerazioni sull'ereditarietà in Javascript...

Ecco, io ho una classe (chiamiamola così) e creo una classe "discendente" che eredita i suoi membri.

Ora creo due istanze, una della classe madre e una della classe figlia.


<script>


function Veicolo(passeggeri){
 this.velocita=5;
 this.passeggeri=0;
 if(passeggeri>0)
  this.passeggeri=passeggeri;

 this.carica=function(passeggeri){
  this.passeggeri+=passeggeri;
 }
 
  

}

function Aereo(passeggeri){
 this.altitudine=0;
 this.decolla=function(){
  this.altitudine=10;
 }
}

auto=new Veicolo();
jumbo=new Aereo();
alert(auto.velocita);
alert(auto.altitudine);
alert(jumbo.altitudine)

</script>
Ecco: l'istanza della classe genitrice, che non ha la proprietà altitudine, mi dà un undefined quando chiedo di mettermi a video la proprietà altitudine.
Questo non succede per l'istanza della classe figlia, che invece ha una proprietà altitudine.

Sono tutte cose lapalissiane, ma è meglio rimarcarsele!

Critica a un algoritmo per la sincope

Ho integrato l'embrione di ragionamento sulla gestione della sincope con quanto trovato a questo indirizzo.

L'algoritmo che trovo su questo documento è il seguente:



In pratica, questo algoritmo incoraggerebbe a proseguire nella ricerca di possibili cause della sincope, cardiache e non cardiache, in modo libero e lineare, riservando poi ai casi in cui non si individui una causa certa l'approfondimento cardiologico.
Non mi sembra una cosa lineare...

Per prima cosa, io escluderei l'aspetto cardiologico. Preferisco un approccio negativo, preoccupandomi prima di escludere la causa più grave. Se anche trovassi segni indicativi di una sincope di altra natura, perchè non dovrei escludere da subito una causa cardiaca? Non può coesistere una cardiopatia a cause di altro genere?

Nel contempo dell'esclusione di una cardiopatia rilevante, allora mi preoccuperei di individuare poi con calma eventuali segni di altre cause di sincope.
Mi pare più razionale e sicuro...

Approccio all'ereditarietà in Javascript

Proseguo con gli esercizi sul sito che tratta con molta chiarezza dei prototipi a livello introduttivo.

Dunque, che cosa avevo fatto prima?
Avevo imparato come si aggiungono dei metodi a una funzione, i quali possono essere esterni o interni alla funzione stessa. Per evitare eventuali conflitti può essere il caso di definirli all'interno della funzione oggetto.

Ora cerchiamo di vedere questo prototipo.

Avevo una "classe" Veicolo:
<script>


function Veicolo(passeggeri){
 this.velocita=0;
 this.passeggeri=0;
 if(passeggeri>0)
  this.passeggeri=passeggeri;

 this.carica=function(passeggeri){
  this.passeggeri+=passeggeri;
 }
 
  

}

</script>
Ora io creo una classe Aereo:
function Aereo(passeggeri){
 this.altitudine=0;
 this.decolla=function(){
  this.altitudine=10;
 }
}
Questa classe non ha la proprietà velocita della classe Veicolo.

Ora provo a creare un oggetto Aereo
jumbo=new Aereo(3);
alert(jumbo.velocita);
E ottengo una casella di testo con scritto undefined.
Ora invece rendo la classe Aereo "discendente" della classe "Veicolo". Il codice è questo (in cui do alla proprietà velocita della classe Veicolo un valore diverso da zero, giusto per essere sicuro che la cosa funzioni):

<script>


function Veicolo(passeggeri){
 this.velocita=5;
 this.passeggeri=0;
 if(passeggeri>0)
  this.passeggeri=passeggeri;

 this.carica=function(passeggeri){
  this.passeggeri+=passeggeri;
 }
 
  

}

function Aereo(passeggeri){
 this.altitudine=0;
 this.decolla=function(){
  this.altitudine=10;
 }
}

Aereo.prototype=new Veicolo();
jumbo=new Aereo(3);
alert(jumbo.velocita);

</script>
...e ottengo come risultato una casella di testo con il valore 5, in quanto essendo ora la classe Aereo "discendente" della classe Veicolo ne eredita la proprietà velocita. Ecco fatto un primo passo nell'ereditarietà in Javascript!

Un approccio non convenzionale alla sincope...

Perchè il motore funzioni, è necessario del combustibile e del comburente, mediante i quali si possa avere lo sviluppo di energia attraverso la degradazione del combustibile.
Stop.

Detto questo, dobbiamo porre l'attenzione anche al veicolo del combustibile e del comburente, e cioè alla circolazione del sangue, la quale può avere degli ostacoli.
Proporrei quindi una valutazione di tre elementi fondamentali:
  • Combustibile (glicemia...)
  • Comburente (Saturimetria, Emogasanalisi)
  • Sistema di trasporto...

La valutazione di combustibile e comburente è fatta con molta rapidità.
Quello che è più indaginoso è invece studiare tutti i possibili "intoppi" del sistema di veicolazione di questi due componenti.

Ieri ho individuato un possibile "intoppo" in un'anamnesi di stenosi aortica, che, costituendo un'ostruzione al flusso di sangue dal cuore, può portare a un abbassamento della pressione tale da ridurre la veicolazione delle due componenti necessarie al processo energetico.

Mi sembra evidente che di fronte a un'alterazione della coscienza una delle prime indagini vadano fatte su un possibile ostacolo alla veicolazione a carico della pompa: anamnesi e indagini cardiologiche!
Questo sarebbe il punto di partenza fondamentale...

mercoledì 8 febbraio 2012

Costruttori, oggetti, metodi e proprietà...

Seguiamo un po' di esempi da questo sito per capire meglio questo prototype...

<script>
function Veicolo(passeggeri){
 this.velocita=0;
 this.passeggeri=0;
 if(passeggeri>0)
  this.passeggeri=passeggeri;
}
var auto=new Veicolo(1);
alert(auto.passeggeri);
</script>
Questo sarebbe il costruttore di un oggetto.
Ossia, qualcosa che assomiglia alle classi, credo...

Ha due proprietà, l'una che prende il valore del parametro e l'altra che è impostata a zero senza venir modificata inizialmente all'atto in cui si istanzia l'oggetto.
Ecco, adesso modifico la proprietà passeggeri subito e poi modifico l'altra:
<script>
function Veicolo(passeggeri){
 this.velocita=0;
 this.passeggeri=0;
 if(passeggeri>0)
  this.passeggeri=passeggeri;
}
var auto=new Veicolo(1);
var auto2=new Veicolo(1);
auto2.velocita=13;
alert("auto: velocità "+auto.velocita+" passeggeri "+auto.passeggeri);
alert("auto2: velocità "+auto2.velocita+" passeggeri "+auto2.passeggeri);
</script>

Aggiungiamo un metodo...

Ecco: aggiungiamo il metodo scritto all'esterno del costruttore. Provo a esercitarmi...
<script>
function carica(passeggeri){
 this.passeggeri+=passeggeri;
}


function Veicolo(passeggeri){
 this.velocita=0;
 this.passeggeri=0;
 if(passeggeri>0)
  this.passeggeri=passeggeri;

 this.carica=carica;
}
var auto=new Veicolo(1);
alert("auto: velocità "+auto.velocita+" passeggeri "+auto.passeggeri);
auto.carica(4);
alert("auto: velocità "+auto.velocita+" passeggeri "+auto.passeggeri);

</script>
Funziona egregiamente!
Bene... finora niente di particolarmente trascendentale, e mi sono esercitato un po' sull'aggiungere metodi scritti all'esterno del costruttore stesso.
Ecco invece l'aggiunta di un metodo scritto all'interno del costruttore:
<script>


function Veicolo(passeggeri){
 this.velocita=0;
 this.passeggeri=0;
 if(passeggeri>0)
  this.passeggeri=passeggeri;

 this.carica=function(passeggeri){
  this.passeggeri+=passeggeri;
 }

}
var auto=new Veicolo(1);
alert("auto: velocità "+auto.velocita+" passeggeri "+auto.passeggeri);
auto.carica(4);
alert("auto: velocità "+auto.velocita+" passeggeri "+auto.passeggeri);

</script>
Questo si chiama incorporare il metodo all'interno della funzione costruttore.
La sua utilità è evitare i conflitti nel caso si debba creare un metodo con nome analogo per un altro oggetto.

mercoledì 1 febbraio 2012

Uso di indexOf per trovare tutte le occorrenze di una sottostringa

Ed ecco un codice per individuare tutte le occorrenze di una sottostringa nell'ambito di una stringa:
<script src="funzioni.js"></script>
<script>
var stringa="Chi legge è un cretino o è un deficiente!"
var n=0;
var indice;
function inizia(){
 while(indice!=-1){
  indice=stringa.indexOf(" è ",n);
  alert(indice);
  n=indice+1;
 } 
}
 
</script>
<body onload="inizia()">

</body>
Per ora so usare questo metodo, che mi sono creato sul momento. Non so se ne esistono di migliori...

do...while e while.

Le mie peregrinazioni mentali mi portano a voler sezionare le stringhe.

Da qui vado ancora avanti con le associazioni di idee e mi trovo ai cicli Do...until.
< Una volta li praticavo, ma non mi ricordo questa sintassi, che peraltro è comune a diversi linguaggi di programmazione...

Rinfreschiamo le idee!
<script src="funzioni.js"></script>
<script>

function inizia(){
var n=1;
 do{
  n++;
 } while(n<10);
alert(n); 
}
 
</script>
<body onload="inizia()">

</body>

Ecco, ottengo una casella di avvertimento con il numero 10.
Il programma aumenta sempre di uno il numero n finchè resta valida la condizione n<10. Quando poi n arriva a 10 smette e prosegue con l'istruzione successiva alert(n).


Ora provo con il solo while.
<script src="funzioni.js"></script>
<script>

function inizia(){
var n=1;
while(n<10){
 n++;
}
alert(n); 
}
 
</script>
<body onload="inizia()">

</body>
Il risultato è analogo: 10.

Ma qual è la differenza fra le due forme?

Provo a tradurre in italiano...
Prima forma.
"Aumento n di uno. E' minore di 10? Sì. E allora continuo ad aumentare di uno. E' minore di 10? Sì. E allora continuo...". Quando n è uguale a 10: "E' minore di 10? No. E allora smetto di aumentarlo e vado avanti".

Seconda forma.
"n è minore di 10? Sì. E allora lo aumento di uno. E' minore di 10? Sì. E allora lo aumento di uno...". Quando n è uguale a 10: "E' minore di 10? No. E allora vado avanti.

Il risultato è lo stesso. La differenza è solo che nel primo caso l'istruzione viene eseguita una volta, prima di verificare se n è minore di 10, mentre nel secondo caso il processo viene bloccato in partenza.

Provo a costruirmi un codice nel quale si veda la differenza.
<script src="funzioni.js"></script>
<script>

function inizia(){
var n=10;
while(n<10){
 n++;
}
alert(n); 
}
 
</script>
<body onload="inizia()">

</body>
Ecco, partendo da un valore di n pari a 10, ottengo 10 perchè il programma ha verificato subito che n non è minore di 10 e il ciclo non è partito per niente.
Invece con questo:
<script src="funzioni.js"></script>
<script>

function inizia(){
var n=10;
do{
 n++
}while (n<10);
alert(n); 
}
 
</script>
<body onload="inizia()">

</body>
... ottengo 11, perchè la condizione non è stata verificata subito e quindi il ciclo è partito per una volta, prima di essere bloccato all'esecuzione della seconda operazione.