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

sabato 10 gennaio 2015

Summernote - un editor WYSIWYG per Bootstrap

Oggi presento Summernote, un editor WYSIWYG per Bootstrap molto ben fatto. Tra le caratteristiche che lo rendono un ottimo prodotto (a mio parere) sono la facilità di installazione, la gestione del menù personalizzata e la possibilità di mostrare il sorgente del testo immesso.

Installazione

Si può installare direttamente dai sorgenti oppure tramite bower:
bower install summernote

Dipendenze

Utilizza ovviamente Bootstrap (e jQuery), assieme a font-awesome. Questo significa che è necessario includere i seguenti file (se non sono già inclusi nella pagina html):
<link href="//netdna.bootstrapcdn.com/font-awesome/4.0.3/css/font-awesome.min.css" rel="stylesheet"></link>

<!-- include summernote css/js-->
<link href="summernote.css" rel="stylesheet"></link>
<script src="summernote.min.js"></script>

Inserimento del codice html e javascript

Un semplice <div> verrà trasformato in un editor Summernote con poche righe di codice javascript:
<div id="summernote">Hello Summernote</div>
<script>
$(document).ready(function() {
  $('#summernote').summernote();
});
</script>

Risultato


:-)

giovedì 3 aprile 2014

jVectorMap - Mappe geografiche vettoriali in Javascript

jVectoMap è una utile libreria che permette di mostrare ed interagire con mappe geografiche vettoriali in Javascript. Il vantaggio di questo progetto, oltre a quello di essere open source, è che utilizza tecnologie native dei browser, quindi html, javascript, svg o vml, css, senza bisogno di plugin aggiuntivi. La sezione tutorial è molto ben fatta, ne consiglio una attenta lettura.
Qualche tempo fa ho avuto bisogno di sfruttare questa libreria per mostrare una mappa geografica della provenienza dei preventivi richiesti dagli utenti su un determinato sito web. Per ottimizzare tutto però ho voluto caricare i dati relativi al numero dei preventivi dei singoli stati in ajax con il formato JSON, vediamo come.
<div id="mappamondo-richieste" style="height:350px;width:100%;"></div>

$.ajax({
   type: "GET",
   url: 'http://api.example.com/stats/world/',
   dataType: "json",
   }).done(function( json_response ) { 
                            
     $('#mappamondo-richieste').vectorMap({
      map: 'world_mill_en',
      series: {
        regions: [{
          values: json_response.worldData,
          scale: ['#C8EEFF', '#0071A4'],
          normalizeFunction: 'polynomial'
        }]
      },
      onRegionLabelShow: function(e, el, code){
        if(!json_response.worldData[code]) json_response.worldData[code] = 0;
          el.html(el.html()+' ('+json_response.worldData[code]+')');
        }
      });
                            
    }).fail(function(jqXHR, textStatus) {
       console.log( "Request failed: " + textStatus + " " + jqXHR.status );
    });

La mappa utilizzata è la world_mill_en, ossia rappresenta l'intero globo terrestre. Le sigle delle nazioni seguono il formato a due lettere (ad esempio IT per Italia, FR per Francia, DE per Germania, ecc.).
L'url richiamata è una API (nel mio progetto scritta in Php) che risponde in formato JSON con una particolare struttura, ad esempio:
{
  "worldData":
  {
    "IT":"97",
    "US":"357"
  }
}
Il risultato finale non delude le mie aspettative :-)

martedì 13 dicembre 2011

FullCalendar - un calendario jQuery con agenda e drag & drop

Per un piccolo gestionale medico ultimamente mi è capitato sotto mano FullCalendar, un ottimo calendario jQuery "full-size" altamente configurabile. Già dalla home page di questo progetto emergono i punti forti del plugin: eventi di tutto il giorno o schedulati, drag & drop degli eventi, viste per mese, per settimana e vista giornaliera. Il progetto è molto ben documentato, quindi per un utilizzo base rimando ogni spiegazione al sito.
Voglio pubblicare però la configurazione che ho utilizzato, cercando di mostrarne le potenzialità:
$('#calendar_strutture').fullCalendar({
   header: {
    left: 'prev,next today',
    center: 'title',
    right: 'month' //,agendaWeek,agendaDay
   },
   firstHour: 6,
   firstDay: 1,
   allDaySlot : false,
   timeFormat: 'HH:mm',
   monthNames:['Gennaio','Febbraio','Marzo','Aprile','Maggio','Giugno','Luglio','Agosto','Settembre','Ottobre','Novembre','Dicembre'],
   monthNamesShort: ['Gen', 'Feb', 'Mar', 'Apr', 'Mag', 'Giu', 'Lug', 'Ago', 'Set', 'Ott', 'Nov', 'Dic'],
   dayNames: ['Domenica', 'Lunedì', 'Martedì', 'Mercoledì', 'Giovedì', 'Venerdì', 'Sabato'],
   dayNamesShort: ['Dom', 'Lun', 'Mar', 'Mer', 'Gio', 'Ven', 'Sab'],
   buttonText: {
    prev:     ' &#9668 ',  // left triangle
    next:     ' &#9658 ',  // right triangle
    prevYear: ' &lt;&lt; ', // <<
    nextYear: ' &lt;&lt; ', // >>
    today:    'Oggi',
    month:    'Mese',
    week:     'Settimana',
    day:      'Giorno'
   },
   columnFormat: {
    month: 'ddd',    // Mon
    week: 'd/M ddd', // Mon 9/7
    day: 'dddd d/M'  // Monday 9/7
   },
   editable: true,
   
   events: {
    url: 'lista_calendario_strutture.php',
    cache: true,
    //color: 'purple',   // a non-ajax option
          textColor: 'white' // a non-ajax option
   },
   lazyFetching: false,
     
   eventClick: function(calEvent) {
    if(confirm("Elimino dal calendario la disponibilita' della struttura per il giorno selezionato?")) {
     $.ajax({
       url: "interventi.php?section=calendario_strutture&action=delete",
       type: 'POST',
       data: {
      struttura: calEvent.title,
      data: calEvent.start.getTime()
       },
       success: function(msg){
      //alert(msg); //debug
      $('#calendar_strutture').fullCalendar('removeEvents',calEvent.id); 
       },
       error: function() {
      revertFunc();
       }
     });
    }
   },
   
   eventMouseover: function(calEvent) {
    $(this).find('.fc-event-title').html('<img src="template/default/admin/assets/images/delete.png" /> '+calEvent.title);
   },
   
   eventMouseout: function(calEvent) {
    $(this).find('.fc-event-title').html(calEvent.title);  
   },
   
   eventDrop: function(calEvent,dayDelta,minuteDelta,allDay,revertFunc) {
    //Qui ajax per spostamento evento
    $.ajax({
      url: "interventi.php?section=calendario_strutture&action=move",
      type: 'POST',
      data: {
     struttura: calEvent.title,
     movimento: dayDelta,
     nuova_data: calEvent.start.getTime()
               },
      success: function(msg){
     //alert(msg);
      },
      error: function() {
     revertFunc();
      }
    });
   },
   droppable: true,
   drop: function(date, allDay) { // this function is called when something is dropped
   
    // retrieve the dropped element's stored Event Object
    var originalEventObject = $(this).data('eventObject');
    
    // we need to copy it, so that multiple events don't have a reference to the same object
    var copiedEventObject = $.extend({}, originalEventObject);
    
    var today = new Date();
    
    // assign it the date that was reported
    copiedEventObject.id = today.getTime();
    copiedEventObject.start = date;
    copiedEventObject.allDay = allDay;
    
    //alert(copiedEventObject.title + ' ' + copiedEventObject.start.getTime());
    
    //Qui ajax per inserimento disponibilita in calendario struttura
    $.ajax({
      url: "interventi.php?section=calendario_strutture&action=insert",
      type: 'POST',
      data: {
     struttura: copiedEventObject.title,
     data: copiedEventObject.start.getTime()
               },
      success: function(msg){
     //alert(msg); //debug
     // render the event on the calendar
     $('#calendar_strutture').fullCalendar('renderEvent', copiedEventObject, false);
      }
    });
    
   }
   
  });

$('#external-events div.external-event').each(function() {

 // create an Event Object (http://arshaw.com/fullcalendar/docs/event_data/Event_Object/)
 // it doesn't need to have a start or end
 var eventObject = {
  title: $.trim($(this).text()), // use the element's text as the event title
  backgroundColor: $(this).css('background-color')
 };
 
 // store the Event Object in the DOM element so we can get to it later
 $(this).data('eventObject', eventObject);
 
 // make the event draggable using jQuery UI
 $(this).draggable({
  zIndex: 999,
  revert: true,      // will cause the event to go back to its
  revertDuration: 0  //  original position after the drag
 });
 
});

Questa prima parte, che deve essere contenuta nella parte relativa a $(document).ready(...), specifica il comportamento del calendario, in particolare:
  1. deve poter gestire, tramite chiamate ajax, lo spostamento degli eventi (eventDrop), che in questo caso particolare, sono "disponibilità" delle sale operatorie in determinate strutture ospedaliere
  2. deve gestire l'eliminazione delle disponibilità, mediante click del mouse (eventClick) sull'evento stesso (notare che quando il mouse si trova sopra l'evento viene mostrata una icona "cestino")
  3. deve gestire la creazione delle disponibilità mediante il trascinamento dall'elenco strutture sulla sinistra al calendario (drop), date una occhiata allo screenshot per capire di cosa sto parlando
  4. La parte finale del codice jQuery è relativa al punto 3, fa capire al motore javascript che i
    sulla sinistra deve gestirli come "draggable" e creare un oggetto evento (Event Object) in modo da poterlo poi gestire in FullCalendar.
Di seguito il codice html utilizzato (elenco strutture + calendario):
<div id='wrap' style="width:100%;margin: 0 auto;"> 
                 <div id='external-events' style="float: left;width: 150px;padding: 0 10px;border: 1px solid #ccc;background: #eee;text-align: left;margin-right:20px;">
                  <h4>Elenco Strutture</h4>
                                    <div class='external-event' style="background-color:#0099FF">Struttura Ospedaliera 1</div>
                                    <div class='external-event' style="background-color:#996699">Struttura Ospedaliera 2</div>

                                    </div>
                 <div id='calendar_strutture' style="width: 900px;float:left;"></div>
                 <div style='clear:both'></div>
              </div>
            </div>
Il risultato finale!

mercoledì 27 luglio 2011

jQuery: semplice e veloce slideshow (base)

Girovagando per la rete, mi sono imbattuto in questo codice per creare una veloce slideshow con il framework jQuery.
Ovviamente fare il copia e incolla non è nel mio stile quindi ho apportato qualche piccola modifica nel codice (niente di speciale, tempistiche e stile degli elementi).
Questo perché, se utilizzate direttamente il codice originale, verrà mostrato un effetto non voluto: durante la transizione delle immagini, se ne vedono due in una volta che sembra che facciano a botte tra di loro per mostrarsi (ok, fate prima a provare di persona per capire cosa intendo). 
Per la cronaca, l'autore del codice originale lascia all'utilizzatore finale il compito di aggiungere tutto lo stile CSS. E così ho fatto :-)

Qui di seguito il listato della slideshow personalizzata. Iniziamo con la testata del file html (standard), dove andremo ad inglobare jQuery:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<title>Prova Slideshow</title>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.5.1/jquery.min.js"></script>
Proseguiamo con il cuore del codice:
<script>
$(function(){
    $('.slideshow img:gt(0)').hide();
    setInterval(function(){$('.slideshow :first-child').fadeOut(1500).next('img').fadeIn(1500).end().appendTo('.slideshow');}, 2400);
});
</script>
Io ho aggiunto la tempistica del fadeOut e del fadeIn (1 secondo e mezzo).
Applichiamo uno stile css adeguato ai nostri scopi: slideshow centrato, sovrapposizione delle immagini per evitare effetto "litigio", eccetera:
<style type="text/css">
body {
 margin:0;
 padding:0;
 text-align:center;
}
.slideshow {
 margin:0 auto;
 padding:0;
 width:618px;
 height:246px;
 border:1px solid #eeeeee;
}
.slideshow img { 
 display:block;
 position:absolute;
}
</style>
E finiamo in bellezza con il codice html dello slideshow (e del resto della pagina)
</head>
<body>
 <div class="slideshow">
  <img src="1.jpg"/>
  <img src="2.jpg"/>
  <img src="3.jpg"/>
 </div>
</body>
</html>

martedì 26 luglio 2011

jQuery: eliminare una riga di una tabella (con richiesta ajax)

Poco tempo fa ho avuto la necessità di sviluppare un piccolo programma di protocollo. Caratteristica base era che ogni documento protocollato poteva avere più mittenti e più destinatari: la cancellazione degli stessi, così come la modifica, doveva avvenire in modo trasparente e veloce, ossia... tramite ajax :-)
Ricercando nel web, mi sono imbattuto in questa soluzione, facilmente adattata alle mie esigenze:
function cancellaMittente(id,num_progressivo,anno_progressivo){
 if (confirm('Sicuro di voler eliminare questo mittente?')) {
  jQuery.post('cancella_mittente.php', {id: +id, num_progressivo: + num_progressivo, anno_progressivo: +anno_progressivo },
  function(){
   jQuery("#mittente_"+id).fadeOut("slow");
  });
 }
}
Questa funzione verrà richiamata ogni volta che si vorrà eliminare un determinato mittente ed eseguirà le operazioni:
  1. esecuzione di una richiesta ajax di tipo post al file cancella_mittente.php con parametro id (dell'anagrafica), num_progressivo e anno_progressivo (questi ultimi identificano il documento protocollato);
  2. fadeOut, e quindi dissolvenza e cancellazione, della riga selezionata (la discriminazione è per id del tag, ad esempio mittente_1
Lato html invece la questione è semplice:
<tr id="destinatario_1">
   <td width="50">
      <a href="#" onclick="cancellaDestinatario(1,12,2011)">
      <img src="img/remove.png" /></a>
   </td>
   <td align="center">Pinco Pallino</td>
</tr>
Il file richiamato via post ajax avrà il compito di eliminare dal database la entry relativa all'id passato per parametro. Di seguito l'implementazione vera, con due parametri (num_progressivo e anno_progressivo) che per semplicità sono stati omessi nei listati precedenti:
<?php

require('engine/config.php');

if(is_numeric($_REQUEST['num_progressivo']) && is_numeric($_REQUEST['anno_progressivo']) && is_numeric($_REQUEST['id'])) {

$ris=$db->query("DELETE FROM ". $__TABLE_PREFIX."protocollo_mittente WHERE mittente_documento_num_progressivo='".$_REQUEST['num_progressivo']."' AND mittente_documento_anno_progressivo='".$_REQUEST['anno_progressivo']."' AND mittente_id_anagrafica='".$_REQUEST['id']."'");

}

?>

giovedì 26 novembre 2009

Image Zoom con MooTools

Ho trovato un interessante articolo per creare un effetto "zoom": per intenderci, quello con una miniatura da cui si sceglie, con il mouse, l'area da ingrandire e l'immagine zoomata che riflette la scelta precedente.
Nella figura sottostante è possibile vedere l'esempio concreto:
Il codice, che si basa sulla libreria MooTools, è scaricabile all'indirizzo: http://www.php-help.ro/mootools-12-javascript-examples/mootools-12-javascript-image-zoom/