From 2389d66da849798f8d4ec5f10e3b07c11da49185 Mon Sep 17 00:00:00 2001 From: Michael Francis Date: Sat, 28 May 2011 13:28:16 -0400 Subject: Initial Commit --- .../layouts/presentation_files/visualize.jQuery.js | 463 +++++++++++++++++++++ 1 file changed, 463 insertions(+) create mode 100644 views/layouts/presentation_files/visualize.jQuery.js (limited to 'views/layouts/presentation_files/visualize.jQuery.js') diff --git a/views/layouts/presentation_files/visualize.jQuery.js b/views/layouts/presentation_files/visualize.jQuery.js new file mode 100644 index 0000000..dbd4af4 --- /dev/null +++ b/views/layouts/presentation_files/visualize.jQuery.js @@ -0,0 +1,463 @@ +/* + * -------------------------------------------------------------------- + * jQuery inputToButton plugin + * Author: Scott Jehl, scott@filamentgroup.com + * Copyright (c) 2009 Filament Group + * licensed under MIT (filamentgroup.com/examples/mit-license.txt) + * -------------------------------------------------------------------- +*/ +(function($) { +$.fn.visualize = function(options, container){ + return $(this).each(function(){ + //configuration + var o = $.extend({ + type: 'bar', //also available: area, pie, line + width: $(this).width(), //height of canvas - defaults to table height + height: $(this).height(), //height of canvas - defaults to table height + appendTitle: true, //table caption text is added to chart + title: null, //grabs from table caption if null + appendKey: true, //color key is added to chart + rowFilter: ' ', + colFilter: ' ', + colors: ['#be1e2d','#666699','#92d5ea','#ee8310','#8d10ee','#5a3b16','#26a4ed','#f45a90','#e9e744'], + textColors: [], //corresponds with colors array. null/undefined items will fall back to CSS + parseDirection: 'x', //which direction to parse the table data + pieMargin: 20, //pie charts only - spacing around pie + pieLabelsAsPercent: true, + pieLabelPos: 'inside', + lineWeight: 4, //for line and area - stroke weight + barGroupMargin: 10, + barMargin: 1, //space around bars in bar chart (added to both sides of bar) + yLabelInterval: 30 //distance between y labels + },options); + + //reset width, height to numbers + o.width = parseFloat(o.width); + o.height = parseFloat(o.height); + + + var self = $(this); + + //function to scrape data from html table + function scrapeTable(){ + var colors = o.colors; + var textColors = o.textColors; + var tableData = { + dataGroups: function(){ + var dataGroups = []; + if(o.parseDirection == 'x'){ + self.find('tr:gt(0)').filter(o.rowFilter).each(function(i){ + dataGroups[i] = {}; + dataGroups[i].points = []; + dataGroups[i].color = colors[i]; + if(textColors[i]){ dataGroups[i].textColor = textColors[i]; } + $(this).find('td').filter(o.colFilter).each(function(){ + dataGroups[i].points.push( parseFloat($(this).text()) ); + }); + }); + } + else { + var cols = self.find('tr:eq(1) td').filter(o.colFilter).size(); + for(var i=0; itopValue) topValue = parseFloat(this); + }); + return topValue; + }, + bottomValue: function(){ + var bottomValue = 0; + var allData = this.allData().join(',').split(','); + $(allData).each(function(){ + if(thistopYtotal) topYtotal = parseFloat(this); + }); + return topYtotal; + }, + totalYRange: function(){ + return this.topValue() - this.bottomValue(); + }, + xLabels: function(){ + var xLabels = []; + if(o.parseDirection == 'x'){ + self.find('tr:eq(0) th').filter(o.colFilter).each(function(){ + xLabels.push($(this).html()); + }); + } + else { + self.find('tr:gt(0) th').filter(o.rowFilter).each(function(){ + xLabels.push($(this).html()); + }); + } + return xLabels; + }, + yLabels: function(){ + var yLabels = []; + yLabels.push(bottomValue); + var numLabels = Math.round(o.height / o.yLabelInterval); + var loopInterval = Math.ceil(totalYRange / numLabels) || 1; + while( yLabels[yLabels.length-1] < topValue - loopInterval){ + yLabels.push(yLabels[yLabels.length-1] + loopInterval); + } + yLabels.push(topValue); + return yLabels; + } + }; + + return tableData; + }; + + + //function to create a chart + var createChart = { + pie: function(){ + + canvasContain.addClass('visualize-pie'); + + if(o.pieLabelPos == 'outside'){ canvasContain.addClass('visualize-pie-outside'); } + + var centerx = Math.round(canvas.width()/2); + var centery = Math.round(canvas.height()/2); + var radius = centery - o.pieMargin; + var counter = 0.0; + var toRad = function(integer){ return (Math.PI/180)*integer; }; + var labels = $('
    ') + .insertAfter(canvas); + + //draw the pie pieces + $.each(memberTotals, function(i){ + var fraction = (this <= 0 || isNaN(this))? 0 : this / dataSum; + ctx.beginPath(); + ctx.moveTo(centerx, centery); + ctx.arc(centerx, centery, radius, + counter * Math.PI * 2 - Math.PI * 0.5, + (counter + fraction) * Math.PI * 2 - Math.PI * 0.5, + false); + ctx.lineTo(centerx, centery); + ctx.closePath(); + ctx.fillStyle = dataGroups[i].color; + ctx.fill(); + // draw labels + var sliceMiddle = (counter + fraction/2); + var distance = o.pieLabelPos == 'inside' ? radius/1.5 : radius + radius / 5; + var labelx = Math.round(centerx + Math.sin(sliceMiddle * Math.PI * 2) * (distance)); + var labely = Math.round(centery - Math.cos(sliceMiddle * Math.PI * 2) * (distance)); + var leftRight = (labelx > centerx) ? 'right' : 'left'; + var topBottom = (labely > centery) ? 'bottom' : 'top'; + var percentage = parseFloat((fraction*100).toFixed(2)); + + if(percentage){ + var labelval = (o.pieLabelsAsPercent) ? percentage + '%' : this; + var labeltext = $('' + labelval +'') + .css(leftRight, 0) + .css(topBottom, 0); + if(labeltext) + var label = $('
  • ') + .appendTo(labels) + .css({left: labelx, top: labely}) + .append(labeltext); + labeltext + .css('font-size', radius / 8) + .css('margin-'+leftRight, -labeltext.width()/2) + .css('margin-'+topBottom, -labeltext.outerHeight()/2); + + if(dataGroups[i].textColor){ labeltext.css('color', dataGroups[i].textColor); } + } + counter+=fraction; + }); + }, + + line: function(area){ + + if(area){ canvasContain.addClass('visualize-area'); } + else{ canvasContain.addClass('visualize-line'); } + + //write X labels + var xInterval = canvas.width() / (xLabels.length -1); + var xlabelsUL = $('
      ') + .width(canvas.width()) + .height(canvas.height()) + .insertBefore(canvas); + $.each(xLabels, function(i){ + var thisLi = $('
    • '+this+'
    • ') + .prepend('') + .css('left', xInterval * i) + .appendTo(xlabelsUL); + var label = thisLi.find('span:not(.line)'); + var leftOffset = label.width()/-2; + if(i == 0){ leftOffset = 0; } + else if(i== xLabels.length-1){ leftOffset = -label.width(); } + label + .css('margin-left', leftOffset) + .addClass('label'); + }); + + //write Y labels + var yScale = canvas.height() / totalYRange; + var liBottom = canvas.height() / (yLabels.length-1); + var ylabelsUL = $('
        ') + .width(canvas.width()) + .height(canvas.height()) + .insertBefore(canvas); + + $.each(yLabels, function(i){ + var thisLi = $('
      • '+this+'
      • ') + .prepend('') + .css('bottom',liBottom*i) + .prependTo(ylabelsUL); + var label = thisLi.find('span:not(.line)'); + var topOffset = label.height()/-2; + if(i == 0){ topOffset = -label.height(); } + else if(i== yLabels.length-1){ topOffset = 0; } + label + .css('margin-top', topOffset) + .addClass('label'); + }); + + //start from the bottom left + ctx.translate(0,zeroLoc); + //iterate and draw + $.each(dataGroups,function(h){ + ctx.beginPath(); + ctx.lineWidth = o.lineWeight; + ctx.lineJoin = 'round'; + var points = this.points; + var integer = 0; + ctx.moveTo(0,-(points[0]*yScale)); + $.each(points, function(){ + ctx.lineTo(integer,-(this*yScale)); + integer+=xInterval; + }); + ctx.strokeStyle = this.color; + ctx.stroke(); + if(area){ + ctx.lineTo(integer,0); + ctx.lineTo(0,0); + ctx.closePath(); + ctx.fillStyle = this.color; + ctx.globalAlpha = .3; + ctx.fill(); + ctx.globalAlpha = 1.0; + } + else {ctx.closePath();} + }); + }, + + area: function(){ + createChart.line(true); + }, + + bar: function(){ + + canvasContain.addClass('visualize-bar'); + + //write X labels + var xInterval = canvas.width() / (xLabels.length); + var xlabelsUL = $('
          ') + .width(canvas.width()) + .height(canvas.height()) + .insertBefore(canvas); + $.each(xLabels, function(i){ + var thisLi = $('
        • '+this+'
        • ') + .prepend('') + .css('left', xInterval * i) + .width(xInterval) + .appendTo(xlabelsUL); + var label = thisLi.find('span.label'); + label.addClass('label'); + }); + + //write Y labels + var yScale = canvas.height() / totalYRange; + var liBottom = canvas.height() / (yLabels.length-1); + var ylabelsUL = $('
            ') + .width(canvas.width()) + .height(canvas.height()) + .insertBefore(canvas); + $.each(yLabels, function(i){ + var thisLi = $('
          • '+this+'
          • ') + .prepend('') + .css('bottom',liBottom*i) + .prependTo(ylabelsUL); + var label = thisLi.find('span:not(.line)'); + var topOffset = label.height()/-2; + if(i == 0){ topOffset = -label.height(); } + else if(i== yLabels.length-1){ topOffset = 0; } + label + .css('margin-top', topOffset) + .addClass('label'); + }); + + //start from the bottom left + ctx.translate(0,zeroLoc); + //iterate and draw + for(var h=0; h')) + .height(o.height) + .width(o.width) + .append(canvas); + + //scrape table (this should be cleaned up into an obj) + var tableData = scrapeTable(); + var dataGroups = tableData.dataGroups(); + var allData = tableData.allData(); + var dataSum = tableData.dataSum(); + var topValue = tableData.topValue(); + var bottomValue = tableData.bottomValue(); + var memberTotals = tableData.memberTotals(); + var totalYRange = tableData.totalYRange(); + var zeroLoc = o.height * (topValue/totalYRange); + var xLabels = tableData.xLabels(); + var yLabels = tableData.yLabels(); + + //title/key container + if(o.appendTitle || o.appendKey){ + var infoContain = $('
            ') + .appendTo(canvasContain); + } + + //append title + if(o.appendTitle){ + $('
            '+ title +'
            ').appendTo(infoContain); + } + + + //append key + if(o.appendKey){ + var newKey = $('
              '); + var selector; + if(o.parseDirection == 'x'){ + selector = self.find('tr:gt(0) th').filter(o.rowFilter); + } + else{ + selector = self.find('tr:eq(0) th').filter(o.colFilter); + } + + selector.each(function(i){ + $('
            • '+ $(this).text() +'
            • ') + .appendTo(newKey); + }); + newKey.appendTo(infoContain); + }; + + //append new canvas to page + + if(!container){canvasContain.insertAfter(this); } + if( typeof(G_vmlCanvasManager) != 'undefined' ){ G_vmlCanvasManager.init(); G_vmlCanvasManager.initElement(canvas[0]); } + + //set up the drawing board + var ctx = canvas[0].getContext('2d'); + + //create chart + createChart[o.type](); + + //clean up some doubled lines that sit on top of canvas borders (done via JS due to IE) + $('.visualize-line li:first-child span.line, .visualize-line li:last-child span.line, .visualize-area li:first-child span.line, .visualize-area li:last-child span.line, .visualize-bar li:first-child span.line,.visualize-bar .visualize-labels-y li:last-child span.line').css('border','none'); + if(!container){ + //add event for updating + canvasContain.bind('visualizeRefresh', function(){ + self.visualize(o, $(this).empty()); + }); + } + }).next(); //returns canvas(es) +}; +})(jQuery); + + -- cgit v1.2.3