Related
I am trying to create a neural net visualization using d3.js in Angular 7. I have successfully created the nodes but the links are not appearing. The code refers to a css class defined in the components css file. What am I doing wrong?
Shown below is the code responsible for link creation:
// draw links
var link:any = svg.selectAll(".link")
.data(links)
.enter().append("line")
.attr("class", "link")
.attr("x1", function(d) { return nodes[d.source].x; })
.attr("y1", function(d) { return nodes[d.source].y; })
.attr("x2", function(d) { return nodes[d.target].x; })
.attr("y2", function(d) { return nodes[d.target].y; })
.style("stroke-width", function(d) {return Math.sqrt(d.value); });
css :
.link {
stroke: #999;
stroke-opacity: .6;
}
shown below is the code of my complete neural.component.ts file (which contains the above typescript code).
import { Component, OnInit,Input } from '#angular/core';
import {select,schemeCategory10,scaleOrdinal} from 'd3';
import { angularMath } from 'angular-ts-math';
declare var $:any;
#Component({
selector: 'app-neuralcanvas',
templateUrl: './neuralcanvas.component.html',
styleUrls: ['./neuralcanvas.component.css']
})
export class NeuralcanvasComponent implements OnInit {
// color = scaleOrdinal().range(schemeCategory10)
inputLayerHeight = 4;
outputLayerHeight=5;
hiddenLayersDepths =[3,4];
hiddenLayersCount =2;
nodeSize = 17;
width :any = 500 ;
height = 400;
constructor() { }
ngOnInit() {
this.draw()
}
draw() {
console.log('in draw')
if (!select("svg")[0]) {
} else {
//clear d3
select('svg').remove();
}
var svg = select("#neuralNet").append("svg")
.attr("width", this.width)
.attr("height", this.height);
var networkGraph : any = this.buildNodeGraph();
//buildNodeGraph();
this.drawGraph(networkGraph, svg);
}
buildNodeGraph() {
var newGraph:any = {
"nodes": []
};
//construct input layer
var newFirstLayer: any = [];
for (var i = 0; i < this.inputLayerHeight; i++) {
var newTempLayer1 :any = {"label": "i"+i, "layer": 1};
newFirstLayer.push(newTempLayer1);
}
//construct hidden layers
var hiddenLayers:any = [];
for (var hiddenLayerLoop = 0; hiddenLayerLoop < this.hiddenLayersCount; hiddenLayerLoop++) {
var newHiddenLayer:any = [];
//for the height of this hidden layer
for (var i = 0; i < this.hiddenLayersDepths[hiddenLayerLoop]; i++) {
var newTempLayer2:any = {"label": "h"+ hiddenLayerLoop + i, "layer": (hiddenLayerLoop+2)};
newHiddenLayer.push(newTempLayer2);
}
hiddenLayers.push(newHiddenLayer);
}
//construct output layer
var newOutputLayer:any = [];
for (var i = 0; i < this.outputLayerHeight; i++) {
var newTempLayer3 = {"label": "o"+i, "layer": this.hiddenLayersCount + 2};
newOutputLayer.push(newTempLayer3);
}
//add to newGraph
var allMiddle:any = newGraph.nodes.concat.apply([], hiddenLayers);
newGraph.nodes = newGraph.nodes.concat(newFirstLayer, allMiddle, newOutputLayer );
return newGraph;
}
drawGraph(networkGraph, svg) {
var color = scaleOrdinal(schemeCategory10);
var graph = networkGraph;
var nodes = graph.nodes;
// get network size
var netsize = {};
nodes.forEach(function (d) {
if(d.layer in netsize) {
netsize[d.layer] += 1;
} else {
netsize[d.layer] = 1;
}
d["lidx"] = netsize[d.layer];
});
// calc distances between nodes
var largestLayerSize = Math.max.apply(
null, Object.keys(netsize).map(function (i) { return netsize[i]; }));
var xdist = this.width / Object.keys(netsize).length,
ydist = (this.height-15) / largestLayerSize;
// create node locations
nodes.map(function(d) {
d["x"] = (d.layer - 0.5) * xdist;
d["y"] = ( ( (d.lidx - 0.5) + ((largestLayerSize - netsize[d.layer]) /2 ) ) * ydist )+10 ;
});
// autogenerate links
var links:any = [];
nodes.map(function(d, i) {
for (var n in nodes) {
if (d.layer + 1 == nodes[n].layer) {
links.push({"source": parseInt(i), "target": parseInt(n), "value": 1}) }
}
}).filter(function(d) { return typeof d !== "undefined"; });
// draw links
var link:any = svg.selectAll(".link")
.data(links)
.enter().append("line")
.attr("class", "link")
.attr("x1", function(d) { return nodes[d.source].x; })
.attr("y1", function(d) { return nodes[d.source].y; })
.attr("x2", function(d) { return nodes[d.target].x; })
.attr("y2", function(d) { return nodes[d.target].y; })
.style("stroke-width", function(d) {return Math.sqrt(d.value); });
// draw nodes
var node = svg.selectAll(".node")
.data(nodes)
.enter().append("g")
.attr("transform", function(d) {
return "translate(" + d.x + "," + d.y + ")"; }
);
var circle = node.append("circle")
.attr("class", "node")
.attr("r", this.nodeSize)
.style("fill", function(d) { return color(d.layer); });
node.append("text")
.attr("dx", "-.35em")
.attr("dy", ".35em")
.attr("font-size", ".6em")
.text(function(d) { return d.label; });
}
}
the code of the neural.component.css:
.link {
stroke: #999;
stroke-opacity: .6;
}
The current output lokks like this:
I want to show the inks as:
As you'll see the generation code is already there I want to know how to refer the class to get the links appearing in Angular 7
Just started learning meteor and d3 / crossfilter charting libraries.
Picked up some example code off the Web, and have it working in my local app.
I do have an empty this.autorun() function in my meteor client code, but have no idea what part of the lengthy d3 initialization and composition routine should be put into autorun, in order for these charts to react to the data changes.
I have tried to just put the Flights.find().fetch() inside the autorun, but in that case, the page never seem to finish loading.
Here is my entire meteor code:
if (Meteor.isClient) {
Template.dashboard.helpers({
});
Template.dashboard.events({
});
Template.dashboard.rendered = function(){
var flights = Flights.find().fetch();
if (!flights.length) return;
var crossData = crossfilter(flights);
// d3.csv(data, function(error, flights) {
// Various formatters.
var formatNumber = d3.format(",d"),
formatChange = d3.format("+,d"),
formatDate = d3.time.format("%B %d, %Y"),
formatTime = d3.time.format("%I:%M %p");
// A nest operator, for grouping the flight list.
var nestByDate = d3.nest()
.key(function(d) { return d3.time.day(d.date); });
// A little coercion, since the CSV is untyped.
flights.forEach(function(d, i) {
d.index = i;
d.date = parseDate(d.date);
d.delay = +d.delay;
d.distance = +d.distance;
});
// Create the crossfilter for the relevant dimensions and groups.
var flight = crossfilter(flights),
all = flight.groupAll(),
date = flight.dimension(function(d) { return d.date; }),
dates = date.group(d3.time.day),
hour = flight.dimension(function(d) { return d.date.getHours() + d.date.getMinutes() / 60; }),
hours = hour.group(Math.floor),
delay = flight.dimension(function(d) { return Math.max(-60, Math.min(149, d.delay)); }),
delays = delay.group(function(d) { return Math.floor(d / 10) * 10; }),
distance = flight.dimension(function(d) { return Math.min(1999, d.distance); }),
distances = distance.group(function(d) { return Math.floor(d / 50) * 50; });
var charts = [
barChart()
.dimension(hour)
.group(hours)
.x(d3.scale.linear()
.domain([0, 24])
.rangeRound([0, 10 * 24])),
barChart()
.dimension(delay)
.group(delays)
.x(d3.scale.linear()
.domain([-60, 150])
.rangeRound([0, 10 * 21])),
barChart()
.dimension(distance)
.group(distances)
.x(d3.scale.linear()
.domain([0, 2000])
.rangeRound([0, 10 * 40])),
barChart()
.dimension(date)
.group(dates)
.round(d3.time.day.round)
.x(d3.time.scale()
.domain([new Date(2001, 0, 1), new Date(2001, 3, 1)])
.rangeRound([0, 10 * 90]))
.filter([new Date(2001, 1, 1), new Date(2001, 2, 1)])
];
// Given our array of charts, which we assume are in the same order as the
// .chart elements in the DOM, bind the charts to the DOM and render them.
// We also listen to the chart's brush events to update the display.
var chart = d3.selectAll(".chart")
.data(charts)
.each(function(chart) { chart.on("brush", renderAll).on("brushend", renderAll); });
// Render the initial lists.
var list = d3.selectAll(".list")
.data([flightList]);
// Render the total.
d3.selectAll("#total")
.text(formatNumber(flight.size()));
renderAll();
// Renders the specified chart or list.
function render(method) {
d3.select(this).call(method);
}
// Whenever the brush moves, re-rendering everything.
function renderAll() {
chart.each(render);
list.each(render);
d3.select("#active").text(formatNumber(all.value()));
}
// Like d3.time.format, but faster.
function parseDate(d) {
return new Date(2001,
d.substring(0, 2) - 1,
d.substring(2, 4),
d.substring(4, 6),
d.substring(6, 8));
}
window.filter = function(filters) {
filters.forEach(function(d, i) { charts[i].filter(d); });
renderAll();
};
window.reset = function(i) {
charts[i].filter(null);
renderAll();
};
function flightList(div) {
var flightsByDate = nestByDate.entries(date.top(40));
div.each(function() {
var date = d3.select(this).selectAll(".date")
.data(flightsByDate, function(d) { return d.key; });
date.enter().append("div")
.attr("class", "date")
.append("div")
.attr("class", "day")
.text(function(d) { return formatDate(d.values[0].date); });
date.exit().remove();
var flight = date.order().selectAll(".flight")
.data(function(d) { return d.values; }, function(d) { return d.index; });
var flightEnter = flight.enter().append("div")
.attr("class", "flight");
flightEnter.append("div")
.attr("class", "time")
.text(function(d) { return formatTime(d.date); });
flightEnter.append("div")
.attr("class", "origin")
.text(function(d) { return d.origin; });
flightEnter.append("div")
.attr("class", "destination")
.text(function(d) { return d.destination; });
flightEnter.append("div")
.attr("class", "distance")
.text(function(d) { return formatNumber(d.distance) + " mi."; });
flightEnter.append("div")
.attr("class", "delay")
.classed("early", function(d) { return d.delay < 0; })
.text(function(d) { return formatChange(d.delay) + " min."; });
flight.exit().remove();
flight.order();
});
}
function barChart() {
if (!barChart.id) barChart.id = 0;
var margin = {top: 10, right: 10, bottom: 20, left: 10},
x,
y = d3.scale.linear().range([100, 0]),
id = barChart.id++,
axis = d3.svg.axis().orient("bottom"),
brush = d3.svg.brush(),
brushDirty,
dimension,
group,
round;
function chart(div) {
var width = x.range()[1],
height = y.range()[0];
y.domain([0, group.top(1)[0].value]);
div.each(function() {
var div = d3.select(this),
g = div.select("g");
// Create the skeletal chart.
if (g.empty()) {
div.select(".title").append("a")
.attr("href", "javascript:reset(" + id + ")")
.attr("class", "reset")
.text("reset")
.style("display", "none");
g = div.append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
g.append("clipPath")
.attr("id", "clip-" + id)
.append("rect")
.attr("width", width)
.attr("height", height);
g.selectAll(".bar")
.data(["background", "foreground"])
.enter().append("path")
.attr("class", function(d) { return d + " bar"; })
.datum(group.all());
g.selectAll(".foreground.bar")
.attr("clip-path", "url(#clip-" + id + ")");
g.append("g")
.attr("class", "axis")
.attr("transform", "translate(0," + height + ")")
.call(axis);
// Initialize the brush component with pretty resize handles.
var gBrush = g.append("g").attr("class", "brush").call(brush);
gBrush.selectAll("rect").attr("height", height);
gBrush.selectAll(".resize").append("path").attr("d", resizePath);
}
// Only redraw the brush if set externally.
if (brushDirty) {
brushDirty = false;
g.selectAll(".brush").call(brush);
div.select(".title a").style("display", brush.empty() ? "none" : null);
if (brush.empty()) {
g.selectAll("#clip-" + id + " rect")
.attr("x", 0)
.attr("width", width);
} else {
var extent = brush.extent();
g.selectAll("#clip-" + id + " rect")
.attr("x", x(extent[0]))
.attr("width", x(extent[1]) - x(extent[0]));
}
}
g.selectAll(".bar").attr("d", barPath);
});
function barPath(groups) {
var path = [],
i = -1,
n = groups.length,
d;
while (++i < n) {
d = groups[i];
path.push("M", x(d.key), ",", height, "V", y(d.value), "h9V", height);
}
return path.join("");
}
function resizePath(d) {
var e = +(d == "e"),
x = e ? 1 : -1,
y = height / 3;
return "M" + (.5 * x) + "," + y
+ "A6,6 0 0 " + e + " " + (6.5 * x) + "," + (y + 6)
+ "V" + (2 * y - 6)
+ "A6,6 0 0 " + e + " " + (.5 * x) + "," + (2 * y)
+ "Z"
+ "M" + (2.5 * x) + "," + (y + 8)
+ "V" + (2 * y - 8)
+ "M" + (4.5 * x) + "," + (y + 8)
+ "V" + (2 * y - 8);
}
}
brush.on("brushstart.chart", function() {
var div = d3.select(this.parentNode.parentNode.parentNode);
div.select(".title a").style("display", null);
});
brush.on("brush.chart", function() {
var g = d3.select(this.parentNode),
extent = brush.extent();
if (round) g.select(".brush")
.call(brush.extent(extent = extent.map(round)))
.selectAll(".resize")
.style("display", null);
g.select("#clip-" + id + " rect")
.attr("x", x(extent[0]))
.attr("width", x(extent[1]) - x(extent[0]));
dimension.filterRange(extent);
});
brush.on("brushend.chart", function() {
if (brush.empty()) {
var div = d3.select(this.parentNode.parentNode.parentNode);
div.select(".title a").style("display", "none");
div.select("#clip-" + id + " rect").attr("x", null).attr("width", "100%");
dimension.filterAll();
}
});
chart.margin = function(_) {
if (!arguments.length) return margin;
margin = _;
return chart;
};
chart.x = function(_) {
if (!arguments.length) return x;
x = _;
axis.scale(x);
brush.x(x);
return chart;
};
chart.y = function(_) {
if (!arguments.length) return y;
y = _;
return chart;
};
chart.dimension = function(_) {
if (!arguments.length) return dimension;
dimension = _;
return chart;
};
chart.filter = function(_) {
if (_) {
brush.extent(_);
dimension.filterRange(_);
} else {
brush.clear();
dimension.filterAll();
}
brushDirty = true;
return chart;
};
chart.group = function(_) {
if (!arguments.length) return group;
group = _;
return chart;
};
chart.round = function(_) {
if (!arguments.length) return round;
round = _;
return chart;
};
return d3.rebind(chart, brush, "on");
}
// });
this.autorun(function(){
})
}
}
if (Meteor.isServer) {
Meteor.startup(function () {
});
}
If this helps, here is my attempt at reproducing one of the d3 force layout examples with collision detection / custom gravity functions https://gist.github.com/gmlnchv/80dd206440cca39800b8. I'm using observe() to react to changes.
I am using Ext5 pie chart.
When I mouse hover the pie chart it is being cut off.
The code for the pie chart is given below.
{
type: 'pie',
field: 'item1',
renderer: function(sprite, config, rendererData, index) {
var record = rendererData.store.getAt(rendererData.series.sprites.indexOf(sprite));
var name = record.get('name');
if(chartObj.baseThemeColors[name]){
var color = chartObj.baseThemeColors[name];
} else {
color = chartObj.getRandomColor();
chartObj.baseThemeColors[name] = color;
}
return Ext.apply(rendererData, {
fill: color
});
return rendererData;
},
subStyle: {
strokeStyle: 'white',
insertPadding: '50',
lineWidth: '0.5'
},
highlight: {
segment: {
margin: 20
}
},
tooltip: {
trackMouse: true,
width: 'auto',
height: 40,
renderer: function(storeItem, item) {
//calculate percentage.
var total = 0;
var idType = storeItem.get('type');
chartStore.each(function(rec) {
total += rec.get('item1');
});
if(storeItem.get('item1') == 0){
this.setTitle('');
}else {
var pct = ((storeItem.get('item1')/total) * 100).toFixed(0);
var tipText = pct + '% (' + storeItem.get('item1') + ' of ' + total + ')<br/>' + storeItem.get('name')
this.setTitle(tipText);
}
}
},
label: {
field: 'name',
display: 'rotate',
font: '14px Arial',
renderer: function(text, sprite, config, rendererData, index){
var item = rendererData.store.getAt(index);
var total = 0,
idType = item.get('type'),
labelText = "";
chartStore.each(function(rec) {
total += rec.get('item1');
});
if(item.get('item1') == 0){
labelText = '';
} else {
var pct = ((item.get('item1') / total) * 100).toFixed(0);
if(pct>1){
labelText = text + ' ' + pct+'%';
} else {
labelText = '';
}
}
return labelText;
}
}
}
Here is the image of the issue.
As you can see top of the 'negative' slice is being cut off when mouse hovering. And I cannot remove that slice moving animation when hovering.
Is there any solution for this?
Thanks in advance.
Try setting
trackMouse: false
Instead of
trackMouse: true
I've installed Nivo Slider using the code from the demo included in the free download.
All of the images I am including in the slider are 800 pixels wide.
However, they are being resized to 1440 pixels wide. Extra code is being inserted:
<img src="images/bar.jpg" data-thumb="images/bar.jpg" alt="" title="" style="display: none; width: 1440px;">
I have searched the CSS and JS and can find no mention of 1440.
Where is this width being set?
Nivo Slider is responsive by default, if you want to limit the sliders width, use the below class in your CSS
.slider-wrapper.theme-default {
width: 800px; /* Desired width */
}
The above will work if you are using default theme of nivo slider, if you are using some other theme, than simply change the .theme-default to theme specific class which is assigned to the slider wrapper.
Use my custom nivo script code
/*
* jQuery Nivo Slider v2.5.1
* http://nivo.dev7studios.com
*
* Copyright 2011, Gilbert Pellegrom
* Free to use and abuse under the MIT license.
* http://www.opensource.org/licenses/mit-license.php
*
* March 2010
*/
(function($) {
var NivoSlider = function(element, options) {
var settings = $.extend({}, $.fn.nivoSlider.defaults, options);
var vars = {
currentSlide : 0,
currentImage : '',
totalSlides : 0,
randAnim : '',
running : false,
paused : false,
stop : false
};
var slider = $(element);
slider.data('nivo:vars', vars);
slider.css('position', 'relative');
slider.addClass('nivoSlider');
var kids = slider.children();
kids.each(function() {
var child = $(this);
var link = '';
if (!child.is('img')) {
if (child.is('a')) {
child.addClass('nivo-imageLink');
link = child;
}
child = child.find('img:first');
}
var childWidth = child.width();
if (childWidth == 0)
childWidth = child.attr('width');
var childHeight = child.height();
if (childHeight == 0)
childHeight = child.attr('height');
if (childWidth > slider.width()) {
slider.width(childWidth);
}
if (childHeight > slider.height()) {
slider.height(childHeight);
}
if (link != '') {
link.css('display', 'none');
}
child.css('display', 'none');
vars.totalSlides++;
});
if (settings.startSlide > 0) {
if (settings.startSlide >= vars.totalSlides)
settings.startSlide = vars.totalSlides - 1;
vars.currentSlide = settings.startSlide;
}
if ($(kids[vars.currentSlide]).is('img')) {
vars.currentImage = $(kids[vars.currentSlide]);
} else {
vars.currentImage = $(kids[vars.currentSlide]).find('img:first');
}
if ($(kids[vars.currentSlide]).is('a')) {
$(kids[vars.currentSlide]).css('display', 'block');
}
slider.css({
'background' : 'url("' + vars.currentImage.attr('src') + '") no-repeat',
'background-size' : settings.backgroundSize
});
slider.append($('<div class="nivo-caption"><p></p></div>').css({
display : 'none',
opacity : settings.captionOpacity
}));
var processCaption = function(settings) {
var nivoCaption = $('.nivo-caption', slider);
if (vars.currentImage.attr('title') != '') {
var title = vars.currentImage.attr('title');
if (title.substr(0, 1) == '#')
title = $(title).html();
if (nivoCaption.css('display') == 'block') {
nivoCaption.find('p').fadeOut(settings.animSpeed, function() {
$(this).html(title);
$(this).fadeIn(settings.animSpeed);
});
} else {
nivoCaption.find('p').html(title);
}
nivoCaption.fadeIn(settings.animSpeed);
} else {
nivoCaption.fadeOut(settings.animSpeed);
}
}
processCaption(settings);
var timer = 0;
if (!settings.manualAdvance && kids.length > 1) {
timer = setInterval(function() {
nivoRun(slider, kids, settings, false);
}, settings.pauseTime);
}
if (settings.directionNav) {
slider.append('<div class="nivo-directionNav"><a class="nivo-prevNav">' + settings.prevText + '</a><a class="nivo-nextNav">' + settings.nextText + '</a></div>');
if (settings.directionNavHide) {
$('.nivo-directionNav', slider).hide();
slider.hover(function() {
$('.nivo-directionNav', slider).show();
}, function() {
$('.nivo-directionNav', slider).hide();
});
}
$('a.nivo-prevNav', slider).live('click', function() {
if (vars.running)
return false;
clearInterval(timer);
timer = '';
vars.currentSlide -= 2;
nivoRun(slider, kids, settings, 'prev');
});
$('a.nivo-nextNav', slider).live('click', function() {
if (vars.running)
return false;
clearInterval(timer);
timer = '';
nivoRun(slider, kids, settings, 'next');
});
}
if (settings.controlNav) {
var nivoControl = $('<div class="nivo-controlNav"></div>');
slider.append(nivoControl);
for (var i = 0; i < kids.length; i++) {
if (settings.controlNavThumbs) {
var child = kids.eq(i);
if (!child.is('img')) {
child = child.find('img:first');
}
if (settings.controlNavThumbsFromRel) {
nivoControl.append('<a class="nivo-control" rel="' + i + '"><img src="' + child.attr('rel') + '" alt="" /></a>');
} else {
nivoControl.append('<a class="nivo-control" rel="' + i + '"><img src="' + child.attr('src').replace(settings.controlNavThumbsSearch, settings.controlNavThumbsReplace) + '" alt="" /></a>');
}
} else {
nivoControl.append('<a class="nivo-control" rel="' + i + '">' + (i + 1) + '</a>');
}
}
$('.nivo-controlNav a:eq(' + vars.currentSlide + ')', slider).addClass('active');
$('.nivo-controlNav a', slider).live('click', function() {
if (vars.running)
return false;
if ($(this).hasClass('active'))
return false;
clearInterval(timer);
timer = '';
slider.css({
'background' : 'url("' + vars.currentImage.attr('src') + '") no-repeat',
'background-size' : settings.backgroundSize
});
vars.currentSlide = $(this).attr('rel') - 1;
nivoRun(slider, kids, settings, 'control');
});
}
if (settings.keyboardNav) {
$(window).keypress(function(event) {
if (event.keyCode == '37') {
if (vars.running)
return false;
clearInterval(timer);
timer = '';
vars.currentSlide -= 2;
nivoRun(slider, kids, settings, 'prev');
}
if (event.keyCode == '39') {
if (vars.running)
return false;
clearInterval(timer);
timer = '';
nivoRun(slider, kids, settings, 'next');
}
});
}
if (settings.pauseOnHover) {
slider.hover(function() {
vars.paused = true;
clearInterval(timer);
timer = '';
}, function() {
vars.paused = false;
if (timer == '' && !settings.manualAdvance) {
timer = setInterval(function() {
nivoRun(slider, kids, settings, false);
}, settings.pauseTime);
}
});
}
slider.bind('nivo:animFinished', function() {
vars.running = false;
$(kids).each(function() {
if ($(this).is('a')) {
$(this).css('display', 'none');
}
});
if ($(kids[vars.currentSlide]).is('a')) {
$(kids[vars.currentSlide]).css('display', 'block');
}
if (timer == '' && !vars.paused && !settings.manualAdvance) {
timer = setInterval(function() {
nivoRun(slider, kids, settings, false);
}, settings.pauseTime);
}
settings.afterChange.call(this);
});
var createSlices = function(slider, settings, vars) {
for (var i = 0; i < settings.slices; i++) {
var sliceWidth = Math.round(slider.width() / settings.slices);
if (i == settings.slices - 1) {
slider.append($('<div class="nivo-slice"></div>').css({
left : (sliceWidth * i) + 'px',
width : (slider.width() - (sliceWidth * i)) + 'px',
height : '0px',
opacity : '0',
background : 'url("' + vars.currentImage.attr('src') + '") no-repeat -' + ((sliceWidth + (i * sliceWidth)) - sliceWidth) + 'px 0%',
'background-size': settings.backgroundSize
}));
} else {
slider.append($('<div class="nivo-slice"></div>').css({
left : (sliceWidth * i) + 'px',
width : sliceWidth + 'px',
height : '0px',
opacity : '0',
background : 'url("' + vars.currentImage.attr('src') + '") no-repeat -' + ((sliceWidth + (i * sliceWidth)) - sliceWidth) + 'px 0%',
'background-size': settings.backgroundSize
}));
}
}
}
var createBoxes = function(slider, settings, vars) {
var boxWidth = Math.round(slider.width() / settings.boxCols);
var boxHeight = Math.round(slider.height() / settings.boxRows);
for (var rows = 0; rows < settings.boxRows; rows++) {
for (var cols = 0; cols < settings.boxCols; cols++) {
if (cols == settings.boxCols - 1) {
slider.append($('<div class="nivo-box"></div>').css({
opacity : 0,
left : (boxWidth * cols) + 'px',
top : (boxHeight * rows) + 'px',
width : (slider.width() - (boxWidth * cols)) + 'px',
height : boxHeight + 'px',
background : 'url("' + vars.currentImage.attr('src') + '") no-repeat -' + ((boxWidth + (cols * boxWidth)) - boxWidth) + 'px -' + ((boxHeight + (rows * boxHeight)) - boxHeight) + 'px',
'background-size': settings.backgroundSize
}));
} else {
slider.append($('<div class="nivo-box"></div>').css({
opacity : 0,
left : (boxWidth * cols) + 'px',
top : (boxHeight * rows) + 'px',
width : boxWidth + 'px',
height : boxHeight + 'px',
background : 'url("' + vars.currentImage.attr('src') + '") no-repeat -' + ((boxWidth + (cols * boxWidth)) - boxWidth) + 'px -' + ((boxHeight + (rows * boxHeight)) - boxHeight) + 'px',
'background-size': settings.backgroundSize
}));
}
}
}
}
var nivoRun = function(slider, kids, settings, nudge) {
var vars = slider.data('nivo:vars');
if (vars && (vars.currentSlide == vars.totalSlides - 1)) {
settings.lastSlide.call(this);
}
if ((!vars || vars.stop) && !nudge)
return false;
settings.beforeChange.call(this);
if (!nudge) {
slider.css({'background':'url("' + vars.currentImage.attr('src') + '") no-repeat','background-size': settings.backgroundSize });
} else {
if (nudge == 'prev') {
slider.css({'background':'url("' + vars.currentImage.attr('src') + '") no-repeat','background-size': settings.backgroundSize });
}
if (nudge == 'next') {
slider.css({'background':'url("' + vars.currentImage.attr('src') + '") no-repeat','background-size': settings.backgroundSize });
}
}
vars.currentSlide++;
if (vars.currentSlide == vars.totalSlides) {
vars.currentSlide = 0;
settings.slideshowEnd.call(this);
}
if (vars.currentSlide < 0)
vars.currentSlide = (vars.totalSlides - 1);
if ($(kids[vars.currentSlide]).is('img')) {
vars.currentImage = $(kids[vars.currentSlide]);
} else {
vars.currentImage = $(kids[vars.currentSlide]).find('img:first');
}
if (settings.controlNav) {
$('.nivo-controlNav a', slider).removeClass('active');
$('.nivo-controlNav a:eq(' + vars.currentSlide + ')', slider).addClass('active');
}
processCaption(settings);
$('.nivo-slice', slider).remove();
$('.nivo-box', slider).remove();
if (settings.effect == 'random') {
var anims = new Array('sliceDownRight', 'sliceDownLeft', 'sliceUpRight', 'sliceUpLeft', 'sliceUpDown', 'sliceUpDownLeft', 'fold', 'fade', 'boxRandom', 'boxRain', 'boxRainReverse', 'boxRainGrow', 'boxRainGrowReverse');
vars.randAnim = anims[Math.floor(Math.random() * (anims.length + 1))];
if (vars.randAnim == undefined)
vars.randAnim = 'fade';
}
if (settings.effect.indexOf(',') != -1) {
var anims = settings.effect.split(',');
vars.randAnim = anims[Math.floor(Math.random() * (anims.length))];
if (vars.randAnim == undefined)
vars.randAnim = 'fade';
}
vars.running = true;
if (settings.effect == 'sliceDown' || settings.effect == 'sliceDownRight' || vars.randAnim == 'sliceDownRight' || settings.effect == 'sliceDownLeft' || vars.randAnim == 'sliceDownLeft') {
createSlices(slider, settings, vars);
var timeBuff = 0;
var i = 0;
var slices = $('.nivo-slice', slider);
if (settings.effect == 'sliceDownLeft' || vars.randAnim == 'sliceDownLeft')
slices = $('.nivo-slice', slider)._reverse();
slices.each(function() {
var slice = $(this);
slice.css({
'top' : '0px'
});
if (i == settings.slices - 1) {
setTimeout(function() {
slice.animate({
height : '100%',
opacity : '1.0'
}, settings.animSpeed, '', function() {
slider.trigger('nivo:animFinished');
});
}, (100 + timeBuff));
} else {
setTimeout(function() {
slice.animate({
height : '100%',
opacity : '1.0'
}, settings.animSpeed);
}, (100 + timeBuff));
}
timeBuff += 50;
i++;
});
} else if (settings.effect == 'sliceUp' || settings.effect == 'sliceUpRight' || vars.randAnim == 'sliceUpRight' || settings.effect == 'sliceUpLeft' || vars.randAnim == 'sliceUpLeft') {
createSlices(slider, settings, vars);
var timeBuff = 0;
var i = 0;
var slices = $('.nivo-slice', slider);
if (settings.effect == 'sliceUpLeft' || vars.randAnim == 'sliceUpLeft')
slices = $('.nivo-slice', slider)._reverse();
slices.each(function() {
var slice = $(this);
slice.css({
'bottom' : '0px'
});
if (i == settings.slices - 1) {
setTimeout(function() {
slice.animate({
height : '100%',
opacity : '1.0'
}, settings.animSpeed, '', function() {
slider.trigger('nivo:animFinished');
});
}, (100 + timeBuff));
} else {
setTimeout(function() {
slice.animate({
height : '100%',
opacity : '1.0'
}, settings.animSpeed);
}, (100 + timeBuff));
}
timeBuff += 50;
i++;
});
} else if (settings.effect == 'sliceUpDown' || settings.effect == 'sliceUpDownRight' || vars.randAnim == 'sliceUpDown' || settings.effect == 'sliceUpDownLeft' || vars.randAnim == 'sliceUpDownLeft') {
createSlices(slider, settings, vars);
var timeBuff = 0;
var i = 0;
var v = 0;
var slices = $('.nivo-slice', slider);
if (settings.effect == 'sliceUpDownLeft' || vars.randAnim == 'sliceUpDownLeft')
slices = $('.nivo-slice', slider)._reverse();
slices.each(function() {
var slice = $(this);
if (i == 0) {
slice.css('top', '0px');
i++;
} else {
slice.css('bottom', '0px');
i = 0;
}
if (v == settings.slices - 1) {
setTimeout(function() {
slice.animate({
height : '100%',
opacity : '1.0'
}, settings.animSpeed, '', function() {
slider.trigger('nivo:animFinished');
});
}, (100 + timeBuff));
} else {
setTimeout(function() {
slice.animate({
height : '100%',
opacity : '1.0'
}, settings.animSpeed);
}, (100 + timeBuff));
}
timeBuff += 50;
v++;
});
} else if (settings.effect == 'fold' || vars.randAnim == 'fold') {
createSlices(slider, settings, vars);
var timeBuff = 0;
var i = 0;
$('.nivo-slice', slider).each(function() {
var slice = $(this);
var origWidth = slice.width();
slice.css({
top : '0px',
height : '100%',
width : '0px'
});
if (i == settings.slices - 1) {
setTimeout(function() {
slice.animate({
width : origWidth,
opacity : '1.0'
}, settings.animSpeed, '', function() {
slider.trigger('nivo:animFinished');
});
}, (100 + timeBuff));
} else {
setTimeout(function() {
slice.animate({
width : origWidth,
opacity : '1.0'
}, settings.animSpeed);
}, (100 + timeBuff));
}
timeBuff += 50;
i++;
});
} else if (settings.effect == 'fade' || vars.randAnim == 'fade') {
createSlices(slider, settings, vars);
var firstSlice = $('.nivo-slice:first', slider);
firstSlice.css({
'height' : '100%',
'width' : slider.width() + 'px'
});
firstSlice.animate({
opacity : '1.0'
}, (settings.animSpeed * 2), '', function() {
slider.trigger('nivo:animFinished');
});
} else if (settings.effect == 'slideInRight' || vars.randAnim == 'slideInRight') {
createSlices(slider, settings, vars);
var firstSlice = $('.nivo-slice:first', slider);
firstSlice.css({
'height' : '100%',
'width' : '0px',
'opacity' : '1'
});
firstSlice.animate({
width : slider.width() + 'px'
}, (settings.animSpeed * 2), '', function() {
slider.trigger('nivo:animFinished');
});
} else if (settings.effect == 'slideInLeft' || vars.randAnim == 'slideInLeft') {
createSlices(slider, settings, vars);
var firstSlice = $('.nivo-slice:first', slider);
firstSlice.css({
'height' : '100%',
'width' : '0px',
'opacity' : '1',
'left' : '',
'right' : '0px'
});
firstSlice.animate({
width : slider.width() + 'px'
}, (settings.animSpeed * 2), '', function() {
firstSlice.css({
'left' : '0px',
'right' : ''
});
slider.trigger('nivo:animFinished');
});
} else if (settings.effect == 'boxRandom' || vars.randAnim == 'boxRandom') {
createBoxes(slider, settings, vars);
var totalBoxes = settings.boxCols * settings.boxRows;
var i = 0;
var timeBuff = 0;
var boxes = shuffle($('.nivo-box', slider));
boxes.each(function() {
var box = $(this);
if (i == totalBoxes - 1) {
setTimeout(function() {
box.animate({
opacity : '1'
}, settings.animSpeed, '', function() {
slider.trigger('nivo:animFinished');
});
}, (100 + timeBuff));
} else {
setTimeout(function() {
box.animate({
opacity : '1'
}, settings.animSpeed);
}, (100 + timeBuff));
}
timeBuff += 20;
i++;
});
} else if (settings.effect == 'boxRain' || vars.randAnim == 'boxRain' || settings.effect == 'boxRainReverse' || vars.randAnim == 'boxRainReverse' || settings.effect == 'boxRainGrow' || vars.randAnim == 'boxRainGrow' || settings.effect == 'boxRainGrowReverse' || vars.randAnim == 'boxRainGrowReverse') {
createBoxes(slider, settings, vars);
var totalBoxes = settings.boxCols * settings.boxRows;
var i = 0;
var timeBuff = 0;
var rowIndex = 0;
var colIndex = 0;
var box2Darr = new Array();
box2Darr[rowIndex] = new Array();
var boxes = $('.nivo-box', slider);
if (settings.effect == 'boxRainReverse' || vars.randAnim == 'boxRainReverse' || settings.effect == 'boxRainGrowReverse' || vars.randAnim == 'boxRainGrowReverse') {
boxes = $('.nivo-box', slider)._reverse();
}
boxes.each(function() {
box2Darr[rowIndex][colIndex] = $(this);
colIndex++;
if (colIndex == settings.boxCols) {
rowIndex++;
colIndex = 0;
box2Darr[rowIndex] = new Array();
}
});
for (var cols = 0; cols < (settings.boxCols * 2); cols++) {
var prevCol = cols;
for (var rows = 0; rows < settings.boxRows; rows++) {
if (prevCol >= 0 && prevCol < settings.boxCols) {
(function(row, col, time, i, totalBoxes) {
var box = $(box2Darr[row][col]);
var w = box.width();
var h = box.height();
if (settings.effect == 'boxRainGrow' || vars.randAnim == 'boxRainGrow' || settings.effect == 'boxRainGrowReverse' || vars.randAnim == 'boxRainGrowReverse') {
box.width(0).height(0);
}
if (i == totalBoxes - 1) {
setTimeout(function() {
box.animate({
opacity : '1',
width : w,
height : h
}, settings.animSpeed / 1.3, '', function() {
slider.trigger('nivo:animFinished');
});
}, (100 + time));
} else {
setTimeout(function() {
box.animate({
opacity : '1',
width : w,
height : h
}, settings.animSpeed / 1.3);
}, (100 + time));
}
})(rows, prevCol, timeBuff, i, totalBoxes);
i++;
}
prevCol--;
}
timeBuff += 100;
}
}
}
var shuffle = function(arr) {
for (var j, x, i = arr.length; i; j = parseInt(Math.random() * i), x = arr[--i], arr[i] = arr[j], arr[j] = x);
return arr;
}
var trace = function(msg) {
if (this.console && typeof console.log != "undefined")
console.log(msg);
}
this.stop = function() {
if (!$(element).data('nivo:vars').stop) {
$(element).data('nivo:vars').stop = true;
trace('Stop Slider');
}
}
this.start = function() {
if ($(element).data('nivo:vars').stop) {
$(element).data('nivo:vars').stop = false;
trace('Start Slider');
}
}
settings.afterLoad.call(this);
return this;
};
$.fn.nivoSlider = function(options) {
return this.each(function(key, value) {
var element = $(this);
if (element.data('nivoslider'))
return element.data('nivoslider');
var nivoslider = new NivoSlider(this, options);
element.data('nivoslider', nivoslider);
});
};
$.fn.nivoSlider.defaults = {
backgroundSize:'',
effect : 'random',
slices : 15,
boxCols : 8,
boxRows : 4,
animSpeed : 500,
pauseTime : 3000,
startSlide : 0,
directionNav : true,
directionNavHide : true,
controlNav : true,
controlNavThumbs : false,
controlNavThumbsFromRel : false,
controlNavThumbsSearch : '.jpg',
controlNavThumbsReplace : '_thumb.jpg',
keyboardNav : true,
pauseOnHover : true,
manualAdvance : false,
captionOpacity : 0.8,
prevText : 'Prev',
nextText : 'Next',
beforeChange : function() {
},
afterChange : function() {
},
slideshowEnd : function() {
},
lastSlide : function() {
},
afterLoad : function() {
}
};
$.fn._reverse = [].reverse;
})(jQuery);
When you initial nivoSlide pass my new parameter backgroundSize:'your width size px your height size px';
Example:
$('#slider').nivoSlider({
backgroundSize:'687px 400px',
effect: 'random',
animSpeed: 500,
pauseTime: 3000,
directionNav: true,
controlNav: true,
controlNavThumbs: false,
pauseOnHover: true});
});
I'm new to d3, but learned it by trial. The following code works fine with the dataset (data/clusterRsult.json) when I do not incorporate any css style. Now that I would like to have css style for header and footer; and for the content, I would like to have a div on the left for the graph,and a div on the right for detail text of the nodes. When I added the css style in the previous codes (that works without any div), the Firefox and Google chrome debugger mode give me the error following error:
[18:09:55.694] TypeError: this[type] is undefined # file:///C:/Users/mcoyne/workspace_d3js/d3_v3/d3.v3.js:372
===========================
My Code:
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8">
<title>Clustering Results - Works</title>
<link href="NSFStyles/nsfstyle.css" rel="stylesheet" type="text/css" />
<script type="text/javascript" src="d3_v3/d3.js"></script>
<script type="text/javascript" src="d3_v3/lib/colorbrewer/colorbrewer.js"></script>
<script type="text/javascript" scr="d3_v3/src/layout/layout.js"></script>
<script type="text/javascript" scr="d3_v3/src/geom/geom.js"></script>
<link href="css/nsfstyle.css" rel="stylesheet" type="text/css" />
<link href="css/csEoSVisContent.css" rel="stylesheet" type="text/css"/>
<style>
p {
-webkit-margin-after: 0em;
-webkit-margin-before: 0em;
margin-bottom: 0em;
margin-top: 5em;
}
#h_emphasis01 {
font-weight: bold;
}
</style>
</head>
<body>
<div class="csnsfheader"></div>
<div style="text-align: right; padding-right: 1em; font-family: Verdana; font-size: 60%; top:auto;vertical-align: top; font-weight: bold; padding-top: 1px" id="Help" align="right">
<a style="text-decoration: none" href="helpEos.html"
target="_blank">HELP | </a><a style="text-decoration: none" title="Send us an email"href="mailto:xyz#abc.gov">CONTACT |</a>
</div>
<div class = "svg">
<div class="csnsfbody.svg.containerLeft" id="clusterLeftPanel"> </div>
<div class="csnsfbody.svg.containerRight" id="clusterRightPanel"> </div>
<script type="text/javascript" src="d3_v3/d3.v3.js"></script>
<!--script type="text/javascript" src="http://d3js.org/d3.v3.min.js"></script-->
<script>
var width = 620,
height = width,
radius = Math.min(width, height) /2,
node,
link,
root,
x = d3.scale.linear().range([0, 2 * Math.PI]),
y = d3.scale.pow().exponent(1.3).domain([0,1]).range([0, radius]);
// y = d3.scale.linear().range([0, radius]),
padding = 5,
duration = 1000,
color = d3.scale.category20c();
var colorScaleTop = d3.scale.ordinal().domain([101, 1000.0]).range(colorbrewer.Dark2[5]);
var colorScaleMiddle = d3.scale.ordinal().domain([1, 1000.0]).range(colorbrewer.Pastel1[6]);
var colorScaleLeaf = d3.scale.ordinal().domain([1]).range(colorbrewer.Set2[5]);
// set up the left section of the screen for the graph
var vis = d3.select("body")
.append ("csnsfbody.svg.containerLeft")
.attr("class", "csnsfbody.svg.containerLeft")
.style("width", width + "px")
.style("height", height + "px")
.append("svg:svg")
.attr("width", width + padding * 2 )
.attr("height", height + padding * 2)
.append("svg:g")
.attr("transform", "translate(" + [radius + padding, radius + padding] + ")")
;
// set up the right section of the screen for text displaying
var clusterDetails = d3.select("body")
.append("csnsfbody.svg.containerRight")
.attr("class", "csnsfbody.svg.containerRight")
.style("width", width + "px")
.style("height", height + "px")
.style("margin-left", "100px")
.style("background","#F8FBEF")
.style("position", "absolute")
;
// *** Error encounter on this line
// ***
d3.json("data/clusterResult.json", function(error, json) {
if (error) return console.log("there was an error loading the data: " + error);
var force = d3.layout.force()
.size([width, height])
.charge(function(d) { return getCharge(d);})
.linkDistance(function(d) { return getLinkDistance(d); })
.on("tick", tick)
.on("mouseover",mouseover)
.on("mouseout", mouseout)
;
// successfully load data from data.json
console.log("there are " + json.size + " nodes in my dataset");
console.log("there are " + json.children.length + " categories in my dataset");
root = json;
update();
});
function update() {
var nodes = flatten(root),
links = d3.layout.tree().links(nodes),
total = nodes.length || 1;
console.log("nodes.length = " + nodes.length);
console.log("total=" + total);
// Restart the force layout.
force
.gravity(Math.atan(total / 50) / Math.PI * 0.4)
.nodes(nodes)
.links(links)
.start();
// Update the links
// link = vis.selectAll("line.link")
// .data(force.links())
// .attr("class", "link")
link = svg.selectAll('.link')
.data( force.links() )
.enter().append('line')
.attr('class', 'link')
.style("stroke-width", function(d) { return Math.sqrt(d.value); });
;
// Enter any new links.
link.enter().insert("svg:line", ".node")
.attr("class", "link")
.attr("x1", function(d) { return d.source.x; })
.attr("y1", function(d) { return d.source.y; })
.attr("x2", function(d) { return d.target.x; })
.attr("y2", function(d) { return d.target.y; });
// Exit any old links.
link.exit().remove();
// Update the nodes
node = vis.selectAll("circle.node")
.data(force.nodes())
.classed("collapsed", function(d) { return d._children ? 1 : 0; })
.attr("class", "node")
.style("fill", function(d) { return color(d);} )
;
node.select ("circle")
.style("fill", function(d) { return color(d);} );
// Enter any new nodes.
var nodeEnter = node.enter().append("svg:g")
.attr("class", "node")
.call(force.drag)
;
nodeEnter.append("svg:circle")
.attr("class", "node")
.classed('directory', function(d) { return (d._children || d.children) ? 1 : 0; })
.attr("r", function(d) {return getRadius(d); })
.attr("fill", function(d) { return color(d); })
.call(force.drag)
//.on("click",click) // This is NOT working
;
nodeEnter.append("svg:text")
.attr("text-anchor", "middle")
.attr("dy", ".35em")
.style("font-size", function (d) { return d.children ? "12px" : "8px"; })
.style("font-weight", function (d) { return d.children ? "600" : "200"; })
.text(function(d) {return d.children ? (d.name + " (" + d.size + ")") : ""; });
// Exit any old nodes
node.exit().remove();
// reselect for update
link = vis.selectAll("line.link");
node = vis.selectAll("g.node");
force.on("tick", tick);
} // end update function
function tick() {
link.attr("x1", function(d) { return d.source.x; })
.attr("y1", function(d) { return d.source.y; })
.attr("x2", function(d) { return d.target.x; })
.attr("y2", function(d) { return d.target.y; });
node.attr("transform", function(d) {
return "translate(" + Math.max(5, Math.min(width - 5, d.x)) + "," + Math.max(5, Math.min(height - 5, d.y)) + ")";
});
}
// Color leaf nodes orange, and packages white or blue.
function color(d) {
//if (d.type=="root") {return colorScaleTop(d.children);}
//if (d.type == "label") {return colorScaleMiddle (d.children);}
if (d.type == "root" ){return "#FFFF33"; }
if (d.type == "label") {
if (d.size <= 50) { return "#7FBF7B"; } // good color 66C2A5, cute green A1D76A
if (d.size > 50 && d.size <= 100) { return "#FC8D62"; }
if (d.size > 100) { return "#E9A3C9"; }
}
if (d.type == "leaf") {return "#2C7FB8"; } // lavender #BEAED4
// light green ADDD8E
}
function getRadius (d) {
if (d.type == "root") {return 20;}
if (d.type == "label") {return 12; }
if (d.type == "leaf") {return 2;}
}
function getLinkDistance (d) {
if (d.target.type == "label") {return 8; }
if (d.target.type == "leaf") {return 3;}
}
function getCharge (d) {
if (d.type == "root") {return -300; }
if (d.type == "label") {return -600; }
if (d.type == "leaf") {return -40;}
}
// Toggle children on click.
function click(d) {
if (d.children) {
d._children = d.children;
d.children = null;
} else {
d.children = d._children;
d._children = null;
}
update();
}
function mouseover (d) {
if (d.type == "leaf") {
this.text.attr('transform', 'translate(' + d.x + ',' + (d.y - 5 - (d.children ? 3.5 : Math.sqrt(d.size) / 2)) + ')')
.text(d.name)
//.style('display', null)
;
}
}
// Returns a list of all nodes under the root.
function flatten(root) {
var nodes = [], i = 0;
function recurse(node) {
if (node.children) node.children.forEach(recurse);
if (!nodes.id) nodes.id = ++i;
nodes.push(node);
}
recurse(root);
return nodes;
}
function mouseover(d)
{
console.log("mouseouver <" + d.name + ">");
if (d.type == "root") {
console.log("mouseouver, root <" + d.name + ">");
clusterDetais.append("p")
.style("font-weight", 600)
.text(d.name);
}
if (d.type== "label") {
console.log("mouseouver, label <" + d.name + ">");
clusterDetails.append("p")
.style("font-weight", 600)
.text("Cluster Name: " + d.name + " (" + d.size + ")")
;
var myChildren = new Array;
myChildren = getChildrenOf(d, myChildren);
for (var i = 0; i < myChildren.length; i++) {
if (myChildren[i].type === "label" && myChildren[i].children) {
clusterDetails.append("p")
.style("font-weight", 600)
.text ("Sub-cluster name: " + myChildren[i].name + " (" + myChildren[i].size + ")")
;
}
else { clusterDetails.append("p")
.text(myChildren[i].name);
}
} // end for
}
if(d.type=="leaf" ){
clusterDetails.append("p")
.text ("Proposal id: " + d.name)
.text ("Title: " + "TBA")
.text ("PI/CoPi: " + "TBA")
;
}
} // end mouseover
//mouseout function which removes the values and replaces them with a blank space
function mouseout(d)
{
clusterDetails.html(' ');
}
</script>
</div>
<!-- ====================================================================== -->
<!-- Footer -->
<!-- ====================================================================== -->
<div class="csnsffooter" >
<!-- Add footer here -->
<span></span>
</body>
</html>