phpvirtualbox/panes/tabVMSnapshots.html

856 lines
30 KiB
HTML

<!--
VM Snapshots Pane
Copyright (C) 2010-2015 Ian Moore (imoore76 at yahoo dot com)
$Id: tabVMSnapshots.html 595 2015-04-17 09:50:36Z imoore76 $
-->
<div id='vboxTabVMSnapshots' class='vboxInvisible' style='display: none; width:100%;'>
<table class='vboxInvisible' style='height: 99%; width: 99%'>
<tr style='vertical-align: top; height: 1%'>
<td><div id='vboxSnapshotToolbar'></div></td>
</tr>
<tr style='vertical-align: top;'>
<td><ul style='min-height: 400px' class='vboxBordered vboxTreeView' id='vboxSnapshotList'></ul></td>
</tr>
</table>
<!--
New Snapshot Dialog
-->
<div id='vboxSnapshotNew' class='vboxDialogContent' style='display: none;'>
<table class='vboxVertical'>
<tr style='vertical-align: top'>
<th>
<img id='vboxSnapshotNewImg' src='images/vbox/os_other.png' height='32' width='32' />
</th>
<td>
<div style='height: 100%'>
<div class='translate'>Snapshot Name</div>
<input id='vboxSnapshotNewName' style='width: 100%'/>
<div class='translate'>Snapshot Description</div>
<textarea rows='10' id='vboxSnapshotNewDesc' style='width: 100%;'></textarea>
</div>
</td>
</tr>
</table>
</div>
<!--
Snapshot Details Dialog
-->
<div id='vboxSnapshotDetails' class='vboxDialogContent' style='display: none;'>
<table class='vboxVertical'>
<tr>
<th><span class='translate'>Name:</span></th>
<td style='width:100%'>
<input id='vboxSnapshotDetailsName' style='width: 100%'/>
</td>
<td rowspan='2' id='vboxSnapshotSS' style='width:1%'></td>
</tr>
<tr>
<th><span class='translate'>Taken:</span></th>
<td style='width:100%'>
<span id='vboxSnapshotDetailsTaken'></span>
</td>
</tr>
<tr>
<th><span class='translate'>Description:</span></th>
<td colspan='2'>
<textarea rows='12' id='vboxSnapshotDetailsDesc' name='vboxSnapshotDetailsDescElm'></textarea>
</td>
</tr>
<tr>
<th><span class='translate'>Details:</span></th>
<td class='vboxSnapshotDetailsMachine' colspan='2'>
<div id='vboxSnapshotDetailsVM' style='overflow: auto; height: 100%'></div>
</td>
</tr>
</table>
</div>
<script type='text/javascript'>
vboxInitDisplay('vboxSnapshotNew','VBoxTakeSnapshotDlg');
vboxInitDisplay('vboxSnapshotDetails','VBoxSnapshotDetailsDlg');
var vboxSnapshotButtons = [
{
'name' : 'take_snapshot',
'label' : 'Take Snapshot...',
'language_context': 'UIActionPool',
'icon' : 'snapshot_take',
'enabled' : function(item) {
if(typeof item == 'string') state = item;
else if(item && $(item).data('vboxSnapshot')) state = $(item).data('vboxSnapshot').state;
else return false;
var vm = vboxChooser.getSingleSelected();
return (item && state == 'current' && jQuery.inArray(vm.state, ['RestoringSnapshot','LiveSnapshotting','DeletingSnapshot']) == -1);
},
'click' : function (callback) {
var vm = vboxChooser.getSingleSelected();
$('#vboxSnapshotNewImg').attr('src',"images/vbox/" + vboxGuestOSTypeIcon(vm.OSTypeId));
var snRegEx = new RegExp('^' + trans('Snapshot %1','VBoxSnapshotsWgt').replace('%1','([0-9]+)') + '$');
// Get max snapshot name
var snMax = 0;
var snList = $('#vboxSnapshotList').find('li');
for(var i = 0; i < snList.length; i++) {
var snNum = snRegEx.exec($(snList[i]).data('vboxSnapshot').name);
if(snNum) snMax = Math.max(parseInt(snNum[1]), snMax);
}
$('#vboxSnapshotNewName').val(trans('Snapshot %1','VBoxSnapshotsWgt').replace('%1',(snMax+1)));
$('#vboxSnapshotNewDesc').val('');
var buttons = {};
buttons[trans('OK','QIMessageBox')] = function() {
// Get fresh VM state when this is clicked
var vm = vboxChooser.getSingleSelected();
if(!vm) return;
// Deferred object that will trigger
// taking a snapshot on success
var isPausedOrNotRunning = $.Deferred();
// Take snapshot function when machine is in
// a valid paused or not running state
$.when(isPausedOrNotRunning).done(function(paused) {
var l = new vboxLoader('snapshotTake');
l.add('snapshotTake',function(d){
if(d && d.responseData && d.responseData.progress) {
vboxProgress({'progress':d.responseData.progress,'persist':d.persist},function(pres){
// Unpause machine if it was paused
if(paused) {
vboxAjaxRequest('machineSetState',{'vm':vm.id,'state':'resume'});
}
// If progress operation errored, refresh snapshot list
if(pres && !pres.success)
$.when(vboxAjaxRequest('machineGetSnapshots',{'vm':vm.id})).done(__vboxTabSnapshotsFill);
// callback passed to click()? else Refresh vm list
if(typeof callback == 'function') { callback(pres); }
},'progress_snapshot_create_90px.png', trans('Take a snapshot of the current virtual machine state','VBoxSnapshotsWgt'),
vm.name);
} else {
// Unpause machine if it was paused
if(paused) {
vboxAjaxRequest('machineSetState',{'vm':vm.id,'state':'resume'});
}
if(d && d.error) vboxAlert(d.error);
$.when(vboxAjaxRequest('machineGetSnapshots',{'vm':vm.id})).done(__vboxTabSnapshotsFill);
}
},{'vm':vm.id,'name':$('#vboxSnapshotNewName').val(),'description':$('#vboxSnapshotNewDesc').val()});
l.run();
}).fail(function(){
$.when(vboxAjaxRequest('machineGetSnapshots',{'vm':vm.id})).done(__vboxTabSnapshotsFill);
});
// Set to paused state if VM is running
if(vboxVMStates.isRunning(vm)) {
var pl = new vboxLoader('machineSetStatePaused');
pl.add('machineSetState', function(d) {
if(d && d.success) isPausedOrNotRunning.resolve(true);
else isPausedOrNotRunning.reject();
},{'vm':vm.id,'state':'pause'});
pl.run();
} else {
isPausedOrNotRunning.resolve();
}
$(this).dialog('close');
};
buttons[trans('Cancel','QIMessageBox')] = function() { $(this).dialog('close'); };
$('#vboxSnapshotNew').dialog({'closeOnEscape':false,'width':'400px','height':'auto','buttons':buttons,'modal':true,'autoOpen':true,'dialogClass':'vboxDialogContent','title':'<img src="images/vbox/snapshot_take_16px.png" class="vboxDialogTitleIcon" height="16" width="16" /> ' + trans('Take Snapshot of Virtual Machine','VBoxTakeSnapshotDlg')});
}
},
{
'name' : 'discard_cur_state',
'label' : 'Restore Snapshot',
'icon' : 'snapshot_restore',
'enabled' : function(item) {
var vm = vboxChooser.getSingleSelected();
return ( item && $(item).data('vboxSnapshot') && $(item).data('vboxSnapshot') && $(item).data('vboxSnapshot').name && $(item).data('vboxSnapshot').state != 'current' && !vboxVMStates.isRunning(vm) && !vboxVMStates.isPaused(vm));
},
'click' : function () {
var vm = vboxChooser.getSingleSelected();
var snapshot = $('#vboxSnapshotList').find('div.vboxListItemSelected').first().parent().data('vboxSnapshot');
var buttons = {};
var q = '';
// Check if the current state is modified
if(vm.currentStateModified) {
q = trans("<p>You are about to restore snapshot <nobr><b>%1</b></nobr>.</p>" +
"<p>You can create a snapshot of the current state of the virtual machine first by checking the box below; " +
"if you do not do this the current state will be permanently lost. Do you wish to proceed?</p>",'UIMessageCenter');
q += '<p><label><input type="checkbox" id="vboxRestoreSnapshotCreate" checked /> ' + trans('Create a snapshot of the current machine state','UIMessageCenter') + '</label></p>';
buttons[trans('Restore','UIMessageCenter')] = function() {
var snrestore = function(takeSnapshot){
// Don't do anything if taking a snapshot failed
if(takeSnapshot && !takeSnapshot.success)
return;
var l = new vboxLoader();
l.add('snapshotRestore',function(d){
if(d && d.responseData && d.responseData.progress) {
vboxProgress({'progress':d.responseData.progress,'persist':d.persist},function(){
// Let events get picked up. Nothing to do here
},'progress_snapshot_restore_90px.png',trans('Restore Snapshot','VBoxSnapshotsWgt'),
vm.name);
} else if(d && d.error) {
vboxAlert(d.error);
}
},{'vm':vm.id,'snapshot':snapshot.id});
l.run();
};
if($('#vboxRestoreSnapshotCreate').prop('checked')) {
vboxSnapshotButtons[0].click(snrestore);
} else {
snrestore();
}
$(this).empty().remove();
};
} else {
q = trans('<p>Are you sure you want to restore snapshot <nobr><b>%1</b></nobr>?</p>','UIMessageCenter');
buttons[trans('Restore','UIMessageCenter')] = function() {
var l = new vboxLoader();
l.add('snapshotRestore',function(d){
if(d && d.responseData && d.responseData.progress) {
vboxProgress({'progress':d.responseData.progress,'persist':d.persist},function(){
// Let events get picked up. Nothing to do here
},'progress_snapshot_restore_90px.png',trans('Restore Snapshot','VBoxSnapshotsWgt'),
vm.name);
} else if(d && d.error) {
vboxAlert(d.error);
}
},{'vm':vm.id,'snapshot':snapshot.id});
$(this).empty().remove();
l.run();
};
}
vboxConfirm(q.replace('%1',$('<div />').text(snapshot.name).html()),buttons);
},
'separator' : true
},
{
'name' : 'delete_snapshot',
'label' : 'Delete Snapshot',
'icon' : 'snapshot_delete',
'enabled' : function(item) {
return (item && $(item).data('vboxSnapshot') && $(item).data('vboxSnapshot').name && $(item).data('vboxSnapshot').state != 'current' && $(item).data('vboxSnapshot').children.length <= 1);
},
'click' : function () {
var vm = vboxChooser.getSingleSelected();
var snapshot = $('#vboxSnapshotList').find('div.vboxListItemSelected').first().parent().data('vboxSnapshot');
var buttons = {};
buttons[trans('Delete','UIMessageCenter')] = function() {
var l = new vboxLoader();
l.add('snapshotDelete',function(d){
if(d && d.responseData && d.responseData.progress) {
vboxProgress({'progress':d.responseData.progress,'persist':d.persist},function(){
// Let events get picked up. Nothing to do here
},'progress_snapshot_discard_90px.png',trans('Delete Snapshot','VBoxSnapshotsWgt'),
vm.name + ' - ' + snapshot.name);
}
},{'vm':vm.id,'snapshot':snapshot.id});
$(this).empty().remove();
l.run();
};
vboxConfirm(trans('<p>Deleting the snapshot will cause the state information saved in it to be lost, and '+
'storage data spread over several image files that VirtualBox has created together with the snapshot '+
'will be merged into one file. This can be a lengthy process, and the information in the snapshot cannot '+
'be recovered.</p></p>Are you sure you want to delete the selected snapshot <b>%1</b>?</p>','UIMessageCenter').replace('%1',$('<div />').text(snapshot.name).html()),buttons);
}
},
{
'name' : 'show_snapshot_details',
'label' : 'Show Details',
'icon' : 'snapshot_show_details',
'enabled' : function(item) {
return (item && $(item).data('vboxSnapshot') && $(item).data('vboxSnapshot').name && $(item).data('vboxSnapshot').state != 'current');
},
'click' : function () {
// Current snapshot
var snapshot = $('#vboxSnapshotList').find('div.vboxListItemSelected').first().parent().data('vboxSnapshot');
var vm = vboxChooser.getSingleSelected();
var l = new vboxLoader();
l.add('snapshotGetDetails',function(d){
$('#vboxSnapshotDetailsName').val(d.responseData.name);
$('#vboxSnapshotDetailsTaken').html(vboxDateTimeString(d.responseData.timeStamp));
$('#vboxSnapshotDetailsDesc').val(d.responseData.description);
if(d.responseData.online) {
$('#vboxSnapshotSS').html('<a href="'+ vboxEndpointConfig.screen +'?vm='+vm.id+
'&snapshot='+d.responseData.id+'&full=1" target="_blank"><img src="'+vboxEndpointConfig.screen+'?vm='+
vm.id+'&snapshot='+d.responseData.id+'" /></a>').show();
} else {
$('#vboxSnapshotSS').empty().hide();
}
// Display details
$('#vboxSnapshotDetailsVM').empty();
// Enclosing details Table
var vboxDetailsTable = $('<table />').attr({'class':'vboxDetailsTable'});
// Set to isSnapshot
d.responseData.machine._isSnapshot = true;
for(var i in vboxVMDetailsSections) {
section = vboxVMDetailsSections[i];
if(section.noSnapshot) continue;
$('<tr />').attr({'class':'vboxDetailsHead'}).append(
$('<th />').attr({'class':'vboxDetailsSection','colspan':'2'}).disableSelection()
.html("<img style='float:left; margin-right: 3px; ' src='images/vbox/" + section.icon + "' height='16' width='16' /> ")
.append(
$('<span />').css({'float':'left'}).append(document.createTextNode(trans(section.title, section.language_context) +' '))
)
).appendTo(vboxDetailsTable);
__vboxDetailAddRows(d.responseData.machine, section.rows, vboxDetailsTable);
}
$('#vboxSnapshotDetailsVM').append(vboxDetailsTable);
},{'vm':vm.id,'snapshot':snapshot.id});
l.onLoad = function(){
var buttons = {};
buttons[trans('OK','QIMessageBox')] = function() {
// Current snapshot
var snapshot = $('#vboxSnapshotList').find('div.vboxListItemSelected').first().parent().data('vboxSnapshot');
var l = new vboxLoader();
l.add('snapshotSave',function(d){
// Let events get picked up. Nothing to do here
},{'vm':vm.id,'snapshot':snapshot.id,'name':$('#vboxSnapshotDetailsName').val(),'description':$('#vboxSnapshotDetailsDesc').val()});
$(this).dialog('close');
l.run();
};
buttons[trans('Cancel','QIMessageBox')] = function(){
$(this).dialog('close');
};
$('#vboxSnapshotDetails').dialog({'closeOnEscape':false,'width':'600px','height':'auto','buttons':buttons,'modal':true,'autoOpen':true,'dialogClass':'vboxDialogContent','title':'<img src="images/vbox/snapshot_show_details_16px.png" class="vboxDialogTitleIcon" /> '+trans('Details of %1 (%2)','VBoxSnapshotDetailsDlg').replace('%1',$('<div />').text(snapshot.name).html()).replace('%2',vm.name)});
};
l.run();
}
},
{
'name' : 'clone',
'label' : 'Clone...',
'language_context': 'UIActionPool',
'icon' : 'vm_clone',
'separator' : true,
'enabled' : function(item) {
var vm = vboxChooser.getSingleSelected();
return (item && $(item).data('vboxSnapshot') && $(item).data('vboxSnapshot').name && !vboxVMStates.isPaused(vm) && !vboxVMStates.isRunning(vm));
},
'click' : function () {
var vm = vboxChooser.getSingleSelected();
// Current snapshot
var snapshot = $('#vboxSnapshotList').find('div.vboxListItemSelected').first().parent().data('vboxSnapshot');
new vboxWizardCloneVMDialog({'vm':vm,'snapshot':(snapshot.state == 'current' ? undefined : snapshot)}).run();
}
},
];
/* Append Top Toolbar */
var vboxSnapshotToolbar = new vboxToolbarSmall({buttons: vboxSnapshotButtons, size: 22, language_context: 'VBoxSnapshotsWgt'});
// special case for 'clone' button because it is 16px rather than 22px
vboxSnapshotToolbar.addButtonCSS('clone', {'background-position':'6px 4px'});
vboxSnapshotToolbar.renderTo('vboxSnapshotToolbar');
vboxInitDisplay('vboxSnapshotToolbar','VBoxSnapshotsWgt');
// Context menu for snapshots
var vboxSnapshotContextMenu = new vboxMenu({name:'vboxSnapshotContextMenu', language_context: 'VBoxSnapshotsWgt'});
vboxSnapshotContextMenu.addMenu(vboxSnapshotButtons.slice(-(vboxSnapshotButtons.length-1)));
//Context menu for current state
var vboxSnapshotContextMenuCurrent = new vboxMenu({name: 'vboxSnapshotContextMenuCurrent', language_context: 'VBoxSnapshotsWgt'});
vboxSnapshotContextMenuCurrent.addMenu([vboxSnapshotButtons[0],vboxSnapshotButtons[(vboxSnapshotButtons.length-2)]]);
/* Toolbar and menu updates*/
$('#vboxSnapshotList').on('select',function(e,item) {
// Update toolbar
vboxSnapshotToolbar.update(item);
vboxSnapshotContextMenu.update(item);
vboxSnapshotContextMenuCurrent.update(item);
});
// Hold timer and date vars
vboxSnapshotToolbar._timer = null;
vboxSnapshotToolbar._timeSpans = new Array();
vboxSnapshotToolbar._timeSpans['days'] = 86400;
vboxSnapshotToolbar._timeSpans['hours'] = 3600,
vboxSnapshotToolbar._timeSpans['minutes'] = 60,
vboxSnapshotToolbar._timeSpans['seconds'] = 1;
vboxSnapshotToolbar._timeSpans.sort(function(a,b){return (a > b ? -1 : 1);});
/* Selected VM changed */
$('#vboxPane').on('vmSelectionListChanged',function(){
$('#vboxTabVMSnapshotsTitle').html(trans('Snapshots','UIVMDesktop'));
var vm = vboxChooser.getSingleSelected();
$('#vboxSnapshotList').trigger('select',null);
// Got vm and it's not host
if(vm && vm.id != 'host') {
// Enable tab
$('#vboxTabVMSnapshots').parent().trigger('enableTab', ['vboxTabVMSnapshots']);
$.when(vboxVMDataMediator.getVMDetails(vm.id)).done(function(vm) {
$('#vboxTabVMSnapshotsTitle').html(trans('Snapshots','UIVMDesktop') + (vm && vm.snapshotCount ? trans(' (%1)','VBoxSnapshotsWgt').replace('%1',vm.snapshotCount):''));
});
// Unset last vm
$('#vboxTabVMSnapshots').data('lastVM',0);
// Remove children
$('#vboxSnapshotList').children().empty().remove();
// Fill snapshots if this tab is being shown
if($('#vboxTabVMSnapshots').data('vboxShowing')) {
// Keep track of last VM shown
$('#vboxTabVMSnapshots').data('lastVM',vm.id);
// append spinner
$('#vboxSnapshotList').append($('<li />').attr({'class':'last'}).html("<div><img src='images/spinner.gif'></div>"));
$.when(vboxAjaxRequest('machineGetSnapshots',{'vm':vm.id})).done(__vboxTabSnapshotsFill);
}
// No single selected VM or it is host
} else {
// disable tab
$('#vboxTabVMConsole').parent().trigger('disableTab', ['vboxTabVMSnapshots']);
$('#vboxTabVMSnapshots').data('lastVM',0);
}
/**
*
* VBOX event list triggered
*
*/
}).on('vboxEvents',function(e,eventList) {
var redrawCurrent = false;
for(var i = 0; i < eventList.length; i++) {
switch(eventList[i].eventType) {
//////////////////////////
//
// Snapshot events
//
/////////////////////////
case 'OnSnapshotTaken':
case 'OnSnapshotDeleted':
case 'OnSnapshotRestored':
case 'OnSnapshotChanged':
// Is this vm selected
if(vboxChooser.getSingleSelectedId() == eventList[i].machineId) {
// Update title
$('#vboxTabVMSnapshotsTitle').html(trans('Snapshots','UIVMDesktop') +
(eventList[i].enrichmentData && eventList[i].enrichmentData.snapshotCount ? trans(' (%1)','VBoxSnapshotsWgt').replace('%1',eventList[i].enrichmentData.snapshotCount):''));
// Redraw snapshots if this is shown
if($('#vboxTabVMSnapshots').data('lastVM') == eventList[i].machineId) {
$('#vboxSnapshotList').children().empty().remove();
// Append spinner
$('#vboxSnapshotList').append($('<li />').attr({'class':'last'}).html("<div><img src='images/spinner.gif'></div>"));
$.when(vboxAjaxRequest('machineGetSnapshots',{'vm':eventList[i].machineId})).done(__vboxTabSnapshotsFill);
return;
}
}
break;
/////////////////////////
//
// Session or state change
//
////////////////////////
case 'OnSessionStateChanged':
case 'OnMachineStateChanged':
if($('#vboxTabVMSnapshots').data('lastVM') == eventList[i].machineId && vboxChooser.getSingleSelectedId() == eventList[i].machineId) {
redrawCurrent = true;
}
break;
}
}
// Redraw current snapshot
if(redrawCurrent) {
var vmid = vboxChooser.getSingleSelectedId();
// Get current state and details data
$.when(vboxVMDataMediator.getVMData(vmid), vboxVMDataMediator.getVMDetails(vmid)).done(function(vm, vmd) {
if($('#vboxTabVMSnapshots').data('lastVM') != vm.id) return;
var selected = $('#vboxTabVMSnapshots').find('li.vboxSnapshotCurrentState').children('div.vboxListItemSelected').length;
$('#vboxTabVMSnapshots').find('li.vboxSnapshotCurrentState').replaceWith(__vboxTabSnapshotCurrent($.extend(true,{},vm,vmd)));
if(selected) {
$('#vboxSnapshotList').trigger('select',
$('#vboxTabVMSnapshots').find('li.vboxSnapshotCurrentState').children('div.vboxListItem').addClass('vboxListItemSelected').parent());
}
});
}
});
// Load snapshots on show
$('#vboxTabVMSnapshots').on('show',function(e){
$('#vboxTabVMSnapshots').data('vboxShowing', 1);
var vm = vboxChooser.getSingleSelected();
if(vm && vm.id) {
if($('#vboxTabVMSnapshots').data('lastVM') == vm.id) return;
$('#vboxTabVMSnapshots').data('lastVM', vm.id);
} else {
$('#vboxSnapshotList').children().remove();
$('#vboxTabVMSnapshots').data('lastVM',0);
vboxSnapshotToolbar.disable();
return;
}
// Get snapshots
// Append spinner
$('#vboxSnapshotList').append($('<li />').attr({'class':'last'}).html("<div><img src='images/spinner.gif'></div>"));
$.when(vboxAjaxRequest('machineGetSnapshots',{'vm':vm.id})).done(__vboxTabSnapshotsFill);
}).on('hide',function(e) {
$('#vboxTabVMSnapshots').data('vboxShowing', 0);
});
/*
* Fill Snapshots
*/
function __vboxTabSnapshotsFill(response) {
var snapshotData = response.responseData;
if(vboxSnapshotToolbar._timer) {
window.clearTimeout(vboxSnapshotToolbar._timer);
vboxSnapshotToolbar._timer = null;
}
if(!snapshotData) return;
// Get current state and details data
$.when(vboxVMDataMediator.getVMData(response.responseData.vm), vboxVMDataMediator.getVMDetails(response.responseData.vm)).done(function(vm, vmd) {
if($('#vboxTabVMSnapshots').data('lastVM') != vm.id) return;
var list = $('#vboxSnapshotList');
$(list).children().remove();
var vmc = $.extend(true, {}, vm, vmd);
// Snapshots exist
if(snapshotData.snapshot && snapshotData.snapshot.name) {
// Traverse snapshots
$(list).append(__vboxTabSnapshot(snapshotData.snapshot, snapshotData.currentSnapshotId));
// Append current state to last snapshot
if(snapshotData.currentSnapshotId) {
// Has children
if($('#'+snapshotData.currentSnapshotId).children('ul').first()[0]) {
$('#'+snapshotData.currentSnapshotId).children('ul').last().append(__vboxTabSnapshotCurrent(vmc));
} else {
$('#'+snapshotData.currentSnapshotId).append($('<ul />').append(__vboxTabSnapshotCurrent(vmc)));
};
};
// No snapshots. Append current state to list
} else {
$(list).append(__vboxTabSnapshotCurrent(vmc));
}
// Init vbox tree list
$('#vboxSnapshotList').vbtree();
vboxSnapshotToolbar.enable();
$('#vboxSnapshotList').trigger('select');
__vboxTabSnapshotTimestamps();
});
}
/* Snapshot list item */
function __vboxTabSnapshot(s, currentId) {
var li = $('<li />').attr({'id':s.id});
$(li).data('vboxSnapshot',s);
// Use timestamp
var t = '';
if(s.timeStampSplit['seconds'] == 0)
s.timeStampSplit['seconds'] = 1;
var ago = 0;
var ts = 'seconds';
for(var i in s.timeStampSplit) {
var l = Math.floor(t / s.timeStampSplit[i]);
if(l > 0) {
ago = l;
ts = i;
break;
}
}
switch(ts) {
case 'days':
ts = trans('%n day(s)','VBoxGlobal', ago).replace('%n', ago);
break;
case 'hours':
ts = trans('%n hour(s)', 'VBoxGlobal', ago).replace('%n', ago);
break;
case 'minutes':
ts = trans('%n minute(s)', 'VBoxGlobal', ago).replace('%n', ago);
break;
case 'seconds':
ts = trans('%n second(s)', 'VBoxGlobal', ago).replace('%n', ago);
break;
}
ts = trans(' (%1 ago)','VBoxSnapshotsWgt').replace('%1', ts);
$(li).append(' ').append(
$('<div />').attr({'class':'vboxListItem'})
.html('<img src="images/vbox/snapshot_'+(s.online ? 'online' : 'offline')+'_16px.png" height="16" width="16" /> ' +
$('<div />').text(s.name).html())
.append($('<span />').attr({'class':'timestamp'}).data({'vboxTimestamp':s.timeStamp}).text(ts))
// Context menu
.contextMenu({
menu: vboxSnapshotContextMenu.menuId(),
clickthrough: true
},vboxSnapshotContextMenu.menuClickCallback)
// show details on dblclick
.dblclick(vboxSnapshotButtons[4].click).disableSelection()
// tool tip
.tipped({'position':'mouse','delay':1500,'source':'<p><strong>'+$('<div />').text(s.name).html()+'</strong> ('+trans((s.online ? 'online)' : 'offline)'),'VBoxSnapshotsWgt')+'</p>'+
'<p>'+ vboxDateTimeString(s.timeStamp, trans('Taken at %1','VBoxSnapshotsWgt'), trans('Taken on %1','VBoxSnapshotsWgt'))+'</p>' +
(s.description ? '<hr />' + $('<div />').text(s.description).html() : '')})
).addClass(currentId == s.id ? 'vboxSnapshotCurrent' : '').children('div.vboxListItem').first().click(function(){
$('#vboxSnapshotList').find('div.vboxListItemSelected').first().removeClass('vboxListItemSelected');
$(this).addClass('vboxListItemSelected');
$('#vboxSnapshotList').trigger('select',$(this).parent());
});
if(s.children.length) {
var ul = $('<ul />');
for(var i = 0; i < s.children.length; i++) {
$(ul).append(__vboxTabSnapshot(s.children[i], currentId));
}
$(li).append(ul);
}
return li;
}
/* Current state list item */
function __vboxTabSnapshotCurrent(vm) {
return $('<li />').data('vboxSnapshot',{'state':'current','name':trans((vm.currentStateModified ? 'Current State (changed)' : 'Current State'),'VBoxSnapshotsWgt')}).html(' ')
.addClass('last vboxSnapshotCurrent vboxSnapshotCurrentState')
.append(
$('<div />').attr({'class':'vboxListItem'}).html('<img src="images/vbox/'+vboxMachineStateIcon(vm.state)+'" height="16" width="16" /> ' + $('<div />').text(trans((vm.currentStateModified ? 'Current State (changed)' : 'Current State'),'VBoxSnapshotsWgt')).html())
.contextMenu({
menu: vboxSnapshotContextMenuCurrent.menuId(),
clickthrough : true
},vboxSnapshotContextMenuCurrent.menuClickCallback)
.click(function(){
$('#vboxSnapshotList').find('div.vboxListItemSelected').first().removeClass('vboxListItemSelected');
$(this).addClass('vboxListItemSelected');
$('#vboxSnapshotList').trigger('select',$(this).parent());
})
.tipped({'position':'mouse','delay':1500,'source':'<strong>'+
trans((vm.currentStateModified ? 'Current State (changed)' : 'Current State'),'VBoxSnapshotsWgt') + '</strong><br />'+
trans('%1 since %2','VBoxSnapshotsWgt').replace('%1',trans(vboxVMStates.convert(vm.state),'VBoxGlobal'))
.replace('%2',vboxDateTimeString(vm.lastStateChange))
+ (vm.snapshotCount > 0 ? '<hr />' + (vm.currentStateModified ?
trans('The current state differs from the state stored in the current snapshot','VBoxSnapshotsWgt')
: trans('The current state is identical to the state stored in the current snapshot','VBoxSnapshotsWgt'))
: '')
})
);
}
/* Update snapshot timestamps */
function __vboxTabSnapshotTimestamps() {
// Shorthand
var timeSpans = vboxSnapshotToolbar._timeSpans;
// Keep minimum timestamp
var minTs = 60;
var currentTime = new Date();
currentTime = Math.floor(currentTime.getTime() / 1000);
$('#vboxTabVMSnapshots').find('span.timestamp').each(function(){
var sts = parseInt($(this).data('vboxTimestamp'));
var t = Math.max(currentTime - sts, 1);
minTs = Math.min(minTs,t);
// Check for max age.
if(Math.floor(t / 86400) > 30) {
var sdate = new Date(sts * 1000);
$(this).html(trans(' (%1)','VBoxSnapshotsWgt').replace('%1',sdate.toLocaleString()));
return;
}
var ago = 0;
var ts = 'seconds';
for(var i in timeSpans) {
var l = Math.floor(t / timeSpans[i]);
if(l > 0) {
ago = l;
ts = i;
break;
}
}
switch(ts) {
case 'days':
ts = trans('%n day(s)', 'VBoxGlobal', ago).replace('%n', ago);
break;
case 'hours':
ts = trans('%n hour(s)', 'VBoxGlobal', ago).replace('%n', ago);
break;
case 'minutes':
ts = trans('%n minute(s)', 'VBoxGlobal', ago).replace('%n', ago);
break;
case 'seconds':
ts = trans('%n second(s)', 'VBoxGlobal', ago).replace('%n', ago);
break;
}
$(this).html(ts = trans(' (%1 ago)','VBoxSnapshotsWgt').replace('%1', ts));
});
var timerSet = (minTs >= 60 ? 60 : 10);
vboxSnapshotToolbar._timer = window.setTimeout(__vboxTabSnapshotTimestamps,(timerSet * 1000));
}
</script>
</div>