var modelview_neuron_viewers = [];
var last_right, last_top;
var doc_width = document.width;
function reposition_dialog(id) {
// set next to the last positioned dialog
var me = $('#' + id);
var mep = me.parent();
mep.offset({left: last_right + 10, top: last_top});
// except: drop down if too far to the right
if (mep.offset().left + mep.outerWidth() > doc_width) {
mep.offset({left: 20, top: last_top + 100});
}
last_top = mep.offset().top;
last_right = mep.offset().left + mep.outerWidth();
}
var colorbar_types = [];
var did_sub;
function init_modelview() {
// only call setup modelview if no substitutions to do
// if there are substitutions, process_level_ will recall init_modelview
// when done
did_sub = false;
process_level_(modelview_data.tree);
if (did_sub) {
// if here, then did an include so stop and will be rerun later
return;
}
setup_modelview();
}
var json_parent_obj_, json_index_;
function jsonp_callback_(new_row) {
json_parent_obj_[json_index_] = new_row;
init_modelview();
}
function process_level_(data) {
// returns true if requested a substitution; else false
$.each(data, function(i, row) {
if (row.include != undefined) {
// do substitution via JSONP
json_index_ = i;
json_parent_obj_ = data;
// force including from the internet when testing locally
// TODO: is this always a good idea?
if ((window.location.protocol == 'file:' || window.location.protocol == 'file') && row.include.substr(0, 2) == '//') {
row.include = 'http:' + row.include;
}
$('body').append('<script src="' + row.include + '"></script>');
did_sub = true;
}
if (did_sub) {
return true;
}
if (row.include == undefined && row.children != undefined) {
if (process_level_(row.children)) {
return true;
}
}
});
return false;
}
function setup_modelview() {
if (modelview_data.title != undefined) {
document.title = 'ModelView: ' + modelview_data.title;
} else {
document.title = 'ModelView';
modelview_data.title = 'ModelView';
}
if (modelview_data.short_title == undefined) {
modelview_data.short_title = modelview_data.title;
}
if (modelview_data.colorbars != undefined) {
$.each(modelview_data.colorbars, function(i, colorbar_data) {
colorbar_types.push(colorbar_data.type);
if (colorbar_data.type == 'css') {
DeclareCSSClass('colorbar' + i, colorbar_data.css);
} else {
console.log('unknown colorbar type: ' + colorbar_data.type)
}
});
}
// create a dialog for the tree with no close box
tree_dialog = MakeDialog(modelview_data.short_title, true);
var tree_dialog_handle = $('#' + tree_dialog);
tree_dialog_handle.parent().addClass('no-close');
// generate the tree
AddTree(tree_dialog, modelview_build_tree_(modelview_data.tree));
// start with a fixed initial height for this dialog.
// the user can still resize it, but this prevents it from growing when the
// tree is expanded
var spacing = tree_dialog_handle.parent().height() - tree_dialog_handle.height();
// start at 2/3 of the height. arbitrary.
tree_dialog_handle.parent().height(document.height * 0.66);
tree_dialog_handle.height(tree_dialog_handle.parent().height() - spacing);
// position it somewhere better
tree_dialog_handle.parent().css('top', '1em');
tree_dialog_handle.parent().css('left', '1em');
last_top = tree_dialog_handle.parent().offset().top;
last_right = tree_dialog_handle.parent().offset().left + tree_dialog_handle.parent().outerWidth();
last_positioned_dialog = tree_dialog;
// open all links in new window, based on http://trevordavis.net/blog/use-jquery-to-open-all-external-links-in-a-new-window
$('a').attr('target', '_blank');
// setup the neuron views
if (modelview_data.neuron == undefined) {
modelview_data.neuron = [];
}
if (modelview_data.neuronviewer == undefined) {
modelview_data.neuronviewer = [];
}
$.each(modelview_data.neuronviewer, function(i, neuron_view) {
var neuron_data = modelview_data.neuron[neuron_view];
var new_view_id = MakeNeuronViewer(neuron_data.title, neuron_data.morphology);
seg_names_[new_view_id] = neuron_data.seg_names;
reposition_dialog(new_view_id);
modelview_neuron_viewers.push(new_view_id);
hide_dialog(new_view_id);
});
// flot dialog (TODO: allow many)
flot_dialog = MakeDialog(modelview_data.short_title, true);
$('#' + flot_dialog).parent().addClass('no-close');
counter++;
flot_title = AddComponent(flot_dialog, '<div style="text-align: center;" id=' + counter + '>title</div>');
flot_fig = AddChart(flot_dialog, {contextmenu: false, doplot: false});
plottedFlot['placeholder' + flot_fig] = $.plot($('#placeholder' + flot_fig), []);
$('#' + flot_dialog).resize(function() {
$('#placeholder' + flot_fig).height(max(300, $('#' + flot_dialog).height() - $('#' + flot_title).height() - 50));
plottedFlot['placeholder' + flot_fig].draw();
});
reposition_dialog(flot_dialog);
hide_dialog(flot_dialog);
// svg dialog (TODO: combine with flot dialog(s)?)
svg_dialog = MakeDialog(modelview_data.short_title, true);
$('#' + svg_dialog).parent().addClass('no-close');
reposition_dialog(svg_dialog);
hide_dialog(svg_dialog);
}
function show_flot_(data, title, xaxes, yaxes, hoverable, clickable) {
if (xaxes == undefined || !xaxes.length) xaxes = undefined;
if (yaxes == undefined || !yaxes.length) yaxes = undefined;
if (title == undefined) title = '';
show_dialog(flot_dialog);
$('#' + flot_title)[0].innerHTML = title;
var opts = {zoom: {interactive: true}, pan: {interactive: true}, xaxes: xaxes, yaxes: yaxes};
if (hoverable || clickable) {
opts.grid = {'hoverable': hoverable, 'clickable': clickable};
}
plottedFlot['placeholder' + flot_fig] = $.plot($('#placeholder' + flot_fig), data, opts);
}
function modelview_hide_all_() {
var i, id;
$.each(modelview_neuron_viewers, function (i, id) {
hide_dialog(id);
});
hide_dialog(flot_dialog);
hide_dialog(svg_dialog);
}
function set_colorbar(id, colorbar, orientation, lo, hi) {
var obj = $('#below' + id);
if (colorbar == undefined) {
obj.css('display', 'none');
} else {
if (orientation != 'horizontal') {
console.log('unsupported colorbar orientation: ' + orientation);
} else {
if (colorbar_types[colorbar] != 'css') {
console.log('unsupported colorbar type: ' + colorbar_types[colorbar]);
} else {
obj.html('<div class="colorbar' + colorbar + '"> </div><div><span style="float: left">' + lo + '</span><span style="float: right">' + hi + '</span></div><div style="clear: both;"></div>');
obj.css('display', 'block');
}
}
}
}
function ensure_tooltip(id) {
if (!$('#tooltip' + id).length) {
$('<div id="tooltip' + id + '"></div>').css({
position: 'absolute',
display: 'none',
border: '1px solid #000',
padding: '2px',
'background-color': '#fee',
opacity: 0.8,
zIndex: 10000
}).appendTo('body');
}
}
var flot_highlighted = undefined;
var neuron_highlighted_ = undefined;
var neuron_highlighted_pt_ = undefined;
function clear_neuron_highlight_() {
if (neuron_highlighted_ != undefined) {
neuron_highlighted_.unhighlight(neuron_highlighted_pt_, 0);
neuron_highlighted_ = undefined;
}
}
seg_names_ = {};
function modelview_build_tree_(src_tree) {
var result = [];
var f, i, j;
$.each(src_tree, function (i, row) {
children = undefined;
if (row.children != undefined) {
children = modelview_build_tree_(row.children);
if (children.length == 0) children = undefined;
}
if (row.noop == true) {
f = undefined;
} else {
if (row.action != undefined) {
f = function() {
modelview_hide_all_();
$.each(row.action, function (j, action) {
if (action.kind == 'neuronviewer') {
var id = modelview_neuron_viewers[action.id];
neuron_hoverable_[id] = true;
show_dialog(id);
set_neuron_markers(id, action.markers);
if (action.highlight != undefined) {
set_neuron_highlights(id, action.highlight);
} else {
if (action.colors != undefined) {
while (action.colors.length < neuron_data_[id].length) {
action.colors.push('black');
}
}
set_neuron_colors(id, action.colors);
}
set_colorbar(id, action.colorbar, action.colorbar_orientation, action.colorbar_low, action.colorbar_high);
var placeholder = $('#' + id).children('span')[0].id.replace('flotContainer', 'placeholder');
ensure_tooltip(id);
$('#' + placeholder).bind("plothover", function (event, pos, item) {
if (item) {
var tooltip_text = '';
if (item.seriesIndex < neuron_data_[id].length) {
var pt = neuron_data_[id][item.seriesIndex][item.dataIndex];
if (seg_names_[id] != undefined) {
tooltip_text += seg_names_[id][item.seriesIndex] + '<br/>';
}
tooltip_text += '(' + pt[0].toPrecision(4) + ', ' + pt[1].toPrecision(4) + ', ' + pt[2].toPrecision(4) + ')';
if (action.colored_var != undefined && action.values != undefined) {
if (item.seriesIndex < action.values.length && action.values[item.seriesIndex] != 'nan') {
tooltip_text += '<br/>' + action.colored_var + ' = ' + Number(action.values[item.seriesIndex]).toPrecision(6);
}
}
if (action.hover_text != undefined) {
tooltip_text += '<br/>' + action.hover_text[item.seriesIndex];
}
$('#tooltip' + id).html(tooltip_text).css({left: item.pageX + 5, top: item.pageY + 5}).show();
if (flot_highlighted != undefined) {
plottedFlot['placeholder' + flot_fig].unhighlight(0, flot_highlighted);
flot_highlighted = undefined;
}
if (action.flotindices != undefined) {
flot_highlighted = action.flotindices[item.seriesIndex];
if (flot_highlighted != undefined && flot_highlighted >= 0) {
plottedFlot['placeholder' + flot_fig].highlight(0, flot_highlighted);
}
}
} else if (item.seriesIndex == neuron_data_[id].length) {
// markers!
if (action.marker_mouseovers != undefined) {
tooltip_text += action.marker_mouseovers[item.dataIndex];
}
$('#tooltip' + id).html(tooltip_text).css({left: item.pageX + 5, top: item.pageY + 5}).show();
}
} else {
if (flot_highlighted != undefined) {
plottedFlot['placeholder' + flot_fig].unhighlight(0, flot_highlighted);
flot_highlighted = undefined;
}
$('#tooltip' + id).hide();
}
});
} else if (action.kind == 'flot') {
show_flot_(action.data, action.title, action.xaxes, action.yaxes, action.hoverable, action.clickable);
if (action.hoverable) {
ensure_tooltip(flot_fig);
$('#placeholder' + flot_fig).bind("plothover", function (event, pos, item) {
if (item) {
var tooltip = '(' + item.datapoint[0].toPrecision(4) + ', ' + item.datapoint[1].toPrecision(4) + ')';
// seg_names_[new_view_id] = neuron_data.seg_names;
if (action.neuron_highlight_id != undefined) {
clear_neuron_highlight_();
var id = modelview_neuron_viewers[action.neuron_highlight_id];
var placeholder = $('#' + id).children('span')[0].id.replace('flotContainer', 'placeholder');
plottedFlot[placeholder].highlight(action.neuron_highlight_segs[item.dataIndex], 0);
neuron_highlighted_ = plottedFlot[placeholder];
neuron_highlighted_pt_ = action.neuron_highlight_segs[item.dataIndex];
tooltip = seg_names_[id][item.dataIndex] + '<br/>' + tooltip;
}
$('#tooltip' + flot_fig).html(tooltip).css({left: item.pageX + 5, top: item.pageY + 5}).show();
} else {
clear_neuron_highlight_();
$('#tooltip' + flot_fig).hide();
}
//console.log(item.series);
});
}
} else if (action.kind == 'svg') {
$('#' + svg_dialog).html('<svg xmlns="http://www.w3.org/2000/svg" viewbox="' + action.viewbox + '" style="width:100%; height:100%">' + action.svg + '</svg>');
show_dialog(svg_dialog);
} else {
console.log('ignoring unknown action kind: ' + action.kind);
}
});
}
} else {
f = modelview_hide_all_;
}
}
result.push([row.text, {children: children, callback: f, noop: row.noop}]);
});
return result;
}