Using XTK or AMI.js to display Freesurfer while/pial objects on T1.mgz - xtk

I'd like to recreate a web version of FreeSurfer pial/white surfaces overlaid on T1.mgz similar to the first freeview image at https://surfer.nmr.mgh.harvard.edu/fswiki/FsTutorial/PialEdits_freeview. Using XTK I can get something that hints at that using advice from Othographic Projection in XTK. The code I used to create the image (along with kruft from multiple attempts) is below the image.
Is this possible with XTK or should I switch over to AMI.js (which has freesurfer surfaces and MGZ file formats on their roadmap but are not implemented)?
In either case, pointers to how to accomplish this would be appreciated.
Thanks.
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<title>FS XTK test</title>
</head>
<body>
<script type="text/javascript" src="/Xdevel/lib/google-closure-library/closure/goog/base.js"></script>
<script type="text/javascript" src="/Xdevel/xtk-deps.js"></script>
<script type="text/javascript" src="/Xdevel/xtk_xdat.gui.js"></script>
<script type="text/javascript">
var view2D_X = null;
var view2D_Y = null;
var view2D_Z = null;
var view3D = null;
var volume3D = null;
var meshes = new Array(6);
var meshFiles = new Array(6);
var t1File = 'T1.mgz';
meshFiles[0]='lh.orig';
meshFiles[1]='rh.orig';
meshFiles[2]='lh.pial';
meshFiles[3]='rh.pial';
meshFiles[4]='lh.white.pial';
meshFiles[5]='rh.white.pial';
var colors = [ //Matlab jet(28)
[ 0, 1, 0],
[ 0, 1, 0],
[ 1, 0, 0],
[ 1, 0, 0],
[ 0, 0, 1],
[ 0, 0, 1]
];
function setView(pos)
{
switch(pos)
{
case 1:
camPos=[ 0, 0, -1, 0,
-1, 0, -0, 0,
0, 1, 0, 0,
1, 0, -1, 1];
break;
case 2:
camPos=[-1, 0, 0, 0,
0, 0, 1, 0,
0, 1, -0, 0,
0, -1, -1, 1];
break;
default: //Case 3
camPos=[-1, 0, -0, 0,
-0, 1, -0, 0,
0, 0, 1, 0,
0, -0, -1, 1];
break;
}
camPos[14] = 200*camPos[14]; //zoomout
view3D.camera.view=new Float32Array(camPos);
}
// include all used X-classes here
// this is only required when using the xtk-deps.js file
goog.require('X.renderer2D');
goog.require('X.renderer3D');
goog.require('X.mesh');
function addLoadEvent(func) {
var oldonload = window.onload;
if (typeof window.onload != 'function') {
window.onload = func;
} else {
window.onload = function() {
if (oldonload) {
oldonload();
}
func();
}
}
}
</script>
<div id="view3D_div" style="background-color: #000; width: 399px; height: 399px;"></div>
<script type="text/javascript">
function loadMeshes()
{
for (var a = 0; a < 6; a++)
{
try
{
meshes[a] = new X.mesh();
meshes[a].file=meshFiles[a];
meshes[a].color = colors[a];
meshes[a].visible=true;
view3D.add(meshes[a]);
}
catch(err)
{
console.log('failed to load: '+meshFiles[a]);
console.log(err.message);
}
}
}
var _meshConfig = {
'width' : 399,
'height' : 399,
'unknown' : 180.5,
'diff' : 0.3
};
function setMainSlice()
{
// console.log('height: ' + height + ' width: ' + width);
console.log('X: ' + volume3D.indexX + 'Y: ' + volume3D.indexY + 'Z: ' + volume3D.indexZ);
_meshConfig.unknown=volume3D.indexZ+92.5;
console.log('width: '+_meshConfig.width + ' height: ' + _meshConfig.height + ' unknown: ' + _meshConfig.unknown);
view3D.camera._perspective=X.matrix.makeOrtho(X.matrix.identity(), -(_meshConfig.width/2), (_meshConfig.width/2), -(_meshConfig.height/2), (_meshConfig.height/2), _meshConfig.unknown+_meshConfig.diff, _meshConfig.unknown-_meshConfig.diff);
// view3D.camera._perspective=goog.vec.Mat4.createFromValues(1,0,0,0,0,1,0,0,0,0,1,0,volume3D.indexX,volume3D.indexY,volume3D.indexZ,1);
// view3D.camera._perspective=goog.vec.Mat4.createFromValues(0.005,0,0,0, 0,0.005,0,0, 0,0,3,0, 0,0,256+(volume3D.indexZ*2),1);
}
addLoadEvent(function () {
view3D = new X.renderer3D();
view3D.container = 'view3D_div';
view3D.init();
volume3D = new X.volume();
volume3D.file = t1File;
// volume3D.labelmap.file='all.white.mgz';
view3D.add(volume3D);
loadMeshes();
setView(3);
// view3D.camera.position=[-0, 0, 90];
// view3D.camera.view[14] = -200;
view3D.render();
view3D.onShowtime = function () {
view2D_X.onScroll = setMainSlice;
view2D_X.add(volume3D);
view2D_X.render();
view2D_Y.onScroll = setMainSlice;
view2D_Y.add(volume3D);
view2D_Y.render();
view2D_Z.onScroll = setMainSlice;
view2D_Z.add(volume3D);
view2D_Z.render();
setView(3);
};
var gui = new dat.GUI();
var anat_folder = gui.addFolder('T1');
anat_folder.add(volume3D,'visible');
anat_folder.add(volume3D,'opacity',0,1);
anat_folder.add(volume3D,'indexX');
anat_folder.add(volume3D,'indexY');
anat_folder.add(volume3D,'indexZ',0,256);
anat_folder.open();
var lh_orig_folder = gui.addFolder('Freesurfer lh.orig');
lh_orig_folder.add(meshes[0],'visible');
lh_orig_folder.add(meshes[0],'opacity',0,1);
lh_orig_folder.addColor(meshes[0],'color');
// lh_orig_folder.open();
var rh_orig_folder = gui.addFolder('Freesurfer rh.orig');
rh_orig_folder.add(meshes[1],'visible');
rh_orig_folder.add(meshes[1],'opacity',0,1);
rh_orig_folder.addColor(meshes[1],'color');
// rh_orig_folder.open();
var lh_pial_folder = gui.addFolder('Freesurfer lh.pial');
lh_pial_folder.add(meshes[2],'visible');
lh_pial_folder.add(meshes[2],'opacity',0,1);
lh_pial_folder.addColor(meshes[2],'color');
// lh_pial_folder.open();
var rh_pial_folder = gui.addFolder('Freesurfer rh.pial');
rh_pial_folder.add(meshes[3],'visible');
rh_pial_folder.add(meshes[3],'opacity',0,1);
rh_pial_folder.addColor(meshes[3],'color');
// rh_pial_folder.open();
var lh_white_folder = gui.addFolder('Freesurfer lh.white');
lh_white_folder.add(meshes[4],'visible');
lh_white_folder.add(meshes[4],'opacity',0,1);
lh_white_folder.addColor(meshes[4],'color');
// lh_white_folder.open();
var rh_white_folder = gui.addFolder('Freesurfer rh.white');
rh_white_folder.add(meshes[5],'visible');
rh_white_folder.add(meshes[5],'opacity',0,1);
rh_white_folder.addColor(meshes[5],'color');
// rh_white_folder.open();
var mesh_folder = gui.addFolder('Mesh');
mesh_folder.add(_meshConfig,'height');
mesh_folder.add(_meshConfig,'width');
mesh_folder.add(_meshConfig,'unknown');
mesh_folder.open();
for (c in gui.__controllers)
{
gui.__controllers[c].onFinishChange(update);
}
});
</script>
<table style="border-collapse: collapse">
<tr>
<td style="background-color: red;">
<div id="view2D_X_div" style="background-color: #000; width: 131px; height: 131px;"></div>
<script type="text/javascript">
addLoadEvent(function () {
view2D_X = new X.renderer2D();
view2D_X.container = 'view2D_X_div';
view2D_X.orientation = 'X';
view2D_X.init();
});
</script>
</td>
<td style="background-color: green;">
<div id="view2D_Y_div" style="background-color: #000; width: 131px; height: 131px;"></div>
<script type="text/javascript">
addLoadEvent(function () {
view2D_Y = new X.renderer2D();
view2D_Y.container = 'view2D_Y_div';
view2D_Y.orientation = 'Y';
view2D_Y.init();
});
</script>
</td>
<td style="background-color: blue;">
<div id="view2D_Z_div" style="background-color: #000; width: 131px; height: 131px;"></div>
<script type="text/javascript">
addLoadEvent(function () {
view2D_Z = new X.renderer2D();
view2D_Z.container = 'view2D_Z_div';
view2D_Z.orientation = 'Z';
view2D_Z.init();
});
</script>
</td>
</tr>
<tr>
<td style="background-color: red;">
<!-- <button onClick="setView([-90,0,0]);">Set View</button>-->
<button onClick="setView(1);">Set View</button>
</td>
<td style="background-color: green;">
<!-- <button onClick="setView([0,90,0]);">Set View</button>-->
<button onClick="setView(2);">Set View</button>
</td>
<td style="background-color: blue;">
<!-- <button onClick="setView([0,0,90]);">Set View</button>-->
<button onClick="setView(3);">Set View</button>
</td>
</tr>
</table>
Green is orig<br>
Red is pial<br>
Blue is white<br>
</body>
</html>

You can now do it in AMI (thanks to your PR: https://fnndsc.github.io/ami/#viewers_quadview)
Display intersection between a mesh and a plane
Post process the intersection to display the contours.
There are different techniques to display mesh/plane intersection:
With a stencil buffer (https://github.com/daign/clipping-with-caps)
Playing the the mesh opacity (https://github.com/FNNDSC/ami/tree/dev/examples/viewers_quadview)
All those techniques are computationally expensive at it requires 3 renders pass to display contours of 1 mesh and there may be a better approach but not sure what would be the best alternative.
HTH

Related

How to add vertical lines and annotations Google timeline chart

I am using a google timeline similar to the code snippet below. I want my chart to look like the one below. I have managed to get everything to work expect how to add the dashed lines and text notation. Unfortunately, when I am searching for annotations I keep getting the AnnotatedTimeline, which is a different google chart.
Is there a simple way to do this?
<html>
<head>
<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
<script type="text/javascript">
google.charts.load('current', {'packages':['timeline']});
google.charts.setOnLoadCallback(drawChart);
function drawChart() {
var container = document.getElementById('timeline');
var chart = new google.visualization.Timeline(container);
var dataTable = new google.visualization.DataTable();
dataTable.addColumn({ type: 'string', id: 'President' });
dataTable.addColumn({ type: 'date', id: 'Start' });
dataTable.addColumn({ type: 'date', id: 'End' });
dataTable.addRows([
[ 'Washington', new Date(1789, 3, 30), new Date(1797, 2, 4) ],
[ 'Adams', new Date(1797, 2, 4), new Date(1801, 2, 4) ],
[ 'Jefferson', new Date(1801, 2, 4), new Date(1809, 2, 4) ]]);
chart.draw(dataTable);
}
</script>
</head>
<body>
<div id="timeline" style="height: 180px;"></div>
</body>
</html>
I was able to get this to work by finding the position of the rects. I started by drawing divs for each line I would want to show. Then after the timeline is draw I repositions those divs based on the location of the rectangle. I was not able to get a good minimal working snippet here because of the window positions used in the snippet code, but I got pretty close. In my own code I have it working perfectly.
.hline {
border-left: 5px solid black;
height: 100px;
position:absolute;
visibility:hidden;
top:144px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<html>
<head>
<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
</head>
<body>
<div id="timeline" style="height: 180px;"></div>
<div id = "Hline1" class= "hline" > <div style = "position: relative; top:-18px">HLine1</div>
<div id = "Hline2" class= "hline" > <div style = "position: relative; top:-18px">HLine2</div>
<div id = "Hline3" class= "hline" > <div style = "position: relative; top:-18px">HLine3</div>
</div>
</body>
<script>
var options = {
timeline: { showRowLabels: false }
};
const lime="#00ff00" //color for average time
google.charts.load('current', {'packages':['timeline']});
google.charts.setOnLoadCallback(drawChart);
function drawChart() {
var container = document.getElementById('timeline');
var chart = new google.visualization.Timeline(container);
var dataTable = new google.visualization.DataTable();
dataTable.addColumn({ type: 'string', id: 'Project Stage', });
dataTable.addColumn({ type: 'string', id: 'Bar'});
dataTable.addColumn({ type: 'string', role: 'style'});
dataTable.addColumn({ type: 'date', id: 'Start' });
dataTable.addColumn({ type: 'date', id: 'End' });
dataTable.addRows([
[ 'Washington','Washington',lime, new Date(1789, 3, 30), new Date(1797, 2, 4) ],
[ 'Adams', 'Adams',lime, new Date(1797, 2, 4), new Date(1801, 2, 4) ],
[ 'Jefferson','Jefferson',lime, new Date(1801, 2, 4), new Date(1809, 2, 4) ]]);
chart.draw(dataTable,options);
function redraw (){
var rects = $('rect') //get all rectangles on plot.
function checkColor(arr){
var results = [];
for (let i of arr){
var colorCheck=$(i).attr('fill')
var x =$(i).attr('x')
var width = $(i).attr('width')
var x2 =parseFloat(x)+parseFloat(width)
if(colorCheck == lime){results.push(x2)}
};
return results
};
var linPositions = checkColor(rects) //get x coordinates for vertical lines
var yStart = $('rect')
//console.log(linPositions)
yStart = $(yStart[0]).offset().top;
xMargin=$("#timeline").offset().left;
var yHeight = $('rect')
yHeight = $(yHeight[0]).attr('height');
var lineNames=['Hline1','Hline2','Hline3']
for (let i = 0; i < linPositions.length; i++) {
var position = linPositions[i]+xMargin+"px"
var newTop = i*yHeight + yStart
/* set line information based on current chart positions */
document.getElementById(lineNames[i]).style.left = position;
document.getElementById(lineNames[i]).style.visibility = "visible";
document.getElementById(lineNames[i]).style.top = newTop;
document.getElementById(lineNames[i]).style.height = yHeight;
};
};
redraw()
function resizeChart () {
chart.draw(dataTable, options);
}
if (document.addEventListener) {
window.addEventListener('resize', resizeChart);
window.addEventListener('resize', redraw)
}
else if (document.attachEvent) {
window.attachEvent('onresize', resizeChart);
window.attachEvent('onresize', redraw);
}
else {
window.resize = resizeChart;
window.resize = redraw;
}
}
</script>
</html>

DataTables using Export Buttons and YADCF causes select lists to be exported

Is there a way to use the export buttons and yadcf chozen filter together without messing up the column headers in the export see below the column Order Number has Select appended
Order NumberSelect
value20766903232802532374885123748865237490732374944323749625x
Code:
<!doctype html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<meta name="description" content="" />
<meta name="keywords" content="" />
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" />
<link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/1.10.15/css/jquery.dataTables.min.css">
<link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/buttons/1.3.1/css/buttons.dataTables.min.css">
<link rel="stylesheet" href="/newwebadmin/mvc/orders/assets/css/cancellationStatistics.css" />
<link rel="stylesheet" type="text/css" href="/newwebadmin/js/chosen/chosen.min.css" />
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/yadcf/0.9.1/jquery.dataTables.yadcf.css">
<script src="/newwebadmin/mvc/orders/assets/js/cancellations/ChartNew.js"></script>
<script src="/newwebadmin/mvc/orders/assets/js/cancellations/shapesInChart.js"></script>
<script src="/newwebadmin/mvc/orders/assets/js/cancellations/specialInChartData.js"></script>
<script src="//code.jquery.com/jquery-1.12.4.js"></script>
<script src="//code.jquery.com/ui/1.11.4/jquery-ui.js"></script>
<script type="text/javascript" language="javascript" src="//cdn.datatables.net/1.10.15/js/jquery.dataTables.min.js"></script>
<script type="text/javascript" language="javascript" src="//cdn.datatables.net/buttons/1.3.1/js/dataTables.buttons.min.js"></script>
<script type="text/javascript" language="javascript" src="//cdn.datatables.net/buttons/1.3.1/js/buttons.flash.min.js"></script>
<script type="text/javascript" language="javascript" src="//cdnjs.cloudflare.com/ajax/libs/jszip/3.1.3/jszip.min.js"></script>
<script type="text/javascript" language="javascript" src="//cdn.rawgit.com/bpampuch/pdfmake/0.1.27/build/pdfmake.min.js"></script>
<script type="text/javascript" language="javascript" src="//cdn.rawgit.com/bpampuch/pdfmake/0.1.27/build/vfs_fonts.js"></script>
<script type="text/javascript" language="javascript" src="//cdn.datatables.net/buttons/1.3.1/js/buttons.html5.min.js"></script>
<script type="text/javascript" language="javascript" src="//cdn.datatables.net/buttons/1.3.1/js/buttons.print.min.js"></script>
<script src="/newwebadmin/js/Chosen/chosen.jquery.min.js" type="text/javascript" ></script>
<script type="text/javascript" language="javascript" src="//cdnjs.cloudflare.com/ajax/libs/yadcf/0.9.1/jquery.dataTables.yadcf.min.js"></script>
<style>
input[type="search"] {
border:1px #cccccc solid;
padding:2px;
border-radius: 2px;
}
</style>
<title>Cancel Order Reportle></title>
</head>
<cfset local.getCancellationReportData = rc.cancellations>
<body>
<!--- <cfdump var="#local#"> --->
<cfoutput>
<div class="flexbox-container">
<div class="main-content clearfix">
<div class="container">
<form action="" method="post">
<label for="startDate">Date Range: </label>
<input type="text" id="startDate" name="startDate" class="button" value="#structKeyExists(form, "startDate") ? form.startDate : DateFormat(Now(),'mm/dd/yyyy') #">
<label for="endDate">to</label>
<input type="text" id="endDate" name="endDate" class="button" value="#structKeyExists(form, "endDate") ? form.endDate : DateFormat(DateAdd('m',1,Now()),'mm/dd/yyyy') #">
<input type="submit" id="btnFilter" value="Filter" class="button">
</form>
<br><br>
<button id="platinum" class="button">Show Platinum Customers</button>
<button id="nonplatinum" class="button">Show Non-Platinum Customers</button>
<button id="all" class="button">Show All</button>
<br><br>
<table id="report" class="display" cellspacing="0" width="100%">
<thead>
<th align="left">Order Number</th>
<th align="left">VendorID</th>
<th align="left">User Index</th>
<th align="left">Customer Type</th>
<th align="left">Date</th>
<th align="left">## of items cancelled</th>
<th align="left">Total$</th>
<th align="left">Canceled By</th>
<th align="left">Reason</th>
</tr>
</thead>
<tfoot>
<tr>
<th colspan="5" style="text-align:right">Total:</th>
<th style="text-align:left"></th>
<th colspan="2" style="text-align:left"></th>
<th></th>
</tr>
</tfoot>
<tbody>
<cfloop query="local.getCancellationReportData">
<tr data-isPlatinum="#is_platinum#">
<td>#order_number#</td>
<td>#len(vendorID) ? vendorID: 'unknown'#</td>
<td>#len(dbo_tblEmployee_ID) ? dbo_tblEmployee_ID: 'unknown'#</td>
<td>#customerType#</td>
<td>#DateFormat(date,'mm/dd/yyyy')# #timeFormat(date,'hh:mm TT')#</td>
<td>#qty#</td>
<td align="right">#DollarFOrmat(ExtendedCost)#</td>
<td>#cancelledBy#</td>
<td>#cancellation_reason#</td>
</tr>
</cfloop>
</tbody>
</table>
</div>
</div>
</div>
</cfoutput>
<script>
$(document).ready(function() {
var table = $('#report').DataTable( {
dom: 'Bfrtip',
buttons: [
{extend :'excel', text:'Export to Excel'}
,{extend :'pdf' , text:'Export to PDF', orientation: 'landscape', pageSize: 'LEGAL'}
,'print'
],
"footerCallback": function ( row, data, start, end, display ) {
var api = this.api(), data;
// Remove the formatting to get integer data for summation
var intVal = function ( i ) {
return typeof i === 'string' ?
i.replace(/[\$,]/g, '')*1 :
typeof i === 'number' ?
i : 0;
};
// Total over all pages
total = api
.column( 6 )
.data()
.reduce( function (a, b) {
return intVal(intVal(a) + intVal(b)).toFixed(2);
} );
// Total over this page
pageTotal = api
.column( 6, { page: 'current'} )
.data()
.reduce( function (a, b) {
return intVal(intVal(a) + intVal(b)).toFixed(2);
}, 0 );
// Total over all pages
cantotal = api
.column( 5 )
.data()
.reduce( function (a, b) {
return intVal(intVal(a) + intVal(b));
} );
// Total over this page
canpageTotal = api
.column( 5, { page: 'current'} )
.data()
.reduce( function (a, b) {
return intVal(intVal(a) + intVal(b));
}, 0 );
// Update footer
$( api.column( 6 ).footer() ).html(
'$'+pageTotal +' ( $'+ total +' total )'
);
// Update footer
$( api.column( 5 ).footer() ).html(
''+canpageTotal +' ( out of '+ cantotal +')'
);
}
});
$("#platinum").click(function() {
$.fn.dataTable.ext.search.pop();
table.draw();
$.fn.dataTable.ext.search.push(
function(settings, data, dataIndex) {
return $(table.row(dataIndex).node()).attr('data-isPlatinum') == 1;
}
);
table.draw();
});
$("#nonplatinum").click(function() {
$.fn.dataTable.ext.search.pop();
table.draw();
$.fn.dataTable.ext.search.push(
function(settings, data, dataIndex) {
return $(table.row(dataIndex).node()).attr('data-isPlatinum') == 0;
}
);
table.draw();
});
$("#all").click(function() {
$.fn.dataTable.ext.search.pop();
table.draw();
});
$('.button').button();
var dateFormat = "mm/dd/yy",
from = $( "#startDate" )
.datepicker({
defaultDate: "+1w",
changeMonth: true,
numberOfMonths: 3
})
.on( "change", function() {
to.datepicker( "option", "minDate", getDate( this ) );
}),
to = $( "#endDate" ).datepicker({
defaultDate: "+1w",
changeMonth: true,
numberOfMonths: 3
})
.on( "change", function() {
from.datepicker( "option", "maxDate", getDate( this ) );
});
function getDate( element ) {
var date;
try {
date = $.datepicker.parseDate( dateFormat, element.value );
} catch( error ) {
date = null;
}
return date;
};
yadcf.init(table, [
{column_number : 0},
{column_number : 1, filter_type: "multi_select",select_type: 'chosen'},
{column_number : 2},
{column_number : 3},
{column_number : 4},
{column_number : 5},
{column_number : 6},
{column_number : 7},
{column_number : 8},
{column_number : 9}
]);
});
</script>
I have tied this
buttons: [
{extend :'excel', text:'Export to Excel'}
,{extend :'pdf' , text:'Export to PDF', orientation: 'landscape', pageSize: 'LEGAL'
,exportOptions:{
rows: ':not(.notPrintable)'
}
}
,'print'
],
...
yadcf.init(table, [
{column_number : 0},
{column_number : 1, filter_type: "multi_select",select_type: 'chosen'},
{column_number : 2},
{column_number : 3},
{column_number : 4},
{column_number : 5},
{column_number : 6},
{column_number : 7},
{column_number : 8}
]);
$(".yadcf-filter-wrapper").addClass("notPrintable");
This is what worked for me
buttons: [
{extend :'excel', text:'Export to Excel'
,exportOptions: {
format: {
header: function ( data, row, column, node ) {
var newdata = data;
newdata = newdata.replace(/<.*?<\/*?>/gi, '');
newdata = newdata.replace(/<div.*?<\/div>/gi, '');
newdata = newdata.replace(/<\/div.*?<\/div>/gi, '');
return newdata;
}
}
}
}
,{extend :'pdf' , text:'Export to PDF'
,exportOptions: {
format: {
header: function ( data, row, column, node ) {
var newdata = data;
newdata = newdata.replace(/<.*?<\/*?>/gi, '');
newdata = newdata.replace(/<div.*?<\/div>/gi, '');
newdata = newdata.replace(/<\/div.*?<\/div>/gi, '');
return newdata;
}
}
}
}
,{extend :'print' , text:'Print'
,exportOptions: {
format: {
header: function ( data, row, column, node ) {
var newdata = data;
newdata = newdata.replace(/<.*?<\/*?>/gi, '');
newdata = newdata.replace(/<div.*?<\/div>/gi, '');
newdata = newdata.replace(/<\/div.*?<\/div>/gi, '');
return newdata;
}
}
}
}
],

Famo.us how to select the surfaces in a scrollView that were not clicked on?

I have a scrollView that contains 5 surfaces. If I click on a surface, I would like the others to be either faded out, z-indexed far behind or translated off the screen. The problem is, I do not know how to implement the selection of the other surfaces.
Famo.us Code:
Famous.Engine = famous.core.Engine;
Famous.Surface = famous.core.Surface;
Famous.RenderNode = famous.core.RenderNode;
Famous.Transform = famous.core.Transform;
Famous.Modifier = famous.core.Modifier;
Famous.EventHandler = famous.core.EventHandler;
Famous.ContainerSurface = famous.surfaces.ContainerSurface;
Famous.ScrollView = famous.views.Scrollview;
Famous.Transitionable = famous.transitions.Transitionable;
Famous.SnapTransition = famous.transitions.SnapTransition;
Famous.Easing = famous.transitions.Easing;
Famous.TransitionableTransform = famous.transitions.TransitionableTransform;
Famous.StateModifier = famous.modifiers.StateModifier;
var projectsList = document.getElementById('projects-list');
var mainContext = Famous.Engine.createContext(projectsList);
var scrollView = new Famous.ScrollView({
direction: 0
});
Famous.Transitionable.registerMethod('snap', Famous.SnapTransition);
var snap = { method: 'snap', period: 600, dampingRatio: 0.6 }
var surfaces = [];
for (var i = 0; i < 5; i++) {
var surface = new Famous.Surface({
size: [undefined, undefined],
properties: {
backgroundColor: "#fff", // "hsl(" + (i * 360 / 40) + ", 100%, 50%)",
textAlign: "center"
}
});
surface.open = false;
surface.state = new Famous.Modifier();
surface.trans = new Famous.Transitionable(500);
surface.state.sizeFrom(function(){
return [this.trans.get(), undefined];
}.bind(surface));
surface.node = new Famous.RenderNode();
surface.node.add(surface.state).add(surface);
surface.pipe(scrollView);
surface.on('click',function(event){
if (this.open) {
this.trans.halt();
this.trans.set(500, snap);
/* place code to reverse the animation that placed the other surfaces off-screen here */
} else {
this.trans.halt();
this.trans.set($(window).width(), snap);
/* how to implement the selection of the other surfaces that were not clicked */
}
this.open = !this.open;
}.bind(surface));
surfaces.push(surface.node);
// sequenceFrom method sets the collection of renderables under the Scrollview instance's control. You can pass array of items or ViewSequence object.
scrollView.sequenceFrom(surfaces);
}
mainContext.add(scrollView);
An example Surface HTML Generated:
<div class="famous-surface" style="background-color: rgb(255, 255, 255); text-align: center; width: 500px; height: 662px; opacity: 0.999999; transform-origin: 0% 0% 0px; transform: matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);">
<div class="surface-content-wrapper">
<div class="container-fluid">
<section class="row project-preview">
<article class="col-lg-12">
<img class="img-responsive" src="/images/project_name_header.png">
<h1>A Surface</h1>
<div class="project-stats">
</article>
</section>
</div>
</div>
</div>
All the surfaces in the scrollView have the same class attributes. So if I click on the first surface, how do I tell famo.us to do something with the remaining four surfaces?
When I click on the specific surface the console logs for this and event.currentTarget are:
this: Surface { _matrix=[16], _opacity=1, _origin=[2], more...}
project...875d127 (line 116)
event: <div class="famous-surface" style="background-color: rgb(255, 255, 255); text-align: center; width: 500px; height: 662px; opacity: 0.999999; transform-origin: 0% 0% 0px; transform: matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);">
You can use the scrollview's backing array directly.
surfaces
Once you get here, you'll have access to the nodes that are in your surfaces array. From there, it's a matter of excluding the surface that was returned as this from the array and interacting with the properties that you placed on your surface object, which you can do using underscore.
_(surfaces).each(function(node) {
surface = node._child;
if (surface != clickedSurface) {
//Do whatever you want to do to the node or surfaces
}
});
Your instinct that you should avoid using the siblings relationship is right. Further, I'd bet that you'd run into same nasty bugs in the future if you tried to manipulate your layout at all. You should stick to your famo.us objects whenever possible.
UPDATE: Please see answer given by #obsidian06 for proper solution.
For now, I'm going with Underscore's each() block that animates the surface's opacity on the click event.
var $otherSurfacesNotClicked = $(event.currentTarget).siblings();
_.each($otherSurfacesNotClicked, function(surface){
console.log("surface in each loop: ", surface);
$(surface).animate({opacity: 0});
});
There's a performance hit on mobile. Most likely the problem is using the jQuery animate(). Need to find the native Famo.us way of performing the same task.

display data in specific areas on google scatter

I have a google scatter graph like this:
<html>
<head>
<script type="text/javascript" src="https://www.google.com/jsapi"></script>
<script type="text/javascript">
google.load("visualization", "1", {packages:["corechart"]});
google.setOnLoadCallback(drawChart);
function drawChart() {
var data = google.visualization.arrayToDataTable([
['Age', 'Weight'],
[ 8, 12],
[ 4, 5.5],
[ 11, 14],
[ 4, 5],
[ 3, 3.5],
[ 6.5, 7]
]);
var options = {
title: 'Age vs. Weight comparison',
hAxis: {title: 'Age', minValue: 0, maxValue: 15},
vAxis: {title: 'Weight', minValue: 0, maxValue: 15},
legend: 'none'
};
var chart = new google.visualization.ScatterChart(document.getElementById('chart_div'));
chart.draw(data, options);
}
</script>
</head>
<body>
<div id="chart_div" style="width: 900px; height: 500px;"></div>
</body>
</html>
I would like when click on a circle, showing only those cycles that are within a radius x from the choosen circle. Any idea??
Thank you!
You need to filter the DataTable to get all of the points within the given radius of the selected point. Here's some code that will do this for you:
google.visualization.events.addListener(chart, 'select', function () {
var selection = chart.getSelection();
if (selection.length > 0) {
// get all data points within radius r of the selected point
var r, x, y;
r = <the radius to use>;
x = data.getValue(selection[0].row, 0);
y = data.getValue(selection[0].row, 1);
var rows = [];
for (var i = 0, count = data.getNumberOfRows(), dx, dy; i < count; i++) {
dx = data.getValue(i, 0) - x;
dy = data.getValue(i, 1) - y;
if (Math.sqrt(dx * dx + dy * dy) <= r) {
rows.push(i);
}
}
// do something with filtered rows
}
});
Here's a proof-of-concept demonstrating how it works: http://jsfiddle.net/asgallant/tgshL/

Gone fishing, because i like it

I have been trying to create Task manager with JavaScript and HTML. I'm quite new to programming, so hopefully someone will help me out with the following issue:
For some reason, the items of the array will not get into the table. Any helpful idea to solve this enigma? All help is appreciated!
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Untitled Document</title>
<script>
window.onload = init;
var descriptionS = new Array();
function init(){
var delBtn = document.getElementById("buttonDel");
delBtn.addEventListener('click', deleteRow, false);
var addTaskBtn = document.getElementById("addTask");
addTaskBtn.addEventListener('click', getTaskData, false);
var displayListBtn = document.getElementById("displayList");
displayListBtn.addEventListener('click', generateList, false);
var sortByNumBtn = document.getElementById("sortByNumber");
sortByNumBtn.addEventListener('click', sortListByNum, false);
}
function getTaskData(){
var myDescription = document.getElementById("descriptionField").value;
var myDate = document.getElementById("dateField").value;
var myPriority = document.getElementById("selRow0").value;
var description = new Object();
description.descriptionData = myDescription;
description.descriptionDate = myDate;
description.descriptionPriority = myPriority;
descriptionS.push(description);
}
function generateList(){
var myTaskList = document.getElementsByTagName("td");
myTaskList.innerHTML ="";
for(var p = 0; p < descriptionS.length; p++){
var tbl = document.getElementById('tblSample');
var lastRow = tbl.rows.length;
// if there's no header row in the table, then iteration = lastRow + 1
var iteration = lastRow;
var row = tbl.insertRow(lastRow);
//Select cell
var cell0 = row.insertCell(0);
var selT = document.createElement("input");
selT.type = 'checkbox';
selT.name = 'chkBox';
selT.id = 'chkBox';
cell0.appendChild(selT);
// ID cell
var cell1 = document.createElement("td");
cell1 = row.insertCell(1);
var idFill = document.createTextNode(iteration);
cell1.appendChild(idFill);
cellSelect.appendChild(cell1);
//Description cell
var cell2 = document.createElement("td");
cell2 = row.insertCell(2);
var elF = document.createTextNode(descriptionS[p].descriptionData);
//elF.innerHTML = document.getElementById("descriptionField").value;
cell2.appendChild(elF);
// Priority cell
var cellPri = document.createElement("td");
cellPri = row.insertCell(3);
var pri = document.getElementbyId('selRow0').value;
pri.name = 'selRow' + iteration;
cellPri.appendChild(pri);
//Date
var cell4 = document.createElement("td");
cell4 = row.insertCell(4);
var elF1 = document.createTextNode(descriptionS[p].descriptionDate);
//elF.innerHTML = document.getElementById("descriptionField").value;
cell4.appendChild(elF1);
// Delete cell
var cell5 = document.createElement("td");
cell5 = row.insertCell(5);
var del1 = document.createElement('input');
del1.type = 'button';
del1.name = 'buttonDel';
del1.id = 'buttonDel';
del1.value = "Delete";
del1.onclick = function () {
var table = document.getElementById("tblSample");
var rowCount = table.rows.length;
for(var i=0; i<rowCount; i++) {
var row = table.rows[i];
var chkbox = row.cells[0].childNodes[0];
if(null != chkbox && true == chkbox.checked) {
table.deleteRow(i);
rowCount--;
i--;
}
}
};
cell5.appendChild(del1);
}
}
function sortListByNum(){
descriptionS.sort(sortFunctionByNumber);
generateList();
}
function sortFunctionByNumber(a, b){
return a.descriptionData-b.descriptionData;
}
function deleteRow(tableID) {
var table = document.getElementById("tblSample");
var rowCount = table.rows.length;
for(var i=0; i<rowCount; i++) {
var row = table.rows[i];
var chkbox = row.cells[0].childNodes[0];
if(null != chkbox && true == chkbox.checked) {
table.deleteRow(i);
rowCount--;
i--;
}
}
}
</script>
</head>
<body>
<form action="">
<p>
Description: <input type="text" id="descriptionField" />
Date: <input type="text" id="dateField" />
Priority: <select name="selRow0" id="selRow0" />
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
</select>
<input type="button" id="addTask" value="Add Task" />
<input type="button" id="displayList" value="Display Task" />
<input type="button" id="sortByNumber" value="Sort" />
</p>
<p>
<span id="spanOutput" style="border: 1px solid #000; padding: 3px;"> </span>
</p>
<table border="1" id="tblSample">
<tr>
<th>Select</th>
<th>ID</th>
<th>Description</th>
<th>Priority</th>
<th>Date</th>
<th>Delete</th>
</tr>
<tr>
<td><INPUT type="checkbox" name="chk"/></td>
<td>1</td>
<td>Example</td>
<td>
<select name="selRow1">
<option value="value1">1</option>
<option value="value2">2</option>
<option value="value3">3</option>
</select>
</td>
<td>06/06/2013</td>
<td>
<input type="button" value="Delete" id="buttonDel" />
</td>
</tr>
</table>
</form>
</body>
</html>
Use ExtJS GridPanel http://docs.sencha.com/ext-js/4-1/#!/example/grid/cell-editing.html
(Click to edit cell)