Skip to content

Instantly share code, notes, and snippets.

@koyachi
Created February 17, 2010 07:43
Show Gist options
  • Save koyachi/306407 to your computer and use it in GitHub Desktop.
Save koyachi/306407 to your computer and use it in GitHub Desktop.
// http://assets1.github.com/javascripts/bundle_github.js のグラフ書いてる処理抜粋
$(function(){
$(".graph .bars").each(function(){
var a = this;
if ($(a).is(":visible")) {
var b = function(c){ new ParticipationGraph(a,c) },
d = $(this).attr("rel");
$.get(d,null,b,"text")
}
})
});
ParticipationGraph = function(a,b) {
this.BAR_WIDTH = 7;
this.ownerCommits = this.allCommits = null;
this.primer = new Primer(a,416,20);
this.data = b;
this.readData();
this.draw()
};
ParticipationGraph.prototype = {
readData: function() {
var a = this.data.split("\n");
this.allCommits = a[0] ? this.base64BytesToIntArray(a[0]) : "";
this.ownerCommits = a[1] ? this.base64BytesToIntArray(a[1]) : ""
},
max: function(a) {
for (var b=a[0],d=1;d<a.length;d++)
if (a[d]>b) b=a[d];
return b
},
integerize: function(a) {
for (var b=[],d=0;d<a.length;d++)
b.push(parseInt(a[d]));
return b
},
base64ByteToInt: function(a) {
var b = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!-";
return b.indexOf(a)
},
base64BytesToIntArray: function(a) {
for(var b=[],d,c=0;c<a.length;c++)
if (c%2==0)
d=64*this.base64ByteToInt(a.charAt(c));
else {
d+=this.base64ByteToInt(a.charAt(c));
b.push(d)
}
return b
},
draw: function() {
var a = this.max(this.allCommits);
a = a >= 20 ? 19/a : 1;
var b = new Primer.Layer;
b.bind(this.primer);
for (var d=0; d<this.allCommits.length; d++) {
var c = new Primer.Layer;
c.bind(this.primer);
c.setFillStyle("#CACACA");
var e = this.allCommits[d]*a;
c.fillRect(d*(this.BAR_WIDTH+1),20-e,this.BAR_WIDTH,e);
b.addChild(c)
}
var f = new Primer.Layer;
f.bind(this.primer);
for (d=0;d<this.ownerCommits.length;d++) {
c = new Primer.Layer;
c.bind(this.primer);
c.setFillStyle("#336699");
e = this.ownerCommits[d]*a;
c.fillRect(d*(this.BAR_WIDTH+1),20-e,this.BAR_WIDTH,e);
f.addChild(c)
}
this.primer.addChild(b);
this.primer.addChild(f)
}
};
//-------
function definePrimer(a) {
function b(d,c,e,f) {
this.container = d;
this.width = c;
this.height = e;
this.primer = this;
this.useGlobalMouseMove = f;
this.actions = [];
this.init();
this.autoDraw = true
}
b.prototype = {
init: function() {
a("html head").append("<style>.primer_text { position: absolute; margin: 0; padding: 0; line-height: normal; z-index: 0;}</style>");
var d = a(this.container).eq(0);
d.append('<div id="primer_text"></div>');
var c = a("#primer_text",d).eq(0);
c.css("position","relative");
this.element = c;
c = document.createElement("canvas");
c.width = this.width;
c.height=this.height;
c.style.zIndex = "0";
if (c.getContext) d.append(c);
else window.G_vmlCanvasManager && window.G_vmlCanvasManager.initElement(a(c).appendTo(d).get(0));
d = a("canvas",d);
var e = d[0];
this.context = e.getContext("2d");
this.root = new b.Layer;
this.root.bind(this);
this.setupExt();
var f=this;
this.useGlobalMouseMove ?
a("body").bind("mousemove", function(g) {
if (a(g.target).parents().find(this.container)) {
var h = a(e);
h = h.offset();
g.localX = g.pageX - h.left;
g.localY = g.pageY - h.top;
f.ghost(g)
}
else
f.outOfBounds()
}) :
d.eq(0).bind("mousemove", function(g){
var h = a(g.currentTarget).offset();
g.localX = g.pageX - h.left;
g.localY = g.pageY - h.top;
f.ghost(g)
})
},
getX: function() {
return 0
},
getY: function() {
return 0
},
getGlobalX: function() {
return 0
},
getGlobalY: function() {
return 0
},
addChild: function(d) {
d.bind(this);
this.root.addChild(d);
this.draw()
},
removeChild: function(d){
this.root.removeChild(d);
this.draw()
},
draw: function(d) {
if (d||this.autoDraw) {
this.context.clearRect(0,0,this.width,this.height);
a(".primer_text",this.element).remove();
this.setupExt();
this.root.draw()
}
},
ghost: function(d){
this.root.ghost(d);
for (var c in this.actions) {
d = this.actions[c];
d[0](d[1])
}
this.actions = []
},
outOfBounds: function(){},
setupExt: function(){
this.context.ext = {
textAlign: "left",
font: "10px sans-serif"
}
}
};
b.Layer = function() {
this.element = this.context = this.primer = null;
this.children = [];
this.calls = [];
this.yVal = this.xVal = 0;
this.visibleVal = true;
this.mouseoverVal = function(){};
this.mouseoutVal = function(){};
this.mouseWithin = false
};
b.Layer.prototype = {
bind: function(d){
this.parent = d;
this.primer = d.primer;
this.context = this.primer.context;
this.element = this.primer.element;
for (var c in this.children) this.children[c].bind(this)
},
getX: function() {
return this.xVal
},
setX: function(d) {
this.xVal = d;
this.primer && this.primer.draw()
},
getY: function() {
return this.yVal
},
setY: function(d) {
this.yVal = d;
this.primer && this.primer.draw()
},
getGlobalX: function() {
return this.getX() + this.parent.getGlobalX()
},
getGlobalY: function() {
return this.getY() + this.parent.getGlobalY()
},
getVisible: function() {
return this.visibleVal
},
setVisible: function(d) {
this.visibleVal = d;
this.primer && this.primer.draw()
},
addChild: function(d) {
d.bind(this);
this.children.push(d);
this.primer && this.primer.draw()
},
removeChild: function(d) {
for (var c=[],e=0;e<this.children.length;e++) {
var f = this.children[e];
f != d && c.push(f)
}
this.children = c
},
mouseover: function(d) {
this.mouseoverVal = d
},
mouseout: function(d) {
this.mouseoutVal = d
},
setFillStyle: function(d) {
this.calls.push(["fillStyle",d])
},
setStrokeStyle: function(d) {
this.calls.push(["strokeStyle",d])
},
setLineWidth: function(d) {
this.calls.push(["lineWidth",d])
},
beginPath: function() {
this.calls.push(["beginPath"])
},
moveTo: function(d,c) {
this.calls.push(["moveTo",d,c])
},
lineTo: function(d,c){
this.calls.push(["lineTo",d,c])
},
quadraticCurveTo: function(d,c,e,f) {
this.calls.push(["quadraticCurveTo",d,c,e,f])
},
arc: function(d,c,e,f,g,h) {
this.calls.push(["arc",d,c,e,f,g,h])
},
fill: function() {
this.calls.push(["fill"])
},
stroke: function() {
this.calls.push(["stroke"])
},
fillRect: function(d,c,e,f) {
this.calls.push(["fillRect",d,c,e,f])
},
fillText:function(d,c,e,f,g) {
this.calls.push(["fillText",d,c,e,f,g])
},
setTextAlign: function(d){
this.calls.push(["textAlign",d])
},
setFont: function(d) {
this.calls.push(["font",d])
},
rect: function(d,c,e,f) {
this.beginPath();
this.moveTo(d,c);
this.lineTo(d+e,c);
this.lineTo(d+e,c+f);
this.lineTo(d,c+f);
this.lineTo(d,c)
},
roundedRect: function(d,c,e,f,g) {
this.beginPath();
this.moveTo(d,c+g);
this.lineTo(d,c+f-g);
this.quadraticCurveTo(d,c+f,d+g,c+f);
this.lineTo(d+e-g,c+f);
this.quadraticCurveTo(d+e,c+f,d+e,c+f-g);
this.lineTo(d+e,c+g);
this.quadraticCurveTo(d+e,c,d+e-g,c);
this.lineTo(d+g,c);
this.quadraticCurveTo(d,c,d,c+g)
},
fillRoundedRect: function(d,c,e,f,g) {
this.roundedRect(d,c,e,f,g);
this.fill()
},
draw: function() {
if (this.getVisible()) {
this.context.save();
this.context.translate(this.getX(),this.getY());
for (var d in this.calls) {
var c = this.calls[d];
switch (c[0]) {
case "strokeStyle":
this.context.strokeStyle = c[1];
break;
case "lineWidth":
this.context.lineWidth = c[1];
break;
case "fillStyle":
this.context.fillStyle = c[1];
break;
case "fillRect":
this.context.fillRect(c[1],c[2],c[3],c[4]);
break;
case "beginPath":
this.context.beginPath();
break;
case "moveTo":
this.context.moveTo(c[1],c[2]);
break;
case "lineTo":
this.context.lineTo(c[1],c[2]);
break;
case "quadraticCurveTo":
this.context.quadraticCurveTo(c[1],c[2],c[3],c[4]);
break;
case "arc":
this.context.arc(c[1],c[2],c[3],c[4],c[5],c[6]);
break;
case "fill":
this.context.fill();
break;
case "stroke":
this.context.stroke();
break;
case "fillText":
this.extFillText(c[1],c[2],c[3],c[4],c[5]);
break;
case "textAlign":
this.context.ext.textAlign=c[1];
case "font":
this.context.ext.font=c[1]
}
}
for (d=0;d<this.children.length;d++) this.children[d].draw();
this.context.restore()
}
},
extFillText: function(d,c,e,f,g) {
var h = "";
h += "left: " + (this.getGlobalX() + c) + "px;";
h += "top: " + (this.getGlobalY() + e) + "px;";
h += "width: " + f + "px;";
h += "text-align: " + this.context.ext.textAlign + ";";
h += "color: " + this.context.fillStyle + ";";
h += "font: " + this.context.ext.font + ";";
this.element.append('<p class="primer_text ' + g + '" style="' + h + '">' + d + "</p>")
},
ghost: function(d) {
if (this.getVisible()) {
this.context.save();
this.context.translate(this.getX(),this.getY());
for (var c in this.calls) {
var e = this.calls[c];
switch (e[0]) {
case "fillRect":
this.ghostFillRect(d,e[1],e[2],e[3],e[4]);
break;
case "beginPath":
this.context.beginPath();
break;
case "moveTo":
this.context.moveTo(e[1],e[2]);
break;
case "lineTo":
this.context.lineTo(e[1],e[2]);
break;
case "quadraticCurveTo":
this.context.quadraticCurveTo(e[1],e[2],e[3],e[4]);
break;
case "arc":
this.context.arc(e[1],e[2],e[3],e[4],e[5],e[6]);
break;
case "fill":
this.ghostFill(d);
break
}
}
if (!jQuery.browser.safari) {
d.localX -= this.getX();
d.localY -= this.getY()
}
for (c in this.children) this.children[c].ghost(d);
if (!jQuery.browser.safari) {
d.localX += this.getX();
d.localY += this.getY()
}
this.context.restore()
}
},
ghostDetect: function(d) {
if (jQuery.browser.safari) {
testX = d.localX;
testY = d.localY
}
else {
testX = d.localX - this.getX();
testY = d.localY - this.getY()
}
if (this.context.isPointInPath(testX,testY)) {
this.mouseWithin || this.primer.actions.push([this.mouseoverVal,d]);
this.mouseWithin = true
}
else {
this.mouseWithin && this.primer.actions.push([this.mouseoutVal,d]);
this.mouseWithin = false
}
},
ghostFillRect: function(d,c,e,f,g) {
this.context.beginPath();
this.context.moveTo(c,e);
this.context.lineTo(c+f,e);
this.context.lineTo(c+f,e+g);
this.context.lineTo(c,e+g);
this.context.lineTo(c,e);
this.ghostDetect(d)
},
ghostFill: function(d) {
this.ghostDetect(d)
}
};
return b
}
var Primer = definePrimer(window.jQuery);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment