Files
iTop/js/simple_graph.js
2015-05-26 16:39:51 +00:00

758 lines
27 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// jQuery UI style "widget" for displaying a graph
////////////////////////////////////////////////////////////////////////////////
//
// graph
//
$(function()
{
// the widget definition, where "itop" is the namespace,
// "dashboard" the widget name
$.widget( "itop.simple_graph",
{
// default options
options:
{
align: 'center',
'vertical-align': 'middle',
source_url: null,
sources: {},
excluded: {},
export_as_pdf: null,
page_format: { label: 'Page Format:', values: { A3: 'A3', A4: 'A4', Letter: 'Letter' }, 'default': 'A4'},
page_orientation: { label: 'Page Orientation:', values: { P: 'Portait', L: 'Landscape' }, 'default': 'L' },
labels: {
export_pdf_title: 'PDF Export Options',
cancel: 'Cancel', 'export': 'Export',
title: 'Document Title',
include_list: 'Include the list of objects',
comments: 'Comments',
grouping_threshold: 'Grouping Threshold',
additional_context_info: 'Additional Context Info',
refresh: 'Refresh',
check_all: 'Check All',
uncheck_all: 'Uncheck All',
none_selected: 'None',
nb_selected: '# selected',
},
export_as_document: null,
drill_down: null,
grouping_threshold: 10,
excluded_classes: [],
attachment_obj_class: null,
attachment_obj_key: null,
additional_contexts: [],
context_key: ''
},
// the constructor
_create: function()
{
var me = this;
this.aNodes = [];
this.aEdges = [];
this.fZoom = 1.0;
this.xOffset = 0;
this.yOffset = 0;
this.iTextHeight = 12;
this.oPaper = Raphael(this.element.get(0), this.element.width(), this.element.height());
this.element
.addClass('panel-resized')
.addClass('itop-simple-graph')
.addClass('graph');
this._create_toolkit_menu();
this._build_context_menus();
$(window).bind('resized', function() { var that = me; window.setTimeout(function() { that._on_resize(); }, 50); } );
if (this.options.source_url != null)
{
this.load_from_url(this.options.source_url);
}
},
// called when created, and later when changing options
_refresh: function()
{
this.draw();
},
// events bound via _bind are removed automatically
// revert other modifications here
_destroy: function()
{
var sId = this.element.attr('id');
this.element
.removeClass('itop-simple-graph')
.removeClass('graph');
$('#tk_graph'+sId).remove();
$('#graph_'+sId+'_export_as_pdf').remove();
},
// _setOptions is called with a hash of all options that are changing
_setOptions: function()
{
this._superApply(arguments);
},
// _setOption is called for each individual option that is changing
_setOption: function( key, value )
{
this._superApply(arguments);
},
draw: function()
{
this._updateBBox();
this.auto_scale();
this.oPaper.clear();
for(var k in this.aNodes)
{
this.aNodes[k].aElements = [];
this._draw_node(this.aNodes[k]);
}
for(var k in this.aEdges)
{
this.aEdges[k].aElements = [];
this._draw_edge(this.aEdges[k]);
}
this._make_tooltips();
},
_draw_node: function(oNode)
{
var iWidth = oNode.width;
var iHeight = 32;
var iFontSize = 10;
var xPos = Math.round(oNode.x * this.fZoom + this.xOffset);
var yPos = Math.round(oNode.y * this.fZoom + this.yOffset);
oNode.tx = 0;
oNode.ty = 0;
switch(oNode.shape)
{
case 'disc':
oNode.aElements.push(this.oPaper.circle(xPos, yPos, iWidth*this.fZoom / 2).attr(oNode.disc_attr));
var oText = this.oPaper.text(xPos, yPos, oNode.label);
oNode.text_attr['font-size'] = iFontSize * this.fZoom;
oText.attr(oNode.text_attr);
//oText.transform('s'+this.fZoom);
oNode.aElements.push(oText);
break;
case 'group':
oNode.aElements.push(this.oPaper.circle(xPos, yPos, iWidth*this.fZoom / 2).attr({fill: '#fff', 'stroke-width':0}));
oNode.aElements.push(this.oPaper.circle(xPos, yPos, iWidth*this.fZoom / 2).attr(oNode.disc_attr));
var xIcon = xPos - 18 * this.fZoom;
var yIcon = yPos - 18 * this.fZoom;
oNode.aElements.push(this.oPaper.image(oNode.icon_url, xIcon, yIcon, 16*this.fZoom, 16*this.fZoom).attr(oNode.icon_attr));
oNode.aElements.push(this.oPaper.image(oNode.icon_url, xIcon + 18*this.fZoom, yIcon, 16*this.fZoom, 16*this.fZoom).attr(oNode.icon_attr));
oNode.aElements.push(this.oPaper.image(oNode.icon_url, xIcon + 9*this.fZoom, yIcon + 18*this.fZoom, 16*this.fZoom, 16*this.fZoom).attr(oNode.icon_attr));
var oText = this.oPaper.text(xPos, yPos +2, oNode.label);
oNode.text_attr['font-size'] = iFontSize * this.fZoom;
oText.attr(oNode.text_attr);
//oText.transform('s'+this.fZoom);
var oBB = oText.getBBox();
var dy = iHeight/2*this.fZoom + oBB.height/2;
oText.remove();
oText = this.oPaper.text(xPos, yPos +dy +2, oNode.label);
oText.attr(oNode.text_attr);
//oText.transform('s'+this.fZoom);
oNode.aElements.push(oText);
oNode.aElements.push(this.oPaper.rect( xPos - oBB.width/2 -2, yPos - oBB.height/2 + dy, oBB.width +4, oBB.height).attr({fill: '#fff', stroke: '#fff', opacity: 0.9}));
oText.toFront();
break;
case 'icon':
if(Raphael.svg)
{
// the colorShift plugin works only in SVG
oNode.aElements.push(this.oPaper.image(oNode.icon_url, xPos - iWidth * this.fZoom/2, yPos - iHeight * this.fZoom/2, iWidth*this.fZoom, iHeight*this.fZoom).colorShift('#fff', 1));
}
oNode.aElements.push(this.oPaper.image(oNode.icon_url, xPos - iWidth * this.fZoom/2, yPos - iHeight * this.fZoom/2, iWidth*this.fZoom, iHeight*this.fZoom).attr(oNode.icon_attr));
var idx = 0;
for(var i in oNode.context_icons)
{
var sgn = 2*(idx % 2) -1; // Suite: -1, 1, -1, 1, -1, 1, -1, etc.
var coef = Math.floor((1+idx)/2) * sgn; // Suite: 0, 1, -1, 2, -2, 3, -3, etc.
var alpha = coef*Math.PI/4 - Math.PI/2;
var x = xPos + Math.cos(alpha) * 1.25*iWidth * this.fZoom / 2;
var y = yPos + Math.sin(alpha) * 1.25*iWidth * this.fZoom / 2;
var l = iWidth/3 * this.fZoom;
oNode.aElements.push(this.oPaper.image(oNode.context_icons[i], x - l/2, y - l/2, l , l).attr(oNode.icon_attr));
idx++;
}
var oText = this.oPaper.text( xPos, yPos, oNode.label);
oNode.text_attr['font-size'] = iFontSize * this.fZoom;
oText.attr(oNode.text_attr);
//oText.transform('S'+this.fZoom);
var oBB = oText.getBBox();
var dy = iHeight/2*this.fZoom + oBB.height/2;
oText.remove();
oText = this.oPaper.text( xPos, yPos + dy, oNode.label);
oText.attr(oNode.text_attr);
//oText.transform('S'+this.fZoom);
oNode.aElements.push(oText);
oNode.aElements.push(this.oPaper.rect( xPos - oBB.width/2 -2, yPos - oBB.height/2 + dy, oBB.width +4, oBB.height).attr({fill: '#fff', stroke: '#fff', opacity: 0.9}).toBack());
break;
}
if (oNode.source)
{
oNode.aElements.push(this.oPaper.circle(xPos, yPos, 1.25*iWidth*this.fZoom / 2).attr({stroke: '#c33', 'stroke-width': 3*this.fZoom }).toBack());
}
if (oNode.sink)
{
oNode.aElements.push(this.oPaper.circle(xPos, yPos, 1.25*iWidth*this.fZoom / 2).attr({stroke: '#33c', 'stroke-width': 3*this.fZoom }).toBack());
}
var me = this;
for(k in oNode.aElements)
{
var sNodeId = oNode.id;
$(oNode.aElements[k].node).attr({'data-type': oNode.shape, 'data-id': oNode.id} ).attr('class', 'popupMenuTarget');
oNode.aElements[k].drag(
function(dx, dy, x, y, event) {
clearTimeout($(this.node).data('openTimeoutId'));
me._move(sNodeId, dx, dy, x, y, event);
},
function(x, y, event) {
me._drag_start(sNodeId, x, y, event);
},
function (event) {
me._drag_end(sNodeId, event);
}
);
}
},
_move: function(sNodeId, dx, dy, x, y, event)
{
var origDx = dx / this.fZoom;
var origDy = dy / this.fZoom;
var oNode = this._find_node(sNodeId);
oNode.x = oNode.xOrig + origDx;
oNode.y = oNode.yOrig + origDy;
for(k in oNode.aElements)
{
oNode.aElements[k].transform('t'+(oNode.tx + dx)+', '+(oNode.ty + dy));
for(j in this.aEdges)
{
var oEdge = this.aEdges[j];
if ((oEdge.source_node_id == sNodeId) || (oEdge.sink_node_id == sNodeId))
{
var sPath = this._get_edge_path(oEdge);
oEdge.aElements[0].attr({path: sPath});
}
}
}
},
_drag_start: function(sNodeId, x, y, event)
{
var oNode = this._find_node(sNodeId);
oNode.xOrig = oNode.x;
oNode.yOrig = oNode.y;
},
_drag_end: function(sNodeId, event)
{
var oNode = this._find_node(sNodeId);
oNode.tx += (oNode.x - oNode.xOrig) * this.fZoom;
oNode.ty += (oNode.y - oNode.yOrig) * this.fZoom;
oNode.xOrig = oNode.x;
oNode.yOrig = oNode.y;
this._updateBBox();
},
_updateBBox: function()
{
this.options.xmin = 9999;
this.options.xmax = -9999;
this.options.ymin = 9999;
this.options.ymax = -9999;
for(var k in this.aNodes)
{
this.options.xmin = Math.min(this.aNodes[k].x + this.aNodes[k].tx, this.options.xmin);
this.options.xmax = Math.max(this.aNodes[k].x + this.aNodes[k].tx, this.options.xmax);
this.options.ymin = Math.min(this.aNodes[k].y + this.aNodes[k].ty, this.options.ymin);
this.options.ymax = Math.max(this.aNodes[k].y + this.aNodes[k].ty, this.options.ymax);
}
},
_get_edge_path: function(oEdge)
{
var oStart = this._find_node(oEdge.source_node_id);
var oEnd = this._find_node(oEdge.sink_node_id);
var iArrowSize = 5;
if ((oStart == null) || (oEnd == null)) return '';
var xStart = Math.round(oStart.x * this.fZoom + this.xOffset);
var yStart = Math.round(oStart.y * this.fZoom + this.yOffset);
var xEnd = Math.round(oEnd.x * this.fZoom + this.xOffset);
var yEnd = Math.round(oEnd.y * this.fZoom + this.yOffset);
var sPath = Raphael.format('M{0},{1}L{2},{3}', xStart, yStart, xEnd, yEnd);
var vx = (xEnd - xStart);
var vy = (yEnd - yStart);
var l = Math.sqrt(vx*vx+vy*vy);
vx = vx / l;
vy = vy / l;
var ux = -vy;
var uy = vx;
var lPos = Math.max(l/2, l - 40*this.fZoom);
var xArrow = xStart + vx * lPos;
var yArrow = yStart + vy * lPos;
sPath += Raphael.format('M{0},{1}l{2},{3}M{4},{5}l{6},{7}', xArrow, yArrow, this.fZoom * iArrowSize *(-vx + ux), this.fZoom * iArrowSize *(-vy + uy), xArrow, yArrow, this.fZoom * iArrowSize *(-vx - ux), this.fZoom * iArrowSize *(-vy - uy));
return sPath;
},
_draw_edge: function(oEdge)
{
var fStrokeSize = Math.max(1, 2 * this.fZoom);
var sPath = this._get_edge_path(oEdge);
var oAttr = $.extend(oEdge.attr);
oAttr['stroke-linecap'] = 'round';
oAttr['stroke-width'] = fStrokeSize;
oEdge.aElements.push(this.oPaper.path(sPath).attr(oAttr).toBack());
},
_find_node: function(sId)
{
for(var k in this.aNodes)
{
if (this.aNodes[k].id == sId) return this.aNodes[k];
}
return null;
},
auto_scale: function()
{
var fMaxZoom = 1.5;
var maxHeight = this.element.parent().height();
// Compute the available height
var element = this.element;
this.element.parent().children().each(function() {
if($(this).is(':visible') && !$(this).hasClass('graph') && ($(this).attr('id') != element.attr('id')))
{
maxHeight = maxHeight - $(this).height();
}
});
this.element.height(maxHeight - 20);
iMargin = 10;
xmin = this.options.xmin - iMargin;
xmax = this.options.xmax + iMargin;
ymin = this.options.ymin - iMargin;
ymax = this.options.ymax + iMargin;
var xScale = this.element.width() / (xmax - xmin);
var yScale = this.element.height() / (ymax - ymin + this.iTextHeight);
this.fZoom = Math.min(xScale, yScale, fMaxZoom);
switch(this.options.align)
{
case 'left':
this.xOffset = -xmin * this.fZoom;
break;
case 'right':
this.xOffset = (this.element.width() - (xmax - xmin) * this.fZoom);
break;
case 'center':
this.xOffset = -xmin * this.fZoom + (this.element.width() - (xmax - xmin) * this.fZoom) / 2;
break;
}
switch(this.options['vertical-align'])
{
case 'top':
this.yOffset = -ymin * this.fZoom;
break;
case 'bottom':
this.yOffset = this.element.height() - (ymax + this.iTextHeight) * this.fZoom;
break;
case 'middle':
this.yOffset = -ymin * this.fZoom + (this.element.height() - (ymax - ymin + this.iTextHeight) * this.fZoom) / 2;
break;
}
},
add_node: function(oNode)
{
oNode.aElements = [];
oNode.tx = 0;
oNode.ty = 0;
this.aNodes.push(oNode);
},
add_edge: function(oEdge)
{
oEdge.aElements = [];
this.aEdges.push(oEdge);
},
show_group: function(sGroupId)
{
// Activate the 3rd tab
this.element.closest('.ui-tabs').tabs("option", "active", 2);
// Scroll into view the group
if ($('#'+sGroupId).length > 0)
{
$('#'+sGroupId)[0].scrollIntoView();
}
},
_create_toolkit_menu: function()
{
var sPopupMenuId = 'tk_graph'+this.element.attr('id');
var sHtml = '<div class="graph_config">';
var sId = this.element.attr('id');
sHtml += this.options.labels.grouping_threshold+'&nbsp;<input type="text" name="g" value="'+this.options.grouping_threshold+'" id="'+sId+'_grouping_threshold" size="2">';
if (this.options.additional_contexts.length > 0)
{
sHtml += '&nbsp;'+this.options.labels.additional_context_info+' <select id="'+sId+'_contexts" name="contexts" class="multiselect" multiple size="1">';
for(var k in this.options.additional_contexts)
{
sHtml += '<option value="'+k+'" selected>'+this.options.additional_contexts[k].label+'</option>';
}
sHtml += '</select>'
}
sHtml += '&nbsp;<button type="button" id="'+sId+'_refresh_btn">'+this.options.labels.refresh+'</button>';
sHtml += '<div class="itop_popup toolkit_menu graph" style="font-size: 12px;" id="'+sPopupMenuId+'"><ul><li><img src="../images/toolkit_menu.png"><ul>';
if (this.options.export_as_pdf != null)
{
sHtml += '<li><a href="#" id="'+sPopupMenuId+'_pdf">'+this.options.export_as_pdf.label+'</a></li>';
}
if (this.options.export_as_attachment != null)
{
sHtml += '<li><a href="#" id="'+sPopupMenuId+'_attachment">'+this.options.export_as_attachment.label+'</a></li>';
}
//sHtml += '<li><a href="#" id="'+sPopupMenuId+'_reload">Refresh</a></li>';
sHtml += '</ul></li></ul></div>';
sHtml += '</div>';
this.element.before(sHtml);
$('#'+sPopupMenuId+'>ul').popupmenu();
var me = this;
$('#'+sPopupMenuId+'_pdf').click(function() { me.export_as_pdf(); });
$('#'+sPopupMenuId+'_attachment').click(function() { me.export_as_attachment(); });
$('#'+sId+'_grouping_threshold').spinner({ min: 2});
$('#'+sId+'_contexts').multiselect({header: true, checkAllText: this.options.labels.check_all, uncheckAllText: this.options.labels.uncheck_all, noneSelectedText: this.options.labels.none_selected, selectedText: this.options.labels.nb_selected, selectedList: 1});
$('#'+sId+'_refresh_btn').button().click(function() { me.reload(); });
},
_build_context_menus: function()
{
var sId = this.element.attr('id');
var me = this;
$.contextMenu({
selector: '#'+sId+' .popupMenuTarget',
build: function(trigger, e) {
// this callback is executed every time the menu is to be shown
// its results are destroyed every time the menu is hidden
// e is the original contextmenu event, containing e.pageX and e.pageY (amongst other data)
var sType = trigger.attr('data-type');
var sNodeId = trigger.attr('data-id');
var oNode = me._find_node(sNodeId);
clearTimeout(trigger.data('openTimeoutId'));
/*
var sObjName = trigger.attr('data-class');
var sIndex = trigger.attr('data-index');
var originalEvent = e;
var bHasItems = false;
*/
var oResult = {callback: null, items: {}};
switch(sType)
{
case 'group':
var sGroupIndex = oNode.group_index;
if( $('#relation_group_'+sGroupIndex).length > 0)
{
oResult = {
callback: function(key, options) {
var me = $('.itop-simple-graph').data('itopSimple_graph'); // need a live value
me.show_group('relation_group_'+sGroupIndex);
},
items: { 'show': {name: me.options.drill_down.label } }
};
}
break;
case 'icon':
var sObjClass = oNode.obj_class;
var sObjKey = oNode.obj_key;
oResult = {
callback: function(key, options) {
var me = $('.itop-simple-graph').data('itopSimple_graph'); // need a live value
var sURL = me.options.drill_down.url.replace('%1$s', sObjClass).replace('%2$s', sObjKey);
window.location.href = sURL;
},
items: { 'details': {name: me.options.drill_down.label } }
};
break;
default:
oResult = false; // No context menu
}
return oResult;
}
});
},
export_as_pdf: function()
{
this._export_dlg(this.options.labels.export_pdf_title, this.options.export_as_pdf.url, 'download_pdf');
},
_export_dlg: function(sTitle, sSubmitUrl, sOperation)
{
var sId = this.element.attr('id');
var me = this;
var oPositions = {};
for(k in this.aNodes)
{
oPositions[this.aNodes[k].id] = {x: this.aNodes[k].x, y: this.aNodes[k].y };
}
var sHtmlForm = '<div id="GraphExportDlg'+this.element.attr('id')+'"><form id="graph_'+this.element.attr('id')+'_export_dlg" target="_blank" action="'+sSubmitUrl+'" method="post">';
sHtmlForm += '<input type="hidden" name="g" value="'+this.options.grouping_threshold+'">';
sHtmlForm += '<input type="hidden" name="context_key" value="'+this.options.context_key+'">';
$('#'+sId+'_contexts').multiselect('getChecked').each(function() {
sHtmlForm += '<input type="hidden" name="contexts['+$(this).val()+']" value="'+me.options.additional_contexts[$(this).val()].oql+'">';
});
sHtmlForm += '<input type="hidden" name="positions" value="">';
for(k in this.options.excluded_classes)
{
sHtmlForm += '<input type="hidden" name="excluded_classes[]" value="'+this.options.excluded_classes[k]+'">';
}
for(var k1 in this.options.sources)
{
for(var k2 in this.options.sources[k1])
{
sHtmlForm += '<input type="hidden" name="sources['+k1+'][]" value="'+this.options.sources[k1][k2]+'">';
}
}
for(var k1 in this.options.excluded)
{
for(var k2 in this.options.excluded[k1])
{
sHtmlForm += '<input type="hidden" name="excluded['+k1+'][]" value="'+this.options.excluded[k1][k2]+'">';
}
}
if (sOperation == 'attachment')
{
sHtmlForm += '<input type="hidden" name="obj_class" value="'+this.options.export_as_attachment.obj_class+'">';
sHtmlForm += '<input type="hidden" name="obj_key" value="'+this.options.export_as_attachment.obj_key+'">';
}
sHtmlForm += '<table>';
sHtmlForm += '<tr><td>'+this.options.page_format.label+'</td><td><select name="p">';
for(k in this.options.page_format.values)
{
var sSelected = (k == this.options.page_format['default']) ? ' selected' : '';
sHtmlForm += '<option value="'+k+'"'+sSelected+'>'+this.options.page_format.values[k]+'</option>';
}
sHtmlForm += '</select></td></tr>';
sHtmlForm += '<tr><td>'+this.options.page_orientation.label+'</td><td><select name="o">';
for(k in this.options.page_orientation.values)
{
var sSelected = (k == this.options.page_orientation['default']) ? ' selected' : '';
sHtmlForm += '<option value="'+k+'"'+sSelected+'>'+this.options.page_orientation.values[k]+'</option>';
}
sHtmlForm += '</select></td></tr>';
sHtmlForm += '<tr><td>'+this.options.labels.title+'</td><td><input name="title" value="'+this.options.labels.untitled+'" style="width: 20em;"/></td></tr>';
sHtmlForm += '<tr><td>'+this.options.labels.comments+'</td><td><textarea style="width: 20em; height:5em;" name="comments"/></textarea></td></tr>';
sHtmlForm += '<tr><td colspan=2><input type="checkbox" checked id="include_list_checkbox" name="include_list" value="1"><label for="include_list_checkbox">&nbsp;'+this.options.labels.include_list+'</label></td></tr>';
sHtmlForm += '<table>';
sHtmlForm += '</form></div>';
$('body').append(sHtmlForm);
$('#graph_'+this.element.attr('id')+'_export_dlg input[name="positions"]').val(JSON.stringify(oPositions));
var me = this;
if (sOperation == 'attachment')
{
$('#GraphExportDlg'+this.element.attr('id')+' form').submit(function() { return me._on_export_as_attachment(); });
}
$('#GraphExportDlg'+this.element.attr('id')).dialog({
width: 'auto',
modal: true,
title: sTitle,
close: function() { $(this).remove(); },
buttons: [
{text: this.options.labels['cancel'], click: function() { $(this).dialog('close');} },
{text: this.options.labels['export'], click: function() { $('#graph_'+me.element.attr('id')+'_export_dlg').submit(); $(this).dialog('close');} },
]
});
},
_on_resize: function()
{
this.element.closest('.ui-tabs').tabs({ heightStyle: "fill" });
this.auto_scale();
this.oPaper.setSize(this.element.width(), this.element.height());
this.draw();
},
load: function(oData)
{
this.aNodes = [];
this.aEdges = [];
for(k in oData.nodes)
{
this.add_node(oData.nodes[k]);
}
for(k in oData.edges)
{
this.add_edge(oData.edges[k]);
}
this._updateBBox();
this.auto_scale();
this.oPaper.setSize(this.element.width(), this.element.height());
this.draw();
},
load_from_url: function(sUrl)
{
this.options.load_from_url = sUrl;
var me = this;
var sId = this.element.attr('id');
this.options.grouping_threshold = $('#'+sId+'_grouping_threshold').val();
if (this.options.grouping_threshold < 2)
{
this.options.grouping_threshold = 2;
$('#'+sId+'_grouping_threshold').val(this.options.grouping_threshold);
}
var aContexts = [];
$('#'+sId+'_contexts').multiselect('getChecked').each(function() { aContexts[$(this).val()] = me.options.additional_contexts[$(this).val()].oql; });
this.element.closest('.ui-tabs').tabs({ heightStyle: "fill" });
this._close_all_tooltips();
this.oPaper.rect(0, 0, this.element.width(), this.element.height()).attr({fill: '#000', opacity: 0.4, 'stroke-width': 0});
$.post(sUrl, {excluded_classes: this.options.excluded_classes, g: this.options.grouping_threshold, sources: this.options.sources, excluded: this.options.excluded, contexts: aContexts, context_key: this.options.context_key }, function(data) {
me.load(data);
}, 'json');
},
export_as_attachment: function()
{
this._export_dlg(this.options.labels.export_as_attachment_title, this.options.export_as_attachment.url, 'attachment');
},
_on_export_as_attachment: function()
{
var oParams = {};
var oPositions = {};
var jForm = $('#GraphExportDlg'+this.element.attr('id')+' form');
for(k in this.aNodes)
{
oPositions[this.aNodes[k].id] = {x: this.aNodes[k].x, y: this.aNodes[k].y };
}
oParams.positions = JSON.stringify(oPositions);
oParams.sources = this.options.sources;
oParams.excluded_classes = this.options.excluded_classes;
oParams.title = jForm.find(':input[name="title"]').val();
oParams.comments = jForm.find(':input[name="comments"]').val();
oParams.include_list = jForm.find(':input[name="include_list"]:checked').length;
oParams.o = jForm.find(':input[name="o"]').val();
oParams.p = jForm.find(':input[name="p"]').val();
oParams.obj_class = this.options.export_as_attachment.obj_class;
oParams.obj_key = this.options.export_as_attachment.obj_key;
oParams.contexts = [];
var me = this;
$('#'+this.element.attr('id')+'_contexts').multiselect('getChecked').each(function() {
oParams.contexts[$(this).val()] = me.options.additional_contexts[$(this).val()].oql;
});
oParams.context_key = this.options.context_key;
var sUrl = jForm.attr('action');
var sTitle = oParams.title;
var jPanel = $('#attachments').closest('.ui-tabs-panel');
var jTab = null;
var sTabText = null;
if (jPanel.length > 0)
{
var sTabId = jPanel.attr('id');
jTab = $('li[aria-controls='+sTabId+']');
sTabText = jTab.find('span').html();
jTab.find('span').html(sTabText+' <img style="vertical-align:bottom" src="../images/indicator.gif">');
}
$.post(sUrl, oParams, function(data) {
var sDownloadLink = GetAbsoluteUrlAppRoot()+'pages/ajax.render.php?operation=download_document&class=Attachment&id='+data.att_id+'&field=contents';
var sIcon = GetAbsoluteUrlModulesRoot()+'itop-attachments/icons/pdf.png';
$('#attachments').append('<div class="attachment" id="display_attachment_'+data.att_id+'"><a data-preview="false" href="'+sDownloadLink+'"><img src="'+sIcon+'"><br/>'+sTitle+'.pdf<input id="attachment_'+data.att_id+'" type="hidden" name="attachments[]" value="'+data.att_id+'"/></a><br/><input type="button" class="btn_hidden" value="{$sDeleteBtn}" onClick="RemoveAttachment('+data.att_id+');"/></div>');
if (jTab != null)
{
var re = /^([^(]+)\(([0-9]+)\)(.*)$/;
var aParts = re.exec(sTabText);
var iPrevCount = parseInt(aParts[2], 10);
jTab.find('span').html(aParts[1]+'('+(1 + iPrevCount)+')'+aParts[3]);
}
}, 'json');
return false;
},
reload: function()
{
this.load_from_url(this.options.load_from_url);
},
_make_tooltips: function()
{
var me = this;
$( ".popupMenuTarget" ).tooltip({
content: function() {
var sDataId = $(this).attr('data-id');
var sTooltipContent = '<div class="tooltip-close-button" data-id="'+sDataId+'" style="display:inline-block; float:right; cursor:pointer; padding-left:0.25em;">×</div>';
sTooltipContent += me._get_tooltip_content(sDataId);
return sTooltipContent;
},
items: '.popupMenuTarget',
position: {
my: "center bottom-10",
at: "center top",
using: function( position, feedback ) {
$(this).css( position );
$( "<div>" )
.addClass( "arrow" )
.addClass( feedback.vertical )
.addClass( feedback.horizontal )
.appendTo( this );
}
}
})
.off( "mouseover mouseout" )
.on( "mouseover", function(event){
event.stopImmediatePropagation();
var jMe = $(this);
$(this).data('openTimeoutId', setTimeout(function() {
var sDataId = jMe.attr('data-id');
if ($('.tooltip-close-button[data-id="'+sDataId+'"]').length == 0)
{
jMe.tooltip('open');
}
}, 500));
})
.on( "mouseout", function(event){
event.stopImmediatePropagation();
clearTimeout($(this).data('openTimeoutId'));
});
/* Happens at every on_drag_end !!!
.on( "click", function(){
var sDataId = $(this).attr('data-id');
if ($('.tooltip-close-button[data-id="'+sDataId+'"]').length == 0)
{
$(this).tooltip( 'open' );
}
else
{
$(this).tooltip( 'close' );
}
$( this ).unbind( "mouseleave" );
return false;
});
*/
$('body').on('click', '.tooltip-close-button', function() {
var sDataId = $(this).attr('data-id');
$('.popupMenuTarget[data-id="'+sDataId+'"]').tooltip('close');
});
},
_get_tooltip_content: function(sNodeId)
{
var oNode = this._find_node(sNodeId);
if (oNode !== null)
{
return oNode.tooltip;
}
return '<p>Node Id:'+sNodeId+'</p>';
},
_close_all_tooltips: function()
{
this.element.find('.popupMenuTarget').tooltip('close');
}
});
});