Articoli con Tag ‘Internet’
Per realizzare delle Tabstrip davvero accattivanti esiste una tecnica particolarmente indicata che consente di mediare tra difficoltà grafiche e codice Javascript. Vediamo prima di tutto come costruire un templete in Photoshop per le nostre Tabstrip:
Costruita un tabstrip simile a quella mostrata qui sopra in figura, usiamo il tool per la selezione delle area di taglio per generare la forma che avrà la nostra tabella HTML. L’uso della tabella, in questo caso, è particolarmente indicato – come vedremo, in quanto semplifica sia il design che il codice Javascript. Ritagliamo dunque la nostra Tabstrip nel modo seguente:
Nel nostro file Photoshop dobbiamo considerare tutte le combinazioni delle schede (tab). Abbiamo quindi la scheda iniziale selezionata (taglio 3), i punti intermedi (taglio 5 e taglio 7) e la scheda finale non selezionata (taglio 9) con – eventuale – bordo di rifinitura (taglio 10 – opzionale a seconda del design). Bastano poi 3 combinazioni per risolvere tutti i casi visivi. Come mostrato qui sotto:
Graficamente parlando potete disporre le schede anche in sovrapposizione e sfalsate, come mostrato qui sotto:
Questione di gusto e di necessità… tornando all’immagine completa, con le tre strisce Tabstrip per le combinazioni, le ultime due servono per risolvere i casi limite; tagliatele come mostrato qui sotto:
Il taglio 17 e il taglio 23 risolvono i due casi limite: prima tab non selezionata, ultima selezionata. Il taglio 19 è l’opposto del taglio 5 e del taglio 7, visti in precedenza. L’immagine completa che otteniamo e che possiamo salvare per futuri cambiamenti di design è la seguente:
Per non confonderci quando affronteremo la parte Javascript, il nome dei tagli è il seguente:
- taglio 3 = tabLeftFirstOn
- taglio 4 = tabStripeOn
- taglio 5 = tabMiddleOnOff
- taglio 6 = tabStripeOff
- taglio 7 = tabMiddleOffOff
- taglio 9 = tabRightLastOff
- taglio 10 = topBg
- taglio 17 = tabLeftFirstOff
- taglio 19 = tabMiddleOffOn
- taglio 23 = tabRightLastOn
Per realizzare tutto ciò ci serve adesso un codice HTML, un codice CSS e un codice Javascript come gestore dei click sulle schede tab. Il codice HTML è banale ma articolato. Quindi propongo una classe PHP in grado di generarlo ogni volta che ci serve. In sostanza si tratta di creare una tabella HTML racchiusa in determinati DIV con ID particolari che ci serviranno poi per l’esecuzione del codice Javascript e per racchiudere il design tramite i CSS. Il codice HTML generato – tanto per farsi un’idea – di un Tabstrip con quattro schede è il seguente:
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
| <div id="cscoTabStrip">
<div id="jscoTabStrip_info">
<table width="100%" cellspacing="0" cellpadding="0" border="0">
<tr>
<td><div class="tabLeftFirstOn"></div></td>
<td nowrap="" class="tabStripeOn"><a id="jscoTS_tab1" onclick="_onTabStrip( this );" class="tabsLink" title="Caratteristiche">Caratteristiche </a></td>
<td><div class="tabMiddleOnOff"></div></td>
<td nowrap="" class="tabStripeOff"><a id="jscoTS_tab2" onclick="_onTabStrip( this );" class="tabsLink" title="Come funziona">Come funziona </a></td>
<td><div class="tabMiddleOffOff"></div></td>
<td nowrap="" class="tabStripeOff"><a id="jscoTS_tab3" onclick="_onTabStrip( this );" class="tabsLink" title="Interfaccia">Interfaccia </a></td>
<td><div class="tabMiddleOffOff"></div></td>
<td nowrap="" class="tabStripeOff"><a id="jscoTS_tab4" onclick="_onTabStrip( this );" class="tabsLink" title="Richiesta Iscrizione">Richiesta Iscrizione </a></td>
<td><div class="tabRightLastOff"></div></td>
<td width="100%" class="topBG"></td>
</tr>
</table>
</div>
<div id="jscoTSC_jscoTS_tab1" class="tabStripContent">
<p>contenuto SCHEDA TAB 1 </p>
</div>
<div id="jscoTSC_jscoTS_tab2" class="tabStripContentHidden">
<p>contenuto SCHEDA TAB 2 </p>
</div>
<div id="jscoTSC_jscoTS_tab3" class="tabStripContentHidden">
<p>contenuto SCHEDA TAB 3 </p>
</div>
<div id="jscoTSC_jscoTS_tab4" class="tabStripContentHidden">
<p>contenuto SCHEDA TAB 4 </p>
</div>
</div> |
Il codice PHP che genera questo HTML è il seguente:
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 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132
| // ***********************************************************
//
// file : tabstrip.php
// Author : Giovambattista Fazioli (www.undolog.com)
// Web : http://www.undolog.com
// E-mail : info (at) undolog (dot) (com)
// Created : 03/10/2005 10.07
// Modified : 06/11/2005 07.17
//
// PROPERTIES
// name - (STRING) - Nome (ID) della Window
// style - (STRING) - Stile aggiuntivi in linea
// tabs - (ARRAY) - Elenco delle schede (tab)
//
// METHODS
// addTab() - Aggiunge una scheda al TabStrip
// toString() - Restituisce l'output HTML per la Window
// show() - Visualizza l'output HTML per la Window
//
// NOTE
//
// EXAMPLES
//
// ***********************************************************
class CSCO_UI_TABSTRIP {
// #public properties
var $name;
var $style;
var $tabs;
var $jsListener;
// #private properties
var $strHeader;
var $strBody;
// =====================================================
// CONSTRUCTOR:
// =====================================================
function CSCO_UI_TABSTRIP ( $name, $jsListener="" ) {
$this->name = $name;
$this->jsListener = $jsListener;
$this->tabs = array();
}
// =====================================================
// METHOD: addTab()
//
// DESCRIPTION
// Aggiunge una scheda al TabStrip.
//
// EXAMPLES
//
// =====================================================
function addTab ( $name, $label, $tooltip, $content, $selected=false ) {
$tab = array( "name" => $name,
"label" => $label,
"tooltip" => $tooltip,
"content" => $content,
"selected" => $selected );
$this->tabs[] = $tab;
}
// =====================================================
// METHOD: toString()
//
// DESCRIPTION
// Restituisce l'output HTML per la TabStrip.
//
// EXAMPLES
//
// =====================================================
function toString () {
//
$this->strHeader = '<div id="cscoTabStrip" '.
( ($this->style != "")? 'style="'.$this->style.'"':'' ).'>'.
'<div '.
'id="jscoTabStrip_'.$this->name.'">'.
'<table style="border-collapse: collapse;" width="100%" border="0" cellspacing="0" cellpadding="0">'.
'<tr>';
$strBody = "";
// FirstLeft
$classLeft = ( $this->tabs[0]["selected"] )? "tabLeftFirstOn":"tabLeftFirstOff";
$this->strHeader .= '<td><div class="'.$classLeft.'"></div></td>';
for($i=0; $i < sizeof($this->tabs); $i++) {
//
$classBck = ( $this->tabs[$i]["selected"] )? "tabStripeOn":"tabStripeOff";
//
if( $i == ( sizeof($this->tabs) -1) ) {
$classMiddle = ( $this->tabs[$i]["selected"] )? "tabRightLastOn":"tabRightLastOff";
} else {
if( $this->tabs[$i]["selected"] ) {
$classMiddle = "tabMiddleOnOff";
} else {
$classMiddle = ( $this->tabs[$i+1]["selected"] )? "tabMiddleOffOn":"tabMiddleOffOff";
}
}
//
//
$this->strHeader .= '<td nowrap="nowrap" class="'.$classBck.'">'.
'<a title="'.$this->tabs[$i]["tooltip"].'" class="tabsLink" onclick="_onTabStrip( this '.( ($this->jsListener!="")? (",'".$this->jsListener."'"):"" ).' );" id="jscoTS_'.$this->tabs[$i]["name"].'">'.$this->tabs[$i]["label"].'</a>'.
'</td>'.
'<td><div class="'.$classMiddle.'"></div></td>';
//
$class = ($this->tabs[$i]["selected"])? "tabStripContent":"tabStripContentHidden";
$strBody .= '<div class="'.$class.'" id="jscoTSC_jscoTS_'.$this->tabs[$i]["name"].'">'.$this->tabs[$i]["content"].'</div>';
//
}
// align foo
$this->strHeader .= '<td class="topBG" width="100%"></td>'.
'</tr></table>';
$this->strBody = '<div>'.$strBody.'</div>';
//
return( $this->strHeader.$this->strBody.'</div></div>');
}
// =====================================================
// METHOD: show()
//
// DESCRIPTION
// Visualizza l'output HTML per la TabStrip.
//
// EXAMPLES
//
// =====================================================
function show () {
echo ( $this->toString() );
}
} // END OF SCO_UI_TABSTRIP.PHP FILE |
Per usare la classe basta questo frammento:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| // File con la definizione della class
require "tabstrip.php";
// Creo oggetto Tabstrip
$t = new CSCO_UI_TABSTRIP( "info" );
// Creo / leggo da file - i contenuti delle schede
$s1 = "Contenuto 1";
$s2 = "Contenuto 2";
$s3 = "Contenuto 3";
$s4 = "Contenuto 4";
// Aggiungo schede
$t->addTab("tab1","Caratteristiche","Caratteristiche", $s1, true);
$t->addTab("tab2","Come funziona","Come funziona", $s2);
$t->addTab("tab3","Interfaccia","Interfaccia", $s3);
$t->addTab("tab4","Richiesta Iscrizione","Richiesta Iscrizione", $s4);
// Mostro tutto - in alternativa usare toString() method
$t->show(); |
Definiamo ora gli stili:
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
| div#cscoTabStrip {font-size:13px}
div#cscoTabStrip .tabStripeOff a.tabsLink,
div#cscoTabStrip .tabStripeOff a.tabsLink:link,
div#cscoTabStrip .tabStripeOff a.tabsLink:visited {display:block;cursor:pointer;white-space:nowrap;color:#888;margin:0 4px 0 4px}
div#cscoTabStrip .tabStripeOff a.tabsLink:hover {color:#f70}
div#cscoTabStrip .tabStripeOn a.tabsLink,
div#cscoTabStrip .tabStripeOn a.tabsLink:link,
div#cscoTabStrip .tabStripeOn a.tabsLink:visited {display:block;cursor:pointer;white-space:nowrap;color:#000;font-weight:bold;margin:0 4px 0 4px}
div#cscoTabStrip .tabStripeOn a.tabsLink:hover {}
div#cscoTabStrip .tabLeftFirstOff {display:block;width:20px;height:35px;background:url(tabstrip/tabLeftFirstOff.png) no-repeat;}
div#cscoTabStrip .tabLeftFirstOn {display:block;width:20px;height:35px;background:url(tabstrip/tabLeftFirstOn.png) no-repeat;}
div#cscoTabStrip .tabMiddleOffOff {display:block;width:20px;height:35px;background:url(tabstrip/tabMiddleOffOff.png) no-repeat;}
div#cscoTabStrip .tabMiddleOffOn {display:block;width:20px;height:35px;background:url(tabstrip/tabMiddleOffOn.png) no-repeat;}
div#cscoTabStrip .tabMiddleOnOff {display:block;width:20px;height:35px;background:url(tabstrip/tabMiddleOnOff.png) no-repeat;}
div#cscoTabStrip .tabStripeOff {background:url(tabstrip/tabStripeOff.png) repeat-x;}
div#cscoTabStrip .tabStripeOn {background:url(tabstrip/tabStripeOn.png) repeat-x;}
div#cscoTabStrip .tabRightLastOff {display:block;width:20px;height:35px;background:url(tabstrip/tabRightLastOff.png) no-repeat;}
div#cscoTabStrip .tabRightLastOn {display:block;width:20px;height:35px;background:url(tabstrip/tabRightLastOn.png) no-repeat;}
div#cscoTabStrip .topBG {text-align:right;background:url(tabstrip/topBg.png) repeat-x;}
div#cscoTabStrip .tabStripContent {width:100%;padding:0;}
div#cscoTabStrip .tabStripContentHidden {display:none;} |
Il codice Javascript è assai blando, scritto in un’epoca lontata quando Prototype.js non esisteva. Inoltre nell’esempio qui sotto faccio uso di una libreria di effetti (non esisteva nemmeno Scriptaculous) ancora valida, quindi la riga che usa la transizione Opacity la potete sostituire con quello che volete:
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
| function _onTabStrip(t) {
if( arguments.length > 1 ) {
var evt = "onBeforeClick";
var n = t.id.substr(7);
var e = "var res = "+arguments[1]+"('"+n+"','"+evt+"');";
eval(e);
if(!res) return(false);
}
var tr = t.parentNode.parentNode;
for(var i = 1; i < tr.childNodes.length-2; i++ ) {
var td = tr.childNodes[i];
var el = td.childNodes[0];
//
switch( el.tagName ) {
case "DIV":
el.className = "tabMiddleOffOff";
break;
case "A":
td.className = "tabStripeOff";
break;
}
}
var td = t.parentNode;
td.previousSibling.childNodes[0].className = "tabMiddleOffOn";
td.nextSibling.childNodes[0].className = "tabMiddleOnOff";
tr.childNodes[0].childNodes[0].className = ( tr.childNodes[1].childNodes[0] === t )?"tabLeftFirstOn":"tabLeftFirstOff";
var last = Number( (tr.childNodes.length-2) );
tr.childNodes[last].childNodes[0].className = ( tr.childNodes[last-1].childNodes[0] === t )?"tabRightLastOn":"tabRightLastOff";
t.parentNode.className = "tabStripeOn";
var mc = $G( "jscoTSC_"+t.id );
var d = mc.parentNode;
for (var i = 0; i < d.childNodes.length; i++) {
d.childNodes[i].className = "tabStripContentHidden";
}
mc.className = "tabStripContent";
var to = new OpacityTween(mc,Tween.regularEaseOut, 0, 100, 1);
to.t = t; to.args = arguments;
to.onMotionFinished = function() {
if( this.args.length > 1 ) {
var evt = "onAfterClick";
var n = this.t.id.substr(7);
var e = "var res = "+this.args[1]+"('"+n+"','"+evt+"');";
eval(e);
}
};
to.start();
} |
In pratica le righe dalla 36 alle 46 possono essere sostituite con quello che volete, anche un display=”none”. Il codice è antiquato, almeno rispetto le nuove tecniche di Javascript non intrusivo (oggi lo scriverei in modo diverso). Tuttavia la parte che rimane interessante ed attuale e la configurazione della tabella HTML che gestisce i Tabstrip. Essa permette una resa grafica di alto livello, a differenza di alcuni altri metodi che – in sostanza – trattano le schede Tab come semplici DIV uno accanto all’altro.
Un modo ancora migliore sarebbe quello di sfruttare lo z-index (ordine di visualizzazione) presente negli stili CSS, così da gestire la sovrapposizione di elementi grafici. Purtroppo, ad oggi, è una tecnica assai difficile da implementare a causa delle differenze tra i browser che la rendono di fatto instabile, salvo rare circostanze.
Presto ne farò una versione più moderna… se avete dubbi o domande sono qui!
Continua...
Dopo aver sistemato la grafica di Undolog e aver apportato gli ultimi ritocchi ad alcuni titoli (vedi sidebar), mi sono divertito ad usare l’accoppiata Prototype.js e Scriptaculous, in modalità non intrusiva (Unobtrusive)! Ecco un video (ma lo potete provare di persona qui a destra
) con la simpatica funzione che ho aggiunto alla sidebar di Undolog, che oltre a renderla più gradevole spero la renda anche più funzionale!
Il codice che ho utilizzato è davvero semplice:
1 2 3 4 5 6 7 8 9
| Event.observe(window, 'load', function() {
$$('h2.dropdown').each( function(element) { element.style.cursor="pointer";
element.observe('click', function(event) {
if( this.next().style.display == "" ) new Effect.BlindUp(this.next(),{duration:.5});
else new Effect.BlindDown(this.next(),{duration:.3});
Event.stop(event);
}.bindAsEventListener(element))
})
}) |
Inoltre notate che la prima volta che viene caricata la Home Page di Undolog viene automaticamente chiuso il pannello delle Categorie – identificato dall’id tit_category:
1
| Event.observe(window, 'load', function() {new Effect.BlindUp($("tit_category").next(),{duration:.5}) } ) |
I titoli sulla sidebar sono definiti, quindi, in questo modo:
1 2 3 4
| <h2 id="tit_category" class="dropdown replacetitle" title="Categorie"><span>Categorie </span></h2>
<div>
<p>Contenuto da far sparire! </p>
</div> |
Tramite la classe dropdown vengono identificati i titoli H2 da rendere dinamici, grazie alla funzione doppio-dollaro ($$) di Prototype.js – di cui abbiamo già parlato…
Continua...
Se nel 1979 il celebre brano dei Buggles cantava ”Video killed the radio star”, oggi è il caso di riproporlo modificando i soggetti: Video -> Internet/Net TV e radio -> TV/la televisione come la conosciamo! Il vantaggio di poter trasmettere in diretta e applicare tutte le formule della trasmissione non lineare fanno della Net TV un elemento essenziale ed insostituibile nel panorama informativo fornito da Internet. Il fenomeno è già esploso e la sua avanzata è ormai inesorabile. In Italia, come spesso accade, la lentezza e la poca lungimiranza rendono difficile apprezzare quello che sarà il futuro prossimo della TV. Tuttavia se ne parla e questo è già un inizio. Grazie ai Blog oggi è possibile informare più rapidamente rispetto a qualche tempo fa.
Oltre ai contenuti generati dagli utenti il passo successivo è quello di fornire format, la killer application che probabilmente - almeno nel panorama italiano – ancora stenta a decollare. Joost promette la serie C.S.I., dopo aver attivato un canale sul calcio in italiano (gli italiani si prendono solo con il calcio?), ma ciò non basta evidentemente. Ci deve essere un vero e proprio trasferimento dei contenuti attualmente disponibili sui canali tradizionali, DTT compreso, in modo da far decollare la Net TV come merita; telegionali, serial, film (vedi “I pirati di Silicon Valley” – peccato solo in inglese). Le beta dovrebbero terminare a breve, Babelgum compreso, quindi vediamo cosa accaddrà con i motori accesi e usciti fuori dal garage!
Continua...
Perchè passare ad Apollo per visualizzare HTML e contenuto dinamico quando un browser già lo permette? Perchè usare Joost per vedere la Net TV quando un browser già lo permette?
Perchè chi produce browser non ha inserito due semplici funzioni al loro interno:
- Finestre Windowless
- P2P Object
Finestre Windowless
Questa semplice caratteristica permetterebbe di sfruttare al meglio la connessione HTTP e di rendere davvero utili i browser. Poter aprire finestre (popup nella pratica) con il solo titolo e senza bordi, casomai in trasparenza, aumenterebbe la produzione di Widget da sfruttare con i normali browser, al pari di quello che fa oggi Apollo. Con uno studio attento sulla sicurezza (in quanto penso sia oggi l’unico motivo di questo limite) si aprirebbero scenari davvero interessanti.
P2P Object
Come tutti sappiamo oramai tutti i browser supportono l’oggetto XMLHttpRequest, che ha dato vita ad una quantità sconfinata delle cosiddette applicazioni Ajax. Questo oggetto, utilizzabile tramite Javascript, è in grado di fornire un canale HTTP – parallelo - gestibile tramite script client, sia per l’ìinvio che per la ricezione dati.
Primo o poi, come anticipato in vari altri Blog, Adobe inserirà un P2P all’interno di Flash. Perchè non fare la stessa cosa nei Browser? Un oggetto di questo tipo unito a funzionalità Windowless permetterebbe di creare applicazioni simil-Joost senza installare nulla sulla propria macchina, garantendo una cross-compatibilità degna di Internet, aumentando quindi anche l’efficienza della produzione (ad oggi Joost è sviluppato per ogni singolo sistema operativo, cosa assai gravosa – sia in termini economici che temporali – infatti le beta si susseguono…).
Insomma finestre con RSS FEED testo, audio e video da posizionare dove vogliamo sul nostro desktop, in vero standard W3C. Apertura si canali TCP direttamente da Javascript, con possibilità di scambio dati sconfinate. Evidentemente la volontà è poca e la “criminalità” è alta; hackers, Spam e Phishing sono in agguato e mosse di questo tipo terrorizzano un po’ tutti…
Continua...
Premetto che stiamo parlando di WordPress 2.0.6. Se cercate di impostare le categorie in modalità “combo” – dropdown – occhio alle indicazioni proposte sul sito di WordPress. Quando si realizza una FORM HTML con un bottone SUBMIT bisogna stare attenti a non impostare il nome del TAG INPUT proprio a “submit”, pena mandare in rovina tutto appena si cerca di submittare la FORM via Javascript.
Sul sito di WordPress viene proposto il seguente codice:
1 2 3 4 5 6
| <li id="categories">
<?php _e('Categories:'); ?>
<ul><li>
<form action="<?php echo $PHP_SELF ?>" method="get"> <?php dropdown_cats(); ?> <input type="submit" name="submit" value="view" /> </form>
</li></ul>
</li> |
Notate che il bottone di invio ha l’attributo name impostato a “submit”. Se cercate di esguire una codice Javascript tipo questo:
1
| document.forms.nomeform.submit(); |
L’interprete va in confusione in quanto non distingue il metodo submit() dall’elemento “submit” che è invece un bottone! La soluzione è semplice: chiamate il bottone come vi pare ma non “submit”!
Il codice che ho usato per visualizzare le categorie in dropdown mode io è il seguente:
1 2 3 4 5
| <div id="cmb_months">
<form name="xcats" id="xcats" action="/index.php" method="get">
<?php dropdown_cats(); ?>
</form>
</div> |
Ho dovuto anche modificare il Kernel di WordPress (cosa che non andrebbe fatta…). Nel file “template-functions-category.php” ho modificato la funzione dropdown_cats() quando prepara il TAG SELECT ho aggiunto:
1
| onchange="document.forms['xcats'].submit();" |
Ecco il pezzo di codice da rintracciare:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| $categories = $wpdb->get_results($query);
echo '<select name="cat" class="postform" onchange="document.forms[\'xcats\'].submit();">'."\n";
if ( intval($optionall) == 1 ) {
$all = apply_filters ('list_cats', $all);
echo "\t<option value='0'>Seleziona una Categoria</option>\n";
}
if ( intval($optionnone) == 1 )
echo "\t<option value='-1'>".__ ('None')."</option>\n";
if ( $categories ) {
foreach ( $categories as $category ) {
$cat_name = apply_filters ('list_cats', $category->cat_name, $category);
echo "\t<option value=\"".$category->cat_ID."\"";
if ( $category->cat_ID == $selected )
echo ' selected="selected"';
echo '>';
echo $cat_name;
if ( intval($optioncount) == 1 )
echo ' ('.$category->cat_count.')';
if ( intval($optiondates) == 1 )
echo ' '.$category->lastday.'/'.$category->lastmonth;
echo "</option>\n";
}
}
echo "</select>\n"; |
Una cosa che la funzione non fa è impostare il combo sulla categoria scelta quando viene ricaricata la pagina… appena ho tempo lo guardo meglio.
Come nota a tutto ciò, per esigenze di completezza, sottolineo che bisognava agire con un codice non intrusivo (Unobtrusive) invece di inserire l’onchange direttamente nella costruzione del combo. Inoltre le categorie visualizzate con il combo non sono accessibili per i browser con Javascript disabilitato. Tuttavia questo lo si può risolvere utilizzando il TAG NOSCRIPT nella sidebar e visualizzare le categorie come lista di link – modalità di default di WordPress – aggiustamenti che farò a breve
.
Continua...
L’inserimento di oggetti (in particolare Flash Objects) all’interno delle pagine Web è diventato ultimamente un’attività spesso stressante. In altri Post abbiamo già affrontato l’argomento di come rilevare Flash ed inserirlo nelle pagine in modo appropriato. Dato che abbiamo parlato di tecniche Unobtrusive, vi segnalo due noti script in grado di rilevare (ed eventualmente installare) ed inserire oggetti Flash in una pagina, in modo assai afficiente e poco intrusivo: SWFObject e UFO.
Entrambi gli script offrono in sostanza le stesse caratteristiche e un funzionamento identico. L’approccio è quello che sostituire tramite Javascript un determinato TAG con il contenuto Flash. Come sappiamo questo procedimento elimina il problema dell’attivazione dell’oggetto Flash imposto da Internet Explorer, tuttavia implica che Javascript sia attivato sul target-browser.
Entrambi gli script non fanno uso di librerie esterne, come Prototype.js ad esempio. La differenza più importante tra i due è che SWFObject va chiamato quando il TAG da sostituire è già stato caricato nella pagina, modalità non propriamente Unobtrusive. Ecco uno stralcio di codice che mostra la sequenza di chiamata:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| <div id="flashcontent">
<strong>You need to upgrade your Flash Player </strong>
This is replaced by the Flash content.
Place your alternate content here and users without the Flash plugin or with
Javascript turned off will see this. Content here allows you to leave out <code inline="true">noscript </code>
tags. Include a link to <a href="swfobject.html?detectflash=false">bypass the detection </a> if you wish.
</div>
<script type="text/javascript">
// < ![CDATA[
var so = new SWFObject("so_tester.swf", "sotester", "300", "300", "9", "#FF6600");
so.addVariable("flashVarText", "this is passed in via FlashVars for example only"); // this line is optional, but this example uses the variable and displays this text inside the flash movie
so.write("flashcontent");
// ]]>
</script> |
UFO, invece, permette un’approccio decisamente più in linea con i classici script Unobtrusive. La sostituzione del TAG avviene in modalità trasparente, senza abbligare sequenze di caricamento, come mostrato nell’esempio qui sotto:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| <head>
<title>Unobtrusive Flash Objects (UFO) | Sample page </title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<script type="text/javascript" src="ufo.js"></script>
<script type="text/javascript">
var FO = { movie:"test8.swf", width:"300", height:"120", majorversion:"12", build:"0", xi:"true" };
UFO.create(FO, "ufoDemo");
</script>
</head>
<body>
<div id="ufoDemo">
<p>Replacement content </p>
<p><a href="http://www.macromedia.com/go/getflashplayer"><img src="http://www.macromedia.com/images/shared/download_buttons/get_flash_player.gif" alt="Get macromedia Flash Player" style="border: none;" /></a></p>
</div>
</body> |
Nel codice sorgente dello script di UFO, infatti, si nota immediatamente l’uso – più appropriato – di un evento che attente il caricamento completo della pagina prima di eseguire la sostituizione; approccio quindi estremamente più consono a script non intrusivi.
Continua...
Tra le varie librerie – o insieme di librerie (veri e propri framework), dedicate ad Ajax, estensione dell’interfaccia HTML e Web2.0 che mi è capitato di vedere, Ext è sicuramente degno di nota. Il sito Web e la documentazione sono ben fatti e organizzati, inoltre i demo online sono da non perdere. L’interfaccia grafica, la compatibilità con Prototype e Scriptaculous e l’impletazione dei Yahoo Utils, ne fanno un sistema quantomeno interessante! Attenzione però alla licenza! Nonostante si presenti come open source e gratuito, per usi personali, richiede un pagamento per potenziarne l’uso e l’assistenza. Quest’ultima, infatti, non è mai da sottovalutare in framework di una certa complessità.
Per la documentazione e i demo clicca qui.
In particolare cito questo sistema, che sto ancora analizzando in dettaglio, in quanto è stato utilizzato per creare Fresh Feed Reader, una delle applicazioni di esempio fornite con la versione Alpha di Adobe Apollo (vedi Adobe Apollo Alpha Release). Fresh, quindi, è un duplice esempio dell’uso di Apollo, che dimostra le sue capacità di sfruttare HTML e Javascript al massimo. Fresh, infatti, non è un’applicazione Apollo pura, ma usa il framework Ext- e quindi Javascript e HTML – all’interno del motore Apollo! Fantastico!!
Continua...
Ecco un nuovo ed interessante tool per la compressione e l’oscuramento di codice Javascript (vedi anche Reverse Engineering: i compressori di codice).
Sul sito Web di Dean Edwards è possibile scaricare anche il codice sorgente Javascript di questo compressor. Inoltre l’autore ha reso disponibili le versioni server per Microsoft .NET Framework versione 1.1, Perl, WHS e PHP5.
Online è disponibile una versione funzionante da provare subito, meno complessa - a dire il vero - di quelle che avevo presentato tempo fa. Permette, infatti, di comprimere il codice con due sole scelte: il Base62 encode, che oscura il codice e il Shrink variables, l’ottimizzatore di variabili.
Rispetto alla precedente versione sono stati risolti alcuni bachi che, in situazioni di hack estremi (e davvero interessanti) come:
1
| var isMSIE = /*@cc_on!@*/false; |
non rispettavano l’output generato. Ora sono correttamente supportati sia i conditional comments di Microsoft, sia gli operatori +/- in condizioni come:
Come sottolineato nella pagina di Help, tuttavia:
Packed scripts should successfully unpack on all browsers that support JavaScript. Only basic JavaScript functionality is used to decode the packed script.
Some browsers may not support the packer itself. The web interface requires DOM support. Legacy browsers will display a disabled interface.
Quindi massima attenzione all’utenza finale e al tipo di browser da supportare… come sempre del resto!
Continua...
In questo Post vorrei analizzare l’uso di script unobtrusive dal punto di vista del Web Designer. Normalmente, infatti, uno script non intrusivo è tale nei confronti del navigatore finale!
Ma può esserlo anche per il Web Designer?
Unobtrusive Javascript dal punto di vista del Web Designer
Mettendoci nei panni di un Web Designer potremmo identificare due categorie di unobtrusive Javascript: true unobtrusive Javascript e pseudo unobtrusive Javascript.
Entrambe le categorie, tuttavia, non sono completamente non intrusive (sempre dal punto di vista del Web Designer). Un reale e completo unobtrusive Javascript non dovrebbe richiedere nessun intervento nella pagina Web, ma questo è – per ora – sostanzialmente impossibile. L’operazione minima richiesta durante l’installazione di uno script è comunque l’inserimento dell’inclusione dello script stesso! Viene dunque ammessa tale operazione che – effettivamente – non costringe il Web Designer ad apportare modifiche straordinarie alla struttura della pagina. Il semplice posizionamento dell’inclusione dello script all’interno del Tag head può essere quindi considerato non intrusivo.
Il true unobtrusive Javascript
Gli script di questo tipo sono quelli che richiedono la sola inclusione dello script unobtrusive e non ;pretendono nessun’altra operazione! Script di questo tipo sono, ad esempio (il solito e citatissimo), Snap. Una volta inserito il codice di inclusione il Web Designer non deve svolgere nessuna operazione ulteriore, in quanto lo script di Snap opera su Tag standard.
Gli pseudo unobtrusive Javascript
Questi si differenziano dai precedenti in quanto richiedono una taggatura ulteriore per funzionare correttamente. Esempi di questo tipo sono i Control.Tabs di Ryan Johnson o la libreria per gli slideshow Lightbox JS. Quest’ultima soluzione, ad esempio, richiede l’inserimento nel Tag A dell’attributo rel per identificare i link che devono essere modificati. Lightbox JS, in particolare, richiede addirittura la presenza esplicita sia di Prototype che di Scriptaculous. Come indicato sul sito di Lightbox JS, l’inclusione dello script deve essere di questo tipo:
1 2 3
| <script type="text/javascript" src="js/prototype.js"></script>
<script type="text/javascript" src="js/scriptaculous.js?load=effects"></script>
<script type="text/javascript" src="js/lightbox.js"></script> |
I link che puntano ad un’immmagine che si vuole visualizzare con il sistema Lightbox JS devono essere scritti in questo modo:
1
| <a href="images/image-1.jpg" rel="lightbox" title="my caption">image #1 </a> |
Inoltre per identificare un gruppo di immagini, per aggiungere la capacità di scorrere avanti e indietro le immagini, i Tag A devono essere impostati nel modo seguente:
1 2 3
| <a href="images/image-1.jpg" rel="lightbox[roadtrip]">image #1 </a>
<a href="images/image-2.jpg" rel="lightbox[roadtrip]">image #2 </a>
<a href="images/image-3.jpg" rel="lightbox[roadtrip]">image #3 </a> |
La necessità di tali costrizioni risulta evidente; non esiste un modo semplice per distinguere un elemento link (Tag A) da un altro. In particolare non è possibile capire quale elemento il Web Designer vuole visualizzare in un modo o in un altro. Dev’essere necessariamente il Web Designer ad indicare in qualche modo i Tag e i loro comportamenti. Sono quindi richieste – intrusive – del tutto comprensibili, che non sminuiscono affatto l’utilità e le potenzialità di questi script. Comportano solo un dettaglio maggiore e qualche riga di codice in più al Web Designer.
È interessante, comunque, il doppio aspetto dell’unobtrusive Javascript, analizzato sia dal punto di vista dell’utente finale sia dal punto di vista Web Designer.
Continua...
Visto che ne abbiamo parlato bene nei Post precedenti, è giunto il momento di parlarne male (scherzo), o quantomeno di evidenziare alcuni difetti della tecnica di unobtrusive Javascript.
Se il codice unobtrusive Javascript viene eseguito quando la pagina è completamente caricata, ne deriva che maggiore sarà la quantità di dati (HTML) che forma la nostra pagina e maggiore sarà il tempo di attesa prima che il nostro codice venga eseguito.
Tutto ciò può tradursi in ritardi di esecuzione con un conseguente e fastidioso effetto di sfarfallio se si opera su elementi visivi della pagina. Prendiamo ad esempio il codice usato da Ryan Johnson per creare degli oggetti TabStrip. Se guardate attentamente il demo online vi accorgerete che per un secondo circa, al caricamento della pagina, si vede chiaramente un layout standard sostituito subito dopo da oggetti TabStrip. Ricaricando nuovamente la pagina, grazie alla cache del browser, il problema tende a diminuire (provate a pulire tutta la cache del browser per verificare i tempi).
Tutto questo ci deve far riflettere sui limiti di questa tecnica. Lo stesso Snap soffre esattamente dello stesso rallentamento, soprattutto in pagine spesso estremamente alte come quella di undolog.com. Caricando la home page di questo Blog risultà evidente che Snap viene eseguito qualche secondo dopo, ovvero quando la pagina è completamente caricata.
Per definizione dell’unobtrusive Javascript questo problema è difficilmente risolvibile a livello generale. Tuttavia nello sviluppo di un sito proprietario si possono prendere alcuni accorgimenti tesi a eliminare o ridurre tali difetti. Un modo abbastanza semplice è quello di creare una sorta di preload, elemento diffuso in ambiente Adobe Flash. Si può quindi impostare il Tag body – che contiene tutti gli elementi della pagina – in modo che risulti invisibile, lasciando al codice Javascript il compito di renderlo visibile quando ha terminato le – eventuali – modifiche al DOM:
1
| <body id="ibody" style="display:none"> |
Il codice unobtrusive Javascript, al termine delle sue operazioni:
1 2 3
| document.getElementById("ibody").style.display="";
// Se usate prototype
$("ibody").style.display=""; |
Soluzione, tuttavia, banale e non sempre applicabile. Inoltre, anche se abbiamo in qualche modo risolto il problema del primo caricameno, navigare in un tal modo a lungo andare potrebbe davvero risultare fastidioso per i navigatori. Non essere intrusivi, quindi, ha un prezzo da pagare. Anche operando a livello di oggetto, per esempio impostando solo gli elementi interessanti in modalità nascosta, il fatto che il codice parta alla fine del caricamento dell’intera pagina porta inevitabilmente con sè le stesse identiche problematiche.
Ultimi Commenti
Giovambattista Fazioli: @Nik: Sono contento! In bocca al lupo dunque!!
Nik: Lunedì ho l’esame di informatica su java, grazie mi sei stato utilissimo, il libro che ho era poco chiaro...
Marco: Ti ringrazio moltissimo, mi hai illuminato
ho risolto impostando [cc_objc] //OptionViewController.m -...
Giovambattista Fazioli: @Marco: Ti consiglio un approccio credo più corretto. Se hai eseguito il subclass del tab...
luigi: molto chiaro e semplice devo ammettere che anche scrivendo da un pà difficilmente uso delegati creati da...