BusyBoxDotNet
Nella costruzione di applicazioni web può accadere di dover effettuare sul server delle operazioni che richiedono una discreta quantità di tempo per essere eseguite, come ad esempio la generazione di report o l'esecuzione di query complesse su database.
Attualmente i browser disponibili non prevedono un metodo d'effetto per informare l'utente che la richiesta è stata effettuata e si è in attesa di una risposta, inducendo l'utilizzatore a non capire perchè continui ad essere visualizzata la stessa pagina, e di conseguenza inrtroducendo il rischio che esso continui ad effettuare operazioni che comportano un invio multiplo dei dati, che in molti casi può essere dannoso.
Per ovviare a questo problema BusyBoxDotNet propone una soluzione che non si limita soltanto ad informare l'utente dell'esecuzione dell'operazione, ma lo fa in modo stilisticamente elegante e può prevenire il submit ripetuto di dati.
Background
L'idea originale è meritatamente dovuta a Mark Wagner - di cui BusyBoxDotNet mantiene il nome - che ne ha implementato una versione eccellente e funzionale.
Il motivo per cui BusyBoxDotNet è stato creato è la necessità di includere il tutto in un componente riutilizzabile ed altamente personalizzabile, senza il bisogno di dover scrivere codice Javascript o di modificare manualmente le pagine web.
BusyBoxDotNet è infatti una libreria di WebControls per ASP.NET, il cui controllo principale è appunto BusyBox. Gli altri controlli presenti nella libreria permettono di personalizzarne il comportamento e facilitarne l'integrazione.
Oltre a questo, sebbene BusyBoxDotNet sia inizialmente nato come un semplice porting dell'idea originale ad ASP.NET, in seguito ad un primo rilascio e grazie ai suggerimenti di Matteo Casati i sorgenti della versione originale sono stati abbandonati ed è stato ricreato dal nulla per estenderne la compatibilità con i browser disponibili e per migliorarne il comportamento.
Tecnologie e linguaggi utilizzati
ASP.NET
Javascript
C#
Browser testati
Il funzionamento di BusyBoxDotNet è stato verificato sui seguenti browser:
Internet Explorer 6.0
Opera 8.52 *
Netscape 8.1
Firefox 1.5
* Opera è supportato con alcune limitazioni; vedi le note di seguito.
Introduzione
Esistono diversi modi per risolvere il problema della notifica all'utente di un processo che può potenzialmente richiedere molto tempo per essere completato. Un metodo comune è la visualizzazione di una pagina intermedia che si occupi della notifica, visualizzando ad esempio un'immagine animata ed un messaggio informativo. E' sempre questa poi che si occupa di iniziare il processo a lunga durata, in modo che essa possa restare visualizzata fino al suo completamento.
Questo approccio ha tuttavia alcune limitazioni, più o meno significative:
Funziona solo nella navigazione tra due pagine differenti, non può essere applicato al postback della stessa pagina.
Richiede la modifica manuale di tutte le pagine nel caso in cui voglia essere incluso in un'applicazione preesistente.
Implica la perdita di tutti i vantaggi apportati dal ViewState.
Per questo motivo BusyBoxDotNet è stato realizzato per superare tutte queste limitazioni, nonchè per apportare notevoli miglioramenti:
È applicabile a qualsiasi richiesta al server web, dal postback alla richiesta di una nuova pagina.
Benchè non sia il suo scopo originale è possibile utilizzarlo anche se non avviene un roundtrip verso il server ma anche soltanto lato client.
E' semplice da inserire in pagine preesistenti e non richiede nessuna modifica manuale delle pagine.
L'approccio di BusyBoxDotNet può quindi essere riassunto in questi punti:
Viene incluso nella pagina uno script Javascript che si occupa della sua creazione, assieme ad altre funzioni helper.
La visualizzazione può avvenire intercettando l'evento onbeforeunload dell'elemento window - implicando quindi la visualizzazione durante qualsiasi transizione di pagina, sia essa la richiesta di una nuova risorsa o un postback - intercettando il solo postback della pagina, oppure personalizzando la visualizzazione scegliendo manualmente quando esso debba essere visualizzato (utile per i browser che non supportano l'evento onbeforeunload come Opera).
Tramite Javascript e DOM viene dinamicamente creato ed aggiunto al documento un elemento div, che contiene il messaggio da visualizzare all'utente ed opzionalmente un'immagine animata.
Il recupero delle risorse embedded nell'assembly (scripts e immagini) avviene tramite HttpHandler. Per gli script è anche possibile includere nella pagina il loro contenuto, ed in questo caso l'HttpHandler non viene utilizzato.
Caratteristiche
BusyBoxDotNet può essere utilizzato come qualsiasi altra libreria di controlli web, e come queste i controlli contenuti in BusyBoxDotNet hanno un comportamento di default, che è possibile personalizzare sia a design time che programmaticamente.
Il comportamento standard del controllo BusyBox è riassunto in questi punti:
Visualizzazione al postback della pagina in cui viene inserito. (compatibile con tutti i browser con cui è stato testato)
-
Layout con messaggi ed immagine standard:

Visualizzazione di uno strato di overlay semitrasparente dello stesso colore dello sfondo della pagina, che impedisce ogni ulteriore interazione con gli elementi della pagina durante la visualizzazione del box.
Mentre questo è il comportamento di default, la notevole quantità di proprietà esposte dal controllo consente di personalizzarlo liberamente.
Cosa è possibile fare
Di seguito è riportata una lista di ciò che è possibile fare con BusyBoxDotNet, e successivamente anche di ciò che al momento non è possibile fare, ma che potrà essere presente in future versioni.
Scelta dell'evento che scatena la visualizzazione del BusyBox: onbeforeunload, onsubmit o personalizzato.
Modifica dello stile del box: testo, dimensione, immagine, bordo, sfondo, layout.
Sono presenti immagini preinserite tra le quali è possibile scegliere (accesso tramite HttpHandler), ma è anche possibile sceglierne una personalizzata (recupero dal file system).Possibilità di far apparire il box con un ritardo, nonchè di nasconderlo dopo un certo timeout. Queste caratteristiche sono interessanti nel caso si voglia visualizzare il box solo se un determinato processo richiede più di un tempo definito per essere completato, o nel caso in cui lo si voglia nascondere se entro un certo tempo il processo non sia stato ancora portato a termine.
Possibilità di far apparire il box con un effetto di fade-in, scegliendone la velocità.
Possibilità di effettuare il fading del box quando il mouse vi è posizionato sopra.
Possibilità di disabilitare la visualizzazione dello strato di overlay.
Scelta del colore e dell'opacità dello strato di overlay.
Timing dello strato di overlay. Nel caso in cui il box sia fatto apparire con ritardo e/o scomparire con anticipo, è possibile scegliere il comportamento dello strato di overlay.
Possibilità di scegliere se visualizzare il box anche se il documento non è stato completamente caricato e di mostrare un messaggio di alert in caso affermativo.
Cosa ancora non è possibile fare
Definire manualmente un layout per il box.
Impostare un posizionamento diverso da quello di default (sempre centrato all'interno dell pagina).
Non prevede la presenza di smartnavigation nella pagina.
Non può essere spostato tramite drag-and-drop.
Non può essere chiuso manualmente come una qualsiasi finestra.
Proprietà pubbliche
La tabella seguente elenca le proprietà che è possibile utilizzare per personalizzare lo stile ed il comportamento del controllo BusyBox.
Categoria: stile (appearance)
| Nome | Tipo | Descrizione |
| BackColor | Color | Colore dello sfondo del box. Attenzione: le immagini embedded nell'assembly hanno tutte sfondo bianco, quindi con uno sfondo di altro colore l'effetto non sarà eccezionale. |
|---|---|---|
| BorderColor | Color | Colore del bordo del box. |
| BorderStyle | BorderStyle | Stile del bordo del box. |
| BorderWidtd | Unit | Spessore del bordo del box. |
| FadeOnMouseOverOpacity | Int | Opacità del box quando il mouse vi è sopra. Valore da 0 a 100. 0 significa trasparente, 100 completamente opaco. Questa proprietà è valutata solo se la proprietà FadeOnMouseOver è impostata a true. |
| Image | ImageTemplate | Selezione dell'immagine tra quelle precaricate nell'assembly. |
| ImagePosition | ImagePositioning | Posizione dell'immagine nel box. Disponibile due layout predefiniti. |
| ImageUrl | String | Url dell'immagine personalizzata da mostrare nel busybox. Valutata solo se la proprietà Image è impostata a Custom. |
| Opacity | Int | Opacità del box. Valore da 0 a 100. 0 trasparente, 100 opaco. |
| Text | String | Messaggio da mostrare nel box. |
| TextBold | Bool | Proprietà bold del messaggio. |
| TextColor | Color | Colore del messaggio. |
| TextFontName | String | Font del messaggio. |
| TextItalic | Bool | Proprietà italic del messaggio. |
| TextSize | FontUnit | Dimensione del testo del messaggio. |
| Title | String | Titolo da mostrare nel box. |
| TitleBold | Bool | Proprietà bold del titolo. |
| TitleColor | Color | Colore del titolo. |
| TitleFontName | String | Font del titolo. |
| TitleItalic | Bool | Proprietà italic del titolo. |
| TitleSize | FontUnit | Dimensione del titolo. |
Categoria: comportamento (behavior)
| Nome | Tipo | Descrizione |
| FadeInSpeed | Int | Velocità di comparsa del box. 0 lenta, 100 immediata. |
|---|---|---|
| FadeOnMouseOver | Bool | Se impostato a true il box diventa semitrasparente al passaggio del mouse. |
| ShowBusyBox | ShowBehavior | Impostazioni di comparsa del box.
|
| ShowDelay | Int | Valore in millisecondi del ritardo di comparsa del box. |
| ShowTimeout | Int | Valore in millisecondi del timeout di comparsa del box. Scaduto il tempo esso verrà nascosto. |
| Visible | Bool | Abilita o disabilita la visualizzazione del box a livello di pagina. |
Categoria: layout
| Nome | Tipo | Descrizione |
| Height | Unit | Altezza del box. Se non impostata assume dimensioni predefinite. |
|---|---|---|
| Width | Unit | Larghezza del box. Se non impostata assume dimensioni predefinite. |
Categoria: misc
| Nome | Tipo | Descrizione |
| ID | Int | ID del controllo. |
|---|---|---|
| AlertIfDocumentNotCompletelyLoaded | Bool | Visualizza un messaggio di alert se si cerca di visualizzare il box prima che il documento sia completamente caricato. |
| IncludeScriptsInPage | Bool | Include gli script Javascript direttamente nella pagina, invece che referenziarli tramite l'attributo src. |
| ShowOnlyIfDocumentCompletelyLoaded | Bool | Visualizza il box solo se il documento è stato completamente caricato. |
Categoria: overlay
| Nome | Tipo | Descrizione |
| ImmediatelyOverlay | Bool | Utilizzato quando la proprietà ShowDelay ha un valore maggiore di 0. Se impostata a true, l'overlay viene mostrato appena l'evento di visualizzazione del box viene scatenato, anche se esso, a causa del delay, non è ancora visibile. |
|---|---|---|
| KeepOverlay | Bool | Utilizzato quando la proprietà ShowTimeout ha un valore maggiore di 0. Se impostato a true, l'overlay viene mantenuto anche il box è scomparso a causa del timeout. |
| Overlay | Bool | Consente di decidere se mostrare o meno l'overlay. Tutte le altre proprietà di questa categoria sono valutate solo se questa assume valore true. |
| OverlayColor | Color | Colore dell'overlay. Se non impostato assume il colore impostato per il tag body della pagina. |
| OverlayOpacity | Int | Opacità dell'overlay. Valore da 0 a 100. 0 trasparente, 100 coprente. |
Alternative all'utilizzo degli eventi OnBeforeUnload e OnSubmit
In alcuni casi le due alternative disponibili per la visualizzazione del box non sono quello di cui si può avere bisogno.
Il valore Always della proprietà ShowBusyBox registra l'evento OnBeforeUnload dell'elemento window, mentre il valore OnPostBackOnly registra l'evento OnSubmit della form.
Assieme al problema dell'evento OnBeforeUnload che in Opera non è supportato, è stato il motivo per cui alla libreria sono stati aggiunti tre controlli ulteriori: BusyBoxPanel, BusyBoxHyperLink e BusyBoxButton.
Ognuno di essi eredita dall'omonimo controllo standard di ASP.NET ed espone una proprietà ulteriore: BusyBoxToShow.
Questa proprietà consente di selezionare il controllo BusyBox inserito nella pagina del quale si vuole effettuare la visualizzazione. Per ognuno dei controlli l'evento che triggera la visualizzazione del BusyBox al quale è associato è l'evento onClick lato client.
In altre parole, se si inserisce nella form un controllo di tipo BusyBoxButton e lo si associa ad un controllo BusyBox presente nella pagina, al click sul bottone verrà anche visualizzato il BusyBox. La stessa cosa accade per il controllo BusyBoxHyperLink e per gli elementi, di qualsiasi tipo essi siano, posizionati all'interno di un controllo BusyBoxPanel.
Compatibilità
La libreria BusyBoxDotNet è pienamente compatibile con le versioni indicate del browser, ma non è escluso che sia compatibile con altri browser e versioni differenti da quelle indicate.
Gli unici limiti di compatibilità sono stati riscontrati con Opera, e possono essere sintetizzabili nei seguenti punti:
Opera non supporta l'evento OnBeforeUnload, di conseguenza quando la proprietà ShowBusyBox del controllo BusyBox è impostata a Always (evento OnBeforeUnload), il box non viene visualizzato.
Opera non supporta l'opacità degli elementi, perciò sia il box che l'overlay saranno o completamente invisibili o completamente opachi, e gli effetti di fading non sono ottenibili.
Guida all'utilizzo
Di seguito sono riportati i passi necessari per integrare BusyBoxDotNet all'interno di web forms ASP.NET.
Importare i controlli in Visual Studio .NET
Nel caso si utilizzi Visual Studio .NET è consigliabile importare i controlli contenuti nella libreria all'interno della toolbox.
La procedura dettagliata è descritta in questo articolo: Gestione di elementi e schede nella Casella degli strumenti
Document Type
Per il modo in cui è stato costruito, BusyBoxDotNet richiede che le pagine in cui è inserito siano almeno di tipo XHTML 1.0 Transitional. Il DocType è specificato nella prima riga della pagina e può trovarsi solo in quel punto.
Visual Studio .NET 2003 di default utilizza HTML 4.0, quindi se si utilizza l'IDE di casa Microsoft è necessario modificare manualmente le pagine inserendo questa direttiva:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
Registrazione dell'HttpHandler
Per utilizzare le immagini e gli script inclusi nell'assembly è necessario registrare un HttpHandler nel file di configurazione web.config dell'applicazione in cui BusyBoxDotNet verrà utilizzato, che si occuperà del recupero delle risorse. Per fare ciò è necessario aggiungere la seguente dichiarazione all'interno della sezione <system.web> del web.config:
<httpHandlers>
<add
verb="*"
path="BusyBoxDotNet.axd"
type="BusyBoxDotNet.ResourceHttpHandler, BusyBoxDotNet" />
</httpHandlers>
Riferimenti
Il progetto BusyBoxDotNet è ospitato su sourceforge.net:
Sito Web: http://busybox.sourceforge.net/
Download: http://sourceforge.net/project/showfiles.php?group_id=159977
Questo articolo è riferito alla versione 0.1.2 di BusyBoxDotNet