Skip to content

Embed URL

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
EDGESExplorer
/*
Copyright 2011 Martin Hawksey
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/* =============================================================================== **
Globals
** =============================================================================== */
var w,h,force,nodes,links,svg,d
var w = $(window).width(),
h = $(window).height();
var nodes = [];
var links = [];
var data = [];
var linkDistance = 100;
var degreeMax = 0;
/* =============================================================================== **
jQuery UI
** =============================================================================== */
/**
*
* credits for this plugin go to brandonaaron.net
*
* unfortunately his site is down
*
* @param {Object} up
* @param {Object} down
* @param {Object} preventDefault
*/
jQuery.fn.extend({
mousewheel: function(up, down, preventDefault) {
return this.hover(
function() {
jQuery.event.mousewheel.giveFocus(this, up, down, preventDefault);
},
function() {
jQuery.event.mousewheel.removeFocus(this);
}
);
},
mousewheeldown: function(fn, preventDefault) {
return this.mousewheel(function(){}, fn, preventDefault);
},
mousewheelup: function(fn, preventDefault) {
return this.mousewheel(fn, function(){}, preventDefault);
},
unmousewheel: function() {
return this.each(function() {
jQuery(this).unmouseover().unmouseout();
jQuery.event.mousewheel.removeFocus(this);
});
},
unmousewheeldown: jQuery.fn.unmousewheel,
unmousewheelup: jQuery.fn.unmousewheel
});
jQuery.event.mousewheel = {
giveFocus: function(el, up, down, preventDefault) {
if (el._handleMousewheel) jQuery(el).unmousewheel();
if (preventDefault == window.undefined && down && down.constructor != Function) {
preventDefault = down;
down = null;
}
el._handleMousewheel = function(event) {
if (!event) event = window.event;
if (preventDefault)
if (event.preventDefault) event.preventDefault();
else event.returnValue = false;
var delta = 0;
if (event.wheelDelta) {
delta = event.wheelDelta/120;
if (window.opera) delta = -delta;
} else if (event.detail) {
delta = -event.detail/3;
}
if (up && (delta > 0 || !down))
up.apply(el, [event, delta]);
else if (down && delta < 0)
down.apply(el, [event, delta]);
};
if (window.addEventListener)
window.addEventListener('DOMMouseScroll', el._handleMousewheel, false);
window.onmousewheel = document.onmousewheel = el._handleMousewheel;
},
removeFocus: function(el) {
if (!el._handleMousewheel) return;
if (window.removeEventListener)
window.removeEventListener('DOMMouseScroll', el._handleMousewheel, false);
window.onmousewheel = document.onmousewheel = null;
el._handleMousewheel = null;
}
};
$(document).ready(function() {
$(document).mousemove(function(e){
$('#popup').css('left', e.pageX+10);
$('#popup').css('top', e.pageY-30);
//$('#popup').css('padding', '5px');
});
$(window).resize(function() {
resize();
});
//allow pressing "enter"
$('#search').keypress(function(e) {
if(e.which == 13) {
getSpreadsheetData();
}
});
$("body").mousewheel(function(i,intDelta){
if (intDelta > 0 ) gravityUp();
if (intDelta < 0 ) gravityDown();
});
var gq = '';
var key = $.getUrlVar('key');
var sheet = $.getUrlVar('sheet');
var gqc = $.getUrlVar('gqc');
var gqw = $.getUrlVar('gqw');
var tq = $.getUrlVar('tq');
if(typeof key !== 'undefined' && typeof sheet !== 'undefined') {
$("#topForm").hide();
$('#loading').show('fast');
$('#tweetButton').show();
var url = 'https://spreadsheets.google.com/tq?key='+key+'&sheet='+sheet+'&pub=1';
if(typeof gqc !== 'undefined') {
var gq='select%20'+gqc;
if (gqw!='') gq+='%20where%20'+gqw;
url +='&tq='+gq;
} else if (typeof tq !== 'undefined') {
url += '&tq='+tq;
}
var query = new google.visualization.Query(url);
$("#permlink").attr('href', 'http://hawksey.info/edgesexplorer/?key='+key+'&sheet='+sheet+gq);
query.send(handleSelectResponse);
}
});
$(function() {
$("#help").dialog({modal:true, height:600, width: 750, autoOpen:false, title: "Help"});
if (ie < 9) $("#IEWarning").dialog({modal:true, height:300, width: 400, autoOpen:true, title: "Browser Compatibility"});
});
$.extend({
getUrlVars: function(){
var vars = [], hash;
var hashes = window.location.href.slice(window.location.href.indexOf('?') + 1).split('&');
for(var i = 0; i < hashes.length; i++)
{
hash = hashes[i].split('=');
vars.push(hash[0]);
vars[hash[0]] = hash[1];
}
return vars;
},
getUrlVar: function(name){
return $.getUrlVars()[name];
}
});
function getQueryVars(url){
var vars = [], hash;
var hashes = url.slice(url.indexOf('?') + 1).split('&');
for(var i = 0; i < hashes.length; i++)
{
hash = hashes[i].split('=');
vars.push(hash[0]);
vars[hash[0]] = hash[1];
}
return vars;
}
//http://james.padolsey.com/javascript/detect-ie-in-js-using-conditional-comments/
var ie = (function(){
var undef,
v = 3,
div = document.createElement('div'),
all = div.getElementsByTagName('i');
while (
div.innerHTML = '<!--[if gt IE ' + (++v) + ']><i></i><![endif]-->',
all[0]
);
return v > 4 ? v : undef;
}());
// http://stackoverflow.com/questions/901115/get-query-string-values-in-javascript/901144#901144
function getParameterByName(name,url)
{
name = name.replace(/[\[]/, "\\\[").replace(/[\]]/, "\\\]");
var regexS = "[\\?&]" + name + "=([^&#]*)";
var regex = new RegExp(regexS);
var results = regex.exec(url);
if(results == null)
return "";
else
return decodeURIComponent(results[1].replace(/\+/g, " "));
}
/* =============================================================================== **
Google Spreadsheet Interaction
** =============================================================================== */
// function to get sheet id
function preview() {
$('#sheetSelect').hide();
$('#loader').show();
if ($('#gsKey').val()!='') key=$('#gsKey').val();
if (/key=([^&#]*)/.test(key)) key=getParameterByName('key',key);
var url='https://spreadsheets.google.com/feeds/worksheets/'+key+'/public/basic?alt=json';
$.getJSON(url,function(json){
var vizUrl=document.getElementById('gsSheet');
var optionSelected = 0;
for (var u in json['feed']['entry']) {
var sheetName = json['feed']['entry'][u]['title']['$t'];
var sheetQueryString = getQueryVars(json['feed']['entry'][u]['link'][2]['href']);
var sheetID = sheetQueryString['sheet'];
if (sheetName == "Archive")
optionSelected = u;
vizUrl.options[u]=new Option(sheetName,sheetID);
}
vizUrl.options[optionSelected].selected = true;
$('#loader').hide();
$('#sheetSelect').show();
});
}
function getSpreadsheetData(){
if ($('#gsKey').val()!='') key=$('#gsKey').val();
if (/key=([^&#]*)/.test(key)) key=getParameterByName('key',key);
if ($('#gsSheet').val()!='') sheet=$('#gsSheet').val();
if ($('#gqc').val()!='') gqc=$('#gqc').val();
var url = 'http://hawksey.info/edgesexplorer/?key='+key+'&sheet='+sheet+'&gqc='+gqc+'&gqw=';
window.location = url;
}
function handleSelectResponse(response) {
if (response.isError()) {
alert('Error in query: ' + response.getMessage() + ' ' + response.getDetailedMessage());
return;
}
data = response.getDataTable();
getLiveData(data);
$('#loader2').hide();
$('#nav').show(500);
}
/* =============================================================================== **
Get data and make nodes and edges
** =============================================================================== */
function getLiveData(data)
{
var nodeList = [];
for (i=0; i<data.getNumberOfRows(); i++){
frm_u = data.getValue(i,0);
to_u = data.getValue(i,1);
var type = "solid";
if (data.getNumberOfColumns() == 3) type = data.getValue(i,2);
links.push({source: {id: frm_u}, target: {id: to_u}, type: type});
nodeList[frm_u] = 1;
nodeList[to_u] = 1;
}
for (i in nodeList){
nodes.push({id: i,
outdegree: 0,
indegree: 0,
degree: 0 });
}
$.each(links,function(l,aLink){
$.each(nodes,function(l,val2){
if (aLink.source.id == val2.id || aLink.target.id == val2.id){
nodes[l].degree = nodes[l].degree +1;
if (nodes[l].degree > degreeMax) degreeMax = nodes[l].degree+1;
if (aLink.source.id == val2.id){
nodes[l].indegree = nodes[l].indegree +1;
}
if (aLink.target.id == val2.id){
nodes[l].outdegree = nodes[l].outdegree +1;
}
}
});
aLink.source = findNodePos(aLink.source.id,nodes);
aLink.target = findNodePos(aLink.target.id,nodes);
});
$('#nodeCount').html(nodes.length);
$('#linkCount').html(links.length);
restart();
$('#loading').hide('fast');
}
function findNodePos(element,nodesSet)
{
var foundin = 0;
$.each(nodesSet,function(i,val){
if (val.id == element)
{
foundin = i;
}
});
return foundin;
}
/* =============================================================================== **
Restart
** =============================================================================== */
function restart() {
force = d3.layout.force()
.size([w, h])
.nodes(d3.values(nodes))
.links(links)
.linkDistance(linkDistance)
.charge(-300)
.gravity(0.1)
.on("tick", function () {
path.attr("d", function(d) {
var dx = d.target.x - d.source.x,
dy = d.target.y - d.source.y,
dr = Math.sqrt(dx * dx + dy * dy);
return "M" + d.source.x + "," + d.source.y + "A" + dr + "," + dr + " 0 0,1 " + d.target.x + "," + d.target.y;
});
circle.attr("transform", function(d) {
return "translate(" + d.x + "," + d.y + ")";
});
text.attr("transform", function(d) {
return "translate(" + d.x + "," + d.y + ")";
});
})
.start();
svg = d3.select("body").append("svg:svg")
.attr("width", w)
.attr("height", h);
// Per-type markers, as they don't inherit styles.
svg.append("svg:defs").selectAll("marker")
.data(["solid","dashed","dashedblue"])
.enter().append("svg:marker")
.attr("id", String)
.attr("viewBox", "0 -5 10 10")
.attr("refX", 15)
.attr("refY", -1.5)
.attr("markerWidth", 10)
.attr("markerHeight", 10)
.attr("orient", "auto")
.append("svg:path")
.attr("d", "M0,-5L10,0L0,5");
var path = svg.append("svg:g").selectAll("path")
.data(force.links())
.enter().append("svg:path")
.attr("class", function(d) { return "link " + d.type; })
.attr("marker-end", function(d) { return "url(#" + d.type + ")"; });
var circle = svg.append("svg:g").selectAll("circle")
.data(force.nodes())
.enter().append("svg:circle")
.attr("r", 6)
.on("mouseover", function(d) {showThumb(d.name,d)})
//getLiveData(d.name);
.on("mouseout", function() {
$('#popup').hide();
$('#popup').html('');
})
.call(force.drag);
var text = svg.append("svg:g").selectAll("g")
.data(force.nodes())
.enter().append("svg:g");
// A copy of the text with a thick white stroke for legibility.
text.append("svg:text")
.attr("x", 8)
.attr("y", ".31em")
.attr("class", "shadow")
.attr("style", function(d) {
var size = parseInt(30*d.degree/degreeMax)+8;
return "font-size:"+size+"px" })
.text(function(d) { return d.id; });
text.append("svg:text")
.attr("x", 8)
.attr("y", ".31em")
.attr("style", function(d) {
var size = parseInt(30*d.degree/degreeMax)+8;
return "font-size:"+size+"px" })
.text(function(d) { return d.id; });
}
/* =============================================================================== **
Display stuff
** =============================================================================== */
function showThumb(index,d)
{
var box = '<table cellpadding="2" width="100%"><tr><td align="center"><span class="connections">'+d.degree+'</span><br><span class="fieldname">degree</span></td>';
box += '<td align="center"><span class="connections">'+d.indegree+'</span><br><span class="fieldname">in-degree</span></td>'
box += '<td align="center"><span class="connections">'+d.outdegree+'</span><br><span class="fieldname">out-degree</span></td></tr></table>';
box += '<table cellpadding="2"><tr><td align="right"><span class="fieldname">name </span></td><td><span class="screenname">'+d.id+'</span></td></tr>';
box += '</table>';
$('#popup').fadeIn();
$('#popup').html('<div class="popup">'+box+'</div>');
}
function showNodeDist()
{
$('#tagpanel').hide();
$('#tagpanel').fadeIn('slow');
doTopNodes();
resize();
}
function doTopNodes(){
// Create and populate the data table.
var topNode = new google.visualization.DataTable();
topNode.addColumn('string', 'ID');
topNode.addColumn('number', 'Degree');
topNode.addRows(nodes.length);
for (var j = 0; j < nodes.length; ++j) {
topNode.setValue(j, 0, nodes[j].id);
topNode.setValue(j, 1, nodes[j].degree);
}
topNode.sort([{column: 1, desc: true}]);
$('#ui-dialog-title-tagpanel').text('Top Nodes');
drawTop(topNode,'Top Nodes');
}
function drawTop(aTable,atitle) {
$("#visualization").css("height",h-170);
// Create and draw the visualization.
new google.visualization.BarChart(document.getElementById('visualization')).
draw(aTable,
{ width:350,
fontSize: 10,
hAxis: { textStyle: {color: '#222', fontName: 'Verdana', fontSize: 8}},
height:nodes.length*10,
chartArea: {left:80,top:20,width:"100%",height:"100%"},
colors: ['#069'],
legend: 'none'}
);
}
/* =============================================================================== **
Redraw
** =============================================================================== */
function resize()
{
var h = $(window).height();
var w = $(window).width();
//side panel
h = h - 100;
$('#tagpanel').height(h);
}
/* =============================================================================== **
Controls
** =============================================================================== */
function gravityUp()
{
var value = force.gravity()+0.01;
linkDistance = linkDistance-5;
if(value > 1) value = 1;
force.gravity(value);
if (linkDistance >40) force.linkDistance(linkDistance);
force.start();
}
function gravityDown()
{
var value = force.gravity()-0.01;
linkDistance = linkDistance+5;
if(value < 0) value = 0;
force.linkDistance(linkDistance);
force.gravity(value);
force.start();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.