Categoria ‘Javascript’


Javascript Object (parte I)

Se si ha bisogno di istanziare più oggetti di una classe, un metodo è quello di definire la classe tramite lo pseudo-costruttore function().

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// class definition
function CmyClass(param1,param2) {
    this.myProperty = param1;
    this.myAdding = param1+param2;
    //
    this.myMethod = function(param1) {
         alert( "add: "+this.myAdding+" - Param: "+param1);
    }
}
//
var obj1 = new CmyClass(10,20);
var obj2 = new CmyClass(20,40);
//
obj1.myMethod("Hi from obj1");
//
obj2.myMethod("Hi from obj2");

Definita la classe – con tanto di parametri iniziali – posso creare n istanze del mio oggetto, personalizzandole durante la creazione con la keyword new.
Posso anche inserire una chiamata ad un metodo durante la fase di inizializzazione dell’oggetto, stando solo attento ad inserirlo per ultimo – vedi riga 14:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// class definition
function CmyClass(param1,param2) {
  this.myProperty = param1;
  this.myAdding = param1+param2;
  //
  this.myMethod = function(param1) {
     alert( "Result: "+this.myResult );
  }
  //
  this._init = function() {
    this.myResult = this.myProperty*100;
  }

  this._init();

}
//
var obj1 = new CmyClass(10,20);
var obj2 = new CmyClass(20,40);
//
obj1.myMethod("Hi from obj1");
//
obj2.myMethod("Hi from obj2");

Un modo sbagliato sarebbe – vedi riga 6:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// class definition
function CmyClass(param1,param2) {
  this.myProperty = param1;
  this.myAdding = param1+param2;

  this._init();

  //
  this.myMethod = function(param1) {
     alert( "Result: "+this.myResult );
  }
  //
  this._init = function() {
    this.myResult = this.myProperty*100;
  }


}
//
var obj1 = new CmyClass(10,20);
var obj2 = new CmyClass(20,40);
//
obj1.myMethod("Hi from obj1");
//
obj2.myMethod("Hi from obj2");

Un’altro modo per creare un oggetto al volo (on-fly) è quello di dichiarare una variabile/funzione, mono uso:

1
2
3
4
5
6
7
8
9
var myObject = {
  myProperty: 10,
 
  myMethod: function() {
    alert("Hi from "+this.myProperty);
  }
};

myObject.myMethod();

Questa tecnica è comoda quando si vuole creare una sola istranza di un oggetto, e trattarlo come tale. Questa viene spesso usata nei recenti framework Ajax, come prototype e derivati. A partire da questa, infatti, non è possibile istanziare un nuovo oggetto, in quanto la classe è andata persa.

Si può poi ricorrere all’uso di prototype per estendere una classe, anche vuota. Ad esempio:

1
2
3
4
5
6
7
8
9
10
11
12
13
function CmyClass() {}

CmyClass.prototype = {
  myProperty: 10,
 
  myMethod: function() {
    alert( "Hi from " + this.myProperty);
  }
}

var obj = new CmyClass();

obj.myMethod();

Oppure:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function CmyClass() {
  this.myOldProperty = 1000;
  }

CmyClass.prototype = {
  myProperty: 10,
 
  myMethod: function() {
    alert( "Hi from " + this.myProperty);
    alert( "Hi from " + this.myOldProperty);
  }
}

var obj = new CmyClass();

obj.myMethod();

Continua...

Consigli folli da Microsoft: JScript vs Javascript (parte 1)

Ormai da Microsoft ci aspettiamo davvero di tutto, soprattutto quando si parla di browser. Offendere l’intelligenza della comunità, tuttavia, risulta un po’ sgradevole da accettare.
Sul Blog di IE7 è uscito oggi un articolo (IE+JScript Performance Recommendations Part 3: JavaScript Code Inefficiencies), se così possiamo definirlo di Peter Gurevich, Performance PM for IE, con la parte III dei suoi “consigli” per gli sviluppatori.

Primo appunto: perchè Microsoft si ostina ad implementare una sua versione di Javascript – che chiama appunto JScript – complicando la vita a tutti?

Secondo appunto: proprio perchè il motore di JScript è proprietà della Microsoft, invece di perdere tempo a dire a “noi” come aggirare i difetti, perchè non li sistemano una volta per tutte?

Lasciando stare il primo consiglio di questa III parte, che potete leggere direttamente sul Blog o su Ajaxian, il secondo è davvero eclatante, e sinceramente non lo diregisco proprio.

Don’t use Property Accessor Functions

Quando si dice il progresso! In pieno 2007, un Project Manager della Microsoft viene a dire a noi sviluppatori di Non usare le funzioni di get e set in JScript!
La follia, evidentemente, è uno strano male, che colpisce in modo repentino e fuorviante. JScript – sullo stile di Javascript – è implementato seguendo un modello ad oggetti! È un linguaggio ad oggetti, sulla scia del C++. Il fatto che le variabili siano accessibili dall’esterno (come sottolineato nell’articolo – cosa ovvia tra l’altro) non è assolutamente un vanto, anzi. La tecnica dell’incapsulamento è propria della filosofia della programmazione OO. Incapsulare le proprietà, passando dai virtual-method get e set è una forza del linguaggio Object Oriented, non un limite. Consigliare di non farne uso è a dir poco criminale, e gli eventuali problemi di performance sono a carico dell’interprete e dei suoi autori, non certo dell’end-developer.
Quindi, alla fine, JScript va usato come un semplice C, guai a trattarlo come C++, pena “impallare” il browser o chissà cos’altro.

Inoltre, come segnalato sul Blog, il tutto è un falso problema in quanto JScript NON implementa le vere funzioni di get e set, solo Javascript lo fa!

Ma il problema, evidentemente, rimane. In Javascript (scusate ma JScript non riesco proprio a digerirlo) ci sono varie tecniche per creare un oggetto. Ad esempio lo si può creare in modo immediato in questo modo:

1
2
3
4
5
   var myObject = {
       miaProprieta: 0,

       mioMethodo: function() { alert("Hello"); }
   };

In questo modo non ho dichiarato una classe. L’oggetto viene per così dire dichiarato e creato contemporaneamente. È un modo rapido quando l’oggetto che ci serve è unico.

Oppure, il che è equivalente ai fini pratici:

1
2
3
4
5
6
7
8
function CmyObject() {
    this.miaProprieta = 0;

    this.mioMetodo = function () { alert("Hello") }

}
//
var iMyObject = new CmyObject();

In questo caso prima si definisce la classe – tramite una function- (CmyObject) e poi si crea esplicitamente l’oggetto con new.

A parte le questioni stilistiche relative al singolo sviluppatore, il problema di come accedere alle proprietà di una classe rimane. Consiglio vivamente a tutti gli interessati, comumque, di leggere le risposte al Blog di Microsoft, davvero interessanti.

Sul Blog erano presenti tre modi di accesso: con le funzioni get e set, diretto e passando da prototype. Alla fine la cosa simpatica è stata che sul Blog c’è un codice per eseguire un Testdrive, una prova dei tre metodi indicati sopra. Il codice è presente sul Blog ma lo riporto qui per completezza:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
<script>
// Slow Car definition
function SlowCar()
{
      this.m_tireSize = 17;
      this.m_maxSpeed = 250; // One can always dream!
      this.GetTireSize = SlowCar_get_tireSize;
      this.SetTireSize = SlowCar_put_tireSize;
}
function SlowCar_get_tireSize()
{
      return this.m_tireSize;
}
function SlowCar_put_tireSize(value)
{
      this.m_tireSize = value;
}
</script>


<script>
// Faster Car, no more property accessors
function FasterCar()
{
      this.m_tireSize = 17;
      this.m_maxSpeed = 250; // One can always dream!
}
</script>


<script>
// Prototype Car, use the language features!
function PrototypeCar()
{
      this.m_tireSize = 17;
      this.m_maxSpeed = 250; // One can always dream!
}

PrototypeCar.prototype.GetTireSize = function() { return this.m_tireSize; };
PrototypeCar.prototype.SetTireSize = function(value) { this.m_tireSize = value; };
</script>


<script>
function TestDrive()
{
      var slowCar = new SlowCar(); // Safe and reliable, probably not fast
      var fasterCar = new FasterCar(); // Lacks air-bags, probably faster
      var protoCar = new PrototypeCar(); // Can technology win the day?


      var start = (new Date()).getTime();
      for(var i = 0; i < 100000; i++) { slowCar.SetTireSize(slowCar.GetTireSize() + 1); }
      var end = (new Date()).getTime();
      output.innerHTML += "Slow Car " + (end - start) + "<br>";
     

      start = (new Date()).getTime();
      for(var i = 0; i < 100000; i++) { fasterCar.m_tireSize += 1; }
      end = (new Date()).getTime();
      output.innerHTML += "Faster Car " + (end - start) + "<br>";


      start = (new Date()).getTime();
      for(var i = 0; i < 100000; i++) { protoCar.SetTireSize(protoCar.GetTireSize() + 1); }
      end = (new Date()).getTime();
      output.innerHTML += "Prototype Car " + (end - start) + "<br>";
}
</script>

<button onclick="TestDrive();">Test Drive Cars!</button>
<div id="output"></div>

Ora, questo è l’output (relativo alla mia macchina) con IE7:
Slow Car 515
Faster Car 63
Prototype Car 547

Con FireFox (v.2.0.0.1):
Slow Car 156
Faster Car 47
Prototype Car 172

Con Opera (v.9.10):
Slow Car 172
Faster Car 47
Prototype Car 172

Insomma :) IE7 ne esce davvero male… non so se notate l’enorme differenza. Quindi direi che JScript potrebbe essere abolito, eliminato, cancellato, vaporizzato. Speriamo che Microsoft si decida anche lei ad adottare Javscript e non i surrogati.

Continua...

Classi Javascript e PHP per validare un’indirizzo di posta elettronica

Riprendendo il post Validare email in Javascript e PHP, ecco una simpatica classe Javascript in grado di verificare e controllare indirizzi di posta elettronica. Il suo uso è davvero semplice, anche se è un controllo lato client, quindi facilmente bypassabile; basta infatti disabilitare Javascript (propongo petizione contro questa possibilità ;) oramai tutti i browser permettono di eludere Javascript, e quindi tutti i controlli associato – a breve non funzionerà più nulla su Internet, vedi Ajax :o ).

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
/*
** @name              : ckmail.js
** @description       : Check email syntax
** @author            : =undo=
** @author-web        : http://www.undolog.com
** @author-email      : g.fazioli@undolog.com - g (dot) fazioli (at) undolog (dot) com
** @date              : 21/09/2006 21.24
** @ver               : 1.0
*/


var oCKMail = {
    __release: "1.0",
    __filter: /^([\w-]+(?:\.[\w-]+)*)@((?:[\w-]+\.)*\w[\w-]{0,66})\.([a-z]{2,6}(?:\.[a-z]{2})?)$/i,
    __username: "",
    __domain: "",
    __ext: "",

    // TO DO
    getUsername: function(e) {
        if(this.__init(e)) return(this.__username);
        return(false);
    },

    // TO DO
    getDomain: function(e) {
        if(this.__init(e)) return(this.__domain);
        return(false);
    },

    // TO DO
    getExtension: function(e) {
        if(this.__init(e)) return(this.__ext);
        return(false);
    },

    // TO DO
    __init: function(e) {
        if( !this.__filter.test(e) ) return(false);
        var t = e.split("@");
        this.__username = t[0];
        this.__domain = t[1];
        t = this.__domain.split(".");
        this.__ext = t[1];
        return(true);
    },

    // TO DO
    // synopsis
    //    check(e,extlist,domainlist);
    // Esegue una serie di controlli standard su un indirizzo e-mail.
    //    extlist        - Si pu&ograve; passare un secondo parametro opzionale che corrisponde ad un array di estensioni che
    //                   sono ammesse o escluse (include/exclude extension) in base al primo valore dell'array, tutte le
    //                   altre saranno considerate errore.
    //                   Eg. [true,"it","com"] passano (include list)
    //                   Eg. [false,"it","com"] NON passano (exclude list)
    //                   Se -1 non viene preso in considerazione
    //    domainlist    - Si pu&ograve; passare un terzo parametro opzionale che corrisponde ad un array di domini che
    //                   sono ammessi o esclusi (include/exclude domain) in base al primo valore dell'array, tutte gli
    //                   altri saranno considerate errore.
    //                   Eg. [true,"alice.it","mac.com"] passano (include list)
    //                   Eg. [false,"alice.it","mac.com"] NON passano (exclude list)
    //                   Se -1 non viene preso in considerazione
    //
    check: function(e) {
        if( this.__init(e) ) {
            // check domainExt array check
            if( arguments.length > 1 ) {
                if( typeof( arguments[1] ) == "object" ) {
                    if( arguments[1][0] ) { // include list
                        for(var i=0; i < arguments[1].length; i++) {
                            if( this.__ext == arguments[1][i].toLowerCase() ) return(true);
                        }
                    } else { // exclude list
                        for(var i=0; i < arguments[1].length; i++) {
                            if( this.__ext == arguments[1][i].toLowerCase() ) return(false);
                        }
                        return(true);
                    }
                    return(false);
                }
            }
            // check domainName array check
            if( arguments.length > 2 ) {
                if( typeof( arguments[2] ) == "object" ) {
                    if( arguments[2][0] ) { // include list
                        for(var i=1; i < arguments[2].length; i++) {
                            if( this.__domain == arguments[2][i].toLowerCase() ) return(true);
                        }
                    } else { // exclude list

                        for(var i=1; i < arguments[2].length; i++) {
                            if( this.__domain == arguments[2][i].toLowerCase() ) return(false);
                        }
                        return(true);
                    }
                    return(false);
                }
            }
            return(true); // email correct
        }
        return(false); // error
    }
};

L’oggetto oCKMail mette a disposizione alcuni metodi per effettuare tutta una serie di controlli paralleli sull’indirizzo, come l’estensione, il dominio, ecc…

Per essere proprio sicuri se disponete di PHP potete aggiungere un’ulteriore ed efficace controllo prima di eseguire il comando mail(). Ecco la classe PHP utile a tale scopo:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
/*
** @name              : cckmail.php
** @description       : Check email syntax
** @author            : =undo=
** @author-web        : http://www.undolog.com
** @author-email      : g.fazioli@undolog.com - g (dot) fazioli (at) undolog (dot) com
** @date              : 21/09/2006 23.58
** @ver               : 1.0
**
** EXAMPLES
**
**    // Controlla un indirizzo ESCLUDENDO quelle e-mail con dominio "e-lementi.com" e "mac.com"
**
**    $oCKMail = new CCKMail();
**    $oCKMail->check($email, NULL, array(false,"e-lementi.com","mac.com") );
**
**    // Controlla un indirizzo INCLUDENDO quelle e-mail con dominio "e-lementi.com" e "mac.com"
**
**    $oCKMail = new CCKMail();
**    $oCKMail->check($email, NULL, array(true,"e-lementi.com","mac.com") );
**
**    // Controlla un indirizzo ESCLUDENDO quelle e-mail con estensione "net","it","org"
**
**    $oCKMail = new CCKMail();
**    $oCKMail->check($email, array(false,"net","it","org") );
**
** HISTORY / CHANGE LOG
**
*/


    if (!function_exists('checkdnsrr')) {
        function checkdnsrr($host, $type = '') {
            if(!empty($host)) {
                if($type == '') $type = "MX";
                @exec("nslookup -type=$type $host", $output);
                while(list($k, $line) = each($output)) {
                    if(eregi("^$host", $line)) {
                        return true;
                    }
                }
                return false;
            }
        }
    }
    //
    class CCKMail {
        var $__release = "1.1";
        var $status = false;
        var $username;
        var $domain;
        var $ext;
        //
        function CCKMail() {}
        //
        function _test($e) {
            $this->status = false;
            $p = '/^.+\@(\[?)[a-zA-Z0-9\-\.]+\.([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$/';
            if( (preg_match($p, $e)) ) {
                $t               = explode("@",$e);
                $this->username  = strtolower( $t[0] );
                $this->domain    = strtolower( $t[1] );
                $t               = explode(".",$this->domain);
                $this->ext       = strtolower( $t[1] );
                //
                if(checkdnsrr($this->domain.'.', 'MX') )    $this->status = true;
                if(checkdnsrr($this->domain.'.', 'A') )     $this->status = true;
                if(checkdnsrr($this->domain.'.', 'CNAME') ) $this->status = true;
            }
        }
        //
        function check($m, $e=NULL,$d=NULL) {
            $this->_test($m);
            if( $this->status ) {
                // check domainExt array check
                if( !is_null($e) ) {
                    if( $e[0] ) { // include list
                        for($i=1; $i < sizeof($e); $i++) {
                            if( $this->ext == strtolower( $e[$i] ) ) return(true);
                        }
                    } else { // exclude list
                        for($i=1; $i < sizeof($e); $i++) {
                            if( $this->ext == strtolower( $e[$i] ) ) return(false);
                        }
                        return(true);
                    }
                    return(false);
                }
                // check domainName array check
                if( !is_null($d) ) {
                    if( $d[0] ) { // include list
                        for($i=1; $i < sizeof($d); $i++) {
                            if( $this->domain == strtolower( $d[$i] ) ) return(true);
                        }
                    } else { // exclude list
                        for($i=1; $i < sizeof($d); $i++) {
                            if( $this->domain == strtolower( $d[$i] ) ) return(false);
                        }
                        return(true);
                    }
                    return(false);
                }
                return(true);
            }
            return(false);
        }
    }
?>

La cosa ineteressante è la capacità di questa classe di connettersi ai server MX (vedi checkdnsrr() ) per verificare la presenza del dominio. Quindi oltre ad eseguire un controllo sintattico sull’indirizzo di posta elettronica viene eseguito un vero e proprio ping del dominio passato. Possiamo dire che questo metodo è sicuro all’80%…

Continua...

Classe Javascript per il rilevamento di Flash

Anche se non si realizza un sito interamente in Flash, alcuni componenti possono presentarsi comunque all’interno della pagina, come banner, claim, visori RSS, ecc… Eco quindi un modo semplice per verificare se Flash è attivo e installato. Proponiamo qui un metodo che non necessità di più pagine, come proposto dalla stessa Adobe. Faremo in modo di risolvere tutto all’interno di un’unica pagina.

La classe qui presentata permette anche di risolvere l’ultimo problema nato con Explorer, ovvero quello dell’attivazione di un controllo ActiveX. Per risolverlo basta utilizzare Javascript per inserire il componente Flash, proprio quello che fa la nostra classe.

La prima cosa di cui abbiamo bisogno è una simpatica classe Javascript che ci permetterà di eseguire tutti i controlli necessari:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
<!--
  /*
  ** Detect Flash Class & Path insertFlash Object
  **
  */


var df = {
  __release: "1.0",
  _isIE: ( (navigator.appVersion.indexOf("MSIE") != -1) ? true : false),
  _isWin:( (navigator.appVersion.toLowerCase().indexOf("win") != -1) ? true : false),
  _isOpera:( (navigator.userAgent.indexOf("Opera") != -1) ? true : false),
 
  getSwfVer: function (i) {
    // Le versioni di NS/Opera dalla 3 in poi verificano la presenza del plug-in Flash nell'array dei plug-in
    if (navigator.plugins != null && navigator.plugins.length > 0) {
      if (navigator.plugins["Shockwave Flash 2.0"] || navigator.plugins["Shockwave Flash"]) {
        var swVer2 = navigator.plugins["Shockwave Flash 2.0"] ? " 2.0" : "";
            var flashDescription = navigator.plugins["Shockwave Flash" + swVer2].description;
        var descArray = flashDescription.split(" ");
        var tempArrayMajor = descArray[2].split(".");
        var versionMajor = tempArrayMajor[0];
        var versionMinor = tempArrayMajor[1];
        if ( descArray[3] != "" ) var tempArrayMinor = descArray[3].split("r");
        else var tempArrayMinor = descArray[4].split("r");
        //
            var versionRevision = tempArrayMinor[1] > 0 ? tempArrayMinor[1] : 0;
              var flashVer = versionMajor + "." + versionMinor + "." + versionRevision;
          } else  var flashVer = -1;
    }
    else if (navigator.userAgent.toLowerCase().indexOf("webtv/2.6") != -1) flashVer = 4;
    else if (navigator.userAgent.toLowerCase().indexOf("webtv/2.5") != -1) flashVer = 3;
    else if (navigator.userAgent.toLowerCase().indexOf("webtv") != -1) flashVer = 2;
    else flashVer = -1;
    //
    return flashVer;
  },
 
  detectFlashVer:function (reqMajorVer, reqMinorVer, reqRevision) {
    var reqVer = parseFloat(reqMajorVer + "." + reqRevision);
    for (var i=25;i>0;i--) { 
      if (this._isIE && this._isWin && !this._isOpera) var versionStr = VBgetSwfVer(i);
      else var versionStr = this.getSwfVer(i);
      if (versionStr == -1 ) return false;
      else if (versionStr != 0) {
        if(this._isIE && this._isWin && !this._isOpera) {
          var tempArray         = versionStr.split(" ");
          var tempString        = tempArray[1];
          var versionArray      = tempString .split(",");      
        } else var versionArray = versionStr.split(".");
        //
        var versionMajor      = versionArray[0];
        var versionMinor      = versionArray[1];
        var versionRevision   = versionArray[2];
       
        var versionString     = versionMajor + "." + versionRevision;   // 7.0r24 == 7.24
        var versionNum        = parseFloat(versionString);
            // è la versione maggiore >= versione maggiore richiesta è la versione minore >= versione minore richiesta
        if ( (versionMajor > reqMajorVer) && (versionNum >= reqVer) ) return true;
        else return ((versionNum >= reqVer && versionMinor >= reqMinorVer) ? true : false );
      }
    }
    return (reqVer ? false : 0.0);
  },
 
  // TO DO
  insertFlash: function(n,w,h) {
    if( this.detectFlashVer(8,0,0) ) {
      n += ".swf";
      document.write( '<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=7,0,29,0" width="'+w+'" height="'+h+'">\n' );
      document.write( '<param name="movie" value="'+n+'" />\n');
      document.write( '<param name="quality" value="auto" />\n' );
      document.write( '<embed src="'+n+'" width="'+w+'" height="'+h+'" quality="auto" pluginspage="http://www.macromedia.com/go/getflashplayer" type="application/x-shockwave-flash"></embed>\n' );
      document.write( '</object>\n');
    } else document.write( '<a id="flash_alternate" target="_blank" href="http://www.adobe.com/go/getflashplayer"></a>' );
  }
};

//-->

Come al solito, Internet Explorer (7) si differenzia e vuole un codice appositamente strutturato in VBScript:

[vb]

[/vb]

Salviamo questi due file (df.js e df.vbs nella cartella js) e includiamoli nella nostra pagina (index.html, index.php o default.html, ecc…) all’interno del TAG HEAD.

1
2
<script language="javascript1.2" type="text/javascript" src="js/df.js"></script>
<script language="VBScript" type="text/vbscript" src="js/df.vbs"></script>

Ora abbiamo tutto il necessario e possiamo spostarci nella pagina che conterrà l’oggetto Flash. Posizionatevi nel punto dove Flash sarà visualizzato e inserite il seguente codice:

1
<script language="javascript1.2" type="text/javascript">df.insertFlash("flash/splash","900","122");</script>

Nell’esempio abbiamo assunto che esista un file splash.swf nella cartella flash! Notate che non è necessario inserire l’estensione swf. I due numeri 900 e 122 sono le dimensioni.

Ancora meglio sarebbe supportare il caso – remoto – dove Javascript è stato disabilitato. In questa circostanza potete scegliere di procedere in due modi:

1. Inseire direttamente in codice OBJECT/EMBED
2. Notificare che Javascript è disabilitato

Nel primo caso perdiamo il controllo sulla presenza di Flash ed Explorer richiederà di attivare il controllo ActiveX. Tuttavia il filmato sarà visibile, se Flash è installato.

Nel secondo caso possiamo mostrare un’immagine e/o notoficare che con Javascript spento non è possibile verificare la presenza del Plug-in Adobe Flash. Ad esempio, scegliendo la soluzione numero 1:

1
2
3
4
5
6
7
8
9
10
<div id="claim">
    <script language="javascript1.2" type="text/javascript">df.insertFlash("flash/splash","900","122");</script>
  <noscript>
    <object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=7,0,19,0" width="900" height="122">
            <param name="movie" value="flash/splash.swf" />
            <param name="quality" value="high" />
            <embed src="flash/splash.swf" quality="high" pluginspage="http://www.macromedia.com/go/getflashplayer" type="application/x-shockwave-flash" width="900" height="122"></embed>
    </object>
  </noscript>
</div>

Rilevare Flash e gestire le numerose alternative, come spiegato su Flash detect: come rilevare Flash, non è proprio comodissimo, speriamo almeno che la cosa non andrà a peggiorare con il tempo.

Continua...

HTML dinamico con Javascript

Scrivere codice HTML dinamicamente all’interno di una pagina è possibile ed utile. Il modo più diretto e conosciuto è quello di utilizzare documenti.write() o un contenitore DIV predisposto ad accettare codice inserito tramite innerHTML. In alternativa è possibile agganciarsi ad un TAG esistente ed utilizzare il DOM per aggiungere o rimuovere elementi all’interno della pagina. Ad esempio immmaginiamo di voler caricare un nuovo file Javascript senza utilizzare scripting lato server e quindi il ricaricamento della pagina. La funzioni qui sotto, ad esempio, aggiunge un file Javascript alla vostra pagina, passato come parametro (comprensivo di path).

1
2
3
4
5
6
function addScripting(s) {
 var scriptNode = document.createElement('script');
 document.getElementsByTagName("head")[0].appendChild(scriptNode);
 scriptNode.language='javascript';
 scriptNode.src=s;
}

Similmente è possibile aggiungere un foglio di stile alla nostra pagina, indicato dalla variabile cssfile:

1
2
3
4
5
var cssNode = document.createElement('link');
cssNode.setAttribute('rel', 'stylesheet');
cssNode.setAttribute('type', 'text/css');
cssNode.setAttribute('href', cssfile );
document.getElementsByTagName('head')[0].appendChild(cssNode);

Continua...

Flash detect: come rilevare Flash

Come si può determinare se un browser ha installata la versione corretta del Plugin Adobe Flash? Per fare questo esistono – notoriamente – 5 tecniche:

  • Affidarsi alla caratteristica auto-installante dei TAG OBJECT ed EMBED
  • Utilizzare uno script (Javascript e/o VBScript) appositamente fornito da Adobe
  • Utilizzare un artifizio con un solo filmato Flash
  • Non fare nulla ;)
  • Far scegliere all’utente

Continua...

Ajax senza HTTPRequest

Come molti sviluppatori Web sanno, prima dell’avvento dell’oggetto XMLHttpRequest, il problema del ricaricamento di una pagina Web veniva risolto con la tecnica dei FRAME o IFRAME nascosti. Questo artifizio ha permesso per molti hanni di risolvere alcune problematiche di interfaccia altrimenti irrisolvibili. Un vantaggio nell’uso dei FRAME nascosti, tra l’altro, era la possibilità di mantenere l’HISTORY del browser! Cosa che l’oggetto XMLHttpRequest non permette.

Oltre a tecniche HTML che ricorrono a FRAME o IFRAME nascosti, esiste la possibilità di usare Flash come sub-canale di comunicazione tra la pagina e il Server. Alcune esperienze in tale direzione sono tuttora in sviluppo (vedi ad esempio Fjax). L’idea è quella di “nascondere” un filmato Flash all’interno della pagina HTML (come accadeva con i FRAME) e comunicare con esso tramite Javascript (o VBScript per il solo ambiente Microsoft).

Tuttavia questa tecnica nascoste una serie di insidie. Prima di tutto costringe l’utente finale ad installare il PlugIn di Flash, e quindi non rappresenta una soluzione HTML (pura) pulita. Inoltre richiede comunque l’uso spinto di Javascript come interfaccia tra Flash e la pagina, quindi tanto vale la pena usare l’oggetto XMLHttpRequest. Quando poi si inizia a scrivere un framework in ActionScript viene voglia di realizzare tutto in Flash. Ecco che la variante all’oggetto XMLHttpRequest comincia ad avere poco senso.
In definitiva se non si vuole usare l’oggetto XMLHttpRequest, conviene affidarsi all’ormai consolidata tecnica dei FRAME nascosti. Addirittura c’è chi usa proprio una tecnica mista: XMLHttpRequest + IFRAME!

Tuttavia, oramai, Ajax (nella forma dell’oggetto XMLHttpRequest) ha riscosso un così grande successo che in futuro l’oggetto XMLHttpRequest verrà sia supportato che migliorato dai produttori di browser (come Microsoft, Mozilla, Opera, ecc…). In pratica XMLHttpRequest diventerà un componente di default (come accade già in FireFox) all’interno del browser, raggiungibile via Javascript! Quindi perchè non usarlo?

Continua...

Protopage v3: qualcosa di nuovo all’orizzonte

Su Ajaxan.com è comparso un articolo interessante su un’esperienza londinese davvero simpatica. Protopage è un piccolo sistema operativo dedicato allo condivisione. Il motore dell’ambiente è ben scritto e l’interfaccia risulta estremamente facile da usare. Questo è sicuramente un bell’esempio di come il Web sta evolvendo. Tuttavia rimangono ancora insidie di compatibilità, vedi ad esempio Explorer 7, ma la strada sembra densa di sorprese.

Continua...

Il futuro prossimo venturo di Ajax

Ajax, per qualcuno, è stata una rivoluzione. Per alcuni programmatori “navigati” è stato solo un modo diverso di fare quello che prima si realizzava sfruttando il TAG HTML IFRAME (o i FRAME stessi nascosti). Evidentemente hanno tutti ragione. Ajax è stata una rivoluzione perchè è capitato in un momento particolare, dove la diffusione della banda-larga e la maturità del Web (web 2.0?) hanno permesso un approccio completamente diverso rispetto al passato.

La proliferazione delle Web Applications da parte di grandi gruppi come Microsoft, Yahoo, Google ed altri, dimostra quanto si stia investendo in questo nuovo approccio. Il futuro – prossimo venturo – di Ajax è quindi luminoso, denso di novità e colpi di scena.

I browser e gli scripting server (come PHP) potranno dare ausilio a questo nuovo modo di vedere il Web e le sue risorse! Applick.com ne è una dimostrazione lampante!

Continua...

Internet Explorer 7 (IE7): PNG e CSS ancora lontani?

A Redmond devono avere qualche grosso problema di comprendonio! Risulta magnificamente assurdo che sul finire dell’anno 2006 ancora non ci siano le basi per una – anche – approssimata compatibilità tra IE7 e Firefox! Nonostante il rilascio ufficiale – anche se con un set limitato di localizzazioni – di Internet Explorer 7, l’engine di rendering delle pagine soffre ancora di evidenti difetti di programmazione! Senza infierire entrando in numerosi dettagli elenco solo due clamorosi bachi ancora presenti in questo rilascio ufficiale!!

Prima di tutto i PNG vengono resi differentemente dai GIF… e, peggio ancora, in position absolute subiscono strani contorni a seconda di come gira a IE!! Evidente baco? O follia di qualche junior-developer?

Sul fronte CSS la pseudo classe :hover continua a non essere supportata su tutti i TAG, nonostante molti blog la diano per funzionante! Ma su quale sistema? Vedi W3C
Un semplice p:last-child è praticamente ignorato! Giustamente Microsoft ha supportato p:first-child. Ora, se implementi il first che cosa ti costa implementare anche last? Mistero…

L’apice dell’assurdo, poi, lo si ottiene con le liste puntate! Udite udite! IE7 si comporta esattamente come IE6! Della serie: vi siete portati appresso codice fallato? Troppi copia e incolla evidentemente! Se definitie una lista con i canonici UL LI e un’immagine personalizzata come list-point, non provate ad usare un float sull’elemento LI, l’immagine scomparirà misteriosamente, esattamente come accadeva su IE6!! L’unico, manco a dirlo, a rendere il tutto corretto è il solito – vecchio – FireFox!

Sul blog di IE7 sono numerose le lamentale. Nonostante sia apprezzato lo sforzo del pachiderma Microsoft di aprire un blog durante lo sviluppo di un software come IE7, rimane tuttavia il dubbio dell’efficacia di questa mossa. Hanno davvero ascoltato le richieste degli utenti-sviluppatori? Il blog di IE7 è stato aperto con troppo ritardo?

Ancora una volta non ci resta che attendere una service-pack prossima ventura…

Continua...



Stop SOPA