3ENGINE

Programación y otros cachivaches

Etiqueta: jquery

Página 1/2

Tecnologia

Chart.js: grafica de tipo donut con múltiples anillos


En un artículo anterior expliqué cómo añadir texto dentro de una grafica de tipo donut. Hoy te voy a mostrar cómo crear una gráfica tipo donut con múltiples anillos.

Extra! tambien veremos cómo modificar la información que aparece al pasar el ratón por encima de cada uno de los datos de la gŕafica.

Básicamente tenemos que declarar varios conjuntos de datos, donde cada conjunto de datos es un anillo. Hasta aqui todo bien. Si queremos mostrar una etiqueta «personalizada» para cada uno de los datos, tenemos que añadir las etiquetas en cada conjunto de datos y sobreescribir la función encargada de mostrar la información que aparece al pasar el ratón por encima. Ademas, ya de paso, hemos aprovechado para calcular el porcentage.

Código HTML

 <div id="mychart-holder">
    <canvas id="mychart"/>
 </div>

Código Javascript

var data = {
    labels: [],
    datasets: [
        {
            data: [2, 3, 8, 3, 4],
            backgroundColor: ["orange", "red", "green", "violet", "lightgreen"],
            labels: ["naranjas", "mandarinas", "manzanas", "berenjenas", "calabacines"]
        },
        {
            data: [2 + 3 + 8,  3 + 4],
            backgroundColor: ["springgreen", "lightblue"],
            labels: ["frutas", "hortalizas"],
        },
        {
            data: [2 + 3 + 8 + 3 + 4],
            backgroundColor: ["lightgray"],
            labels: ["total"],
        }
    ]
};

var myChart = new Chart(document.getElementById('mychart'), {
    type: 'doughnut',
    data: data,
    options: {
        cutoutPercentage: 20,
        maintainAspectRatio: true,
        responsive: true,
        legend: {
            display: false
        },
        animation: {
            animateScale: true,
            animateRotate: true
        },
        tooltips: {
             /* activa esta funcion si deseas no mostrar alguna de las etiquetas
            filter: function (item, data) {
                if (item.datasetIndex == 1) {
                if (item.index == 1) {
                   return false;
                  }
                }
                return true;
            },
            */            callbacks: {
                label: function(item, data) {
                    // get label and data
                    var labels = data.datasets[item.datasetIndex].labels;
                    var dataset = data.datasets[item.datasetIndex].data;
                    
                    var currentLabel = labels[item.index];
                    var currentValue = dataset[item.index];
                    
                    // calc percentage
                    var total = dataset.reduce(function(previousValue, currentValue, currentIndex, array) {
                        return previousValue + currentValue;
                    });
                    var percentage = ((currentValue/total) * 100);

                    // put label
                    return " " + currentLabel + ": " + currentValue + " (" + percentage.toFixed(1) + "%)";
                     
                }
            }
        },
    }
});

Aqui dejo el jsfiddle




Tecnologia

Chart.js: cómo añadir texto dentro de una grafica de tipo donut


A continuación te muestro cómo añadir texto dentro de una grafica de tipo donut en Chart.js

Chart.js es una libreria open source para crear gráficos en javascript basados en HTML5. Entre la amplia lista de gráficos disponibles de esta fantástica librería tenemos el donut (doughnut). Que básicamente es un gráfico de torta pero con un agujero en el centro … sorprendidos ¿verdad? 😉

Yo lo que quiero es aprovechar ese agujero del centro para añadir información, ya sea un simple texto o el total. Algo asi como los pop dots 😉

cómo añadir texto dentro de una grafica de tipo donut

Básicamente esto se consigue añadiendo un plugin e implementando el evento beforedraw. En mi ejemplo muestro el total pero podeis modificar el código para mostrar otra información.

Código HTML

<div id="mychart-holder">
    <canvas id="mychart"/>
</div>

Código Javascript

var data = {
    labels: ["Error", "Failure", "Success", "Skip", "Unknown"],
    datasets: [
        {
            data: [10, 5, 20, 2, 1],
            backgroundColor: ["red", "orange", "green", "blue", "violet"],
        }
    ]
};

var myChart = new Chart(document.getElementById('mychart'), {
    type: 'doughnut',
    data: data,
    options: {
        //cutoutPercentage: 50,
        maintainAspectRatio: true,
        responsive: true,
        legend: {
            display: false
        },
        animation: {
            animateScale: true,
            animateRotate: true
        },
    },
    plugins: [{
        id: 'total',
        beforeDraw: function(chart) {
            const width = chart.chart.width;
            const height = chart.chart.height;
            const ctx = chart.chart.ctx;
            ctx.restore();
            const fontSize = (height / 114).toFixed(2);
            ctx.font = fontSize + "em sans-serif";
            ctx.textBaseline = 'middle';
            var total = data.datasets[0].data.reduce(function(previousValue, currentValue, currentIndex, array) {
                return previousValue + currentValue;
            });
            const text = total;
            const textX = Math.round((width - ctx.measureText(text).width) / 2);
            const textY = height / 2;
            ctx.fillText(text, textX, textY);
            ctx.save();
        }
    }]
});

Aquí el código en jsfiddle

Si lo que queremos es utilizar el plugin en varias gráficas, entonces podemos registrar el plugin

Código Javascript (2)

var data = {
    labels: ["Error", "Failure", "Success", "Skip", "Unknown"],
    datasets: [
        {
            data: [10, 5, 20, 2, 1],
            backgroundColor: ["red", "orange", "green", "blue", "violet"],
        }
    ]
};

Chart.Chart.pluginService.register({
    beforeDraw: function(chart) {
        const width = chart.chart.width;
        const height = chart.chart.height;
        const ctx = chart.chart.ctx;
        ctx.restore();
        const fontSize = (height / 114).toFixed(2);
        ctx.font = fontSize + "em sans-serif";
        ctx.textBaseline = 'middle';
        var total = chart.data.datasets[0].data.reduce(function(previousValue, currentValue, currentIndex, array) {
                return previousValue + currentValue;
        });
        const text = total;
        const textX = Math.round((width - ctx.measureText(text).width) / 2);
        const textY = height / 2;
        ctx.fillText(text, textX, textY);
        ctx.save();
    },
});

var myChart = new Chart(document.getElementById('mychart'), {
    type: 'doughnut',
    data: data,
    options: {
        //cutoutPercentage: 50,
        maintainAspectRatio: true,
        responsive: true,
        legend: {
            display: false
        },
        animation: {
            animateScale: true,
            animateRotate: true
        },
    }
});

Aquí el código en jsfiddle




Tecnologia

Bootstrap: cómo agregar estado checked a los elementos de un menu dropdown


A continuación te muestro cómo agregar estado checked a los elementos de un menu dropdown de Bootstrap

Bootstrap es un framework Open Source creado por Twitter que facilita el diseño web. En la lista de componentes facilitados por este genial framework tenemos el dropdown. Un dropdown permite mostrar una lista de opciones en un desplegable. El problema es que bootstrap no permite indicar si una opcion de la lista está checked (activada) o unchecked (desactivada). Para conseguir esto por nuestra cuenta vamos a necesitar un poco de css y javascript:

  • La clase dropdown-item-checked añade un símbolo ‘✓’ a la izquierda de la opción, esto se consigue con CSS.
  • Con HTML asociamos cada una de las opciones del dropdown a la clase option que nos servirá para capturar el evento click y añadimos la clase dropdown-item-checked a las opciones que queremos a checked por defecto.
  • Javascript captura el evento click sobre las opciones y conmuta la clase dropdown-item-checked de la opcion sobre la que hemos hecho click. Cuando la opción no tiene la clase dropdown-item-checked el símbolo ‘✓’ desaparece y viceversa, cuando la opción tiene la clase dropdown-item-checked el símbolo ‘✓’ aparece de nuevo.

Código HTML

<div class="btn-toolbar">
  <div class="input-group">
    <div class="input-group-btn">
      <button type="button" class="btn btn-default" data-toggle="dropdown">
        <span class="caret"></span>
      </button>
      <ul class="dropdown-menu" id="menu">
        <li><a href="#" id="option-one" class="option dropdown-item-checked">My option one</a></li>
        <li><a href="#" id="option-two" class="option">My option two</a></li>
        <li><a href="#" id="option-three" class="option dropdown-item-checked">My option three</a></li>
        <li role="separator" class="divider"></li>
        <li><a href="#" id="option-five" class="option">My option five</a></li>
      </ul>
    </div>
  </div>
</div>

Código CSS

.dropdown-item-checked::before {
   position: absolute;
   left: .4rem;
   content: '✓';
   font-weight: 600;
}

Código Javascript

$(".option").click(function(event){
  event.preventDefault();
  var id = $(this).attr('id');
  $(this).toggleClass("dropdown-item-checked");
  var isChecked = $(this).hasClass("dropdown-item-checked");
  if (id == 'option-one') {
   if (isChecked) {
     // bla bla bla 
     }
  } else if (id == 'option-two') {
  // bla bla bla
  } else if (id == 'option-three') {
  // bla bla bla
  } else if (id == 'option-four') {
  // bla bla bla
  }
});

Aqui el código en jsfiddle




Tecnologia

Cómo mostrar una imagen de progreso con jquery ajax (ajax loader)


Para mostrar una imagen de progreso con jquery ajax antes de nada tenemos que conseguir un gif animado. Por ejemplo podemos obtener de ajaxload.info un gif como este:

loading

Lo que yo quiero conseguir es que aparezca el gif animado sea cual sea la llamada jquery ajax. Esto se consigue con el siguiente código en jquery. Básicamente lo que hace es mostrar un div con id=ajaxBusy que contiene el gif, al iniciar una llamada jquery ajax y esconder el div al finalizar la misma:

$(document).ajaxStart(function () {
    $('#ajaxBusy').show();
}).ajaxStop(function () {
    $('#ajaxBusy').hide();
});

El código HTML con el gif es el siguiente:

<div id="ajaxBusy">
  <p>
    <img src="loading.gif">
  </p>
</div>

Que necesita su correspondiente css:

#ajaxBusy
{
    display: none; 
    margin: 0px;
    paddingLeft: 0px;
    paddingRight: 0px;
    paddingTop: 0px;
    paddingBottom: 0px;
    position: absolute;
    top: 50%;
    left: 50%;
    marginTop: -50px;
    marginLeft: -50px;
    width: 100px;
    height: 100px;
}

Para probar que todo esto funciona he escrito una demo. En la demo he adaptado un servidor HTTP muy simple escrito en Python que explique en la entrada Método rápido para servir archivos a través de HTTP (Servidor HTTP) con SimpleHTTPServer. La adaptación ha consistido en añadir en el método do_POST() un «echo» de modo que el servidor retorne un HTML con el mensaje enviado, en un tiempo opcionalmente parametrizable. En mi caso, esto es util para testear que el gif animado aparece:

from SimpleHTTPServer import SimpleHTTPRequestHandler
import SocketServer
import time
import urlparse
from cgi import parse_header, parse_multipart

class MyRequestHandler(SimpleHTTPRequestHandler):

    def __init__(self, *args):
        SimpleHTTPRequestHandler.__init__(self, *args)

    def parse_POST(self):
        ctype, pdict = parse_header(self.headers['content-type'])
        if ctype == 'multipart/form-data':
            postvars = parse_multipart(self.rfile, pdict)
        elif ctype == 'application/x-www-form-urlencoded':
            length = int(self.headers['content-length'])
            postvars = urlparse.parse_qs(
                    self.rfile.read(length), 
                    keep_blank_values=1)
        else:
            postvars = {}
        return postvars
    
    def do_GET(self):
        print self.command
        print self.path
        return SimpleHTTPRequestHandler.do_GET(self)

    def do_POST(self):
        print self.command
        print self.path
        parse = urlparse.urlparse(self.path)
        fields = self.parse_POST()
        self.send_response(200) 
        self.send_header('Content-type', 'text/html')
        self.end_headers()
        if parse.path == '/echo':
            if fields['delay']:
                seconds = float(fields['delay'][0]) / 1000
                time.sleep(seconds)
            if fields['html']:        
                self.wfile.write(fields['html'][0])
        else:
            self.wfile.write('<ul>')
            for key, value in fields.iteritems():
                self.wfile.write('<li>%s: %s</li>' % (key, value))
            self.wfile.write('</ul>')

PORT = 8000
Handler = MyRequestHandler
httpd = SocketServer.TCPServer(("", PORT), Handler)

print "serving at port", PORT
httpd.serve_forever()

Al final tienes esto:

demo

Enlace para descargar la demo: demo.zip