27 maggio 2011

UBUNTU 11.04 skype crashes, non parte più, non funziona

english version
Il 27 maggio 2011 skype non si avviava più
Ho risolto rimuovendo il file shared.xml di skype. (nell'esempio sotto l'ho rinominato)

gheryd@gheryd-laptop:~$ mv .Skype/shared.xml .Skype/shared.xml.bkp
gheryd@gheryd-laptop:~$ skype &

(La tilde sta per cartella home).

Quando poi riavviate skype, compare la pagina di licenza. Date l'ok e skype ritornerà in vita. :)

Se non vi compare l'icona sulla tray bar date un'occhiata al seguente post:
http://gheryd.blogspot.com/2011/05/ubuntu-skype-icon-nascosta-hidden.html

22 maggio 2011

javascript funzioni browser compatibili (cross browser) per gli eventi

Indice dei tutorials: http://gheryd.blogspot.com/2011/06/javascript-gwt-tutorials.html


Indice:

  • Funzioni per la compatibilità
  • Registrare una funzione handler dll'evento
  • Lista eventi
  • Registrare lo stesso handler per più eventi
  • Eventi da tastiera
  • Tasti speciali
  • Esempio completo: currency text box
  • Handler in html
  • Passare parametri all'handler
  • Esempio completo: editable table
  • Eventi onload e onerror immagini
  • Gestire il submit del form



Introducendo
In questo tutorial mi propongo di spiegare come utilizzare gli eventi DOM con particolare attenzione su casi critici i cui mi sono imbattuto nel mio lavoro di sviluppo e che ho risolto cercando in giro per il web.
Non mi soffermo troppo sulle spiegazioni ma credo che gli esempi siano sufficientemente chiari. Se avete dubbi, correzioni o suggerimenti commentate!
Questo post verrà continuamente aggiornato con altri interessanti spunti e esempi.


Funzioni per la compatibilità
Prima di iniziare introduco tre funzioni che ci garantiranno negli esempi js che seguono la compatibilità con i vari browser:
function ensureEvent(e) { return !e ? e = window.event : e; } 
function getElementByEvent(e) { return (e.target) ? e.target : e.srcElement }
function getKeyByEvent(e) { return e.keyCode ? e.keyCode : e.charCode; }


Registrare una funzione handler dell'evento
Per settare un handler che tratti uno specifico evento è sufficiente procedere nella maniera seguente
var el = document.getElementById("idEl");
el.onclick = function(event) {
      alert("clicked!");
}
Ogni volta che si clicca sull'elemento che ha l'attributo id="idEL" verrà visualizzato un alert.
Da html sarebbe analogo a:
<button  onclick="alert('clicked')">click me</button>
<div onclick="alert('clicked')">...</div>
<a href="#"  onclick="alert('clicked');return false">click me</a>
Il return false annulla  l'eventuale azione su href (il browser non apre la pagina sull'url specificato). In caso contrario mettere un return true.
Comunque negli esempi successivi agganceremo gli handlers via javascript, che è utile soprattutto se si creano elementi dinamicamente:
var button =  document.createElement("button");
button.setAttribute("id", "mybutton");
button.className = "buttonClass"; //la classe di stile non si può settare tramite setAttribute
button.appendChild( document.createTextNode("click me") );
button.onclick = fuction() { alert("clicked"); };
document.getElementById("container").appendChild(button);
la funzione handler dell'evento si può dichiarare anche a parte:
function onClickHandler(event) {
    alert("clicked");
}
quindi assegnamo la funzione dichiarata in questo modo:
button.onclick = onClickHandler;


Lista eventi
E' possibile registrare funzioni handler su svariati eventi. Alcuni tag html supportano solo alcuni degli eventi di seguito elencati.
element.onclick
element.ondblclick
element.onkeyup
element.onkeypress
element.onkeydown
element.onblur
element.onfocus
element.onmouseover
element.onmousedown
element.onmouseup
element.onmouseout
element.onmousemove
element.onchange
element.onselect
element.onresize
element.onload
element.onload
element.onerror
Potrebbe mancare qualche evento, comunque quelli più usati ci sono.

Registrare lo stesso handler per più elementi
Nell'esempio seguente registriamo lo stesso handler su più elementi.
Questo potrebbe essere interessante se avete una funzione di validazione che potete utilizzare su più campi text, per esempio. Oppure a cambiare colore di sfondo sul mouseout o il mouseover.
Qui mi limito a mostrare un alert con informazioni relative all'elemento alla perdita del focus:
function onBlurHandler(event) {
   event = ensureEvent(event);
   vat el = getElementByEvent(event);
   var tagname = el.tagName;
   var id = el.getAttribute("id");
   var value = el.value;
   alert("tagname: "+tagname+"\n"+"id: "+id+"\n"+"value: "+value);
}
document.getElementById("input1").onblur = onBlurHandler;
document.getElementById("input2").onblur = onBlurHandler;
document.getElementById("input3").onblur = onBlurHandler;


Eventi da tastiera
Proviamo ora la gestione degli eventi da tastiera.
var ctrl = "";
function onKeyDownHandler(event) {
     event = ensureEvent(event);
     var unicode = getKeyByEvent(event);
     var msg = "";
     if( unicode == 17 ) {
         ctrl  = "ctrl + ";
    }else {
         msg = ctrl + unicode;
    }
     document.getElementById("messageContainer").innerHTML = msg;
}
function onKeyUpHandler(event) {
    event = ensureEvent(event);
    var unicode = getKeyByEvent(event);
   if( unicode == 17 ) {
       ctrl = "";
  }
}
document.getElementById("idInput").onkeydown = onKeyDownHandler;
document.getElementById("idInput").onkeyup = onKeyUpHandler;
L'html da inserire per l'esempio precedente è:
input: <input id="idInput" type="text" />
<div id="messageContainer" ></div>
Con l'esempio sopra viene visualizzato nel div il codice unicode del tasto premuto. Indica inoltre l'eventuale  combinazione con il tasto control (ctrl).


Tasti speciali
Di particolare interesse sono i codici unicode di alcuni tasti speciali (senza corrispondente carattere):
var specialKey = {
  "DEL" : 8,
  "TAB" : 9,
  "ENTER" : 13,
  "SHIFT" : 16,
  "CTRL" : 17,
  "ALT" : 18,
  "ESC" : 27,
  "SPACE" : 32,
  "PAGEUP" : 33,
  "PAGEDOWN": 34,
  "END": 35,
  "HOME", 36,
  "LEFT" : 37,
  "UP": 38,
  "RIGHT": 39,
  "DOWN": 40,
  "INS": 45,
  "CANC": 46,
  "WINDOWS": 91,
  "F1": 112,
  "F2": 113
}
Ecco un esempio di utilizzo di questa mappa dei tasti speciali all'interno di un key handler:
e.onkeydown = function(event) {
    event = ensureEvent(event);
  var unicodegetKeyByEvent(event);
    if( unicode==specialKey.TAB ) {
        if(event.preventDefault) event.preventDefault();
        return false; 
   }
}
L'input text non perde così il focus premendo il tasto TAB.

Possiamo anche utilizzare la mappa dei caratteri speciali per sapere se il tasto premuto è un carattere speciale:

function getSpecialKeyLabel(unicode) {
    var label = null;
    for(var k in specialKey) {
       if( unicode==specialKey[k){ label = k; break; }       
   }
   return label;
}
e.onkeydown = function(event) {
    event = ensureEvent(event);
  var unicode = getKeyByEvent(event);
    var k = getSpecialKeyLabel(unicode);
    if(!k) k = String.fromCharCode(unicode);
    alert("hai premuto il tasto "+k);
}




Esempio completo: Currency Textbox
In questo esempio lavoriamo su un input text in maniera tale che gestica l'inserimento di un dato numerico sul focus e visualizzi il valore formattato come valuta sul blur. 
L'unico carattere speciale che intercettiamo sul keypress è l'enter (invio) corrispondente al unicode 13. Sempre su questo evento viene verificato l'inserimento solo di numeri e separatore decimale (solo una volta).
Inoltre ho aggiunto un accorgimento per il form. Ho inserito un campo nascosto con name="price". La text box non ha l'attribute name perchè non voglio "submittare" sul server un valore formattato, ma solo il puro valore numerico che viene settato sul campo nascosto prima del submit.(vedi funzione onSubmitHandler)

<html>
<head>
<script type="text/javascript">
function ensureEvent(e) { return !e ? e = window.event : e; } 
function getElementByEvent(e) { return (e.target) ? e.target : e.srcElement }
function getKeyByEvent(e) { return e.keyCode ? e.keyCode : e.charCode; }
function CurrencyTextBox(textBoxId) {
    var me = this;
    var number = 0.0;
    this.el = document.getElementById( textBoxId );
    this.currencySymbol = "E ";
    this.getNumber = function() { return number; }
    this.setNumber = function(n) { 
        n = parseFloat(n);     
        number = isNaN(n) ? 0.0 : n;
        showFormatted();
    }
    if( !this.el || this.el.tagName!="INPUT") throw "element is not input";
    this.el.onkeypress = function(event) {
        event = ensureEvent(event);
        var unicode = getKeyByEvent(event);
        if(unicode==13){            
            me.el.blur();
            if(event.preventDefault) event.preventDefault();
            return false;
        }
        var c = String.fromCharCode(unicode);
        if("1234567890.".indexOf(c)==-1) {
            if(event.preventDefault) event.preventDefault();
            return false;
        }else if(c=="." && me.el.value.indexOf(".")>-1) {
            if(event.preventDefault) event.preventDefault();
            return false;
        }
    }
    this.el.onblur = function(event) {
        me.setNumber( me.el.value );
    }
    this.el.onfocus = function(event) {
        showNumber();
    }
    var showFormatted = function() {
        var v = "";
        var nn = number.toString().split(".", 2);
        var intn = parseInt(nn[0],10);
        if( isNaN(intn) ) intn = 0;
        var intv = intn+"";
        for(var i=intv.length-1;i>=0;i--) {
            var j = intv.length-i-1;
            if(j>0 && j%3==0) v = "."+v;                
            v = intv[i]+v;
        }
        v += ",";
        if( !nn[1]  || nn[1].length==0 ) v += "00";
        else if( nn[1].length==1 ) v += nn[1]+"0";
        else if( nn[1].length>2 ) v += nn[1].substring(0,2);
        else v += nn[1];
        me.el.value = me.currencySymbol+v;
    }
    var showNumber = function() {
        me.el.value = number;
    }
}
function onSubmitHandler(){
    document.getElementById("price").value = currencyTB.getNumber();
    document.getElementById("myForm").submit();
}
var currencyTB = null;
function onLoadBodyHandler(){
    currencyTB = new CurrencyTextBox("currencyTB");
    currencyTB.setNumber(100);
}
</script>
</head>
<body onLoad = "onLoadBodyHandler()">
    <form id="myForm">
        price: <input id="currencyTB" type="text" style="text-align:right"/>
       <input type="hidden" name="price" id="price" />
        <br/>
        <button onClick="onSubmitHandler();">submit</button>
    </form>
</body>
</html>




Handler in innerHTML
E' bene sapere che creare un tag con l'attributo onclick (o qualsiasi altro evento) inserito via innerHMTL non fuziona per internet explorer (ie):
var divEl = document.getElementById("container");
divEl.innerHTML = "<a href='#' class='linkClass' onClick='onClickHandler();return false;'>click me!</a>";


Non funziona su IE!  la funzione onClickHandler non viene chiamata. Questo vale per qualsiasi altro evento (es. mouseOver, mouseMove, mouseDown, etc).

Il codice corretto è:
var linkEl = document.createElement("a");
linkEl.setAttribute("href", "#");
linkEl.className = "linkClass";
linkEl.onclick = onClickHandler;
linkEl.appendChild( document.createTextNode("click me!") );
divEl.appendChild( linkEl );


Passare parametri all'handler
Se occorresse passare uno o più parametri all'handler:
function createClickHandler(par1, par2) { 
        return function(event) {
                alert("par1:"+par1+" par2:"+par2);
        }
}
el1.onClick = createClickHandler("gheryd", 12345);
el2.onClick = createClickHandler("pippo", 67890);


Esempio completo: Editable Table
Segue un esempio più complesso che sfrutta il trucco sopra esposto.
Viene creata dinamicamente una tabella. Vari handlers vengono  agganciati a eventi  onclick,  onmouseover e onmouseout.
Sugli eventi del mouse cambia il colore della riga in cui si trova la cella mentre sull'onclick appare un prompt per modificarne il contenuto.
<html>
<head>
<script type="text/javascript">
function createTable() {
   var createClickHandler = function(td, row, col) {
       return function(event){
           var v = prompt("inserire un nuovo valore per la cella "+row+","+col, td.innerHTML);
           if(v) {
              td.innerHTML = "";
              td.appendChild( document.createTextNode(v) );
           }
       }
   }
   var createMouseOver = function(tr) {
       return function(event) { tr.style.backgroundColor = "yellow"; }
   }
   var createMouseOut = function(tr) {
       return function(event) { tr.style.backgroundColor = "white";  }
   }
   var table = document.createElement("table");
   table.setAttribute("cellpadding", "5px");
   table.setAttribute("border", "1px");
   table.setAttribute("cellspacing", "0");
   table.setAttribute("width", "500px");
   var tbody = document.createElement("tbody");
   table.appendChild(tbody);
   for(var r=0;r<10;r++) {
       var tr = document.createElement("tr");
       for(var c=0;c<5;c++) {
          var td = document.createElement("td");
          td.setAttribute("align", "center");
          td.appendChild(document.createTextNode(r+","+c));
          td.onclick = createClickHandler(td, r,c);
          td.onmouseover = createMouseOver(tr);
          td.onmouseout = createMouseOut(tr);
          tr.appendChild(td);
       }
       tbody.appendChild(tr);
   }
   document.body.appendChild(table);
}
</script>
</head>
<body onload="createTable();"></body>
</html>
Migliorie: come esercizio potrebbe essere interessante sul click della cella inserire un input text al posto di far comparire il prompt. Sulla perdita del focus dell'input, questo scomparirebbe e la cella verrebbe compilata con il nuovo valore.




Eventi onload e onerror immagini
Nell'esempio seguente viene creato dinamicamente un elemento <image> e viene inserito all'interno del contenitore div.
Se l'immagine non esiste viene chiamato l'handler per l'evento onerror, altrimenti verrà richiamato l'handler per l'evento onload quando l'immagine è stata caricata correttamente.

<html>
<head>
<script type="text/javascript">
function onLoadHandler(event) {
   alert("caricata");
}
function onErrorHandler(event) {
   document.getElementById("cont").innerHTML = "immagine non caricata";
}
function onLoadBodyHandler() {
   var img = new Image();
   img.onload = onLoadHandler;
   img.onerror = onErrorHandler;
   document.getElementById("cont").appendChild(img);
   img.src = "img1.jpg";
}
</script>
</head>
<body onLoad="onLoadBodyHandler();">
    <div id="cont"></div>
</body>
</html>
In questo esempio potrebbe essere interessante inserire un messaggio tipo "loading..." all'interno del div finchè l'immagine non è stata caricata (onload). Utile per immagini molto pesanti.


Gestire il submit del form
Tipicamente si vuole impedire o meno il submit del form in seguito  alla validazione dei campi.
Negli esempi che seguono ci riferiremo alla seguente funzione che restituisce un valore booleano true se i campi del form sono validi, false in caso contrario:
function validateForm() {
     var v = document.getElementById("myTextBox").value;
     return v.length>0;
}
I tre seguenti esempi illustrano vari modi di gestire l'evento di onsubmit del form.


Esempio 1: implementare l'attributo onsubmit del tag form:
<form onsubmit="return validateForm()">
    <input type="text" name="fieldName" id="myTextBox" />
    <button type="submit" >submit</button>
</form>
oppure si può registrare un handler via codice:
document.getElementById("myForm").onsubmit = function(event){
     if( validateForm() ) {
            return true;
     }else {
          alert("field is void");
          return false;
     }
}


Esempio 2: implementare l'evento onclick di un pulsante di tipo "submit".
<form id="myForm">
    <input type="text" name="fieldName" id="myTextBox" />
    <button type="submit" onclick="return onClickHandler()">submit</button>
</form>
function onClickHandler() { 
      if( validateForm() ) {
           return true;
      }else {
            alert("field is void"); 
            return false;
      }
}


Esempio 3: implementare l'evento onclick di un pulsante di tipo "button".
<form id="myForm">
    <input type="text" name="fieldName" id="myTextBox" />
    <button type="button" onclick="onClickHandler()">submit</button>
</form>
function onClickHandler() {
      if( validateForm() ) {
           document.getElementById("myForm").submit();
      }else {
            alert("field is void"); 
      }
}
In questo esempio il pulsante di tipo "button" potrebbe essere sostituito da un "div" o da un link, cioè da qualsiasi oggetto html che può gestire l'evento "onclick".
Conclusione
Anche se apparentemente i tre sistemi sopra illustrati possono sembrare equivalenti, in realtà c'è una certa differenza.
Nell'esempio 1 e 2 restituiamo un valore false per impedire il submit. Ma nel caso di errore javascript non viene impedito il submit del form.
Invece nell'esempio 3 avviamo via codice il submit del form. In caso di errore javascript non viene eseguita l'istruzione che effettua il submit.
Inoltre il metodo utilizzato nel terzo esempio può essere applicato per altri eventi al posto dell'onclick.
Per esempio se volessimo avviare un timer che ritarda il submit del form, non potemmo applicare i metodi dell'esempio 1 e 2:
function onClickHandler() {
     var count = 3;
     var t = setInterval(function(){
         count--;
         if(count==0) {
              document.getElementById("myForm").submit();
         }
    }, 1000);
}

21 maggio 2011

UBUNTU LINUX PHP configurare display log error

Per chi sviluppa con php e necessita della visualizzazione degli errori sulle proprie pagine .php, è utile attivare sul file di configurazione php.ini le opportune direttive che di default dovrebbero essere disattivate.
gheryd@gheryd-laptop:~$ cd /etc/php5/apache2/ gheryd@gheryd-laptop:/etc/php5/apache2$ ll totale 76 drwxr-xr-x 2 root root 4096 2011-05-17 12:37 ./ drwxr-xr-x 5 root root 4096 2010-10-31 10:32 ../ lrwxrwxrwx 1 root root 9 2010-05-08 20:07 conf.d -> ../conf.d/ -rw-r--r-- 1 root root 67631 2011-05-17 12:37 php.ini
gheryd@gheryd-laptop:/etc/php5/apache2$ sudo nano php.ini
o se preferite l'editor grafico
gheryd@gheryd-laptop:/etc/php5/apache2$ sudo gedit php.ini &
In evidenza le direttive con i valori da impostare.
; error_reporting = E_ALL & ~E_DEPRECATED error_reporting = E_ALL & ~E_NOTICE ; This directive controls whether or not and where PHP will output errors, ; notices and warnings too. Error output is very useful during development, but ; it could be very dangerous in production environments. Depending on the code ; which is triggering the error, sensitive information could potentially leak ; out of your application such as database usernames and passwords or worse. ; It's recommended that errors be logged on production servers rather than ; having the errors sent to STDOUT. ; Possible Values: ; Off = Do not display any errors ; stderr = Display errors to STDERR (affects only CGI/CLI binaries!) ; On or stdout = Display errors to STDOUT ; Default Value: On ; Development Value: On ; Production Value: Off ; http://php.net/display-errors display_errors = On
Ricordarsi di riavviare il server apache2:
gheryd@gheryd-laptop:/etc/php5/apache2$ sudo /etc/init.d/apache2 restart

18 maggio 2011

browser firefox pagine tab affiancate

Il mio collega ha trovato un utile plugin per affiancare le pagine web:

https://addons.mozilla.org/it/firefox/addon/split-pannel/

Utile per i developer ma anche non ;)

16 maggio 2011

UBUNTU skype icona nascosta sulla tray bar

Se quando avviate skype, non vi compare l'icona sulla barra di notifica (in realtà c'è ma è larga un pixel! ), effettuare da console il seguente comando che termina il processo (poi si riavvia subito in automatico).
In seguito l'icona di skype dovrebbe apparire sulla tray bar.

gheryd@gheryd-laptop:~$ sudo killall gnome-panel

15 maggio 2011

grepolis javascript utility tools

Indice dei tutorials: http://gheryd.blogspot.com/2011/06/javascript-gwt-tutorials.html

Da ex giocatore di grepolis mi ero creato dei tools per ottenere velocemente nei post e nei messaggi liste di città di un player o lista di player di un'alleanza

Istruzioni:
1. copia tutta la stringa relativa alla lista che ti interessa
2. in grepolis vai alla lista delle città di un player o alla lista dei player di un'alleanza
3. incolli la stringa al posto del url e invio (nella barra degli indirizzi del browser)
4. ti appare una textbox in una finestra, copia il contenuto e premere annulla
5. infine incolli sul post (o sul messaggio) che stai editando


Lista città
javascript:var s='';var regex=new RegExp("[showTownInfoPopup]\\(([^\\(#)]*)");var l=$(".game_list a");for(var ii=0; ii<l.length;ii++) {var r= regex.exec(l[ii].onclick+'');s+=r!=null?"["+"town]"+r[1]+"\[/"+"town]\n":"";}prompt("copia il contenuto del text box:",s);

Lista players
javascript:var s = "";var l=$("#player_towns .game_list a");for(var ii=0; ii<l.length ; ii++) s += "["+"player]"+l[ii].innerHTML+"["+"/player]\n";prompt("copia il contenuto del text box:",s);

Nota: se sulla barra degli indirizzi è attiva la ricerca (es.google), quando si incolla la stringa potrebbe sparire il prefisso "javascript:"; eventualmente aggiungerlo.


14 maggio 2011

javascript: regular expression targa italiana

Indice dei tutorials: http://gheryd.blogspot.com/2011/06/javascript-gwt-tutorials.html

Questa regular expression server per testare il corretto formato per le targhe italiane sia nuovo (AA123BB) che vecchio tipo (MI12345, MI123456, ROMA12345, ROMA123456):

var targaRExp = /^(([a-zA-Z]{2}\d{3}[a-zA-Z]{2})|(([a-zA-Z]{2}|roma)(\d{5}|\d{6})))$/i
var targa = prompt("inserire una targa:");
if( targaRExp.test(targa) ) {
alert("formato targa corretto");
}else {
alert("formato targa scorretto");
}

Javascript: parseint per valori "08" e "09"

Indice dei tutorials: http://gheryd.blogspot.com/2011/06/javascript-gwt-tutorials.html

Se usate la funzione parseInt per i valori "08" e "09" (nel mio caso si riferivano ai mesi di agosto e settembre formattati a due cifre)

var n = parseInt("08") ;   // n = 0
var n = parseInt("09") ;   // n = 0

il risultato sarà sempre 0 (zero) perchè vengono interpretati come numeri a base ottale.

Occorre specificare la base numerica decimale (10) nel secondo argomento:

var n = parseInt("08", 10);   // n = 8
var n = parseInt("09", 10);   // n = 9

In generale consiglio sempre un controllo per verificare se il parsing ha avuto buon esito come nell'esempio seguente:

var s = prompt("insert a integer");
var n = parsInt(s, 10);
if(  isNaN(n) ) {
    alert("is not a number");
}else {
   alert("is number");
}



Ubuntu 11.04 attivare/ripristinare desktop classico gnome

english version

Se la versione nuova del desktop (Unity) non vi piace o comunque non vi è pratica, potete passare facilmente alla versione "classica" del desktop gnome.

Quando siete nella pagina di login di ubuntu, selezionate l'utente. Nella parte in basso allo schermo vi comparirà la barra con dei menù in cui potrete selezionare "ubuntu classic".



Personalmente sono passato alla versione classica perchè avevo parecchi problemi con le icone di notifica e  blocchi vari di unity. Penso che a breve questi problemi saranno risolti. Si può ritornare a Unity sempre dalla schermata di login ;)
Nota: ho provato a disattivare unity dal configuratore di compiz, ma aimè si è bloccato :(

Ricordo che per installare il configuratore di compiz basta fare il comando:

gheryd@gheryd-laptop:~$ sudo apt-get install compizconfig-settings-manager

Con il desktop ubuntu classic funziona alla grande :)

Su compiz, sotto la voce "desktop" c'è il flag per attivare il plugin di Unity: