--- /dev/null
+// tipsy, facebook style tooltips for jquery
+// version 1.0.0a
+// (c) 2008-2010 jason frame [jason@onehackoranother.com]
+// releated under the MIT license
+
+(function($) {
+
+ function fixTitle($ele) {
+ if ($ele.attr('title') || typeof($ele.attr('original-title')) != 'string') {
+ $ele.attr('original-title', $ele.attr('title') || '').removeAttr('title');
+ }
+ }
+
+ function Tipsy(element, options) {
+ this.$element = $(element);
+ this.options = options;
+ this.enabled = true;
+ fixTitle(this.$element);
+ }
+
+ Tipsy.prototype = {
+ show: function() {
+ var title = this.getTitle();
+ if (title && this.enabled) {
+ var $tip = this.tip();
+
+ $tip.find('.tipsy-inner')[this.options.html ? 'html' : 'text'](title);
+ $tip[0].className = 'tipsy'; // reset classname in case of dynamic gravity
+ $tip.remove().css({top: 0, left: 0, visibility: 'hidden', display: 'block'}).appendTo(document.body);
+
+ var pos = $.extend({}, this.$element.offset(), {
+ width: this.$element[0].offsetWidth,
+ height: this.$element[0].offsetHeight
+ });
+
+ var actualWidth = $tip[0].offsetWidth, actualHeight = $tip[0].offsetHeight;
+ var gravity = (typeof this.options.gravity == 'function')
+ ? this.options.gravity.call(this.$element[0])
+ : this.options.gravity;
+
+ var tp;
+ switch (gravity.charAt(0)) {
+ case 'n':
+ tp = {top: pos.top + pos.height + this.options.offset, left: pos.left + pos.width / 2 - actualWidth / 2};
+ break;
+ case 's':
+ tp = {top: pos.top - actualHeight - this.options.offset, left: pos.left + pos.width / 2 - actualWidth / 2};
+ break;
+ case 'e':
+ tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth - this.options.offset};
+ break;
+ case 'w':
+ tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width + this.options.offset};
+ break;
+ }
+
+ if (gravity.length == 2) {
+ if (gravity.charAt(1) == 'w') {
+ tp.left = pos.left + pos.width / 2 - 15;
+ } else {
+ tp.left = pos.left + pos.width / 2 - actualWidth + 15;
+ }
+ }
+
+ $tip.css(tp).addClass('tipsy-' + gravity);
+
+ if (this.options.fade) {
+ $tip.stop().css({opacity: 0, display: 'block', visibility: 'visible'}).animate({opacity: this.options.opacity});
+ } else {
+ $tip.css({visibility: 'visible', opacity: this.options.opacity});
+ }
+ }
+ },
+
+ hide: function() {
+ if (this.options.fade) {
+ this.tip().stop().fadeOut(function() { $(this).remove(); });
+ } else {
+ this.tip().remove();
+ }
+ },
+
+ getTitle: function() {
+ var title, $e = this.$element, o = this.options;
+ fixTitle($e);
+ var title, o = this.options;
+ if (typeof o.title == 'string') {
+ title = $e.attr(o.title == 'title' ? 'original-title' : o.title);
+ } else if (typeof o.title == 'function') {
+ title = o.title.call($e[0]);
+ }
+ title = ('' + title).replace(/(^\s*|\s*$)/, "");
+ return title || o.fallback;
+ },
+
+ tip: function() {
+ if (!this.$tip) {
+ this.$tip = $('<div class="tipsy"></div>').html('<div class="tipsy-arrow"></div><div class="tipsy-inner"/></div>');
+ }
+ return this.$tip;
+ },
+
+ validate: function() {
+ if (!this.$element[0].parentNode) {
+ this.hide();
+ this.$element = null;
+ this.options = null;
+ }
+ },
+
+ enable: function() { this.enabled = true; },
+ disable: function() { this.enabled = false; },
+ toggleEnabled: function() { this.enabled = !this.enabled; }
+ };
+
+ $.fn.tipsy = function(options) {
+
+ if (options === true) {
+ return this.data('tipsy');
+ } else if (typeof options == 'string') {
+ return this.data('tipsy')[options]();
+ }
+
+ options = $.extend({}, $.fn.tipsy.defaults, options);
+
+ function get(ele) {
+ var tipsy = $.data(ele, 'tipsy');
+ if (!tipsy) {
+ tipsy = new Tipsy(ele, $.fn.tipsy.elementOptions(ele, options));
+ $.data(ele, 'tipsy', tipsy);
+ }
+ return tipsy;
+ }
+
+ function enter() {
+ var tipsy = get(this);
+ tipsy.hoverState = 'in';
+ if (options.delayIn == 0) {
+ tipsy.show();
+ } else {
+ setTimeout(function() { if (tipsy.hoverState == 'in') tipsy.show(); }, options.delayIn);
+ }
+ };
+
+ function leave() {
+ var tipsy = get(this);
+ tipsy.hoverState = 'out';
+ if (options.delayOut == 0) {
+ tipsy.hide();
+ } else {
+ setTimeout(function() { if (tipsy.hoverState == 'out') tipsy.hide(); }, options.delayOut);
+ }
+ };
+
+ if (!options.live) this.each(function() { get(this); });
+
+ if (options.trigger != 'manual') {
+ var binder = options.live ? 'live' : 'bind',
+ eventIn = options.trigger == 'hover' ? 'mouseenter' : 'focus',
+ eventOut = options.trigger == 'hover' ? 'mouseleave' : 'blur';
+ this[binder](eventIn, enter)[binder](eventOut, leave);
+ }
+
+ return this;
+
+ };
+
+ $.fn.tipsy.defaults = {
+ delayIn: 0,
+ delayOut: 0,
+ fade: false,
+ fallback: '',
+ gravity: 'n',
+ html: false,
+ live: false,
+ offset: 0,
+ opacity: 0.8,
+ title: 'title',
+ trigger: 'hover'
+ };
+
+ // Overwrite this method to provide options on a per-element basis.
+ // For example, you could store the gravity in a 'tipsy-gravity' attribute:
+ // return $.extend({}, options, {gravity: $(ele).attr('tipsy-gravity') || 'n' });
+ // (remember - do not modify 'options' in place!)
+ $.fn.tipsy.elementOptions = function(ele, options) {
+ return $.metadata ? $.extend({}, options, $(ele).metadata()) : options;
+ };
+
+ $.fn.tipsy.autoNS = function() {
+ return $(this).offset().top > ($(document).scrollTop() + $(window).height() / 2) ? 's' : 'n';
+ };
+
+ $.fn.tipsy.autoWE = function() {
+ return $(this).offset().left > ($(document).scrollLeft() + $(window).width() / 2) ? 'e' : 'w';
+ };
+
+})(jQuery);
\ No newline at end of file
--- /dev/null
+/**
+ * MyPlugin: MadDash
+ * Version: 0.1
+ * Description: Template for writing new plugins and illustrating the different
+ * possibilities of the plugin API.
+ * This file is part of the Manifold project
+ * Requires: js/plugin.js
+ * URL: http://www.myslice.info
+ * Author: Jordan Augé <jordan.auge@lip6.fr>
+ * Copyright: Copyright 2012-2013 UPMC Sorbonne Universités
+ * License: GPLv3
+ */
+var SVG='http://www.w3.org/2000/svg';
+var instance = this;
+var colorscale = d3.scale.category10().range(["green", "yellow", "red", "orange", "gray"]);
+
+/* XXX */
+/**
+ * Class: MaDDashGrid
+ * Description: Widget that displays grid of checks. Uses
+ * d3 and jQuery to draw the grid.
+ * Parameters:
+ * parentId: id string of the container element
+ * legendId: id string of the legend element
+ */
+
+(function($){
+
+ var MadDash = Plugin.extend({
+
+ /** XXX to check
+ * @brief Plugin constructor
+ * @param options : an associative array of setting values
+ * @param element :
+ * @return : a jQuery collection of objects on which the plugin is
+ * applied, which allows to maintain chainability of calls
+ */
+ init: function(options, element) {
+ // Call the parent constructor, see FAQ when forgotten
+ this._super(options, element);
+
+
+ /* Member variables */
+ //this.canvas = this.id('canvas');
+ this._legend = this.id('legend'); //legendId;
+ this._labels = Array(
+ 'un', 'deux', 'trois', 'quatre'
+ )
+
+ this._cellsize = 13;
+ this._cellpadding = 2;
+ this._text_block_size = 130;
+
+ this._map_elements = {};
+ this._num_elements = 0;
+
+ this._max_width_elements = 50;
+ this._max_height_elements = 30;
+
+ this._buffer_key_list = new Buffer(this._process_key_list, this);
+ this._buffer_records = new Buffer(this._process_records, this);
+
+ /* Pointers */
+ this._canvas = d3.select("#" + options.plugin_uuid + '__canvas')
+ .style("width", this._max_width_elements * (this._cellsize + 2*this._cellpadding) + 110 + this._text_block_size)
+ .style("height", this._max_height_elements * (this._cellsize + 2*this._cellpadding) + 110 + this._text_block_size)
+ this._left_element = null;
+ this._top_element = null;
+ this._row_element = Array();
+ this._grid_element = null;
+
+
+
+ /* Buffered input */
+// this._buffer = Array();
+// this._update_interval = 1000; /* ms to wait, 1000 = 1 second */
+// setInterval(function(){
+// var tmp = buffer; /* Switch the buffer out quickly so we aren't scrambled
+// if you addToBuffer in the middle of this */
+// buffer = Array();
+// $thisdocument.getElementById(htmlId).innerHTML = tmp.join("");
+// //document.getElementById(htmlId).innerHTML = tmp.join("");
+// }, wait);
+//
+//addToBuffer = function(html){
+// buffer.push(html);
+//};
+
+ /* Plugin events */
+
+ /* Setup query and record handlers */
+
+ // Explain this will allow query events to be handled
+ // What happens when we don't define some events ?
+ // Some can be less efficient
+ this.listen_query(options.query_uuid);
+ this.listen_query(options.query_all_uuid, 'all');
+
+ /* GUI setup and event binding */
+ // call function
+ this._display_legends();
+ this._init_top();
+ this._init_left();
+ this._init_grid();
+ //this._test();
+
+ },
+
+ _test: function()
+ {
+ data = {
+ "name":"OWAMP",
+ "statusLabels":[
+ "Loss is 0",null,"Loss is greater than 0","Unable to retrieve data","Check has not yet run"
+ ],
+ "lastUpdateTime":1385376538,
+ "rows":[
+ {"name":"200.128.79.100","uri":"/maddash/grids/OWAMP/200.128.79.100"},
+ {"name":"ata.larc.usp.br","uri":"/maddash/grids/OWAMP/ata.larc.usp.br"},
+ {"name":"mon-lt.fibre.cin.ufpe.br","uri":"/maddash/grids/OWAMP/mon-lt.fibre.cin.ufpe.br"}
+ ],
+ "columnNames":[
+ "200.128.79.100","ata.larc.usp.br","mon-lt.fibre.cin.ufpe.br"
+ ],
+ "checkNames": ["Loss","Loss Reverse"],
+ "grid": [
+ [
+ /* First line */
+ null,
+ [{
+ "message":" No one-way delay data returned for direction where src=200.128.79.100 dst=ata.larc.usp.br",
+ "status":3,
+ "prevCheckTime":1385376238,
+ "uri":"/maddash/grids/OWAMP/200.128.79.100/ata.larc.usp.br/Loss"
+ },{
+ "message":" No one-way delay data returned for direction where src=ata.larc.usp.br dst=200.128.79.100",
+ "status":2,"prevCheckTime":1385376178,
+ "uri":"/maddash/grids/OWAMP/200.128.79.100/ata.larc.usp.br/Loss+Reverse"
+ }],[{
+ "message":" Loss is 100.000% ",
+ "status":2,
+ "prevCheckTime":1385374877,
+ "uri":"/maddash/grids/OWAMP/200.128.79.100/mon-lt.fibre.cin.ufpe.br/Loss"
+ },{
+ "message":" Loss is 100.000% ",
+ "status":2,
+ "prevCheckTime":1385375498,
+ "uri":"/maddash/grids/OWAMP/200.128.79.100/mon-lt.fibre.cin.ufpe.br/Loss+Reverse"
+ }]
+ ],[
+ /* Second line */
+ [{
+ "message":" Unable to contact MA. Please check that the MA is running and the URL is correct.",
+ "status":3,
+ "prevCheckTime":1385376037,
+ "uri":"/maddash/grids/OWAMP/ata.larc.usp.br/200.128.79.100/Loss"
+ }, {
+ "message":" Unable to contact MA. Please check that the MA is running and the URL is correct.",
+ "status":3,
+ "prevCheckTime":1385376117,
+ "uri":"/maddash/grids/OWAMP/ata.larc.usp.br/200.128.79.100/Loss+Reverse"
+ }],
+ null,
+ [{
+ "message":" Unable to contact MA. Please check that the MA is running and the URL is correct.",
+ "status":3,
+ "prevCheckTime":1385376117,
+ "uri":"/maddash/grids/OWAMP/ata.larc.usp.br/mon-lt.fibre.cin.ufpe.br/Loss"
+ }, {
+ "message":" Unable to contact MA. Please check that the MA is running and the URL is correct.",
+ "status":3,
+ "prevCheckTime":1385376017,
+ "uri":"/maddash/grids/OWAMP/ata.larc.usp.br/mon-lt.fibre.cin.ufpe.br/Loss+Reverse"
+ }]
+ ],[
+ /* Third line */
+ [{
+ "message":" Loss is 100.000% ",
+ "status":2,
+ "prevCheckTime":1385376478,
+ "uri":"/maddash/grids/OWAMP/mon-lt.fibre.cin.ufpe.br/200.128.79.100/Loss"
+ },{
+ "message":" Loss is 100.000% ",
+ "status":2,
+ "prevCheckTime":1385375958,
+ "uri":"/maddash/grids/OWAMP/mon-lt.fibre.cin.ufpe.br/200.128.79.100/Loss+Reverse"
+ }], [{
+ "message":" No one-way delay data returned for direction where src=mon-lt.fibre.cin.ufpe.br dst=ata.larc.usp.br",
+ "status":3,
+ "prevCheckTime":1385376538,
+ "uri":"/maddash/grids/OWAMP/mon-lt.fibre.cin.ufpe.br/ata.larc.usp.br/Loss"
+ },{
+ "message":" No one-way delay data returned for direction where src=ata.larc.usp.br dst=mon-lt.fibre.cin.ufpe.br",
+ "status":3,
+ "prevCheckTime":1385376358,
+ "uri":"/maddash/grids/OWAMP/mon-lt.fibre.cin.ufpe.br/ata.larc.usp.br/Loss+Reverse"
+ }],
+ null
+ ]
+ ]
+ }
+ this._render(data);
+ },
+
+ /* ------------------------------------------------------------------ */
+ /* Accessors */
+ /* ------------------------------------------------------------------ */
+
+ setClickHandler: function(f)
+ {
+ this._handleClick = f;
+ },
+
+ setCellSize: function(value)
+ {
+ this._cellSize = value;
+ },
+
+ setCellPadding: function(value)
+ {
+ this._cellPadding = value;
+ },
+
+ setTextBlockSize: function(value)
+ {
+ this._textBlockSize = value;
+ },
+
+
+
+
+ /* PLUGIN EVENTS */
+ // on_show like in querytable
+
+
+ /* GUI EVENTS */
+
+ // a function to bind events here: click change
+ // how to raise manifold events
+
+
+ /* GUI MANIPULATION */
+
+ /* XXX */
+
+
+ /* TEMPLATES */
+
+ // see in the html template
+ // How to load a template, use of mustache
+
+ /* QUERY HANDLERS */
+
+ // How to make sure the plugin is not desynchronized
+ // He should manifest its interest in filters, fields or records
+ // functions triggered only if the proper listen is done
+
+ // no prefix
+
+ on_filter_added: function(filter)
+ {
+
+ },
+
+ // ... be sure to list all events here
+
+ /* RECORD HANDLERS */
+ on_all_new_record: function(record)
+ {
+ var key_value = record['hrn'];
+ if (!(this._map_elements.hasOwnProperty(key_value))) {
+ /* Add the key_value to the buffer to be drawn */
+ this._buffer_key_list.add(key_value);
+ /* Assign coordinates */
+ this._map_elements[key_value] = this._num_elements++;
+ }
+ /* Add the record to the buffer to be drawn */
+ this._buffer_records.add(record);
+ },
+
+ /* INTERNAL FUNCTIONS */
+
+ _render: function(data)
+ {
+ //TODO: Set title
+ //d3.select("#dashboard_name").html(dashboard.name + " Dashboard");
+ // XXX OLD XXX d3.select("#" + this.parent).html("");
+ //this.elmt().html('')
+
+ this.display_component(data);
+ },
+
+ _init_left: function()
+ {
+ var self = this;
+ this._left_element = this._canvas.append("div")
+ .attr("class", "gleft")
+ .style("overflow-y", "scroll")
+ .style("height", "400px")
+ .append("svg:svg")
+ .attr("width", self._text_block_size)
+ .attr("height", self._max_height_elements * (self._cellsize + 2*self._cellpadding) + 1000)
+
+ },
+
+ _process_left: function(key_list)
+ {
+ var self = this;
+
+ this._left_element = this._left_element
+ .selectAll(".rname")
+ .data(key_list)
+ .enter()
+ .append("g")
+ .attr("class", function(d,i){return "grow" + i})
+ .attr("transform", function(d,i){return "translate(0,"+(i*(self._cellsize+2*self._cellpadding))+")"})
+
+ this._left_element.append("svg:rect")
+ .attr("class", function(d,i){return "grow" + i})
+ .attr("x",0).attr("y",0)
+ .attr("width",this._text_block_size).attr("height",(this._cellsize+2*this._cellpadding))
+
+ this._left_element.append("svg:text")
+ .attr("class", "gtext")
+ .attr("transform", "translate("+ (this._text_block_size-5) +",0)")
+ .text(function(d,i){return d}) //strdata.rows[i].name})
+ .attr("text-anchor", "end")
+ .attr("dy", "1.1em")
+
+ // XXX Let's generate fake records to create all rows
+ var records = Array();
+ for(var i = 0; i < key_list.length; i++) {
+ for(var j = 0; j < key_list.length; j++) {
+ records.push({
+ 'source': key_list[i],
+ 'destination': key_list[j],
+ 'value': Math.floor(Math.random()*4) /* 0 1 2 3 */
+ });
+ }
+ }
+
+ // Create the rows
+ this._row_element = this._grid_element.selectAll(".grow")
+ .data(key_list)
+ .enter()
+ .append("div")
+ .attr("class", function(d,i){return "grow grow" + i})
+ .style("width", "100%")
+ .style("z-index", 1000)
+ // jordan
+ .style('position', 'absolute')
+/*
+ var cells = this._row_element.selectAll('.gcell')
+ .data(records) //function(d,r){ return d.map(function(d,i){ return {celldata:d, row:r}}) }, function(d) { return d['source'] + '--' + d['destination']; })
+ .enter()
+ .append("div")
+ .attr("class", "gcell")
+ .style("height", self._cellsize +"px")
+ .style("width", self._cellsize +"px")
+ .style("margin", (self._cellpadding) +"px")
+
+ .on("mouseover", function(d,i){
+ selected_row = d.row; // We could find the row from the _map_elements
+ selected_col = i;
+ if(d.celldata){
+ d3.select(this).style("margin", (self._cellpadding-1) +"px");
+ d3.select(this).classed("shadow", true);
+ }
+ this._canvas.selectAll(".gcol"+ i).classed("gactive", true);
+ this._canvas.selectAll(".grow"+ d.row).classed("gactive", true);
+ })
+ .on("mouseout", function(d,i){
+ // d3.select(this).classed("shadow", false);
+ // d3.select(this).style("background-color", color.brighter());
+ d3.select(this).style("margin", (self._cellpadding) +"px");
+ d3.select(this).classed("shadow", false);
+ this._canvas.selectAll(".gcol"+ i).classed("gactive", false);
+ this._canvas.selectAll(".grow"+ d.row).classed("gactive", false);
+ })
+*/
+ },
+
+ _init_top: function()
+ {
+ var self = this;
+ this._top_element = this._canvas.append("div")
+ .attr("class", "gtop")
+ .style("margin-left", self._text_block_size + "px")
+ .style("float", "left")
+ .style("overflow-x", "scroll")
+ .style("width", "960px")
+ .append("svg:svg")
+ .attr("height", self._text_block_size)
+ .attr("width", self._max_width_elements * (self._cellsize + 2*self._cellpadding) + 90 + 1000)
+
+ },
+
+
+ _process_top: function(key_list)
+ {
+ var self = this;
+
+ this._top_element = this._top_element
+ .selectAll(".rname")
+ .data(key_list)
+ .enter()
+ .append("g")
+ .attr("class", function(d,i){return "gcol" + i})
+ .attr("transform", function(d,i){ return "translate("+(i*(self._cellsize+2*self._cellpadding))+",0)"})
+
+ this._top_element.append("svg:rect")
+ .attr("class", function(d,i){return "gcol" + i})
+ .attr("x",0).attr("y",0)
+ .attr("transform", "rotate(45,0,"+ self._text_block_size +") translate (-0.5,3)")
+ .attr("height",self._text_block_size).attr("width",(self._cellsize+self._cellpadding))
+ //.attr("transform", "rotate(35,"+ (this._cellsize+this._cellpadding)/2 + "," + this._text_block_size/2 + ")")
+
+
+ this._top_element.append("svg:text")
+ .attr("class", "gtext")
+ .attr("text-anchor", "start")
+ .attr("dy", "1.5em")
+ .attr("dx", "1em")
+ .attr("transform", "rotate(-45,0,"+ self._text_block_size +") translate(0,"+ (self._text_block_size-5) + ")")
+ .text(function(d,i){return d})
+
+ // Create the columns...
+ var cols = this._grid_element.selectAll(".gcol")
+ .data(key_list)
+ .enter()
+ .append("div")
+ .attr("class", function(d,i){return "gcol gcol" + i})
+ .style("width", (self._cellsize+2*self._cellpadding) + "px")
+ .style("height", "100%")
+ .style("left", function(d,i){return (i*(self._cellsize+2*self._cellpadding)) + "px"})
+ },
+
+ _process_key_list: function()
+ {
+ console.log("process key list");
+ var key_list = this._buffer_key_list.get();
+ this._process_top(key_list);
+ this._process_left(key_list);
+ console.log("process key list done");
+ },
+
+ _display_legends: function()
+ {
+ // Color scale = the number of different statuses
+ colorscale.domain(d3.range(0, this._labels.length));
+
+ // Labels
+ var legendsdata = this._labels
+ .map(function(d,i){ return {label:d, color:colorscale(i)} })
+ //.filter(function(d,i){return d.label === null ? false : true})
+
+ // Clear and redraw legend
+ d3.select("#"+this._legend).html("")
+
+ var legends = d3.select("#"+this._legend)
+ .selectAll(".legend")
+ .data(legendsdata)
+ .enter()
+ .append("div").attr("class", "legend");
+ legends.append("div")
+ .attr("class", "lsymbol")
+ .style("background", function(d,i){return d.color})
+ .style("display", function(d,i){return d.label === null ? "none" : "block"})
+ legends.append("div")
+ .attr("class", "ltext")
+ .text(function(d,i){return d.label})
+ .style("display", function(d,i){return d.label === null ? "none" : "block"})
+ },
+
+ _init_grid: function()
+ {
+ this._grid_element = this._canvas
+ .style("width", this._ncols * (this._cellsize + 2*this._cellpadding) + 110 + this._text_block_size)
+ .append("div")
+ .attr("class", "ggrid")
+ // jordan
+ .style('top', '165px')
+ .style('left', '145px')
+ .style('float', 'none')
+ .style('width', '2000px')
+ .style('height', '1000px')
+
+ },
+
+ _process_records: function()
+ {
+ var self = this;
+ var records = this._buffer_records.get();
+ console.log("processing records");
+
+ // XXX Let's generate fake records instead... NxN
+ var _records = Array();
+ for(var i = 0; i < records.length; i++) {
+ for(var j = 0; j < records.length; j++) {
+ if (Math.random() < 0.2) { /* one out of 5 */
+ _records.push({
+ 'source': records[i]['hrn'],
+ 'destination': records[j]['hrn'],
+ 'value': Math.floor(Math.random()*4) /* 0 1 2 3 */
+ })
+ }
+ }
+ }
+
+ //
+
+ // Rows and columns have been created
+
+ var color = "";
+ var selected_row = 0;
+ var selected_col = 0;
+ var cells = this._row_element.selectAll(".gcell")
+ /* Not sure to understand this part of the code */
+ //uses data.grid initially... this is not good anymore
+ .data(_records, function(d) { return d['source'] + '--' + d['destination']; })
+ .style("background", function(d,i){
+ return colorscale(parseInt(d.value));
+ })
+
+ // Associate a tooltip to each cell thanks to tipsy
+ /*
+ this.elmt().find(".gcell").each(function(i,d){
+ var data = d3.select(this).data()[0];
+ if(data.celldata!=null){
+ var html = "<div class='tooltip'><div class='top-tip'>" + (data.celldata[0]? data.celldata[0].message : "") + "</div><div class='bottom-tip'>" + (data.celldata[1]? data.celldata[1].message : "") + "</div></div>";
+ $(this).tipsy({
+ html :true,
+ opacity: 0.9,
+ title : function(){
+ return html
+ }})
+ }
+ })
+ */
+
+ // This seems to create the coloured subcells
+ var temp = cells.selectAll(".gsubcell")
+ .data(function(d,i){return d.celldata===null? [] : d.celldata })
+ .enter()
+ .append("div");
+ temp
+ .style("height", this._cellsize/2 +"px")
+ .style("background", function(d,i){
+ return colorscale(parseInt(d.status));
+ })
+ .on("click", function(d,i){ //CHANGE FROM PORTAL
+ var that = this;
+ if(d!=null && d.uri!=null && self.handleClick != null){
+ self.handleClick(d);
+ }
+ })
+ console.log("processing records done");
+ },
+
+ display_component: function(data)
+ {
+ this._display_grid_container(data);
+ },
+
+ _handleClick: function(d)
+ {
+ var uri = d.uri;
+ $.getJSON(uri, function(data) {
+ var href = data['history'][0].returnParams.graphUrl.replace("https", "http");
+ window.open( href, "Graph", "menubar=0,location=0,height=700,width=700" );
+ })
+
+ }
+
+
+ });
+
+ /* Plugin registration */
+ $.plugin('MadDash', MadDash);
+
+ // TODO Here use cases for instanciating plugins in different ways like in the pastie.
+
+})(jQuery);