Visualizzazione post con etichetta jquery. Mostra tutti i post
Visualizzazione post con etichetta jquery. Mostra tutti i post

18 luglio 2010

Un terminale reale nel browser con JQuery e Django, parte II

Mentre la prima parte è incentrata sull'HTML, il codice javascript e il CSS, in questa seconda parte ci si concentrerà sul lato server-side, ovvero il codice python associato al framework Django.

Per la spiegazione del funzionamento di Django ovviamente rimando al sito ufficiale, in questo articolo vengono riportati solo i passaggi principali.
Vediamo innanzitutto il contenuto del file urls.py, che descrive lo schema delle URL di questa applicazione (molto semplice):

# Copyright (C) 2010 Lorenzo Sfarra (lorenzosfarra@ubuntu.com)
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#


from django.conf.urls.defaults import *
from django.conf import settings

MEDIA_ROOT = settings.MEDIA_ROOT

urlpatterns = patterns('',
(r'^cmd/(?P.*)$', 'terminaljs.terminal.views.cmd'),
(r'^media/(?P.*)$', 'django.views.static.serve',
{'document_root': MEDIA_ROOT}),
(r'^$', 'terminaljs.terminal.views.index'),
)



Definiamo quindi che una URL con cmd/ iniziale richiama la view cmd con un parametro "command", il comando da eseguire. Definiamo inoltre che le URL con "media/" iniziale devono essere processate staticamente, ed infine definiamo la URL predefinita che richiama la view index.

Passiamo quindi a vedere il codice delle view, definito nel file views.py:


# Copyright (C) 2010 Lorenzo Sfarra (lorenzosfarra@ubuntu.com)
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#


from django.shortcuts import render_to_response
from django.http import HttpResponse
from commands import getoutput
import os.path

# global variable
CWD = "/home/lorenzo"

def index(request):
return render_to_response("index.html")

def is_trusted_command(command):
#TODO: check if it's a trusted command
return True

def cmd(request, command):
global CWD
if command.startswith("cd "):
new_path = command.split(" ")[1]
if not new_path.startswith("/"):
# relative path
new_path = os.path.join(CWD, new_path)
if os.path.isdir(new_path):
CWD = new_path
output = ""
else:
output = "cd: " + new_path + ": No such file or directory"
elif is_trusted_command(command):
output = getoutput("cd %s; %s" %(CWD,command))
else:
output = "Untrusted command."
return HttpResponse(output)



Da sottolineare, così come fatto nella prima parte, la funzione is_trusted_command che deve essere implementata anche server-side.

Ovviamente il tutto è puramente dimostrativo, per chi fosse interessato a migliorarlo è presente tutto il codice su Google Code.

17 luglio 2010

Un terminale reale nel browser con JQuery e Django, parte I

Nell'articolo vediamo come realizzare un terminale che accetta comandi e che li esegue effettivamente su una macchina reale.
Questa prima parte si concentra sull'HTML, il codice Javascript e il CSS necessario.
La seconda parte verrà invece incentrata sul lato della programmazione python con il framework Django.
Il lato server è stato realizzato con il web framework Python Django, il lato client sfrutta la libreria JS JQuery anche per le chiamate AJAX.

L'HTML è piuttosto semplice e si trova nel file templates/index.html


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US" lang="en-US">
<head>
<title>Lorenzo Sfarra :: DJSterminal</title>
<link rel="stylesheet" href="/media/css/terminal.css"/>
<script type="text/javascript"
src="http://www.google.com/jsapi"></script>
<script type="text/javascript">
// You may specify partial version numbers, such as "1" or "1.3",
// with the same result. Doing so will automatically load the
// latest version matching that partial revision pattern
// (e.g. 1.3 would load 1.3.2 today and 1 would load 1.4.2).
google.load("jquery", "1.4.2");


</script>

<script src="/media/js/terminal.js" type="text/javascript">/* Terminal */</script>

<script type="text/javascript">
google.setOnLoadCallback(function() {
/* Handle the enter keycode */
$("#commandline").keypress(function(event) {
if (event.keyCode == '13') {
event.preventDefault();
onEnterKey();
}
});
});
</script>
</head>

<body>
<div id="terminal">
<div id="terminaltop"><img src="/media/css/imgs/buttons.png" alt="buttons" align="left"/> <br/>Javascript Terminal</div>

<!-- Command line -->
<textarea id="commandline" cols="80" rows="15">lorenzo@josie:~$ </textarea>
<!-- End command line -->
</div>
</body>
</html>


Nelle prime righe importiamo i file necessari. In particolare sfruttiamo Google per caricare la libreria JQuery.
Nelle linee 20-29 catturiamo il tasto Invio per gestire l'input come una riga di comando.

Il file terminal.js che contiene il sorgente javascript necessario si trova nella directory media/js, ed è il seguente:


/* Copyright (C) 2010 Lorenzo Sfarra (lorenzosfarra@ubuntu.com)

* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.

* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the
* GNU General Public License for more details.

* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * 02110-1301, USA.
*/



// The command line prompt
var cliPrompt = "lorenzo@josie:~$ ";

// the server address where the real console exists
var cliHost = "http://localhost:8000/";

function isTrustedCommand(command) {
/**
* Function to check that the given command is trusted.
* @param command the command to check
* @return boolean
*/
// TODO: check that this is a trusted command!
return true;
}

function executeCommand(text, cliPrompt, command) {
/**
* Function to execute the given command through an AJAX call
* and retrieve the result to update the textarea value.
* @param text the current textarea value
* @param cliPrompt the prompt
* @param command the command to execute
*/
// build the URL for the command
remoteCommand = cliHost + "cmd/" + command;
output = "";
// Perform the AJAX call
$.ajax({
url: remoteCommand,
type: 'GET',
dataType: 'text',
error: function(data, textStatus, errorThrown) {
// readyState == 4? Error.
if (data.readyState == 4) {
output = "Connection error.\n"
}
},
success: function(data) {
output = data + "\n";
$("#commandline").val([text, output, cliPrompt].join("\n"));
// Textarea with focus at bottom
$("#commandline").animate({ scrollTop: 99999}, 10);
}
});

}

function onEnterKey() {
/* Function called when a user press the Enter key on its keyboard. */
text = $("#commandline").val();
// Get the command
promptIndex = text.lastIndexOf(cliPrompt);
// build the command
command = text.substring(promptIndex + cliPrompt.length);
if (command == "clear") {
// simply clear the textarea value
$("#commandline").val(cliPrompt);
} else if (isTrustedCommand(command)) {
executeCommand(text, cliPrompt, command);
} else {
output = "Invalid command.";
$("#commandline").val([text,output,cliPrompt].join("\n"));
}
}



La funzione principale è ovviamente executeCommand() che effettua la chiamata AJAX necessaria per eseguire realmente il comando sul server di riferimento.

ATTENZIONE: una funzione importantissima è isTrustedCommand(command) che ritorna "true" se il comando ha il "permesso" per essere eseguito. Questo ovviamente è necessario per proteggere il server. Al momento la funzione non effettua alcun controllo e ritorna immediatamente "true".

Il foglio di stile terminal.css si trova nella directory media/css.
Passa alla parte II ».

Per lo stile è stato preso come modello di riferimento il terminale presente nell'articolo "Forwarding E-Mails with Postfix".

25 settembre 2009

Segnalazione: JQuery Visual Cheat Sheet

Segnalo un'interessante iniziativa di Antonio Lupetti: JQuery Visual Cheat Sheet.


Consiste in un pratico mini-manuale per jQuery (versione 1.3) che contiene 6 pagine che brevemente spiegano le intere API di jQuery con brevi descrizioni ed esempi. Consiglio il download per i web designer.

23 settembre 2009

Ordine gerarchico per directory (e non solo) con JQuery

Dopo un articolo di qualche mese fà su eleganti box con JQuery, oggi riporto come creare una struttura gerarchica come quelle di un qualunque filesystem, per capirci, che in ambito web può essere utile in varie circostanze.
Anche questo codice, come quella dell'articolo precedente già citato, è stato creato per il progetto Enchanted Webmail, anche se qui è riportato in una versione diversa e limitata. Il codice originale include anche l'uso di AJAX per ottenere dinamicamente le informazioni sulle Mailboxes IMAP, ed è consultabile nella pagina del progetto su Launchpad.

Questa è l'anteprima di quanto è possibile ottenere:



Il codice HTML è troppo lungo per essere scritto interamente qui, quindi riporto un breve estratto. Il link al codice completo è riportato alla fine dell'articolo.

L'HTML non è il massimo dell'eleganza nè validato al 100%, appunto perchè è generato dinamicamente tramite chiamate AJAX (il progetto è ancora in fase di sviluppo).


[..]
<div id="mboxApache" class="mailbox">
<span class="mailboxname">

<img src="media/images/hide_mailbox.png" id="Apache" alt="Hide Children" class="actionmailbox folder">

<a href="/mailboxes/Apache">Apache</a>

</span>

<div class="children" id="childrenApache">

<div id="mboxApache__slash__prova" class="mailbox">

<span class="mailboxname">

<img src="media/images/hide_mailbox.png" id="Apache__slash__prova" alt="Hide Children" class="actionmailbox folder">

<a href="/mailboxes/Apache/prova">prova</a>

</span>
<div class="children" id="childrenApache__slash__prova">

<div id="mboxApache__slash__prova__slash__3rd__space__level__space__2" class="mailbox">
<span class="mailboxname">

<img src="media/images/mailbox_nochildren.png" alt="No Children" class="folder">

<a href="/mailboxes/Apache/prova/3rd%20level%202">3rd level 2</a>

</span>

</div>



<div id="mboxApache__slash__prova__slash__testing__space__29__space__Nov" class="mailbox">
<span class="mailboxname">

<img src="media/images/show_mailbox.png" id="Apache__slash__prova__slash__testing__space__29__space__Nov" alt="Hide Children" class="actionmailbox folder">


<a href="/mailboxes/Apache/prova/testing%2029%20Nov">testing 29 Nov</a>
</span>
[..]


Il file javascript principale è il seguente:


/* Copyright (C) 2008 Lorenzo Sfarra (lorenzosfarra@ubuntu.com)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* NOTE: jquery required.
*/

SHOWMAILBOX='media/images/show_mailbox.png';
HIDEMAILBOX='media/images/hide_mailbox.png';
LOADING='media/images/icons/loading.gif';

function mailboxes_management(element) {
// Add "children" to the current id to obtain the children div's id
var childrenid = "#children" + $(element).attr('id');
if ($(element).attr('src') == SHOWMAILBOX) {
$(childrenid).removeClass("invisible");
$(childrenid).slideDown(400);
$(element).attr('src', HIDEMAILBOX);
} else if ($(element).attr('src') == HIDEMAILBOX) {
$(element).attr('src', SHOWMAILBOX);
$(childrenid).fadeOut(400);
}

}

function show_hide_children() {
$(".mailboxeslist").click(function(event) {
element = $(event.target);
mailboxes_management(element);
});
}

$(document).ready(function() {
show_hide_children();
});



Lo script precedente si occupa di nascondere/mostrare in modo elegante il contenuto della "directory", e di cambiare l'icona della directory stessa in base all'azione appena effettuata.

Vediamo anche il CSS:


.mailboxeslist {
margin-top: 25px;
margin-left: 25px;
margin-bottom: 30px;
}

.mailboxeslist .mailboxname {
margin-left: 10px;
font-size: 1.2em;
margin-top: 0px;
}

.mailboxeslist .children {
margin-left: 10px;
border-left: 1px solid #dddddd;
margin-top: 0px;
padding-top: 5px;
}

.mailboxeslist a, .mailboxeslist a:visited {
color: #002b3d;
}

.mailboxeslist a:hover, .mailboxeslist a:active {
color: #0169c9;
}

.mailboxeslist .leaf, .mailboxeslist .leaf:visited {
color: #d40000;
}

.folder {
float: left;
}

.parentmailbox {
margin-bottom: 20px;
margin-top: 10px;
}

.mailbox {
margin-top: 5px;
}

.mailboxesplainlist {
line-height: 1.7em;
margin: 15px 0px 20px 20px;
color: #002b3d;
}

.mailboxesplainlist a, .mailboxesplainlist a:visited {
color: #002b3d;
}

.mailboxesplainlist a:active, .mailboxesplainlist a:hover {
color: #0169c9;
}

.rootmailbox {
background: #ededed url(../images/mailbox_nochildren.png) no-repeat left 40%;
padding: 5px;
margin: 6px;
padding-left: 40px;
border-top: 1px solid #dddddd;
border-right: 1px solid #dddddd;
border-left: 1px solid #aaaaaa;
border-bottom: 1px solid #aaaaaa;
}


Puoi provare un demo qui.

Per quanto riguarda il codice completo:

31 luglio 2009

Il nuovo banner di ubuntu-it con JQuery

Da pochi giorni abbiamo un nuovo banner nella homepage del sito web di ubuntu-it.
Il suo compito è quello di evidenziare i contenuti del sito più importanti, dato che il menù, essendo un sito che contiene molti contenuti, è piuttosto corposo.
Il nuovo banner utilizza un mix di HTML, CSS e javascript con la libreria JQuery.




Innanzitutto nella pagina in cui verrà incluso il banner dobbiamo includere il file javascript per jquery e quello del banner, oltre ai file CSS: a questo proposito, dobbiamo includere con degli IF condizionali dei CSS speciali per Internet Explorer 7 e Internet Explorer 6, se sono i browser utilizzati dall'utente.



<link rel="stylesheet" href="banner.css">
<!--[if IE 7]><br /> <link rel="stylesheet" href="ie7tricks.css"><br /> <![endif]-->

<!--[if IE 6]><br /> <link rel="stylesheet" href="ie6tricks.css"><br /> <![endif]-->


Per quanto riguarda l'HTML, potete trovarlo qui.

Il file javascript che gestisce il banner (che contiene degli accorgimenti specifici per Internet Explorer 6, che come al solito è categoria a parte), è il seguente:


/* Licenza tagliata per limiti di spazio, si veda il file originale indicato giù per la licenza */


/* The currently selected category */
curCategory = "";
/* The URL realated to the current category */
url = "http://www.ubuntu-it.org/Ottenere_Ubuntu.shtml";
/* category -> url map */
urlsMap = {
"support": "http://www.ubuntu-it.org/Supporto.shtml",
"contribuire": "http://www.ubuntu-it.org/contribuire.shtml",
"newsletter": "http://www.ubuntu-it.org/contenuti/newsletter-italiana.shtml",
"fcm": "http://www.ubuntu-it.org/contenuti/fcm.shtml",
"media": "http://www.ubuntu-it.org/contenuti/media.shtml",
"contatti": "http://www.ubuntu-it.org/contatti.shtml"
}
/* Tracking activated items, if the user highlights more than 1 menu item
* too fast. */
activatedItems = Array();

function changeActiveCategory(liId) {
/* Change the active category in the banner.

@param liId the ID of the selected 'li' element
*/
/* Change 'li' classes for the old selected category and the new one */
newCategory = liId.substring(2);
if (curCategory != "") {
$("#li" + curCategory).removeClass("lihover");
$("#li" + curCategory).addClass("linormal");
}
$("#" + liId).removeClass("linormal");
$("#" + liId).addClass("lihover");
/* Change the main image for the new category*/
$("#bannermainbg").fadeOut("slow", function(data) {
if (curCategory != "") {
$("#bannermainbg").removeClass(curCategory + "main");
}
/* Update info about the new category */
curCategory = newCategory;
url = urlsMap[curCategory];
$("#bannermainbg").addClass(curCategory + "main");
/* Workaround for IE6: CSS class doesn't work properly, so we set
* the background manually. */
if ($.browser.msie) {
/* Check that is IE with version < 7 */
if ($.browser.version < 7.0) {
path = "url(/uploads/file/banner2009/images/" + curCategory + ".png)";
$("#bannermainbg").css("background-image", path);
}
}
$("#bannermainbg").fadeIn("slow");
});

}


$(document).ready(function() {
/* Change the link href, because the user has JS enabled */
$("#bannerlinkslist li a").attr("href", "#");
$("#bannerlinkslist li").hover(function() {
/* Give info about the current 'li' id to the function */
activatedItems.push($(this).attr("id"));
changeActiveCategory($(this).attr("id"));
},
function() {
/* If it's not the currently selected item,
* remove the correspective class */
for (iter = 0; iter < activatedItems.length; iter += 1) {
if (activatedItems[iter] != ("li" + curCategory)) {
$("#" + activatedItems[iter]).removeClass("lihover");
$("#" + activatedItems[iter]).addClass("linormal");
activatedItems.splice(iter);
}
}
});
/* Manage the onclick event on the main banner content */
$("#bannermain").click(function() {
window.location = url;
});
});

//vim: ai ts=2 sw=2 et sts=2


Il codice completo è a questo indirizzo.

La funzione changeActiveCategory() si occupa di:
1) evidenziare la voce correntemente selezionata nella lista della parte destra del banner;
2) riportare nello stato di elemento non selezionato la voce precedentemente selezionata;
3) assicurarsi che soltanto 1 sola voce sia selezionata (il problema si pone se l'utente passa velocemente su più di un elemento, più velocemente dell'effetto, che poteva portare a più voci selezionate nello stesso tempo);
4) cambiare l'immagine principale del banner nella parte sinistra: il tutto è gestito da classi CSS, tranne per IE6 per il quale aggiungiamo un controllo e cambiamo "manualmente" l'immagine;
5) cambiare l'indirizzo a cui si arriva cliccando sul banner.

Il CSS principale è invece consultabile qui.

Il demo, oltre ovviamente al sito di ubuntu-it, è qui.

18 luglio 2009

Box semplici ed eleganti con JQuery

Trovo i box molto efficaci in un layout di un'applicazione web, soprattutto quando è piuttosto complicata e le informazioni da mostrare sono molte. C'è, come fanno molte applicazioni web, il metodo stile accordion, i tab, un mix di stili oppure i box. Ognuna di queste possibilità si adatta meglio al genere di contenuto e al genere di applicazione.
Per una delle mie applicazioni web ancora in sviluppo, Enchanted Webmail (pagina su launchpad) utilizzo appunto i box, di cui riporto l'esempio qui:



Per realizzarli utilizziamo un mix di HTML, CSS e javascript con la libreria JQuery.
Il codice sorgente:
Puoi provarlo subito visitando la pagina demo.

09 febbraio 2009

Webkit: arrivano le animazioni tramite CSS


Una notizia molto interessante, soprattutto per chi come me si trova spesso a sviluppare (applicazioni web e relativi) siti web con animazioni scritte in JavaScript, è che ora WebKit supporta le animazioni completamente in CSS.
Questo è uno dei miglioramenti per quanto riguarda i CSS proposti dal progetto WebKit, che comprende effetti quali gradienti, mask e transizioni. L'obiettivo è quello di creare semplicemente animazioni in CSS e scrivere codice facilmente mantenibile, cosa più complessa in JavaScript anche con l'ausilio di librerie quali JQuery.
Al momento è una caratteristica puramente di WebKit anche se si stanno proponendo le specifiche agli organi che gestiscono gli standard. È comunque una caratteristica già supportata e ottimizzata per piattaforma iPhone 2.0, che garantisce buone prestazioni.
Sicuramente una proposta interessante, che io personalmente seguirò con attenzione.