summaryrefslogtreecommitdiffstats
path: root/js/chooser.js
diff options
context:
space:
mode:
authorTudor Holton <tudor@tudorholton.com>2018-07-13 17:36:48 +1000
committerTudor Holton <tudor@tudorholton.com>2018-07-13 17:36:48 +1000
commit3c61d5eae51e27082945f629d0076edf0c309f96 (patch)
tree01146078eecd1a0fc610ae225192debed7925999 /js/chooser.js
parent013a2e172f2a3bf5cb739dda2c120306918a35d7 (diff)
downloadphpvirtualbox-3c61d5eae51e27082945f629d0076edf0c309f96.zip
phpvirtualbox-3c61d5eae51e27082945f629d0076edf0c309f96.tar.gz
phpvirtualbox-3c61d5eae51e27082945f629d0076edf0c309f96.tar.bz2
Convert from DOS to UNIX format. Update changelog for release.
Diffstat (limited to 'js/chooser.js')
-rw-r--r--js/chooser.js4900
1 files changed, 2450 insertions, 2450 deletions
diff --git a/js/chooser.js b/js/chooser.js
index 41f24bc..1bfa27b 100644
--- a/js/chooser.js
+++ b/js/chooser.js
@@ -1,2451 +1,2451 @@
-/**
- *
- * @fileOverview Chooser (vm list) singleton. Provides vboxChooser
- * @author Ian Moore (imoore76 at yahoo dot com)
- * @version $Id: chooser.js 591 2015-04-11 22:40:47Z imoore76 $
- * @copyright Copyright (C) 2010-2015 Ian Moore (imoore76 at yahoo dot com)
- *
- */
-
-/**
- * Chooser selection mode constants
- */
-var vboxSelectionModeNone = 0;
-var vboxSelectionModeSingleVM = 1;
-var vboxSelectionModeMultiVM = 2;
-var vboxSelectionModeSingleGroup = 3;
-
-
-/**
- * @namespace vboxChooser
- *
- * Draws machine selection chooser and controls selection list
- * @see js/eventlistener.js
- */
-var vboxChooser = {
-
- // VM list
- vms : {},
-
- // VM tool tip
- _vmToolTip : '<nobr>%1<br></nobr><nobr>%2 since %3</nobr><br><nobr>Session %4</nobr>',
-
- // Anchor element
- _anchorid : null,
- _anchor : null,
-
- /* Internal list of all unique selected items */
- _selectedList : [],
-
- /* List of unique selected VMs */
- selectedVMs : [],
-
- /* Holds group definitions */
- _groupDefs : [],
-
- /* selection mode can be
-
- var vboxSelectionModeNone = 0,
- var vboxSelectionModeSingleVM = 1,
- var vboxSelectionModeMultiVM = 2,
- var vboxSelectionModeSingleGroup = 3,
- */
- selectionMode : vboxSelectionModeNone,
-
- /* Check phpVirtualBox version and VirtualBox
- * version compatibility.
- */
- _versionChecked : false,
-
- /* Some items are not editable while vmGroup
- * definitions are being written
- */
- _editable : true,
-
- /* Context menus */
- _vmContextMenuObj : null,
- _vmGroupContextMenuObj : null,
-
- /* Holds history of showing only single groups */
- _showOnlyGroupHistory : [],
-
- /* Group definition extra value key */
- _groupDefinitionKey : '',
-
- /* Whether chooser is in compact mode or not */
- _compact : false,
-
- /**
- * Set anchor id to draw to
- */
- setAnchorId : function(aid) {
- vboxChooser._anchorid = aid;
- vboxChooser._anchor = $('#'+aid);
-
- vboxChooser._anchor.html("<div id='vboxChooserSpinner' style='text-align: center'><div><img src='images/spinner.gif' /></div></div>");
-
- vboxChooser._anchor.hover(function(){
- $(this).addClass('vboxChooserDropTargetHoverRoot');
- },function() {
- $(this).removeClass('vboxChooserDropTargetHoverRoot');
- });
-
- $(window).resize(function(){
-
- // Get anchor id and add / remove class
- var w = parseInt($(vboxChooser._anchor).innerWidth());
- if(w < 120) {
- $(vboxChooser._anchor).addClass('vboxChooserMini');
- vboxChooser._compact = true;
- } else {
- $(vboxChooser._anchor).removeClass('vboxChooserMini');
- vboxChooser._compact = false;
- }
-
- vboxChooser._resizeElements(true);
-
- });
- },
-
- /**
- * Set context menus
- *
- */
- setContextMenu : function(target, menuitems) {
-
- switch(target) {
-
- // Group menu
- case 'group':
- vboxChooser._vmGroupContextMenuObj = new vboxMenu({'name': vboxChooser._anchorid+'vmgroups',
- 'menuItems': menuitems,
- 'language_context': 'UIActionPool'});
- vboxChooser._vmGroupContextMenuObj.update();
- break;
-
- // VM Menu
- case 'vm':
- vboxChooser._vmContextMenuObj = new vboxMenu({'name': vboxChooser._anchorid+'vms',
- 'menuItems': menuitems,
- 'language_context': 'UIActionPool'});
- vboxChooser._vmContextMenuObj.update();
- break;
-
- // Main list menu
- case 'anchor':
-
- var vboxChooserPaneMenu = new vboxMenu({'name': vboxChooser._anchorid+'Pane',
- 'menuItems': menuitems,
- 'language_context': 'UIActionPool'});
- $('#'+vboxChooser._anchorid).parent().contextMenu({
- menu: vboxChooserPaneMenu.menuId()
- },
- vboxChooserPaneMenu.menuClickCallback
- );
-
- break;
-
- default:
- vboxAlert('vboxChooser::setContextMenu: unknown context menu type (' + target + ')');
- }
- },
-
- /*
- * Return true if a selected VM is in the given state
- */
- isSelectedInState : function(state) {
-
- for(var i = 0; i < vboxChooser.selectedVMs.length; i++) {
- if(vboxVMStates['is'+state](vboxVMDataMediator.getVMData(vboxChooser.selectedVMs[i])))
- return true;
- }
- return false;
-
- },
-
- /**
- * Return true if the passed VM is selected
- */
- isVMSelected : function(vmid) {
- return (jQuery.inArray(vmid,vboxChooser.selectedVMs) > -1);
- },
-
- /**
- * Return selected VM data in array
- */
- getSelectedVMsData : function() {
-
- var vms = [];
- for(var i = 0; i < vboxChooser.selectedVMs.length; i++) {
- vms[vms.length] = vboxVMDataMediator.getVMData(vboxChooser.selectedVMs[i]);
- }
- return vms;
- },
-
- /**
- * Triggered when selection list has changed
- */
- selectionListChanged : function(selectionList) {
-
- if(!selectionList) selectionList = [];
-
- selectionMode = vboxSelectionModeNone;
-
- // Hold unique selected VMs
- var vmListUnique = {};
- for(var i = 0; i < selectionList.length; i++) {
- if(selectionList[i].type == 'group') {
- vboxChooser.getGroupElement(selectionList[i].groupPath, true).find('table.vboxChooserVM:not(.ui-draggable-dragging)').each(function(idx,elm){
- if(elm) {
- var vmid = $(elm).data('vmid');
- if(vmid)
- vmListUnique[vmid] = vmid;
- }
- });
- switch(selectionMode) {
- case vboxSelectionModeSingleGroup:
- case vboxSelectionModeSingleVM:
- selectionMode = vboxSelectionModeMultiVM;
- break;
- case vboxSelectionModeNone:
- selectionMode = vboxSelectionModeSingleGroup;
- }
- } else {
- switch(selectionMode) {
- case vboxSelectionModeNone:
- selectionMode = vboxSelectionModeSingleVM;
- break;
- default:
- selectionMode = vboxSelectionModeMultiVM;
- }
-
- vmListUnique[selectionList[i].id] = selectionList[i].id;
- }
- }
-
- // Change selection list
- var selectedVMs = [];
- for(var i in vmListUnique) {
- selectedVMs[selectedVMs.length] = i;
- }
-
- vboxChooser.selectedVMs = selectedVMs;
-
- // If there is only one unique vm selected,
- // selection mode becomes single VM if the
- // current selection mode is not singleGroup
- if(vboxChooser.selectedVMs.length == 1 && selectionMode != vboxSelectionModeSingleGroup)
- selectionMode = vboxSelectionModeSingleVM;
-
- vboxChooser.selectionMode = selectionMode;
-
- vboxChooser._selectedList = selectionList;
-
- $('#vboxPane').trigger('vmSelectionListChanged',[vboxChooser]);
-
-
- },
-
- /**
- * Return the single selected VM's id if
- * only one vm is selected. Else null.
- */
- getSingleSelectedId : function() {
- if(vboxChooser.selectedVMs.length == 1) {
- return vboxChooser.selectedVMs[0];
- }
- return null;
- },
-
- /*
- * Return a single vm if only one is selected.
- * Else null.
- */
- getSingleSelected : function() {
- if(vboxChooser.selectedVMs.length == 1) {
- return vboxVMDataMediator.getVMData(vboxChooser.selectedVMs[0]);
- }
- return null;
- },
-
- /*
- * Update list of VMs from data received
- * from ajax query
- */
- updateList : function(vmlist) {
-
- // We were stopped before the request returned data
- if(!vboxChooser._running) return;
-
-
- // No list? Something is wrong
- if(!vmlist) {
-
- phpVirtualBoxFailure();
-
- vboxChooser.stop();
- vboxChooser._anchor.children().remove();
- return;
- }
-
- // Remove spinner
- vboxChooser._anchor.children().remove();
-
- // Render host
- vboxChooser._anchor.append(vboxChooser.vmHTML(
- {
- 'id':'host',
- 'state':'Hosting',
- 'owner':'',
- 'name':$('#vboxPane').data('vboxConfig').name,
- 'OSTypeId':'VirtualBox_Host'
- }
- ));
-
- // Render root group
- vboxChooser._anchor.append(vboxChooser.groupHTML("/"));
-
- // Enforce VM ownership
- if($('#vboxPane').data('vboxConfig').enforceVMOwnership && !$('#vboxPane').data('vboxSession').admin) {
- vmlist = jQuery.grep(vmlist,function(vm,i){
- return (vm.owner == $('#vboxPane').data('vboxSession').user);
- });
- }
-
- var groups = [];
- // Each item in list
- for(var i = 0; i < vmlist.length; i++) {
- // Update
- vboxChooser.updateVMElement(vmlist[i], true);
- groups = groups.concat(vmlist[i].groups);
- }
-
- // Sort groups
- var groupsSorted = {};
- for(var i = 0; i < groups.length; i++) {
- if(groupsSorted[groups[i]]) continue;
- groupsSorted[groups[i]] = true;
- var gElm = vboxChooser.getGroupElement(groups[i], true);
- if(gElm[0]) vboxChooser.sortGroup(gElm);
- }
-
- // compose group definitions
- vboxChooser.composeGroupDef();
-
- // Set initial resize
- vboxChooser._initialResize = true;
- vboxChooser._resizeElements(true);
-
- },
-
- /*
- * Save collapsed group list
- */
- _collapsedGroups : [],
- _saveCollapsedGroups : function(){
-
- // Write out collapsed group list
- var cGroupList = [];
- vboxChooser._anchor.find('div.vboxVMGroupCollapsed:not(.ui-draggable-dragging)').each(function(idx,elm) {
- cGroupList[cGroupList.length] = $(elm).data('vmGroupPath');
- });
-
- var groupListKey = $('#vboxPane').data('vboxConfig').key+'-collapsedGroups';
- vboxSetLocalDataItem(groupListKey, cGroupList.join(','), true);
-
- // Cache instead of using local storage
- vboxChooser._collapsedGroups = cGroupList;
- },
-
- /*
- * Return true if group is collapsed
- */
- _isGroupCollapsed : function(gpath) {
- return(jQuery.inArray(gpath,vboxChooser._collapsedGroups) > -1);
- },
-
- /*
- * Resize group and VM titles
- */
- _scrollbarWidth : 0,
- _scrollbarWasVisible: false,
- _initialResize: false,
- _resizeElements : function(forceResize) {
-
- // Haven't completed our initial resizing yet
- if(!vboxChooser._initialResize) {
- return;
- }
-
- var sbVisible = (vboxChooser._anchor.get(0).scrollHeight > vboxChooser._anchor.height());
-
- // Nothing changed since resize
- if(!forceResize && (sbVisible == vboxChooser._scrollbarWasVisible)) {
- return;
- }
-
- vboxChooser._scrollbarWasVisible = sbVisible;
-
- var groupTitleWidth = vboxChooser._anchor.width() - (vboxChooser._compact ? 22 : 32) - (sbVisible ? vboxChooser._scrollbarWidth : 0);
- var vmTitleWidth = groupTitleWidth - (vboxChooser._compact ? -12 : 18); // (2px padding on .vboxChooserGroupVMs +
- // 2px border on table + 4px margin on icon) * 2
- var groupLevelOffset = (vboxChooser._compact ? 8 : 8); // (2px margin + 2px border) * 2
-
-
- // Now that we have sizes, we can inject styles
- $('#vboxChooserStyle').empty().remove();
-
- var styleRules = [];
- var path = ['div.vboxChooserGroupRootLevel'];
-
- // Special case for root level VM list
- styleRules[styleRules.length] = 'div.vboxChooserGroupRootLevel > div.vboxChooserGroupVMs table.vboxChooserVM div.vboxFitToContainer { width: ' + vmTitleWidth + 'px; }';
-
- // Special case for group header when only showing one group
- styleRules[styleRules.length] = 'div.vboxChooserGroupShowOnly.vboxChooserGroupRootLevel > div.vboxChooserGroupHeader span.vboxChooserGroupName { max-width: ' + (groupTitleWidth - 4) + 'px; }';
-
- // Bottom group resize bars
- styleRules[styleRules.length] = 'div.vboxChooserGroupRootLevel > div.vboxChooserDropTargetBottom { width: ' + (groupTitleWidth) + 30 + 'px; }';
-
- for(var i = 1; i < 11; i++) {
-
- // Group titles at this level
- styleRules[styleRules.length] = path.join(' > ') + ' > div.vboxChooserGroup > div.vboxChooserGroupHeader span.vboxChooserGroupName { max-width: ' + (groupTitleWidth - (i*groupLevelOffset)) + 'px; }';
-
- // VM titles at this level
- styleRules[styleRules.length] = path.join(' > ') + ' > div.vboxChooserGroup > div.vboxChooserGroupVMs table.vboxChooserVM div.vboxFitToContainer { width: ' + (vmTitleWidth - (i*(groupLevelOffset))) + 'px; }';
-
- // Bottom group resize bars
- styleRules[styleRules.length] = path.join(' > ') +' > div.vboxChooserGroup > div.vboxChooserDropTargetBottom { width: ' + (groupTitleWidth + 30 - (i*groupLevelOffset)) + 'px; }';
-
- path[path.length] = 'div.vboxChooserGroup';
- }
-
- // Style for minified vmlist
- if(vboxChooser._compact) {
- // Title moves left
- styleRules[styleRules.length] = 'div.vboxChooserGroup > div.vboxChooserGroupVMs table.vboxChooserVM div.vboxVMName { position: relative; left: -20px; }';
- // Icon moves down
- styleRules[styleRules.length] = 'div.vboxChooserGroup > div.vboxChooserGroupVMs table.vboxChooserVM img.vboxVMIcon { position: relative; top: 8px; }';
- // State text goes away
- styleRules[styleRules.length] = 'div.vboxChooserGroup > div.vboxChooserGroupVMs table.vboxChooserVM span.vboxVMState { display: none; }';
- // Less padding
- styleRules[styleRules.length] = 'div.vboxChooserGroup > div.vboxChooserGroupVMs table.vboxChooserVM td { padding: 0px; }';
- // Some group header items and drop targets go away
- styleRules[styleRules.length] = 'div.vboxChooserGroup > div.vboxChooserGroupHeader > .vboxChooserGroupNameArrowCollapse, #' +vboxChooser._anchorid + ' div.vboxChooserGroup .vboxChooserDropTarget { display: none; }';
- styleRules[styleRules.length] = 'div.vboxChooserGroup { overflow: hidden; }';
- // host
- styleRules[styleRules.length] = '#vboxChooserVMHost .vboxVMState { display: none; }';
- // group header
- styleRules[styleRules.length] = 'div.vboxChooserGroup div.vboxChooserGroupHeader { height: auto; padding: 2px; }';
-
- }
- $('head').append('<style type="text/css" id="vboxChooserStyle">#'+vboxChooser._anchorid + ' ' + styleRules.join("\n#"+vboxChooser._anchorid + " ") + '</style>');
-
- },
-
- /*
- * Get group element by path
- */
- getGroupElement : function(gpath, noCreate) {
-
- if(!gpath) gpath = '/';
- var gnames = gpath.split('/');
- var groot = vboxChooser._anchor.children('div.vboxChooserGroup:not(.ui-draggable-dragging)');
- for(var i = 1; i < gnames.length; i++) {
-
- if(!gnames[i]) continue;
-
- var group = groot.children('div.vboxChooserGroup:not(.ui-draggable-dragging)').children('div.vboxChooserGroupIdentifier[title="'+gnames[i]+'"]').parent();
-
- // If it does not exist, create it
- if(!group[0]) {
-
- if(noCreate) return null;
-
- var gpath = '/';
- for(var a = 1; a <= i; a++) {
- gpath = gpath + '/' + gnames[a];
- }
- gpath = gpath.replace('//','/');
-
- vboxChooser.groupHTML(gpath).insertBefore(groot.children('div.vboxChooserGroupVMs'));
-
- vboxChooser.sortGroup(groot);
-
- // Resize chooser elements
- vboxChooser._initialResize = true;
- vboxChooser._resizeElements();
-
- groot = groot.children('div.vboxChooserGroup:not(.ui-draggable-dragging)').children('div.vboxChooserGroupIdentifier[title="'+gnames[i]+'"]').parent();
-
- } else {
- groot = group;
- }
-
- }
- return groot;
- },
-
- /*
- *
- * Update VM elements
- *
- */
- updateVMElement : function(vmUpdate, newVM) {
-
- // Not running.. don't do anything
- if(!vboxChooser._running) return;
-
- // Stale event after vm was removed
- if(!vmUpdate) return;
-
- // New VM
- if(newVM) {
-
- // New VM.. add it to groups..
- if(!vmUpdate.groups || vmUpdate.groups.length == 0)
- vmUpdate.groups = ['/'];
-
- for(var i = 0; i < vmUpdate.groups.length; i++) {
- var gElm = $(vboxChooser.getGroupElement(vmUpdate.groups[i]));
- vboxChooser.vmHTML(vmUpdate).appendTo(
- gElm.children('div.vboxChooserGroupVMs')
- );
- }
-
- // Existing VM. Replace existing elements
- } else {
-
- $('#'+vboxChooser._anchorid).find('table.vboxChooserItem-'+vboxChooser._anchorid+'-'+vmUpdate.id).each(function(i,elm){
-
- var newHTML = vboxChooser.vmHTML(vmUpdate);
- if($(elm).hasClass('vboxListItemSelected')) {
- $(newHTML).addClass('vboxListItemSelected').removeClass('vboxHover');
- }
- $(elm).children().replaceWith(newHTML.children());
- });
-
- }
-
- },
-
-
- /*
- * Returns true if there are VMs with ID vmid that are not selected
- */
- vmHasUnselectedCopy : function (vmid) {
- return ($(vboxChooser._anchor).find('table.vboxChooserItem-'+vboxChooser._anchorid+'-'+vmid+':not(.vboxListItemSelected)').length > 0);
- },
-
- /*
- * Remove selected VMs from the list and rewrite group definitions
- * this assumes that there are other copies of these VMs that are not
- * selected.
- */
- removeVMs : function(vmids) {
-
- for(var i = 0; i < vmids.length; i++) {
- $(vboxChooser._anchor).find('table.vboxChooserItem-'+vboxChooser._anchorid+'-'+vmids[i]+'.vboxListItemSelected').remove();
- }
-
- // Update selection list
- vboxChooser._selectedList = vboxChooser._selectedList.filter(function(v){
- return (v.type == 'group' || (jQuery.inArray(v.id, vmids) == -1));
- });
-
- // Tell interface that selection list has changed
- vboxChooser.selectionListChanged(vboxChooser._selectedList);
-
- // compose and save group definitions
- vboxChooser.composeGroupDef(true);
-
-
- // Possible resize needed
- vboxChooser._resizeElements(true);
-
- },
-
- /*
- * Generate HTML from VM definition
- */
- vmHTML : function (vmn) {
-
- var tbl = $('<table />').attr({'class':'vboxChooserItem-'+vboxChooser._anchorid+'-'+vmn.id + " vboxChooserVM"})
- .on('mousedown',vboxChooser.selectItem)
- .hoverClass('vboxHover').data('vmid',vmn.id);
-
-
- // Drag-and-drop functionality
- /////////////////////////////////
- if(vmn.id != 'host' && $('#vboxPane').data('vboxSession').admin) {
-
- $(tbl).draggable({'cursorAt':{left: -10, top: -10},'helper':function(){
- return $(this).clone().css({'width':($(this).width()+2)+'px','display':'inline','background':'#fff','border-color':'#69f'}).removeClass('vboxHover');
-
- // drag start
- },'start':function(e) {
-
- if(!vboxChooser._editable) return false;
-
- $(vboxChooser._anchor).disableSelection();
- vboxChooser._dragging = vmn.id;
- $(vboxChooser._anchor).find('table.vboxHover').removeClass('vboxHover');
-
- // drag stop
- },'stop':function(e) {
- vboxChooser.vmDropped(e, $(this));
- }});
- }
-
- // Functionality to drop above / below VM
- /////////////////////////////////////////////
- var td = $('<td />').attr({'colspan':'2'}).addClass('vboxChooserDropTarget vboxDropTargetTop');
- if(vmn.id != 'host') {
- td.hover(function(){
- if(vboxChooser._dragging && vboxChooser._dragging != vmn.id)
- $(this).addClass('vboxChooserDropTargetHover');
- },function(){
- $(this).removeClass('vboxChooserDropTargetHover');
- }
- );
- }
- $('<tr />').append(td).appendTo(tbl);
-
-
-
- // VM OS type icon
- var tr = $('<tr />');
- if($('#vboxPane').data('vboxConfig').enableCustomIcons && vmn.customIcon) {
- $('<td />').attr({'rowspan':'2'}).html("<img src='" + vmn.customIcon + "' class='vboxVMIcon' />").appendTo(tr);
- } else {
- $('<td />').attr({'rowspan':'2'}).html("<img src='images/vbox/" + vboxGuestOSTypeIcon(vmn.OSTypeId) + "' class='vboxVMIcon" + (vmn.id == 'host' ? " vboxHostIcon" : "") + "' />").appendTo(tr);
- }
-
-
- // VM Name
- var td = $('<td />').attr({'class':'vboxVMTitle'});
-
- // Host will have HTML in name and unique id
- if(vmn.id == 'host') {
-
- $(tbl).attr('id', 'vboxChooserVMHost');
-
- // Check for multiple server config
- if($('#vboxPane').data('vboxConfig').servers.length) {
-
- // If there are multiple servers configured, setup menu
- if(!$('#vboxServerMenu')[0]) {
- var servers = $('#vboxPane').data('vboxConfig').servers;
- var ul = $('<ul />').attr({'id':'vboxServerMenu','style':'display: none','class':'contextMenu'});
- for(var i = 0; i < servers.length; i++) {
- $('<li />').html("<a href='#" + $('<div />').html(servers[i].name).text() + "' style='background-image: url(images/vbox/OSE/VirtualBox_16px.png);'>"+$('<div />').html(servers[i].name).text()+"</a>").appendTo(ul);
- }
- $('#vboxPane').append(ul);
- }
-
- var span = $('<span />').attr({'class':'vboxServerLink'}).text('('+$('#vboxPane').data('vboxConfig').name+')').contextMenu({
- menu: 'vboxServerMenu',
- button: 0,
- mode: 'menu'
- },
- function(a) {
-
- if(a == $('#vboxPane').data('vboxConfig').name) return;
-
- // Show loading screen
- var l = new vboxLoader();
- l.showLoading();
-
- // Empty selection list
- vboxChooser.selectionListChanged();
-
-
- // Unsubscribe from events
- $.when(vboxEventListener.stop()).done(function() {
-
- // Expire data mediator data
- vboxVMDataMediator.expireAll();
-
- // Trigger host change
- vboxSetCookie("vboxServer",a);
- $('#vboxPane').trigger('hostChange',[a]);
-
- }).always(function(){
-
- // remove loading screen
- l.removeLoading();
-
- });
-
-
- }
- );
- $(td).html('<span class="vboxVMName">VirtualBox</span> ').append(span);
- } else {
- $(td).html('<span class="vboxVMName">VirtualBox</span> ('+vmn.name+')');
- }
-
- // Not rendering host
- } else {
-
- $(td).append('<div class="vboxFitToContainer vboxVMName"><span class="vboxVMName">'+$('<span />').text(vmn.name).html()+'</span>'+ (vmn.currentSnapshotName ? '<span class="vboxVMChooserSnapshotName"> (' + $('<span />').text(vmn.currentSnapshotName).html() + ')</span>' : '')+'</div>');
-
-
- // Table gets tool tips
- tip = trans(vboxChooser._vmToolTip, 'UIVMListView').replace('%1',('<b>'+$('<span />')
- .text(vmn.name).html()+'</b>'+(vmn.currentSnapshotName ? ' (' + $('<span />')
- .text(vmn.currentSnapshotName).html() + ')' : '')))
- .replace('%2',trans(vboxVMStates.convert(vmn.state),'VBoxGlobal'))
- .replace('%3',vboxDateTimeString(vmn.lastStateChange))
- .replace('%4',trans(vmn.sessionState,'VBoxGlobal').toLowerCase());
-
- $(tbl).tipped({'source':tip,'position':'mouse','delay':1500});
- }
-
- $(tr).append(td).appendTo(tbl);
-
- // VM state row
- var tr = $('<tr />');
- var td = $('<td />').attr({'class':(vmn.id != 'host' && vmn.sessionState != 'Unlocked' ? 'vboxVMSessionOpen' : '')});
-
- // Add VirtualBox version if hosting
- if(vmn.id == 'host') {
-
- $(td).html("<div class='vboxFitToContainer vboxVMState'><img src='images/vbox/" + vboxMachineStateIcon(vmn.state) +"' /><span class='vboxVMState'>" + trans(vboxVMStates.convert(vmn.state),'VBoxGlobal') + ' - ' + $('#vboxPane').data('vboxConfig').version.string+'</span></div>');
-
- // Check for version mismatches?
- if(!vboxChooser._versionChecked) {
- vboxChooser._versionChecked = true;
- var vStr = $('#vboxPane').data('vboxConfig').phpvboxver.substring(0,$('#vboxPane').data('vboxConfig').phpvboxver.indexOf('-'));
- var vers = $('#vboxPane').data('vboxConfig').version.string.replace('_OSE','').split('.');
- if(vers[0]+'.'+vers[1] != vStr) {
- vboxAlert('This version of phpVirtualBox ('+$('#vboxPane').data('vboxConfig').phpvboxver+') is incompatible with VirtualBox ' + $('#vboxPane').data('vboxConfig').version.string + ". You probably need to <a href='http://sourceforge.net/projects/phpvirtualbox/files/' target=_blank>download the latest phpVirtualBox " + vers[0]+'.'+vers[1] + "-x</a>.<p>See the Versioning section below the file list in the link for more information</p>",{'width':'auto'});
- }
- }
- } else {
- $(td).html("<div class='vboxFitToContainer vboxVMState'><img src='images/vbox/" + vboxMachineStateIcon(vmn.state) +"' /><span class='vboxVMState'>" + trans(vboxVMStates.convert(vmn.state),'VBoxGlobal') + '</span></div>');
- }
-
- $(tr).append(td).appendTo(tbl);
-
- // Droppable targets
- var td = $('<td />').attr({'colspan':'2'}).addClass('vboxChooserDropTarget vboxDropTargetBottom');
- if(vmn.id != 'host') {
- td.hover(function(){
- if(vboxChooser._dragging && vboxChooser._dragging != vmn.id)
- $(this).addClass('vboxChooserDropTargetHover');
- },function(){
- $(this).removeClass('vboxChooserDropTargetHover');
- }
- );
- }
- $('<tr />').addClass('vboxChooserDropTarget').css({'height':'4px'}).append(td).appendTo(tbl);
-
-
- // Context menus?
- if(vboxChooser._vmContextMenuObj) {
-
- $(tbl).contextMenu({
- menu: vboxChooser._vmContextMenuObj.menuId(),
- menusetup : function(el) {
- if(!$(el).hasClass('vboxListItemSelected')) $(el).trigger('click');
- }
- },function(act,el,pos,d,e){
- vboxChooser._vmContextMenuObj.menuClickCallback(act);
- });
-
- // Open settings on dblclick
- $(tbl).dblclick(function(){
- if(vboxChooser._vmContextMenuObj.menuItems['settings'].enabled())
- vboxChooser._vmContextMenuObj.menuItems['settings'].click();
- });
- }
-
- return tbl;
-
- },
-
-
- /*
- * VM Group Dropped
- */
- vmGroupDropped : function(e, droppedGroup) {
-
-
- $(vboxChooser._anchor).enableSelection();
-
-
- var vmGroupPath = vboxChooser._draggingGroup;
- vboxChooser._draggingGroup = false;
- $(droppedGroup).removeClass('vboxHover');
-
- if(!vboxChooser._editable) return false;
-
- // Cannot drag a group that contains a VM without
- // an unlocked session state if it will modify VM
- // Groups
- var sessionLocked = false;
- if($(droppedGroup).find('td.vboxVMSessionOpen')[0])
- sessionLocked=true;
-
-
- // Check for above/below group first
- var dropTarget = vboxChooser._anchor.find('div.vboxChooserDropTargetHover').first();
- if(dropTarget[0]) {
-
- // Make sure that this wasn't dropped onto a sub-group or itself
- if(
- !dropTarget.closest('div.vboxChooserGroup')[0]
- ||
- vmGroupPath == dropTarget.closest('div.vboxChooserGroup').data('vmGroupPath')
- ||
- dropTarget.closest('div.vboxChooserGroup').data('vmGroupPath').indexOf(vmGroupPath + '/') == 0
- ) {
- return;
- }
-
-
- // If we are not still in the same group, check for name conflict
- var currParentGroupPath = $(droppedGroup).closest('div.vboxChooserGroup').parent().closest('div.vboxChooserGroup').data('vmGroupPath');
-
- if(dropTarget.closest('div.vboxChooserGroup').parent().closest('div.vboxChooserGroup').data('vmGroupPath') != currParentGroupPath) {
-
- // Do not allow to be dragged into another group
- // if there is a Vm with a locked session in this one
- if(sessionLocked && !$('#vboxPane').data('vboxConfig')['phpVboxGroups']) return;
-
- // Make sure there are no conflicts
- var groupName = $(droppedGroup).children('div.vboxChooserGroupIdentifier').attr('title');
- var newGroupName = groupName;
-
-
- var i = 2;
- while(vboxChooser.groupNameConflicts(dropTarget.closest('div.vboxChooserGroup').parent(), newGroupName)) {
- newGroupName = groupName + ' (' + (i++) + ')';
- }
-
- $(droppedGroup).children('div.vboxChooserGroupIdentifier').attr({'title':newGroupName})
- .siblings('div.vboxChooserGroupHeader')
- .children('span.vboxChooserGroupName').text(newGroupName);
-
- }
-
- // Insert before or insert after?
- if(dropTarget.hasClass('vboxDropTargetTop')) {
- $(droppedGroup).detach().insertBefore(dropTarget.closest('div.vboxChooserGroup'));
- } else {
- $(droppedGroup).detach().insertAfter(dropTarget.closest('div.vboxChooserGroup'));
- }
-
-
- // Dropped onto a group or main VM list
- } else {
-
- // Will not do this if this group contains
- // a VM with a locked session
- if(sessionLocked && !$('#vboxPane').data('vboxConfig')['phpVboxGroups']) return;
-
- var dropTarget = vboxChooser._anchor.find('div.vboxHover').first();
-
-
- // Dropped onto a group
- if(dropTarget[0] && dropTarget.parent().hasClass('vboxChooserGroup')) {
-
- dropTarget = dropTarget.parent();
-
- // Make sure that this wasn't dropped onto a sub-group or itself
- if(
- vmGroupPath == dropTarget.data('vmGroupPath')
- ||
- dropTarget.closest('div.vboxChooserGroup').data('vmGroupPath').indexOf(vmGroupPath + '/') == 0
- ) {
- return;
- }
-
- // Dropped onto main vm list
- } else if($(vboxChooser._anchor).find('div.vboxGroupHover').length == 0 && $(vboxChooser._anchor).hasClass('vboxChooserDropTargetHoverRoot')) {
-
- dropTarget = null;
-
- // Only showing one group?
- if(vboxChooser._showOnlyGroupHistory.length > 0) {
- dropTarget = $(vboxChooser._showOnlyGroupHistory[vboxChooser._showOnlyGroupHistory.length-1]);
- }
-
- if(!$(dropTarget)[0])
- dropTarget = vboxChooser._anchor.children('div.vboxChooserGroup');
-
- } else {
- return;
- }
-
- // Make sure there are no conflicts
- var newElm = $(droppedGroup).detach();
- var groupName = $(droppedGroup).children('div.vboxChooserGroupIdentifier').attr('title');
- var newGroupName = groupName;
-
- var i = 2;
- while(vboxChooser.groupNameConflicts(dropTarget, newGroupName, $(newElm).data('vmGroupPath'))) {
- newGroupName = groupName + ' (' + (i++) + ')';
- }
-
- $(newElm)
- .children('div.vboxChooserGroupIdentifier').attr({'title':newGroupName})
- .siblings('div.vboxChooserGroupHeader')
- .children('span.vboxChooserGroupName').text(newGroupName);
- $(newElm).insertBefore(dropTarget.children('div.vboxChooserGroupVMs'));
-
- }
-
- // vmGroup dropped - compose and save group definitions
- vboxChooser.composeGroupDef(true);
-
- // Hide group info
- vboxChooser._anchor.find('div.vboxChooserGroupHeader').trigger('mouseout');
-
- // Resize chooser elements
- vboxChooser._resizeElements();
-
- vboxChooser.selectionListChanged(vboxChooser._selectedList);
-
- },
-
- /*
- * VM dropped
- */
- vmDropped : function (e, droppedVM){
-
-
- $(vboxChooser._anchor).enableSelection();
- vboxChooser._dragging = null;
-
- if(!vboxChooser._editable) return false;
-
- // Cannot drag if this VM's session is not open
- var thisSessionLocked = false;
- var vmData = vboxVMDataMediator.getVMData($(droppedVM).data('vmid'));
-
- if(vmData.sessionState != 'Unlocked')
- thisSessionLocked = true;
-
-
-
- // Where was this dropped?
- var dropTarget = $('#'+vboxChooser._anchorid).find('td.vboxChooserDropTargetHover');
-
- // Dropped above / below a VM
- if(dropTarget[0]) {
-
- // Dropped from another group into this one,
- // but this group already has this VM
- if((dropTarget.closest('table').closest('div.vboxChooserGroup').data('vmGroupPath') != $(droppedVM).closest('div.vboxChooserGroup').data('vmGroupPath'))
- && dropTarget.closest('table').siblings('table.vboxChooserItem-'+vboxChooser._anchorid+'-'+$(droppedVM).data('vmid'))[0]) {
- return true;
- }
-
- // If session of this VM is locked, don't allow it to be
- // dragged out of current group
- if(thisSessionLocked && !$('#vboxPane').data('vboxConfig')['phpVboxGroups'] && ($(droppedVM).closest('div.vboxChooserGroup').data('vmGroupPath') != dropTarget.closest('div.vboxChooserGroup').data('vmGroupPath'))) {
- return
- }
-
- // Get VM from target's parent table
- if(dropTarget.hasClass('vboxDropTargetTop')) {
- if(!e.ctrlKey && !e.metaKey) {
- $(droppedVM).detach().insertBefore($(dropTarget).closest('table'));
- } else {
- // Copy
- if($(dropTarget).closest('table').parent().children('table.vboxChooserItem-'+vboxChooser._anchorid+'-'+vmData.id)[0])
- return;
- vboxChooser.vmHTML(vmData).insertBefore($(dropTarget).closest('table'));
- }
- } else {
- if(!e.ctrlKey && !e.metaKey) {
- $(droppedVM).detach().insertAfter($(dropTarget).closest('table'));
- } else {
- // Copy - Don't allow if it already exists
- if($(dropTarget).closest('table').parent().children('table.vboxChooserItem-'+vboxChooser._anchorid+'-'+vmData.id)[0])
- return;
- vboxChooser.vmHTML(vmData).insertAfter($(dropTarget).closest('table'));
- }
- }
-
- // Not dropped above / below vm
- } else {
-
- // Don't allow this if sessoin is locked
- if(thisSessionLocked && !$('#vboxPane').data('vboxConfig')['phpVboxGroups']) return;
-
- // Dropped ON a vm?
- dropTarget = $('#'+vboxChooser._anchorid).find('table.vboxHover:not(.ui-draggable-dragging)').first();
- if($(dropTarget).data('vmid')) {
-
- // Create a group?
- dropTarget = $('#'+vboxChooser._anchorid).find('table.vboxHover').first();
-
- // Nothing to do. Not dropped on valid target
- if(!dropTarget[0] || ($(dropTarget).data('vmid') == $(droppedVM).data('vmid'))) return true;
-
- // Dont' allow this if target VM's session is locked
- if($(dropTarget).find('td.vboxVMSessionOpen')[0])
- return;
-
- // Where to drop vboxChooser..
- var p = dropTarget.closest('div.vboxChooserGroup').children('div.vboxChooserGroupVMs');
- // assume root?
- if(!p[0]) p = vboxChooser._anchor.children('div.vboxChooserGroupVMs');
-
- // Determine group name
- var gname = trans('New group','UIGChooserModel');
- var tgname = gname;
-
- var i = 2;
- while(vboxChooser.groupNameConflicts($(p).parent(), tgname)) {
- tgname = gname + ' ' + (i++);
- }
-
-
- // New position is below target
- var ghtml = vboxChooser.groupHTML(String(dropTarget.closest('div.vboxChooserGroup').data('vmGroupPath')+'/'+tgname).replace('//','/'));
-
- if(!e.ctrlKey && !e.metaKey) {
- ghtml.children('div.vboxChooserGroupVMs').append($(droppedVM).detach());
- } else {
- ghtml.children('div.vboxChooserGroupVMs').append(vboxChooser.vmHTML(vmData));
- }
- ghtml.children('div.vboxChooserGroupVMs').append(dropTarget.detach());
-
- ghtml.insertBefore(p);
-
- // Dropped in the main VM list or group header?
- } else {
-
- dropTarget = $(vboxChooser._anchor).find('div.vboxHover').first();
- if(dropTarget[0] && dropTarget.hasClass('vboxChooserGroupHeader')) {
-
- // Group already has this dragging VM?
- if(dropTarget.siblings('div.vboxChooserGroupVMs').children('table.vboxChooserItem-'+vboxChooser._anchorid+'-'+$(droppedVM).data('vmid'))[0]) {
- return;
- }
-
- if(!e.ctrlKey && !e.metaKey)
- $(droppedVM).detach().appendTo(dropTarget.siblings('div.vboxChooserGroupVMs').first());
- else
- vboxChooser.vmHTML(vmData).appendTo(dropTarget.siblings('div.vboxChooserGroupVMs').first());
-
- // Main VM list
- } else if($(vboxChooser._anchor).find('div.vboxGroupHover').length == 0 && $(vboxChooser._anchor).hasClass('vboxChooserDropTargetHoverRoot')) {
-
- dropTarget = null;
-
- // Only showing one group?
- if(vboxChooser._showOnlyGroupHistory.length > 0) {
- dropTarget = $(vboxChooser._showOnlyGroupHistory[vboxChooser._showOnlyGroupHistory.length-1]);
- }
-
- if(!$(dropTarget)[0])
- dropTarget = vboxChooser._anchor.children('div.vboxChooserGroup');
-
- // Already in this list?
- if(dropTarget.children('div.vboxChooserGroupVMs').children('table.vboxChooserItem-'+vboxChooser._anchorid+'-'+$(droppedVM).data('vmid'))[0]) {
- return true;
- }
-
- if(!e.ctrlKey && !e.metaKey) {
- $(droppedVM).detach().appendTo(dropTarget.children('div.vboxChooserGroupVMs').first());
- } else {
- vboxChooser.vmHTML(vmData).appendTo(dropTarget.children('div.vboxChooserGroupVMs').first());
- }
-
- }
- }
-
- }
-
- // vm dropped - compose and save group definitions
- vboxChooser.composeGroupDef(true);
-
- // Resize chooser elements
- vboxChooser._resizeElements();
-
- vboxChooser.selectionListChanged(vboxChooser._selectedList);
-
- },
-
- /*
- * Group selected items into a new group
- */
- groupSelectedItems : function() {
-
- // Get all group paths to determine new group target
- var groupPaths = {};
- vboxChooser._anchor.find('div.vboxVMGroupSelected').closest('div.vboxChooserGroup').each(function(idx,elm) {
- groupPaths[$(elm).data('vmGroupPath')] = 1;
- });
- vboxChooser._anchor.find('table.vboxListItemSelected').closest('div.vboxChooserGroup').each(function(idx,elm) {
- groupPaths[$(elm).data('vmGroupPath')] = 1;
- });
-
- // The group clsest to the root group will be the target
- var groupPathTarget = null;
- for(var i in groupPaths) {
-
- if(typeof(i) != 'string') continue;
-
- // Already at root group. Nothing to do
- if(groupPathTarget == '/') break;
-
- // No target set yet or equal targets, or this group is the root
- if(!groupPathTarget || groupPathTarget == i || i == '/') {
- groupPathTarget = i;
- continue;
- }
-
- var t1 = groupPathTarget.split("/");
- var t2 = i.split("/");
- for(var i = 0; i < Math.min(t1.length,t2.length); i++) {
- if(t1[i] != t2[i]) {
- groupPathTarget = '';
- for(var a = 0; a < i; a++) {
- groupPathTarget += "/" + t1[a];
- }
- groupPathTarget = groupPathTarget.replace('//','/');
- break;
- }
- }
-
-
- }
-
- var target = vboxChooser.getGroupElement(groupPathTarget, true);
-
- if(!$(target)[0]) return;
-
- // Determine group name
- var gname = trans('New group','UIGChooserModel');
- var tgname = gname;
-
- var i = 2;
- while(vboxChooser.groupNameConflicts($(target), tgname)) {
- tgname = gname + ' ' + (i++);
- }
-
- var gHTML = vboxChooser.groupHTML('/'+tgname);
-
- // Append group and vm elements
- vboxChooser._anchor.find('div.vboxVMGroupSelected').detach().insertAfter(gHTML.children('div.vboxChooserGroupHeader'));
- vboxChooser._anchor.find('table.vboxListItemSelected').detach().appendTo(gHTML.children('div.vboxChooserGroupVMs'));
-
- gHTML.insertBefore($(target).children('div.vboxChooserGroupVMs'));
-
- // group selected items,
- // Compose and save group definitions
- vboxChooser.composeGroupDef(true);
-
- // Resize chooser elements
- vboxChooser._resizeElements();
-
-
-
- },
-
- /**
- * Compose group data from GUI and optionally save it
- *
- * @param save - save group definitions to vbox
- */
- composeGroupDef : function(save) {
-
- var allGroups = [];
- var groupsResolved = false;
-
- // Keep looping through group definitions until
- // there are no groups removed
- while(!groupsResolved) {
-
- allGroups = [];
- groupsResolved = true;
-
- vboxChooser._anchor.find('div.vboxChooserGroup:not(.ui-draggable-dragging)').each(function(idx,elm) {
-
- // Group element was removed
- if(!$(elm)[0]) return;
-
- // Compose group path
- var myPath = $(elm).children('div.vboxChooserGroupIdentifier').attr('title');
- if(!myPath) myPath = '/';
- $(elm).parents('div.vboxChooserGroup:not(.ui-draggable-dragging)').each(function(idx2,elm2){
- var pName = $(elm2).children('div.vboxChooserGroupIdentifier').attr('title');
- if(!pName) pName = '/';
- myPath = String(pName + '/' + myPath).replace('//','/');
- });
-
- // Groups
- var gList = [];
- $(elm).children('div.vboxChooserGroup:not(.ui-draggable-dragging)').each(function(idx2,elm2){
-
- // If this group is selected, we'll have to update its path
- // in the selection list
- var selected = $(elm2).hasClass('vboxVMGroupSelected');
- var oldPath = $(elm2).data('vmGroupPath');
- var newPath = String(myPath + '/' + $(elm2).children('div.vboxChooserGroupIdentifier').attr('title')).replace('//','/');
-
- gList[gList.length] = $(elm2).children('div.vboxChooserGroupIdentifier').attr('title');
-
- // set / correct group path data
- $(elm2).data('vmGroupPath', newPath);
-
- // Group's path changed?
- if(selected && (oldPath != newPath)) {
- for(var i = 0; i < vboxChooser._selectedList.length; i++) {
- if(vboxChooser._selectedList[i].type == 'group' && vboxChooser._selectedList[i].groupPath == oldPath) {
- vboxChooser._selectedList[i].groupPath = String(myPath + '/' + $(elm2).children('div.vboxChooserGroupIdentifier').attr('title')).replace('//','/');
- break;
- }
- }
- }
-
- });
-
- // VMs
- var vmList = [];
- $(elm).children('div.vboxChooserGroupVMs').children('table.vboxChooserVM:not(.ui-draggable-dragging)').each(function(idx3,elm3){
- vmList[vmList.length] = $(elm3).data('vmid');
- });
-
- // Skip and remove if there are no VMs or subgroups
- // And it is not the parent group
- if(gList.length + vmList.length == 0 && !$(elm).hasClass('vboxChooserGroupRoot')) {
-
- // remove from selected list?
- if(elm && $(elm).hasClass('vboxVMGroupSelected')) {
-
- var myPath = $(elm).data('vmGroupPath');
- // Deselect item
- vboxChooser._selectedList = vboxChooser._selectedList.filter(function(v){
- return (v.type != 'group' || (v.groupPath != myPath));
- });
- }
- $(elm).empty().remove();
- groupsResolved = false;
- return false;
- }
-
- // append to all groups list
- gorder = [];
- if(gList.length) gorder[0] = 'go='+gList.join(',go=');
- if(vmList.length) gorder[gorder.length] = 'm='+vmList.join(',m=');
- allGroups[allGroups.length] = {
- path: $(elm).data('vmGroupPath'),
- order: gorder.join(',')
- };
-
- // Update counts span
- $(elm).children('div.vboxChooserGroupVMs').css({'display':(vmList.length || $(elm).data('vmGroupPath') == '/' ? '' : 'none')})
- .siblings('div.vboxChooserGroupHeader')
- .each(function(hidx,header) {
-
- var staticTip = '<strong>'+$(header).siblings('div.vboxChooserGroupIdentifier').attr('title')+'</strong>'+
- (gList.length ? ('<br />' + trans('%n group(s)','UIGChooserItemGroup',gList.length).replace('%n',gList.length)) : '') +
- (vmList.length ? ('<br />' + trans('%n machine(s)','UIGChooserItemGroup',vmList.length).replace('%n',vmList.length)) : '');
-
- $(header).tipped({'source':function() {
-
- // find number of running VMs
- var runningVMs = 0;
-
- if(vmList.length) {
- $(header).siblings('div.vboxChooserGroupVMs').find('td.vboxVMSessionOpen').each(function(idx,elm3) {
- if(vboxVMStates.isRunning(vboxVMDataMediator.getVMData($(elm3).closest('table').data('vmid'))))
- runningVMs++;
- });
- }
-
- return staticTip + (runningVMs > 0 ? ' ' + trans('(%n running)','UIGChooserItemGroup',runningVMs).replace('%n', runningVMs) : '');
- }
- ,'position':'mouse','delay':1500});
- })
- .children('span.vboxChooserGroupInfo')
- .children('span.vboxChooserGroupCounts').html(
- (gList.length ? ('<span style="background-image:url(images/vbox/group_abstract_16px.png);" />'+gList.length) : '') +
- (vmList.length ? ('<span style="background-image:url(images/vbox/machine_abstract_16px.png);" />'+vmList.length) : '')
- );
- });
-
- }
-
- // Save GUI group definition?
- if(!save) return;
-
-
- // Tell the interface we're about to save groups
- vboxChooser._editable = false;
- $('#vboxPane').trigger('vmGroupDefsSaving');
-
- vboxChooser._groupDefs = allGroups;
-
- // Save machine groups and trigger change
- var vms = [];
- var vmList = vboxVMDataMediator.getVMList();
- for(var i = 0; i < vmList.length; i++) {
-
- if(!vmList[i] || vmList[i].id == 'host') continue;
-
- /* If a VM's groups have changed, add it to the list */
- var eGroups = vmList[i].groups;
- var nGroups = vboxChooser.getGroupsForVM(vmList[i].id);
-
- if($(nGroups).not(eGroups).length || $(eGroups).not(nGroups).length) {
-
- vms[vms.length] = {
- 'id' : vmList[i].id,
- 'groups' : nGroups
- };
- }
- }
-
- // Save machines groups?
- if(vms.length) {
-
- // Reload VMs and group definitions
- var reloadAll = function() {
-
- var ml = new vboxLoader();
- ml.add('vboxGetMedia',function(d){$('#vboxPane').data('vboxMedia',d.responseData);});
- ml.add('vboxGroupDefinitionsGet',function(d){vboxChooser._groupDefs = d.responseData;});
-
- // Reload VM list and group definitions, something went wrong
- ml.onLoad = function() {
-
- // Stop vmlist from refreshing..
- vboxChooser.stop();
-
- // reset selections
- $('#vboxPane').trigger('vmSelectionListChanged',[vboxChooser]);
-
- // ask for new one
- vboxChooser.start();
- };
- ml.run();
- };
-
- $.when(vboxAjaxRequest('machinesSaveGroups',{'vms':vms})).done(function(res){
-
- if(res.responseData.errored) {
- reloadAll();
- vboxChooser._editable = true;
- $('#vboxPane').trigger('vmGroupDefsSaved');
- } else {
- $.when(vboxAjaxRequest('vboxGroupDefinitionsSet',{'groupDefinitions':allGroups})).always(function(){
- vboxChooser._editable = true;
- $('#vboxPane').trigger('vmGroupDefsSaved');
- });
- }
-
- }).fail(reloadAll);
-
- } else {
- $.when(vboxAjaxRequest('vboxGroupDefinitionsSet',{'groupDefinitions':allGroups})).always(function(){
- vboxChooser._editable = true;
- $('#vboxPane').trigger('vmGroupDefsSaved');
- });
- }
-
-
- return allGroups;
-
- },
-
- /*
- * Return a list of groups that VM is a member of
- */
- getGroupsForVM : function(vmid) {
- var gPathList = [];
- vboxChooser._anchor.find('table.vboxChooserItem-'+vboxChooser._anchorid+'-'+vmid+':not(.ui-draggable-dragging)').each(function(idx,elm){
- var gParent = $(elm).closest('div.vboxChooserGroup');
- if(!gParent.hasClass('ui-draggable-dragging'))
- gPathList[gPathList.length] = gParent.data('vmGroupPath');
- });
- return gPathList;
- },
-
- /*
- * Determine whether or not a group name conflicts
- * with another group in parent
- */
- groupNameConflicts : function(parentGroup, name, ignoreGroupAtPath) {
- var found = false;
- parentGroup.children('div.vboxChooserGroup:not(.ui-draggable-dragging)').children('div.vboxChooserGroupIdentifier[title="'+name+'"]').parent().each(function(i,elm){
-
- if(ignoreGroupAtPath && (ignoreGroupAtPath == $(elm).data('vmGroupPath')))
- return true;
-
- found=true;
- return false;
- });
- return found;
- },
-
- /*
- * Ungroup selected group
- */
- unGroupSelectedGroup : function() {
-
- var target = $(vboxChooser.getSelectedGroupElements()[0]).siblings('div.vboxChooserGroupVMs');
-
- // Groups
- // - ignore group at path we are currently ungrouping
- var ignoreGroup = $(vboxChooser.getSelectedGroupElements()[0]).data('vmGroupPath');
- $(vboxChooser.getSelectedGroupElements()[0]).children('div.vboxChooserGroup').each(function(i,elm) {
-
- // Make sure there are no conflicts
- var newElm = $(elm).detach();
- var groupName = $(elm).children('div.vboxChooserGroupIdentifier').attr('title');
- var newGroupName = groupName;
-
- var i = 2;
- while(vboxChooser.groupNameConflicts($(target).parent(), newGroupName, ignoreGroup)) {
- newGroupName = groupName + ' (' + (i++) + ')';
- }
-
- $(newElm).children('div.vboxChooserGroupIdentifier').attr({'title':newGroupName})
- .siblings('div.vboxChooserGroupHeader')
- .children('span.vboxChooserGroupName').text(newGroupName);
-
- $(newElm).insertBefore(target);
-
- });
-
- // VMs
- $(vboxChooser.getSelectedGroupElements()[0]).children('div.vboxChooserGroupVMs').children().each(function(i,elm){
- $(elm).detach();
- if(!target.children('table.vboxChooserItem-'+vboxChooser._anchorid+'-'+$(elm).data('vmid'))[0])
- target.append(elm);
- });
-
-
- // ungroup selected items
- // compose and save group definitions
- vboxChooser.composeGroupDef(true);
-
- // Resize chooser elements
- vboxChooser._resizeElements();
-
- vboxChooser.selectionListChanged();
-
-
- },
-
- /*
- * Sort group sub-elements based on VirtualBox
- * group definitions
- */
- sortGroup : function(gElm) {
-
- // Find group orders
- var gPath = $(gElm).data('vmGroupPath');
- var groupList = vboxChooser._groupDefs;
-
- if(!(gPath && groupList)) return;
-
- var machineOrder = [];
- var groupOrder = [];
-
- // Get correct order
- for(var i = 0; i < groupList.length; i++) {
- if(groupList[i].path == gPath) {
- order = groupList[i].order.split(',');
- for(var a = 0; a < order.length; a++) {
- kv = order[a].split('=',2);
- if(kv[0] == 'm') machineOrder[machineOrder.length] = kv[1];
- else groupOrder[groupOrder.length] = kv[1];
- }
- }
- }
-
- // sort groups
- var groups = $(gElm).children('div.vboxChooserGroup').get();
- var maxPos = groups.length;
- groups.sort(function(a,b){
-
- var Pos1 = jQuery.inArray($(a).children('div.vboxChooserGroupIdentifier').attr('title'), groupOrder);
- var Pos2 = jQuery.inArray($(b).children('div.vboxChooserGroupIdentifier').attr('title'), groupOrder);
-
- if(Pos1==-1) Pos1 = maxPos;
- if(Pos2==-1) Pos2 = maxPos;
-
- return (Pos1 > Pos2 || Pos1 == -1 ? -1 : (Pos2 == Pos1 ? 0 : 1));
-
- });
- $.each(groups, function(idx,itm) {
- $(itm).insertAfter($(gElm).children('div.vboxChooserGroupHeader'));
- });
-
- // sort VMs
- var vms = $(gElm).children('div.vboxChooserGroupVMs').children('table.vboxChooserVM').get();
- var maxPos = vms.length;
- vms.sort(function(a,b) {
-
- var Pos1 = jQuery.inArray($(a).data('vmid'), machineOrder);
- var Pos2 = jQuery.inArray($(b).data('vmid'), machineOrder);
-
- if(Pos1==-1) Pos1 = maxPos;
- if(Pos2==-1) Pos2 = maxPos;
-
- return (Pos1 > Pos2 ? 1 : (Pos2 == Pos1 ? 0 : -1));
-
- });
- $.each(vms, function(idx,itm) {
- $(gElm).children('div.vboxChooserGroupVMs').append(itm);
- });
-
-
- },
-
- /*
- * Sort selected group by item names
- */
- sortSelectedGroup : function(rootElm) {
-
- var el = $(vboxChooser.getSelectedGroupElements()[0]);
-
- if(rootElm || !el) {
- el = vboxChooser._anchor.children('div.vboxChooserGroup');
- }
-
- // sort groups
- var groups = $(el).children('div.vboxChooserGroup').get();
- groups.sort(function(a,b){
- return $(b).children('div.vboxChooserGroupIdentifier').attr('title').localeCompare($(a).children('div.vboxChooserGroupIdentifier').attr('title'));
- });
- $.each(groups, function(idx,itm) {
- $(itm).insertAfter($(el).children('div.vboxChooserGroupHeader'));
- });
-
- // sort VMs
- var vms = $(el).children('div.vboxChooserGroupVMs').children('table.vboxChooserVM').get();
- vms.sort(function(a,b) {
- return $(a).find('span.vboxVMName').text().localeCompare($(b).find('span.vboxVMName').text());
- });
- $.each(vms, function(idx,itm) {
- $(el).children('div.vboxChooserGroupVMs').append(itm);
- });
-
- // compose and save group definitions
- vboxChooser.composeGroupDef(true);
-
- },
-
- /*
- * Rename selected group
- */
- renameSelectedGroup : function() {
-
- var el = $(vboxChooser.getSelectedGroupElements()[0]);
-
- // Function to rename group
- var renameGroup = function(e, textbox) {
-
- if(!textbox) textbox = $(this);
-
- var newName = $(textbox).val().replace(/[\\\/:*?"<>,]/g,'_');
-
- if(newName && newName != $(textbox).closest('div.vboxChooserGroup').children('div.vboxChooserGroupIdentifier').attr('title')) {
-
- // Do not rename if it conflicts
- var noConflict = newName;
- var i = 2;
- while(vboxChooser.groupNameConflicts($(textbox).parent().parent().parent().parent(), noConflict)) {
- noConflict = newName + ' (' + (i++) + ')';
- }
- newName = noConflict;
-
- $(textbox).closest('div.vboxChooserGroup')
- .children('div.vboxChooserGroupIdentifier').attr({'title':newName})
- .siblings('div.vboxChooserGroupHeader')
- .children('span.vboxChooserGroupName').html(newName);
-
- // group renamed, compose and save groups
- vboxChooser.composeGroupDef(true);
-
- // Write out collapsed group list
- vboxChooser._saveCollapsedGroups();
-
- }
-
-
- $(textbox).parent().parent().children().css({'display':''});
- $(textbox).parent().empty().remove();
- };
-
- $(el).children('div.vboxChooserGroupHeader').children().css({'display':'none'});
- $(el).children('div.vboxChooserGroupHeader').append(
-
- $('<form />').append(
- $('<input />').attr({'type':'text','value':$(el).children('div.vboxChooserGroupIdentifier').attr('title')}).css({'width':'90%','padding':'0px','margin':'0px'}).on('keypress',function(e){
- if (e.which == 13) {
- $(this).off('blur', renameGroup);
- renameGroup(e,this);
- e.stopPropagation();
- e.preventDefault();
- $(this).trigger('blur');
- return false;
- }
- })
- )
-
- );
- $(el).children('div.vboxChooserGroupHeader').children('form').children('input').focus().select().blur(renameGroup);
-
- },
-
- /*
- * Select a single group
- */
- _selectGroup : function(gelm) {
- $(gelm).addClass('vboxVMGroupSelected');
- },
-
- /*
- * Deselect a single group
- */
- _deselectGroup : function(gelm) {
-
- $(gelm).removeClass('vboxVMGroupSelected');
- },
-
- /*
- * Select (or unselect) an item in our list. Called onmousedown or onCLick
- */
- selectItem : function(e) {
-
- // Right click selects item if it is not selected
- if(e.which != 1) {
-
- // Right click on group header and group is selected
- // just return and show context menu
- if($(this).hasClass('vboxChooserGroupHeader') && $(this).parent().hasClass('vboxVMGroupSelected')) {
- return true;
-
- // Right click on VM and VM is already selected
- // just return and show context menu
- } else if($(this).hasClass('vboxListItemSelected')) {
- return true;
- }
- }
-
- var selectedList = [];
- var item = $(this);
-
-
- // Group?
- if($(item).hasClass('vboxChooserGroupHeader')) {
-
-
- // No control key. Exclusive selection
- if(!e.ctrlKey && !e.metaKey) {
-
- // already selected
- if(vboxChooser._selectedList.length == 1 && vboxChooser._selectedList[0].type == 'group' &&
- vboxChooser._selectedList[0].groupPath == $(item).parent().data('vmGroupPath'))
- return true;
-
- vboxChooser._anchor.find('.vboxListItemSelected').removeClass('vboxListItemSelected');
- vboxChooser._anchor.find('div.vboxVMGroupSelected')
- .each(function(idx,gelm) {
- vboxChooser._deselectGroup(gelm);
- });
-
-
-
- // select current group
- vboxChooser._selectGroup($(item).parent());
-
- selectedList = [{
- type: 'group',
- groupPath: $(item).parent().data('vmGroupPath')
- }];
-
- // Already selected, and ctrl key
- } else if($(item).parent().hasClass('vboxVMGroupSelected')){
-
- // Deselect item
- selectedList = vboxChooser._selectedList.filter(function(v){
- return (v.type != 'group' || (v.groupPath != $(item).parent().data('vmGroupPath')));
- });
-
- vboxChooser._deselectGroup($(item).parent());
-
- // Not already selected, and ctrl key
- } else {
-
- vboxChooser._selectGroup($(item).parent());
-
- selectedList = vboxChooser._selectedList;
-
- selectedList[selectedList.length] = {
- type: 'group',
- groupPath: $(item).parent().data('vmGroupPath')
- };
-
- }
-
-
- // VM
- } else {
-
- // No ctrl key or selection is host. Exclusive selection
- if((!e.ctrlKey && !e.metaKey) || $(item).data('vmid') == 'host') {
-
- vboxChooser._anchor.find('.vboxListItemSelected').removeClass('vboxListItemSelected');
- vboxChooser._anchor.find('div.vboxVMGroupSelected').removeClass('vboxVMGroupSelected')
- .each(function(idx,gelm){
- vboxChooser._deselectGroup(gelm);
- });
-
- // Select current VM
- $(item).addClass('vboxListItemSelected').removeClass('vboxHover');
-
- // already selected
- if(vboxChooser._selectedList.length == 1 && vboxChooser._selectedList[0].type == 'vm' &&
- vboxChooser._selectedList[0].id == $(item).data('vmid'))
- return true;
-
- selectedList = [{
- type: 'vm',
- id: $(item).data('vmid'),
- groupPath: $(item).parent().data('vmGroupPath')
- }];
-
- // Already selected, and ctrl key
- } else if($(item).hasClass('vboxListItemSelected')) {
-
- // Deselect item
- selectedList = vboxChooser._selectedList.filter(function(v){
- return (v.type == 'group' || (v.id != $(item).data('vmid')));
- });
-
- $(item).removeClass('vboxListItemSelected');
-
- // ctrl key, but not already selected
- } else {
-
- $(item).addClass('vboxListItemSelected').removeClass('vboxHover');
-
- selectedList = vboxChooser._selectedList;
-
- selectedList[selectedList.length] = {
- type: 'vm',
- id: $(item).data('vmid'),
- groupPath: $(item).parent().data('vmGroupPath')
- };
-
- }
-
- }
-
- // Remove host?
- if(selectedList.length > 1) {
-
- // Deselect host
- selectedList = selectedList.filter(function(v){
- return (v.type == 'group' || (v.id != 'host'));
- });
-
- vboxChooser._anchor.children('table.vboxChooserItem-'+vboxChooser._anchorid+'-host').removeClass('vboxListItemSelected');
-
- }
-
- vboxChooser.selectionListChanged(selectedList);
-
- return true;
-
-
- },
-
- /*
- * Show only single group element identified by gelm
- */
- showOnlyGroupElm : function(gelm) {
-
- // Going backwards affects animations
- var back = false;
-
- // gelm is null if we're going backwards
- if(!gelm) {
-
-
- if(vboxChooser._showOnlyGroupHistory.length > 1) {
- // this gets rid of current
- vboxChooser._showOnlyGroupHistory.pop();
- // selects previous
- gelm = vboxChooser._showOnlyGroupHistory.pop();
- back = true;
- } else {
- gelm = null;
- }
-
-
- } else {
-
- // Hold history
- vboxChooser._showOnlyGroupHistory[vboxChooser._showOnlyGroupHistory.length] = gelm;
- }
-
-
- // No scrolling
- vboxChooser._anchor.css({'overflow-y':'hidden'});
-
- if($(gelm)[0]) {
-
-
- // Slide over or back
- $.when(vboxChooser._anchor.hide('slide', {direction: (back ? 'right' : 'left'), distance: (vboxChooser._anchor.outerWidth()/1.5)}, 200)).always(function() {
-
-
- /* hide host when showing only a group */
- $('table.vboxChooserItem-'+vboxChooser._anchorid+'-host').hide();
-
-
- /* Undo anything previously performed by this */
- vboxChooser._anchor.find('div.vboxChooserGroupHide').removeClass('vboxChooserGroupHide vboxChooserGroupHideShowContainer');
- vboxChooser._anchor.find('div.vboxChooserGroupShowOnly').removeClass('vboxChooserGroupShowOnly');
-
- $(gelm).parents('div.vboxChooserGroup').addClass('vboxChooserGroupHide vboxChooserGroupHideShowContainer').siblings().addClass('vboxChooserGroupHide');
-
- vboxChooser._anchor.find('div.vboxChooserGroupRootLevel').removeClass('vboxChooserGroupRootLevel');
- $(gelm).addClass('vboxChooserGroupShowOnly vboxChooserGroupRootLevel').siblings().addClass('vboxChooserGroupHide');
-
- $.when(vboxChooser._anchor.show('slide', {direction: (back ? 'left' : 'right'), distance: (vboxChooser._anchor.outerWidth()/1.5)}, 200))
- .done(function(){
-
- // Restore scrolling
- vboxChooser._anchor.css({'overflow-y':'auto'});
-
- // Hide group info
- $(gelm).find('div.vboxChooserGroupHeader').trigger('mouseout');
-
- // Reset title sizes
- vboxChooser._resizeElements();
-
- // force redraw of these
- $(gelm).find('.vboxFitToContainer').css({'display':'none'}).css({'width':'','display':''});
-
-
- });
-
- });
-
- } else {
-
- vboxChooser._showOnlyGroupHistory = [];
-
- // Slide back to anchor
- $.when(vboxChooser._anchor.hide('slide', {direction: 'right', distance: (vboxChooser._anchor.outerWidth()/1.5)}, 200)).always(function() {
-
- /* show host when going back to main list */
- $('table.vboxChooserItem-'+vboxChooser._anchorid+'-host').show();
-
- vboxChooser._anchor.find('div.vboxChooserGroupHide').removeClass('vboxChooserGroupHide vboxChooserGroupHideShowContainer');
- vboxChooser._anchor.find('div.vboxChooserGroupShowOnly').removeClass('vboxChooserGroupShowOnly ');
-
- vboxChooser._anchor.find('div.vboxChooserGroupRootLevel').removeClass('vboxChooserGroupRootLevel');
- vboxChooser._anchor.children('div.vboxChooserGroupRoot').addClass('vboxChooserGroupRootLevel');
-
- $.when(vboxChooser._anchor.show('slide', {direction: 'left', distance: (vboxChooser._anchor.outerWidth()/1.5)}, 200))
- .done(function(){
-
- // Restore scrolling
- vboxChooser._anchor.css({'overflow-y':'auto'});
-
- // Hide group info
- vboxChooser._anchor.find('div.vboxChooserGroupHeader').trigger('mouseout');
-
- // Reset title sizes
- vboxChooser._resizeElements();
-
- // force redraw of these
- vboxChooser._anchor.find('.vboxFitToContainer').css({'display':'none','width':''}).css({'display':''});
- });
- });
- }
-
- },
-
- /*
- * Return HTML for group
- */
- groupHTML : function(gpath) {
-
- if(!gpath) gpath = '/';
- var first = gpath == '/';
- var gname = gpath.substring(gpath.lastIndexOf('/')+1);
- var collapsed = vboxChooser._isGroupCollapsed(gpath);
-
- var gHTML = $('<div />').append(
- $('<div />').addClass('vboxChooserGroupIdentifier').css({'display':'none'}).attr({'title':gname})
- ).append(
- $('<div />').addClass('vboxChooserGroupHeader').css({'display':(first ? 'none' : '')})
- .attr({'title':gname})
- .dblclick(function() {
-
- // Already collapsed?
- var collapsed = $(this).closest('div.vboxChooserGroup').hasClass('vboxVMGroupCollapsed');
-
- // Button rotation function
- var rotateButton = function(){return true;};
-
- var vboxArrowImage = $(this).find('span.vboxChooserGroupNameArrowCollapse');
-
- if(!($.browser.msie && $.browser.version.substring(0,1) < 9)) {
-
- rotateButton = function() {
-
- return $('<div />').animate({left:90},{
- duration: 300,
- step: function(currentStep) {
- if(!collapsed) currentStep = (90 - currentStep);
- vboxArrowImage.css({
- 'transform':'rotate('+currentStep+'deg)',
- '-moz-transform': 'rotate('+currentStep+'deg)',
- '-webkit-transform': 'rotate('+currentStep+'deg)',
- '-o-transform': 'rotate('+currentStep+'deg)',
- '-ms-transform': 'rotate('+currentStep+'deg)'
- });
- },
- queue: true,
- complete: function() {
- vboxArrowImage.css({
- 'transform':'',
- '-moz-transform': '',
- '-webkit-transform': '',
- '-o-transform': '',
- '-ms-transform': ''
- });
- }
-
- });
- };
- }
-
-
- // Run button rotation and toggle class
- $.when(rotateButton(), $(this).closest('div.vboxChooserGroup').toggleClass('vboxVMGroupCollapsed', ($.browser.msie && $.browser.version.substring(0,1) < 9) ? undefined : 300)).always(function(){
-
- // Write out collapsed group list
- vboxChooser._saveCollapsedGroups();
-
- // Reset title sizes
- vboxChooser._resizeElements();
- });
-
-
- })
- .append(
- $('<div />').addClass('vboxChooserDropTarget')
- .addClass('vboxDropTargetTop').hover(function(){
- if(vboxChooser._draggingGroup)
- $(this).addClass('vboxChooserDropTargetHover' + (first ? 'ignore' : ''));
- }, function(){
- $(this).removeClass('vboxChooserDropTargetHover');
- })
- )
- .append(
- $('<span />').addClass('vboxChooserGroupNameArrowLeft vboxChooserGroupNameArrowCollapse vboxArrowImage')
- .mousedown(function(e){
- e.stopPropagation();
- e.preventDefault();
- return false;
- }).mouseup(function(){
- $(this).closest('div.vboxChooserGroupHeader').trigger('dblclick');
- })
-
- ).append(
-
- $('<span />').addClass('vboxChooserGroupNameArrowLeft vboxChooserGroupShowOnlyBack vboxArrowImage')
- .click(function(e) {
- e.stopPropagation();
- e.preventDefault();
- vboxChooser.showOnlyGroupElm();
- return false;
-
- })
-
- )
- .append($('<span />').addClass('vboxChooserGroupInfo').html(
- "<span class='vboxChooserGroupCounts' />"
- ).append(
- $('<span />').addClass('vboxChooserGroupShowOnly vboxArrowImage')
- .click(function(e){
- e.stopPropagation();
- e.preventDefault();
- vboxChooser.showOnlyGroupElm($(this).closest('div.vboxChooserGroup'));
- return false;
- })
-
- ))
- .append($('<span />').html(gname).addClass('vboxChooserGroupName vboxFitToContainer'))
- .append(
- $('<div />').addClass('vboxChooserDropTarget vboxChooserDropTargetBottom')
- .hover(function(){
- if(vboxChooser._draggingGroup)
- $(this).addClass('vboxChooserDropTargetHover' + (first ? 'ignore' : ''));
- }, function(){
- $(this).removeClass('vboxChooserDropTargetHover');
- })
-
- )
- .hover(function(){
-
- if(vboxChooser._compact) return;
-
- $(this).addClass('vboxHover');
-
- // Resize title and add hover class?
- if(!$(this).parent().hasClass('vboxChooserGroupRoot')) {
-
- // Set width of title to -group info span width
- var infoWidth = $(this).children('span.vboxChooserGroupInfo').width();
- var pWidth = $(this).width();
-
- $(this).children('span.vboxChooserGroupName').css({'max-width':(pWidth-infoWidth-20)+'px'});
-
- }
-
-
- },function(){
-
- // Resize title and remove hover class
- $(this).removeClass('vboxHover');
-
- if(!$(this).parent().hasClass('vboxChooserGroupRoot'))
- $(this).children('span.vboxChooserGroupName').css({'max-width':''});
-
- }).on('mousedown',vboxChooser.selectItem)
-
- ).addClass((first ? 'vboxChooserGroupRoot vboxChooserGroupRootLevel ' : (collapsed ? 'vboxVMGroupCollapsed ' : '')) + 'vboxChooserGroup')
- .data({'vmGroupPath':gpath})
- .draggable({'cursorAt':{left: -10, top: -10},'helper':function(){
-
- return $(this).clone().addClass('vboxVMGroupCollapsed vboxVMGroupSelected')
- .children('div.vboxChooserGroupHeader').removeClass('vboxHover').children('.vboxChooserGroupNameArrowCollapse')
- .hide().closest('div.vboxChooserGroup').css({'width':$(this).width()+'px'});
-
-
- },'start':function() {
-
- if(!$('#vboxPane').data('vboxSession').admin) return false;
-
- if(!vboxChooser._editable) return false;
-
- vboxChooser._draggingGroup = $(this).data('vmGroupPath');
- $(vboxChooser._anchor).disableSelection();
-
- },'stop':function(e) {
- vboxChooser.vmGroupDropped(e,$(this));
-
- }}).append($('<div />').addClass('vboxChooserGroupVMs'));
-
-
- // Bottom drop target
- if(!first) {
- gHTML.hover(function(){
- $(this).addClass('vboxGroupHover'); }, function() {
- $(this).removeClass('vboxGroupHover');
- }).append(
- $('<div />').addClass('vboxChooserDropTarget vboxChooserDropTargetBottom')
- .hover(function(){
- if(vboxChooser._draggingGroup)
- $(this).addClass('vboxChooserDropTargetHover');
- }, function(){
- $(this).removeClass('vboxChooserDropTargetHover');
- })
- );
- }
-
-
-
- // Group context menu
- $(gHTML).contextMenu({
- menu: vboxChooser._vmGroupContextMenuObj.menuId(),
- menusetup: function(el) {
- $(el).children('div.vboxChooserGroupHeader').trigger('click');
- }
- },function(act,el,pos,d,e){
- vboxChooser._vmGroupContextMenuObj.menuClickCallback(act, el);
- });
-
- return gHTML;
-
-
-
- },
-
- /*
- * Return selected VM elements
- */
- getSelectedVMElements : function() {
- return vboxChooser._anchor.find('table.vboxSelected');
- },
-
- /*
- * Return selected group elements
- */
- getSelectedGroupElements : function() {
- return vboxChooser._anchor.find('div.vboxVMGroupSelected');
- },
-
-
- /*
- * Start VM list update
- */
- start : function(anchorid) {
-
- // already running?
- if(vboxChooser._running) return;
- vboxChooser._running = true;
-
- // Where are we drawn?
- if(anchorid) {
- vboxChooser._anchorid = anchorid;
- vboxChooser._anchor = $('#'+anchorid);
- }
-
-
- // Set group definition key
- vboxChooser._groupDefinitionKey = $('#vboxPane').data('vboxConfig')['groupDefinitionKey'];
-
- // Get collapsed group list
- vboxChooser._collapsedGroups = vboxGetLocalDataItem($('#vboxPane').data('vboxConfig').key+'-collapsedGroups', true);
- if(!vboxChooser._collapsedGroups) vboxChooser._collapsedGroups = [];
- else vboxChooser._collapsedGroups = vboxChooser._collapsedGroups.split(',');
-
-
- // Get groups and machine list. datamediator will start listener
- $.when(vboxAjaxRequest('vboxGroupDefinitionsGet')).done(function(g) {
-
- vboxChooser._groupDefs = g.responseData;
-
- $.when(vboxVMDataMediator.getVMList()).done(function(d) {
- vboxChooser.updateList(d);
- });
- });
-
- },
-
- /*
- * Stop VM list updates and clear list
- */
- stop : function() {
-
- if(!vboxChooser._running) return;
- vboxChooser._running = false;
-
- vboxChooser._anchor.html("<div id='vboxChooserSpinner' style='text-align: center'><div><img src='images/spinner.gif' /></div></div>");
-
- // reset vars
- vboxChooser._versionChecked = false;
- vboxChooser._selectedList = [];
- vboxChooser.selectedVMs = [];
- vboxChooser.selectionMode = vboxSelectionModeNone;
-
- }
-
-
-
-};
-
-$(document).ready(function(){
-
- // Calculate scrollbar width
- vboxChooser._scrollbarWidth = getScrollbarWidth();
-
- // "Stop" chooser
- $('#vboxPane').on('hostChange',function(){
-
- vboxChooser.stop();
-
- }).on('hostChanged',function(){
-
-
- vboxChooser.start();
-
- // Refresh menus
- }).on('vmGroupDefsSaving vmGroupDefsSaved vmSelectionListChanged', function() {
-
- if(vboxChooser._vmGroupContextMenuObj)
- vboxChooser._vmGroupContextMenuObj.update(vboxChooser);
- if(vboxChooser._vmContextMenuObj)
- vboxChooser._vmContextMenuObj.update(vboxChooser);
-
-
- // Event list queue
- }).on('vboxEvents',function(e, eventList) {
-
- var redrawVMs = [];
- var sortGroups = [];
- var groupsChanged = false;
- var selectedChanged = false;
- var resizeElements = false;
-
- for(var i = 0; i < eventList.length; i++) {
-
- switch(eventList[i].eventType) {
-
- ////////////////////////////////
- //
- // Machine data changed
- //
- ////////////////////////////////
- case 'OnMachineDataChanged':
-
- // Shorthand
- var vmid = eventList[i].machineId;
- var data = vboxVMDataMediator.getVMData(vmid);
-
- // Update VM in list
- if(data) {
-
- // Enforce VM ownership
- if($('#vboxPane').data('vboxConfig').enforceVMOwnership && !$('#vboxPane').data('vboxSession').admin && data.owner != $('#vboxPane').data('vboxSession').user) {
- break;
- }
-
- redrawVMs[redrawVMs.length] = vmid;
-
- // Make sure VM has root group at least
- if(data.groups.length == 0) data.groups = ['/'];
-
- // Remove from groups if they have changed
- var currGroups = vboxChooser.getGroupsForVM(vmid);
- var groupDiff = $(currGroups).not(data.groups);
- groupsChanged = groupDiff.length;
- for(var a = 0; a < groupDiff.length; a++) {
-
- var gElm = vboxChooser.getGroupElement(groupDiff[a], false);
- if(!$(gElm)[0]) return;
-
- selectedChanged = (selectedChanged || $(gElm).children('div.vboxChooserGroupVMs').closest('div.vboxVMGroupSelected').length);
-
- $(gElm).children('div.vboxChooserGroupVMs')
- .children('table.vboxChooserItem-'+vboxChooser._anchorid+'-'+data.id).empty().remove();
-
- }
-
- // Add to other groups
- var groupDiff = $(data.groups).not(currGroups);
- groupsChanged = (groupsChanged || groupDiff.length);
- for(var a = 0; a < groupDiff.length; a++) {
-
- var gElm = vboxChooser.getGroupElement(groupDiff[a]);
-
- // Skip it if it is already there
- if($(gElm).children('div.vboxChooserGroupVMs').children('table.vboxChooserItem-'+vboxChooser._anchorid+'-'+data.id)[0])
- continue;
-
- $(gElm).children('div.vboxChooserGroupVMs')
- .append(
- vboxChooser.vmHTML(data)
- );
-
- selectedChanged = (selectedChanged || $(gElm).children('div.vboxChooserGroupVMs').closest('div.vboxVMGroupSelected').length);
-
- // Sort the group this machine was added to
- sortGroups = sortGroups.concat(data.groups);
-
- }
-
- resizeElements = (resizeElements || groupsChanged);
-
-
- }
-
- break;
-
- /////////////////////////////////
- //
- // Snapshot taken / deleted / restored
- //
- /////////////////////////////////
- case 'OnSnapshotDeleted':
- case 'OnSnapshotTaken':
- case 'OnSnapshotRestored':
- case 'OnSnapshotChanged':
- redrawVMs[redrawVMs.length] = eventList[i].machineId;
- break;
-
- /////////////////////////////////////
- //
- // Machine registered or unregistered
- //
- //////////////////////////////////////
- case 'OnMachineRegistered':
-
- // Shorthand
- var vmid = eventList[i].machineId;
-
- // Unregistered
- if(!eventList[i].registered) {
-
- var wasSelected = vboxChooser.isVMSelected(vmid);
-
- $('#'+vboxChooser._anchorid +' table.vboxChooserItem-'+vboxChooser._anchorid+'-'+vmid).remove();
-
- groupsChanged = true;
-
- // See if VM was selected
- if(wasSelected) {
-
- selectedChanged = true;
-
- vboxChooser._selectedList = vboxChooser._selectedList.filter(function(v){
- return (v.type == 'group' || (v.id != vmid));
- });
-
-
- }
-
- resizeElements = true;
-
-
- break;
-
- }
-
- // Registered
-
- // Enforce VM ownership
- if($('#vboxPane').data('vboxConfig').enforceVMOwnership && !$('#vboxPane').data('vboxSession').admin && eventList[i].enrichmentData.owner != $('#vboxPane').data('vboxSession').user) {
- break;
- }
-
- // Add to list
- vboxChooser.updateVMElement(eventList[i].enrichmentData, true);
-
- resizeElements = true;
- break;
-
-
- ///////////////////////////////////
- //
- // Extra data changed
- //
- ////////////////////////////////////
- case 'OnExtraDataChanged':
-
- if(!eventList[i].machineId && eventList[i].key.indexOf(vboxChooser._groupDefinitionKey) === 0) {
-
- var path = eventList[i].key.substring(vboxChooser._groupDefinitionKey.length);
- if(!path) path = "/";
- var name = path.substring(path.lastIndexOf('/')+1);
- var vboxVMGroups = vboxChooser._groupDefs;
- var found = false;
-
- // No current group definitions?
- if(!vboxVMGroups) break;
-
- // Step through each group, comparing
- for(var a = 0; a < vboxVMGroups.length; a++) {
- if(vboxVMGroups[a].path == path) {
- // Sort this group if it is different
- if(vboxVMGroups[a].order != eventList[i].value)
- sortGroups[sortGroups.length] = path;
- found = true;
- vboxVMGroups[a] = {'path':path,'name':name,'order':eventList[i].value};
- break;
- }
- }
-
- // Add to group if not found
- if(!found) {
- vboxVMGroups[vboxVMGroups.length] = {'path':path,'name':name,'order':eventList[i].value};
- sortGroups[sortGroups.length] = path; // sort when added
- resizeElements = true;
- }
-
- } else {
-
- switch(eventList[i].key) {
-
- // redraw when custom icon changes
- case 'phpvb/icon':
- redrawVMs[redrawVMs.length] = eventList[i].machineId;
- break;
- }
- }
- break;
-
- ////////////////////////////////////////
- //
- // Session or state change gets redrawn
- //
- ///////////////////////////////////////
- case 'OnSessionStateChanged':
- case 'OnMachineStateChanged':
- redrawVMs[redrawVMs.length] = eventList[i].machineId;
- break;
-
- } // </ switch eventType >>
-
-
- } // </ for each event >
-
- // Now redraw each VM
- ///////////////////////////
- var redrawn = {};
- var updateMenus = false;
- for(var i = 0; i < redrawVMs.length; i++) {
-
- if(redrawn[redrawVMs[i]]) continue;
- redrawn[redrawVMs[i]] = true;
-
- vboxChooser.updateVMElement(vboxVMDataMediator.getVMData(redrawVMs[i]));
-
- // Update menus if the VM is selected
- updateMenus = (updateMenus || vboxChooser.isVMSelected(redrawVMs[i]));
-
- }
-
- // Sort groups
- var groupsSorted = {};
- for(var i = 0; i < sortGroups.length; i++) {
- if(groupsSorted[sortGroups[i]]) continue;
- groupsSorted[sortGroups[i]] = true;
- var gElm = $(vboxChooser.getGroupElement(sortGroups[i]),false);
- if(gElm[0])
- vboxChooser.sortGroup(gElm);
-
- }
-
- // Groups changed
- if(groupsChanged || sortGroups.length) {
- vboxChooser.composeGroupDef();
- }
-
-
- // update selection list
- if(selectedChanged) {
-
- vboxChooser.selectionListChanged(vboxChooser._selectedList);
-
- } else if(updateMenus) {
-
- if(vboxChooser._vmGroupContextMenuObj)
- vboxChooser._vmGroupContextMenuObj.update(vboxChooser);
-
-
- if(vboxChooser._vmContextMenuObj)
- vboxChooser._vmContextMenuObj.update(vboxChooser);
-
- }
-
- if(resizeElements) vboxChooser._resizeElements(true);
-
-
-
- });
-
-
-
+/**
+ *
+ * @fileOverview Chooser (vm list) singleton. Provides vboxChooser
+ * @author Ian Moore (imoore76 at yahoo dot com)
+ * @version $Id: chooser.js 591 2015-04-11 22:40:47Z imoore76 $
+ * @copyright Copyright (C) 2010-2015 Ian Moore (imoore76 at yahoo dot com)
+ *
+ */
+
+/**
+ * Chooser selection mode constants
+ */
+var vboxSelectionModeNone = 0;
+var vboxSelectionModeSingleVM = 1;
+var vboxSelectionModeMultiVM = 2;
+var vboxSelectionModeSingleGroup = 3;
+
+
+/**
+ * @namespace vboxChooser
+ *
+ * Draws machine selection chooser and controls selection list
+ * @see js/eventlistener.js
+ */
+var vboxChooser = {
+
+ // VM list
+ vms : {},
+
+ // VM tool tip
+ _vmToolTip : '<nobr>%1<br></nobr><nobr>%2 since %3</nobr><br><nobr>Session %4</nobr>',
+
+ // Anchor element
+ _anchorid : null,
+ _anchor : null,
+
+ /* Internal list of all unique selected items */
+ _selectedList : [],
+
+ /* List of unique selected VMs */
+ selectedVMs : [],
+
+ /* Holds group definitions */
+ _groupDefs : [],
+
+ /* selection mode can be
+
+ var vboxSelectionModeNone = 0,
+ var vboxSelectionModeSingleVM = 1,
+ var vboxSelectionModeMultiVM = 2,
+ var vboxSelectionModeSingleGroup = 3,
+ */
+ selectionMode : vboxSelectionModeNone,
+
+ /* Check phpVirtualBox version and VirtualBox
+ * version compatibility.
+ */
+ _versionChecked : false,
+
+ /* Some items are not editable while vmGroup
+ * definitions are being written
+ */
+ _editable : true,
+
+ /* Context menus */
+ _vmContextMenuObj : null,
+ _vmGroupContextMenuObj : null,
+
+ /* Holds history of showing only single groups */
+ _showOnlyGroupHistory : [],
+
+ /* Group definition extra value key */
+ _groupDefinitionKey : '',
+
+ /* Whether chooser is in compact mode or not */
+ _compact : false,
+
+ /**
+ * Set anchor id to draw to
+ */
+ setAnchorId : function(aid) {
+ vboxChooser._anchorid = aid;
+ vboxChooser._anchor = $('#'+aid);
+
+ vboxChooser._anchor.html("<div id='vboxChooserSpinner' style='text-align: center'><div><img src='images/spinner.gif' /></div></div>");
+
+ vboxChooser._anchor.hover(function(){
+ $(this).addClass('vboxChooserDropTargetHoverRoot');
+ },function() {
+ $(this).removeClass('vboxChooserDropTargetHoverRoot');
+ });
+
+ $(window).resize(function(){
+
+ // Get anchor id and add / remove class
+ var w = parseInt($(vboxChooser._anchor).innerWidth());
+ if(w < 120) {
+ $(vboxChooser._anchor).addClass('vboxChooserMini');
+ vboxChooser._compact = true;
+ } else {
+ $(vboxChooser._anchor).removeClass('vboxChooserMini');
+ vboxChooser._compact = false;
+ }
+
+ vboxChooser._resizeElements(true);
+
+ });
+ },
+
+ /**
+ * Set context menus
+ *
+ */
+ setContextMenu : function(target, menuitems) {
+
+ switch(target) {
+
+ // Group menu
+ case 'group':
+ vboxChooser._vmGroupContextMenuObj = new vboxMenu({'name': vboxChooser._anchorid+'vmgroups',
+ 'menuItems': menuitems,
+ 'language_context': 'UIActionPool'});
+ vboxChooser._vmGroupContextMenuObj.update();
+ break;
+
+ // VM Menu
+ case 'vm':
+ vboxChooser._vmContextMenuObj = new vboxMenu({'name': vboxChooser._anchorid+'vms',
+ 'menuItems': menuitems,
+ 'language_context': 'UIActionPool'});
+ vboxChooser._vmContextMenuObj.update();
+ break;
+
+ // Main list menu
+ case 'anchor':
+
+ var vboxChooserPaneMenu = new vboxMenu({'name': vboxChooser._anchorid+'Pane',
+ 'menuItems': menuitems,
+ 'language_context': 'UIActionPool'});
+ $('#'+vboxChooser._anchorid).parent().contextMenu({
+ menu: vboxChooserPaneMenu.menuId()
+ },
+ vboxChooserPaneMenu.menuClickCallback
+ );
+
+ break;
+
+ default:
+ vboxAlert('vboxChooser::setContextMenu: unknown context menu type (' + target + ')');
+ }
+ },
+
+ /*
+ * Return true if a selected VM is in the given state
+ */
+ isSelectedInState : function(state) {
+
+ for(var i = 0; i < vboxChooser.selectedVMs.length; i++) {
+ if(vboxVMStates['is'+state](vboxVMDataMediator.getVMData(vboxChooser.selectedVMs[i])))
+ return true;
+ }
+ return false;
+
+ },
+
+ /**
+ * Return true if the passed VM is selected
+ */
+ isVMSelected : function(vmid) {
+ return (jQuery.inArray(vmid,vboxChooser.selectedVMs) > -1);
+ },
+
+ /**
+ * Return selected VM data in array
+ */
+ getSelectedVMsData : function() {
+
+ var vms = [];
+ for(var i = 0; i < vboxChooser.selectedVMs.length; i++) {
+ vms[vms.length] = vboxVMDataMediator.getVMData(vboxChooser.selectedVMs[i]);
+ }
+ return vms;
+ },
+
+ /**
+ * Triggered when selection list has changed
+ */
+ selectionListChanged : function(selectionList) {
+
+ if(!selectionList) selectionList = [];
+
+ selectionMode = vboxSelectionModeNone;
+
+ // Hold unique selected VMs
+ var vmListUnique = {};
+ for(var i = 0; i < selectionList.length; i++) {
+ if(selectionList[i].type == 'group') {
+ vboxChooser.getGroupElement(selectionList[i].groupPath, true).find('table.vboxChooserVM:not(.ui-draggable-dragging)').each(function(idx,elm){
+ if(elm) {
+ var vmid = $(elm).data('vmid');
+ if(vmid)
+ vmListUnique[vmid] = vmid;
+ }
+ });
+ switch(selectionMode) {
+ case vboxSelectionModeSingleGroup:
+ case vboxSelectionModeSingleVM:
+ selectionMode = vboxSelectionModeMultiVM;
+ break;
+ case vboxSelectionModeNone:
+ selectionMode = vboxSelectionModeSingleGroup;
+ }
+ } else {
+ switch(selectionMode) {
+ case vboxSelectionModeNone:
+ selectionMode = vboxSelectionModeSingleVM;
+ break;
+ default:
+ selectionMode = vboxSelectionModeMultiVM;
+ }
+
+ vmListUnique[selectionList[i].id] = selectionList[i].id;
+ }
+ }
+
+ // Change selection list
+ var selectedVMs = [];
+ for(var i in vmListUnique) {
+ selectedVMs[selectedVMs.length] = i;
+ }
+
+ vboxChooser.selectedVMs = selectedVMs;
+
+ // If there is only one unique vm selected,
+ // selection mode becomes single VM if the
+ // current selection mode is not singleGroup
+ if(vboxChooser.selectedVMs.length == 1 && selectionMode != vboxSelectionModeSingleGroup)
+ selectionMode = vboxSelectionModeSingleVM;
+
+ vboxChooser.selectionMode = selectionMode;
+
+ vboxChooser._selectedList = selectionList;
+
+ $('#vboxPane').trigger('vmSelectionListChanged',[vboxChooser]);
+
+
+ },
+
+ /**
+ * Return the single selected VM's id if
+ * only one vm is selected. Else null.
+ */
+ getSingleSelectedId : function() {
+ if(vboxChooser.selectedVMs.length == 1) {
+ return vboxChooser.selectedVMs[0];
+ }
+ return null;
+ },
+
+ /*
+ * Return a single vm if only one is selected.
+ * Else null.
+ */
+ getSingleSelected : function() {
+ if(vboxChooser.selectedVMs.length == 1) {
+ return vboxVMDataMediator.getVMData(vboxChooser.selectedVMs[0]);
+ }
+ return null;
+ },
+
+ /*
+ * Update list of VMs from data received
+ * from ajax query
+ */
+ updateList : function(vmlist) {
+
+ // We were stopped before the request returned data
+ if(!vboxChooser._running) return;
+
+
+ // No list? Something is wrong
+ if(!vmlist) {
+
+ phpVirtualBoxFailure();
+
+ vboxChooser.stop();
+ vboxChooser._anchor.children().remove();
+ return;
+ }
+
+ // Remove spinner
+ vboxChooser._anchor.children().remove();
+
+ // Render host
+ vboxChooser._anchor.append(vboxChooser.vmHTML(
+ {
+ 'id':'host',
+ 'state':'Hosting',
+ 'owner':'',
+ 'name':$('#vboxPane').data('vboxConfig').name,
+ 'OSTypeId':'VirtualBox_Host'
+ }
+ ));
+
+ // Render root group
+ vboxChooser._anchor.append(vboxChooser.groupHTML("/"));
+
+ // Enforce VM ownership
+ if($('#vboxPane').data('vboxConfig').enforceVMOwnership && !$('#vboxPane').data('vboxSession').admin) {
+ vmlist = jQuery.grep(vmlist,function(vm,i){
+ return (vm.owner == $('#vboxPane').data('vboxSession').user);
+ });
+ }
+
+ var groups = [];
+ // Each item in list
+ for(var i = 0; i < vmlist.length; i++) {
+ // Update
+ vboxChooser.updateVMElement(vmlist[i], true);
+ groups = groups.concat(vmlist[i].groups);
+ }
+
+ // Sort groups
+ var groupsSorted = {};
+ for(var i = 0; i < groups.length; i++) {
+ if(groupsSorted[groups[i]]) continue;
+ groupsSorted[groups[i]] = true;
+ var gElm = vboxChooser.getGroupElement(groups[i], true);
+ if(gElm[0]) vboxChooser.sortGroup(gElm);
+ }
+
+ // compose group definitions
+ vboxChooser.composeGroupDef();
+
+ // Set initial resize
+ vboxChooser._initialResize = true;
+ vboxChooser._resizeElements(true);
+
+ },
+
+ /*
+ * Save collapsed group list
+ */
+ _collapsedGroups : [],
+ _saveCollapsedGroups : function(){
+
+ // Write out collapsed group list
+ var cGroupList = [];
+ vboxChooser._anchor.find('div.vboxVMGroupCollapsed:not(.ui-draggable-dragging)').each(function(idx,elm) {
+ cGroupList[cGroupList.length] = $(elm).data('vmGroupPath');
+ });
+
+ var groupListKey = $('#vboxPane').data('vboxConfig').key+'-collapsedGroups';
+ vboxSetLocalDataItem(groupListKey, cGroupList.join(','), true);
+
+ // Cache instead of using local storage
+ vboxChooser._collapsedGroups = cGroupList;
+ },
+
+ /*
+ * Return true if group is collapsed
+ */
+ _isGroupCollapsed : function(gpath) {
+ return(jQuery.inArray(gpath,vboxChooser._collapsedGroups) > -1);
+ },
+
+ /*
+ * Resize group and VM titles
+ */
+ _scrollbarWidth : 0,
+ _scrollbarWasVisible: false,
+ _initialResize: false,
+ _resizeElements : function(forceResize) {
+
+ // Haven't completed our initial resizing yet
+ if(!vboxChooser._initialResize) {
+ return;
+ }
+
+ var sbVisible = (vboxChooser._anchor.get(0).scrollHeight > vboxChooser._anchor.height());
+
+ // Nothing changed since resize
+ if(!forceResize && (sbVisible == vboxChooser._scrollbarWasVisible)) {
+ return;
+ }
+
+ vboxChooser._scrollbarWasVisible = sbVisible;
+
+ var groupTitleWidth = vboxChooser._anchor.width() - (vboxChooser._compact ? 22 : 32) - (sbVisible ? vboxChooser._scrollbarWidth : 0);
+ var vmTitleWidth = groupTitleWidth - (vboxChooser._compact ? -12 : 18); // (2px padding on .vboxChooserGroupVMs +
+ // 2px border on table + 4px margin on icon) * 2
+ var groupLevelOffset = (vboxChooser._compact ? 8 : 8); // (2px margin + 2px border) * 2
+
+
+ // Now that we have sizes, we can inject styles
+ $('#vboxChooserStyle').empty().remove();
+
+ var styleRules = [];
+ var path = ['div.vboxChooserGroupRootLevel'];
+
+ // Special case for root level VM list
+ styleRules[styleRules.length] = 'div.vboxChooserGroupRootLevel > div.vboxChooserGroupVMs table.vboxChooserVM div.vboxFitToContainer { width: ' + vmTitleWidth + 'px; }';
+
+ // Special case for group header when only showing one group
+ styleRules[styleRules.length] = 'div.vboxChooserGroupShowOnly.vboxChooserGroupRootLevel > div.vboxChooserGroupHeader span.vboxChooserGroupName { max-width: ' + (groupTitleWidth - 4) + 'px; }';
+
+ // Bottom group resize bars
+ styleRules[styleRules.length] = 'div.vboxChooserGroupRootLevel > div.vboxChooserDropTargetBottom { width: ' + (groupTitleWidth) + 30 + 'px; }';
+
+ for(var i = 1; i < 11; i++) {
+
+ // Group titles at this level
+ styleRules[styleRules.length] = path.join(' > ') + ' > div.vboxChooserGroup > div.vboxChooserGroupHeader span.vboxChooserGroupName { max-width: ' + (groupTitleWidth - (i*groupLevelOffset)) + 'px; }';
+
+ // VM titles at this level
+ styleRules[styleRules.length] = path.join(' > ') + ' > div.vboxChooserGroup > div.vboxChooserGroupVMs table.vboxChooserVM div.vboxFitToContainer { width: ' + (vmTitleWidth - (i*(groupLevelOffset))) + 'px; }';
+
+ // Bottom group resize bars
+ styleRules[styleRules.length] = path.join(' > ') +' > div.vboxChooserGroup > div.vboxChooserDropTargetBottom { width: ' + (groupTitleWidth + 30 - (i*groupLevelOffset)) + 'px; }';
+
+ path[path.length] = 'div.vboxChooserGroup';
+ }
+
+ // Style for minified vmlist
+ if(vboxChooser._compact) {
+ // Title moves left
+ styleRules[styleRules.length] = 'div.vboxChooserGroup > div.vboxChooserGroupVMs table.vboxChooserVM div.vboxVMName { position: relative; left: -20px; }';
+ // Icon moves down
+ styleRules[styleRules.length] = 'div.vboxChooserGroup > div.vboxChooserGroupVMs table.vboxChooserVM img.vboxVMIcon { position: relative; top: 8px; }';
+ // State text goes away
+ styleRules[styleRules.length] = 'div.vboxChooserGroup > div.vboxChooserGroupVMs table.vboxChooserVM span.vboxVMState { display: none; }';
+ // Less padding
+ styleRules[styleRules.length] = 'div.vboxChooserGroup > div.vboxChooserGroupVMs table.vboxChooserVM td { padding: 0px; }';
+ // Some group header items and drop targets go away
+ styleRules[styleRules.length] = 'div.vboxChooserGroup > div.vboxChooserGroupHeader > .vboxChooserGroupNameArrowCollapse, #' +vboxChooser._anchorid + ' div.vboxChooserGroup .vboxChooserDropTarget { display: none; }';
+ styleRules[styleRules.length] = 'div.vboxChooserGroup { overflow: hidden; }';
+ // host
+ styleRules[styleRules.length] = '#vboxChooserVMHost .vboxVMState { display: none; }';
+ // group header
+ styleRules[styleRules.length] = 'div.vboxChooserGroup div.vboxChooserGroupHeader { height: auto; padding: 2px; }';
+
+ }
+ $('head').append('<style type="text/css" id="vboxChooserStyle">#'+vboxChooser._anchorid + ' ' + styleRules.join("\n#"+vboxChooser._anchorid + " ") + '</style>');
+
+ },
+
+ /*
+ * Get group element by path
+ */
+ getGroupElement : function(gpath, noCreate) {
+
+ if(!gpath) gpath = '/';
+ var gnames = gpath.split('/');
+ var groot = vboxChooser._anchor.children('div.vboxChooserGroup:not(.ui-draggable-dragging)');
+ for(var i = 1; i < gnames.length; i++) {
+
+ if(!gnames[i]) continue;
+
+ var group = groot.children('div.vboxChooserGroup:not(.ui-draggable-dragging)').children('div.vboxChooserGroupIdentifier[title="'+gnames[i]+'"]').parent();
+
+ // If it does not exist, create it
+ if(!group[0]) {
+
+ if(noCreate) return null;
+
+ var gpath = '/';
+ for(var a = 1; a <= i; a++) {
+ gpath = gpath + '/' + gnames[a];
+ }
+ gpath = gpath.replace('//','/');
+
+ vboxChooser.groupHTML(gpath).insertBefore(groot.children('div.vboxChooserGroupVMs'));
+
+ vboxChooser.sortGroup(groot);
+
+ // Resize chooser elements
+ vboxChooser._initialResize = true;
+ vboxChooser._resizeElements();
+
+ groot = groot.children('div.vboxChooserGroup:not(.ui-draggable-dragging)').children('div.vboxChooserGroupIdentifier[title="'+gnames[i]+'"]').parent();
+
+ } else {
+ groot = group;
+ }
+
+ }
+ return groot;
+ },
+
+ /*
+ *
+ * Update VM elements
+ *
+ */
+ updateVMElement : function(vmUpdate, newVM) {
+
+ // Not running.. don't do anything
+ if(!vboxChooser._running) return;
+
+ // Stale event after vm was removed
+ if(!vmUpdate) return;
+
+ // New VM
+ if(newVM) {
+
+ // New VM.. add it to groups..
+ if(!vmUpdate.groups || vmUpdate.groups.length == 0)
+ vmUpdate.groups = ['/'];
+
+ for(var i = 0; i < vmUpdate.groups.length; i++) {
+ var gElm = $(vboxChooser.getGroupElement(vmUpdate.groups[i]));
+ vboxChooser.vmHTML(vmUpdate).appendTo(
+ gElm.children('div.vboxChooserGroupVMs')
+ );
+ }
+
+ // Existing VM. Replace existing elements
+ } else {
+
+ $('#'+vboxChooser._anchorid).find('table.vboxChooserItem-'+vboxChooser._anchorid+'-'+vmUpdate.id).each(function(i,elm){
+
+ var newHTML = vboxChooser.vmHTML(vmUpdate);
+ if($(elm).hasClass('vboxListItemSelected')) {
+ $(newHTML).addClass('vboxListItemSelected').removeClass('vboxHover');
+ }
+ $(elm).children().replaceWith(newHTML.children());
+ });
+
+ }
+
+ },
+
+
+ /*
+ * Returns true if there are VMs with ID vmid that are not selected
+ */
+ vmHasUnselectedCopy : function (vmid) {
+ return ($(vboxChooser._anchor).find('table.vboxChooserItem-'+vboxChooser._anchorid+'-'+vmid+':not(.vboxListItemSelected)').length > 0);
+ },
+
+ /*
+ * Remove selected VMs from the list and rewrite group definitions
+ * this assumes that there are other copies of these VMs that are not
+ * selected.
+ */
+ removeVMs : function(vmids) {
+
+ for(var i = 0; i < vmids.length; i++) {
+ $(vboxChooser._anchor).find('table.vboxChooserItem-'+vboxChooser._anchorid+'-'+vmids[i]+'.vboxListItemSelected').remove();
+ }
+
+ // Update selection list
+ vboxChooser._selectedList = vboxChooser._selectedList.filter(function(v){
+ return (v.type == 'group' || (jQuery.inArray(v.id, vmids) == -1));
+ });
+
+ // Tell interface that selection list has changed
+ vboxChooser.selectionListChanged(vboxChooser._selectedList);
+
+ // compose and save group definitions
+ vboxChooser.composeGroupDef(true);
+
+
+ // Possible resize needed
+ vboxChooser._resizeElements(true);
+
+ },
+
+ /*
+ * Generate HTML from VM definition
+ */
+ vmHTML : function (vmn) {
+
+ var tbl = $('<table />').attr({'class':'vboxChooserItem-'+vboxChooser._anchorid+'-'+vmn.id + " vboxChooserVM"})
+ .on('mousedown',vboxChooser.selectItem)
+ .hoverClass('vboxHover').data('vmid',vmn.id);
+
+
+ // Drag-and-drop functionality
+ /////////////////////////////////
+ if(vmn.id != 'host' && $('#vboxPane').data('vboxSession').admin) {
+
+ $(tbl).draggable({'cursorAt':{left: -10, top: -10},'helper':function(){
+ return $(this).clone().css({'width':($(this).width()+2)+'px','display':'inline','background':'#fff','border-color':'#69f'}).removeClass('vboxHover');
+
+ // drag start
+ },'start':function(e) {
+
+ if(!vboxChooser._editable) return false;
+
+ $(vboxChooser._anchor).disableSelection();
+ vboxChooser._dragging = vmn.id;
+ $(vboxChooser._anchor).find('table.vboxHover').removeClass('vboxHover');
+
+ // drag stop
+ },'stop':function(e) {
+ vboxChooser.vmDropped(e, $(this));
+ }});
+ }
+
+ // Functionality to drop above / below VM
+ /////////////////////////////////////////////
+ var td = $('<td />').attr({'colspan':'2'}).addClass('vboxChooserDropTarget vboxDropTargetTop');
+ if(vmn.id != 'host') {
+ td.hover(function(){
+ if(vboxChooser._dragging && vboxChooser._dragging != vmn.id)
+ $(this).addClass('vboxChooserDropTargetHover');
+ },function(){
+ $(this).removeClass('vboxChooserDropTargetHover');
+ }
+ );
+ }
+ $('<tr />').append(td).appendTo(tbl);
+
+
+
+ // VM OS type icon
+ var tr = $('<tr />');
+ if($('#vboxPane').data('vboxConfig').enableCustomIcons && vmn.customIcon) {
+ $('<td />').attr({'rowspan':'2'}).html("<img src='" + vmn.customIcon + "' class='vboxVMIcon' />").appendTo(tr);
+ } else {
+ $('<td />').attr({'rowspan':'2'}).html("<img src='images/vbox/" + vboxGuestOSTypeIcon(vmn.OSTypeId) + "' class='vboxVMIcon" + (vmn.id == 'host' ? " vboxHostIcon" : "") + "' />").appendTo(tr);
+ }
+
+
+ // VM Name
+ var td = $('<td />').attr({'class':'vboxVMTitle'});
+
+ // Host will have HTML in name and unique id
+ if(vmn.id == 'host') {
+
+ $(tbl).attr('id', 'vboxChooserVMHost');
+
+ // Check for multiple server config
+ if($('#vboxPane').data('vboxConfig').servers.length) {
+
+ // If there are multiple servers configured, setup menu
+ if(!$('#vboxServerMenu')[0]) {
+ var servers = $('#vboxPane').data('vboxConfig').servers;
+ var ul = $('<ul />').attr({'id':'vboxServerMenu','style':'display: none','class':'contextMenu'});
+ for(var i = 0; i < servers.length; i++) {
+ $('<li />').html("<a href='#" + $('<div />').html(servers[i].name).text() + "' style='background-image: url(images/vbox/OSE/VirtualBox_16px.png);'>"+$('<div />').html(servers[i].name).text()+"</a>").appendTo(ul);
+ }
+ $('#vboxPane').append(ul);
+ }
+
+ var span = $('<span />').attr({'class':'vboxServerLink'}).text('('+$('#vboxPane').data('vboxConfig').name+')').contextMenu({
+ menu: 'vboxServerMenu',
+ button: 0,
+ mode: 'menu'
+ },
+ function(a) {
+
+ if(a == $('#vboxPane').data('vboxConfig').name) return;
+
+ // Show loading screen
+ var l = new vboxLoader();
+ l.showLoading();
+
+ // Empty selection list
+ vboxChooser.selectionListChanged();
+
+
+ // Unsubscribe from events
+ $.when(vboxEventListener.stop()).done(function() {
+
+ // Expire data mediator data
+ vboxVMDataMediator.expireAll();
+
+ // Trigger host change
+ vboxSetCookie("vboxServer",a);
+ $('#vboxPane').trigger('hostChange',[a]);
+
+ }).always(function(){
+
+ // remove loading screen
+ l.removeLoading();
+
+ });
+
+
+ }
+ );
+ $(td).html('<span class="vboxVMName">VirtualBox</span> ').append(span);
+ } else {
+ $(td).html('<span class="vboxVMName">VirtualBox</span> ('+vmn.name+')');
+ }
+
+ // Not rendering host
+ } else {
+
+ $(td).append('<div class="vboxFitToContainer vboxVMName"><span class="vboxVMName">'+$('<span />').text(vmn.name).html()+'</span>'+ (vmn.currentSnapshotName ? '<span class="vboxVMChooserSnapshotName"> (' + $('<span />').text(vmn.currentSnapshotName).html() + ')</span>' : '')+'</div>');
+
+
+ // Table gets tool tips
+ tip = trans(vboxChooser._vmToolTip, 'UIVMListView').replace('%1',('<b>'+$('<span />')
+ .text(vmn.name).html()+'</b>'+(vmn.currentSnapshotName ? ' (' + $('<span />')
+ .text(vmn.currentSnapshotName).html() + ')' : '')))
+ .replace('%2',trans(vboxVMStates.convert(vmn.state),'VBoxGlobal'))
+ .replace('%3',vboxDateTimeString(vmn.lastStateChange))
+ .replace('%4',trans(vmn.sessionState,'VBoxGlobal').toLowerCase());
+
+ $(tbl).tipped({'source':tip,'position':'mouse','delay':1500});
+ }
+
+ $(tr).append(td).appendTo(tbl);
+
+ // VM state row
+ var tr = $('<tr />');
+ var td = $('<td />').attr({'class':(vmn.id != 'host' && vmn.sessionState != 'Unlocked' ? 'vboxVMSessionOpen' : '')});
+
+ // Add VirtualBox version if hosting
+ if(vmn.id == 'host') {
+
+ $(td).html("<div class='vboxFitToContainer vboxVMState'><img src='images/vbox/" + vboxMachineStateIcon(vmn.state) +"' /><span class='vboxVMState'>" + trans(vboxVMStates.convert(vmn.state),'VBoxGlobal') + ' - ' + $('#vboxPane').data('vboxConfig').version.string+'</span></div>');
+
+ // Check for version mismatches?
+ if(!vboxChooser._versionChecked) {
+ vboxChooser._versionChecked = true;
+ var vStr = $('#vboxPane').data('vboxConfig').phpvboxver.substring(0,$('#vboxPane').data('vboxConfig').phpvboxver.indexOf('-'));
+ var vers = $('#vboxPane').data('vboxConfig').version.string.replace('_OSE','').split('.');
+ if(vers[0]+'.'+vers[1] != vStr) {
+ vboxAlert('This version of phpVirtualBox ('+$('#vboxPane').data('vboxConfig').phpvboxver+') is incompatible with VirtualBox ' + $('#vboxPane').data('vboxConfig').version.string + ". You probably need to <a href='http://sourceforge.net/projects/phpvirtualbox/files/' target=_blank>download the latest phpVirtualBox " + vers[0]+'.'+vers[1] + "-x</a>.<p>See the Versioning section below the file list in the link for more information</p>",{'width':'auto'});
+ }
+ }
+ } else {
+ $(td).html("<div class='vboxFitToContainer vboxVMState'><img src='images/vbox/" + vboxMachineStateIcon(vmn.state) +"' /><span class='vboxVMState'>" + trans(vboxVMStates.convert(vmn.state),'VBoxGlobal') + '</span></div>');
+ }
+
+ $(tr).append(td).appendTo(tbl);
+
+ // Droppable targets
+ var td = $('<td />').attr({'colspan':'2'}).addClass('vboxChooserDropTarget vboxDropTargetBottom');
+ if(vmn.id != 'host') {
+ td.hover(function(){
+ if(vboxChooser._dragging && vboxChooser._dragging != vmn.id)
+ $(this).addClass('vboxChooserDropTargetHover');
+ },function(){
+ $(this).removeClass('vboxChooserDropTargetHover');
+ }
+ );
+ }
+ $('<tr />').addClass('vboxChooserDropTarget').css({'height':'4px'}).append(td).appendTo(tbl);
+
+
+ // Context menus?
+ if(vboxChooser._vmContextMenuObj) {
+
+ $(tbl).contextMenu({
+ menu: vboxChooser._vmContextMenuObj.menuId(),
+ menusetup : function(el) {
+ if(!$(el).hasClass('vboxListItemSelected')) $(el).trigger('click');
+ }
+ },function(act,el,pos,d,e){
+ vboxChooser._vmContextMenuObj.menuClickCallback(act);
+ });
+
+ // Open settings on dblclick
+ $(tbl).dblclick(function(){
+ if(vboxChooser._vmContextMenuObj.menuItems['settings'].enabled())
+ vboxChooser._vmContextMenuObj.menuItems['settings'].click();
+ });
+ }
+
+ return tbl;
+
+ },
+
+
+ /*
+ * VM Group Dropped
+ */
+ vmGroupDropped : function(e, droppedGroup) {
+
+
+ $(vboxChooser._anchor).enableSelection();
+
+
+ var vmGroupPath = vboxChooser._draggingGroup;
+ vboxChooser._draggingGroup = false;
+ $(droppedGroup).removeClass('vboxHover');
+
+ if(!vboxChooser._editable) return false;
+
+ // Cannot drag a group that contains a VM without
+ // an unlocked session state if it will modify VM
+ // Groups
+ var sessionLocked = false;
+ if($(droppedGroup).find('td.vboxVMSessionOpen')[0])
+ sessionLocked=true;
+
+
+ // Check for above/below group first
+ var dropTarget = vboxChooser._anchor.find('div.vboxChooserDropTargetHover').first();
+ if(dropTarget[0]) {
+
+ // Make sure that this wasn't dropped onto a sub-group or itself
+ if(
+ !dropTarget.closest('div.vboxChooserGroup')[0]
+ ||
+ vmGroupPath == dropTarget.closest('div.vboxChooserGroup').data('vmGroupPath')
+ ||
+ dropTarget.closest('div.vboxChooserGroup').data('vmGroupPath').indexOf(vmGroupPath + '/') == 0
+ ) {
+ return;
+ }
+
+
+ // If we are not still in the same group, check for name conflict
+ var currParentGroupPath = $(droppedGroup).closest('div.vboxChooserGroup').parent().closest('div.vboxChooserGroup').data('vmGroupPath');
+
+ if(dropTarget.closest('div.vboxChooserGroup').parent().closest('div.vboxChooserGroup').data('vmGroupPath') != currParentGroupPath) {
+
+ // Do not allow to be dragged into another group
+ // if there is a Vm with a locked session in this one
+ if(sessionLocked && !$('#vboxPane').data('vboxConfig')['phpVboxGroups']) return;
+
+ // Make sure there are no conflicts
+ var groupName = $(droppedGroup).children('div.vboxChooserGroupIdentifier').attr('title');
+ var newGroupName = groupName;
+
+
+ var i = 2;
+ while(vboxChooser.groupNameConflicts(dropTarget.closest('div.vboxChooserGroup').parent(), newGroupName)) {
+ newGroupName = groupName + ' (' + (i++) + ')';
+ }
+
+ $(droppedGroup).children('div.vboxChooserGroupIdentifier').attr({'title':newGroupName})
+ .siblings('div.vboxChooserGroupHeader')
+ .children('span.vboxChooserGroupName').text(newGroupName);
+
+ }
+
+ // Insert before or insert after?
+ if(dropTarget.hasClass('vboxDropTargetTop')) {
+ $(droppedGroup).detach().insertBefore(dropTarget.closest('div.vboxChooserGroup'));
+ } else {
+ $(droppedGroup).detach().insertAfter(dropTarget.closest('div.vboxChooserGroup'));
+ }
+
+
+ // Dropped onto a group or main VM list
+ } else {
+
+ // Will not do this if this group contains
+ // a VM with a locked session
+ if(sessionLocked && !$('#vboxPane').data('vboxConfig')['phpVboxGroups']) return;
+
+ var dropTarget = vboxChooser._anchor.find('div.vboxHover').first();
+
+
+ // Dropped onto a group
+ if(dropTarget[0] && dropTarget.parent().hasClass('vboxChooserGroup')) {
+
+ dropTarget = dropTarget.parent();
+
+ // Make sure that this wasn't dropped onto a sub-group or itself
+ if(
+ vmGroupPath == dropTarget.data('vmGroupPath')
+ ||
+ dropTarget.closest('div.vboxChooserGroup').data('vmGroupPath').indexOf(vmGroupPath + '/') == 0
+ ) {
+ return;
+ }
+
+ // Dropped onto main vm list
+ } else if($(vboxChooser._anchor).find('div.vboxGroupHover').length == 0 && $(vboxChooser._anchor).hasClass('vboxChooserDropTargetHoverRoot')) {
+
+ dropTarget = null;
+
+ // Only showing one group?
+ if(vboxChooser._showOnlyGroupHistory.length > 0) {
+ dropTarget = $(vboxChooser._showOnlyGroupHistory[vboxChooser._showOnlyGroupHistory.length-1]);
+ }
+
+ if(!$(dropTarget)[0])
+ dropTarget = vboxChooser._anchor.children('div.vboxChooserGroup');
+
+ } else {
+ return;
+ }
+
+ // Make sure there are no conflicts
+ var newElm = $(droppedGroup).detach();
+ var groupName = $(droppedGroup).children('div.vboxChooserGroupIdentifier').attr('title');
+ var newGroupName = groupName;
+
+ var i = 2;
+ while(vboxChooser.groupNameConflicts(dropTarget, newGroupName, $(newElm).data('vmGroupPath'))) {
+ newGroupName = groupName + ' (' + (i++) + ')';
+ }
+
+ $(newElm)
+ .children('div.vboxChooserGroupIdentifier').attr({'title':newGroupName})
+ .siblings('div.vboxChooserGroupHeader')
+ .children('span.vboxChooserGroupName').text(newGroupName);
+ $(newElm).insertBefore(dropTarget.children('div.vboxChooserGroupVMs'));
+
+ }
+
+ // vmGroup dropped - compose and save group definitions
+ vboxChooser.composeGroupDef(true);
+
+ // Hide group info
+ vboxChooser._anchor.find('div.vboxChooserGroupHeader').trigger('mouseout');
+
+ // Resize chooser elements
+ vboxChooser._resizeElements();
+
+ vboxChooser.selectionListChanged(vboxChooser._selectedList);
+
+ },
+
+ /*
+ * VM dropped
+ */
+ vmDropped : function (e, droppedVM){
+
+
+ $(vboxChooser._anchor).enableSelection();
+ vboxChooser._dragging = null;
+
+ if(!vboxChooser._editable) return false;
+
+ // Cannot drag if this VM's session is not open
+ var thisSessionLocked = false;
+ var vmData = vboxVMDataMediator.getVMData($(droppedVM).data('vmid'));
+
+ if(vmData.sessionState != 'Unlocked')
+ thisSessionLocked = true;
+
+
+
+ // Where was this dropped?
+ var dropTarget = $('#'+vboxChooser._anchorid).find('td.vboxChooserDropTargetHover');
+
+ // Dropped above / below a VM
+ if(dropTarget[0]) {
+
+ // Dropped from another group into this one,
+ // but this group already has this VM
+ if((dropTarget.closest('table').closest('div.vboxChooserGroup').data('vmGroupPath') != $(droppedVM).closest('div.vboxChooserGroup').data('vmGroupPath'))
+ && dropTarget.closest('table').siblings('table.vboxChooserItem-'+vboxChooser._anchorid+'-'+$(droppedVM).data('vmid'))[0]) {
+ return true;
+ }
+
+ // If session of this VM is locked, don't allow it to be
+ // dragged out of current group
+ if(thisSessionLocked && !$('#vboxPane').data('vboxConfig')['phpVboxGroups'] && ($(droppedVM).closest('div.vboxChooserGroup').data('vmGroupPath') != dropTarget.closest('div.vboxChooserGroup').data('vmGroupPath'))) {
+ return
+ }
+
+ // Get VM from target's parent table
+ if(dropTarget.hasClass('vboxDropTargetTop')) {
+ if(!e.ctrlKey && !e.metaKey) {
+ $(droppedVM).detach().insertBefore($(dropTarget).closest('table'));
+ } else {
+ // Copy
+ if($(dropTarget).closest('table').parent().children('table.vboxChooserItem-'+vboxChooser._anchorid+'-'+vmData.id)[0])
+ return;
+ vboxChooser.vmHTML(vmData).insertBefore($(dropTarget).closest('table'));
+ }
+ } else {
+ if(!e.ctrlKey && !e.metaKey) {
+ $(droppedVM).detach().insertAfter($(dropTarget).closest('table'));
+ } else {
+ // Copy - Don't allow if it already exists
+ if($(dropTarget).closest('table').parent().children('table.vboxChooserItem-'+vboxChooser._anchorid+'-'+vmData.id)[0])
+ return;
+ vboxChooser.vmHTML(vmData).insertAfter($(dropTarget).closest('table'));
+ }
+ }
+
+ // Not dropped above / below vm
+ } else {
+
+ // Don't allow this if sessoin is locked
+ if(thisSessionLocked && !$('#vboxPane').data('vboxConfig')['phpVboxGroups']) return;
+
+ // Dropped ON a vm?
+ dropTarget = $('#'+vboxChooser._anchorid).find('table.vboxHover:not(.ui-draggable-dragging)').first();
+ if($(dropTarget).data('vmid')) {
+
+ // Create a group?
+ dropTarget = $('#'+vboxChooser._anchorid).find('table.vboxHover').first();
+
+ // Nothing to do. Not dropped on valid target
+ if(!dropTarget[0] || ($(dropTarget).data('vmid') == $(droppedVM).data('vmid'))) return true;
+
+ // Dont' allow this if target VM's session is locked
+ if($(dropTarget).find('td.vboxVMSessionOpen')[0])
+ return;
+
+ // Where to drop vboxChooser..
+ var p = dropTarget.closest('div.vboxChooserGroup').children('div.vboxChooserGroupVMs');
+ // assume root?
+ if(!p[0]) p = vboxChooser._anchor.children('div.vboxChooserGroupVMs');
+
+ // Determine group name
+ var gname = trans('New group','UIGChooserModel');
+ var tgname = gname;
+
+ var i = 2;
+ while(vboxChooser.groupNameConflicts($(p).parent(), tgname)) {
+ tgname = gname + ' ' + (i++);
+ }
+
+
+ // New position is below target
+ var ghtml = vboxChooser.groupHTML(String(dropTarget.closest('div.vboxChooserGroup').data('vmGroupPath')+'/'+tgname).replace('//','/'));
+
+ if(!e.ctrlKey && !e.metaKey) {
+ ghtml.children('div.vboxChooserGroupVMs').append($(droppedVM).detach());
+ } else {
+ ghtml.children('div.vboxChooserGroupVMs').append(vboxChooser.vmHTML(vmData));
+ }
+ ghtml.children('div.vboxChooserGroupVMs').append(dropTarget.detach());
+
+ ghtml.insertBefore(p);
+
+ // Dropped in the main VM list or group header?
+ } else {
+
+ dropTarget = $(vboxChooser._anchor).find('div.vboxHover').first();
+ if(dropTarget[0] && dropTarget.hasClass('vboxChooserGroupHeader')) {
+
+ // Group already has this dragging VM?
+ if(dropTarget.siblings('div.vboxChooserGroupVMs').children('table.vboxChooserItem-'+vboxChooser._anchorid+'-'+$(droppedVM).data('vmid'))[0]) {
+ return;
+ }
+
+ if(!e.ctrlKey && !e.metaKey)
+ $(droppedVM).detach().appendTo(dropTarget.siblings('div.vboxChooserGroupVMs').first());
+ else
+ vboxChooser.vmHTML(vmData).appendTo(dropTarget.siblings('div.vboxChooserGroupVMs').first());
+
+ // Main VM list
+ } else if($(vboxChooser._anchor).find('div.vboxGroupHover').length == 0 && $(vboxChooser._anchor).hasClass('vboxChooserDropTargetHoverRoot')) {
+
+ dropTarget = null;
+
+ // Only showing one group?
+ if(vboxChooser._showOnlyGroupHistory.length > 0) {
+ dropTarget = $(vboxChooser._showOnlyGroupHistory[vboxChooser._showOnlyGroupHistory.length-1]);
+ }
+
+ if(!$(dropTarget)[0])
+ dropTarget = vboxChooser._anchor.children('div.vboxChooserGroup');
+
+ // Already in this list?
+ if(dropTarget.children('div.vboxChooserGroupVMs').children('table.vboxChooserItem-'+vboxChooser._anchorid+'-'+$(droppedVM).data('vmid'))[0]) {
+ return true;
+ }
+
+ if(!e.ctrlKey && !e.metaKey) {
+ $(droppedVM).detach().appendTo(dropTarget.children('div.vboxChooserGroupVMs').first());
+ } else {
+ vboxChooser.vmHTML(vmData).appendTo(dropTarget.children('div.vboxChooserGroupVMs').first());
+ }
+
+ }
+ }
+
+ }
+
+ // vm dropped - compose and save group definitions
+ vboxChooser.composeGroupDef(true);
+
+ // Resize chooser elements
+ vboxChooser._resizeElements();
+
+ vboxChooser.selectionListChanged(vboxChooser._selectedList);
+
+ },
+
+ /*
+ * Group selected items into a new group
+ */
+ groupSelectedItems : function() {
+
+ // Get all group paths to determine new group target
+ var groupPaths = {};
+ vboxChooser._anchor.find('div.vboxVMGroupSelected').closest('div.vboxChooserGroup').each(function(idx,elm) {
+ groupPaths[$(elm).data('vmGroupPath')] = 1;
+ });
+ vboxChooser._anchor.find('table.vboxListItemSelected').closest('div.vboxChooserGroup').each(function(idx,elm) {
+ groupPaths[$(elm).data('vmGroupPath')] = 1;
+ });
+
+ // The group clsest to the root group will be the target
+ var groupPathTarget = null;
+ for(var i in groupPaths) {
+
+ if(typeof(i) != 'string') continue;
+
+ // Already at root group. Nothing to do
+ if(groupPathTarget == '/') break;
+
+ // No target set yet or equal targets, or this group is the root
+ if(!groupPathTarget || groupPathTarget == i || i == '/') {
+ groupPathTarget = i;
+ continue;
+ }
+
+ var t1 = groupPathTarget.split("/");
+ var t2 = i.split("/");
+ for(var i = 0; i < Math.min(t1.length,t2.length); i++) {
+ if(t1[i] != t2[i]) {
+ groupPathTarget = '';
+ for(var a = 0; a < i; a++) {
+ groupPathTarget += "/" + t1[a];
+ }
+ groupPathTarget = groupPathTarget.replace('//','/');
+ break;
+ }
+ }
+
+
+ }
+
+ var target = vboxChooser.getGroupElement(groupPathTarget, true);
+
+ if(!$(target)[0]) return;
+
+ // Determine group name
+ var gname = trans('New group','UIGChooserModel');
+ var tgname = gname;
+
+ var i = 2;
+ while(vboxChooser.groupNameConflicts($(target), tgname)) {
+ tgname = gname + ' ' + (i++);
+ }
+
+ var gHTML = vboxChooser.groupHTML('/'+tgname);
+
+ // Append group and vm elements
+ vboxChooser._anchor.find('div.vboxVMGroupSelected').detach().insertAfter(gHTML.children('div.vboxChooserGroupHeader'));
+ vboxChooser._anchor.find('table.vboxListItemSelected').detach().appendTo(gHTML.children('div.vboxChooserGroupVMs'));
+
+ gHTML.insertBefore($(target).children('div.vboxChooserGroupVMs'));
+
+ // group selected items,
+ // Compose and save group definitions
+ vboxChooser.composeGroupDef(true);
+
+ // Resize chooser elements
+ vboxChooser._resizeElements();
+
+
+
+ },
+
+ /**
+ * Compose group data from GUI and optionally save it
+ *
+ * @param save - save group definitions to vbox
+ */
+ composeGroupDef : function(save) {
+
+ var allGroups = [];
+ var groupsResolved = false;
+
+ // Keep looping through group definitions until
+ // there are no groups removed
+ while(!groupsResolved) {
+
+ allGroups = [];
+ groupsResolved = true;
+
+ vboxChooser._anchor.find('div.vboxChooserGroup:not(.ui-draggable-dragging)').each(function(idx,elm) {
+
+ // Group element was removed
+ if(!$(elm)[0]) return;
+
+ // Compose group path
+ var myPath = $(elm).children('div.vboxChooserGroupIdentifier').attr('title');
+ if(!myPath) myPath = '/';
+ $(elm).parents('div.vboxChooserGroup:not(.ui-draggable-dragging)').each(function(idx2,elm2){
+ var pName = $(elm2).children('div.vboxChooserGroupIdentifier').attr('title');
+ if(!pName) pName = '/';
+ myPath = String(pName + '/' + myPath).replace('//','/');
+ });
+
+ // Groups
+ var gList = [];
+ $(elm).children('div.vboxChooserGroup:not(.ui-draggable-dragging)').each(function(idx2,elm2){
+
+ // If this group is selected, we'll have to update its path
+ // in the selection list
+ var selected = $(elm2).hasClass('vboxVMGroupSelected');
+ var oldPath = $(elm2).data('vmGroupPath');
+ var newPath = String(myPath + '/' + $(elm2).children('div.vboxChooserGroupIdentifier').attr('title')).replace('//','/');
+
+ gList[gList.length] = $(elm2).children('div.vboxChooserGroupIdentifier').attr('title');
+
+ // set / correct group path data
+ $(elm2).data('vmGroupPath', newPath);
+
+ // Group's path changed?
+ if(selected && (oldPath != newPath)) {
+ for(var i = 0; i < vboxChooser._selectedList.length; i++) {
+ if(vboxChooser._selectedList[i].type == 'group' && vboxChooser._selectedList[i].groupPath == oldPath) {
+ vboxChooser._selectedList[i].groupPath = String(myPath + '/' + $(elm2).children('div.vboxChooserGroupIdentifier').attr('title')).replace('//','/');
+ break;
+ }
+ }
+ }
+
+ });
+
+ // VMs
+ var vmList = [];
+ $(elm).children('div.vboxChooserGroupVMs').children('table.vboxChooserVM:not(.ui-draggable-dragging)').each(function(idx3,elm3){
+ vmList[vmList.length] = $(elm3).data('vmid');
+ });
+
+ // Skip and remove if there are no VMs or subgroups
+ // And it is not the parent group
+ if(gList.length + vmList.length == 0 && !$(elm).hasClass('vboxChooserGroupRoot')) {
+
+ // remove from selected list?
+ if(elm && $(elm).hasClass('vboxVMGroupSelected')) {
+
+ var myPath = $(elm).data('vmGroupPath');
+ // Deselect item
+ vboxChooser._selectedList = vboxChooser._selectedList.filter(function(v){
+ return (v.type != 'group' || (v.groupPath != myPath));
+ });
+ }
+ $(elm).empty().remove();
+ groupsResolved = false;
+ return false;
+ }
+
+ // append to all groups list
+ gorder = [];
+ if(gList.length) gorder[0] = 'go='+gList.join(',go=');
+ if(vmList.length) gorder[gorder.length] = 'm='+vmList.join(',m=');
+ allGroups[allGroups.length] = {
+ path: $(elm).data('vmGroupPath'),
+ order: gorder.join(',')
+ };
+
+ // Update counts span
+ $(elm).children('div.vboxChooserGroupVMs').css({'display':(vmList.length || $(elm).data('vmGroupPath') == '/' ? '' : 'none')})
+ .siblings('div.vboxChooserGroupHeader')
+ .each(function(hidx,header) {
+
+ var staticTip = '<strong>'+$(header).siblings('div.vboxChooserGroupIdentifier').attr('title')+'</strong>'+
+ (gList.length ? ('<br />' + trans('%n group(s)','UIGChooserItemGroup',gList.length).replace('%n',gList.length)) : '') +
+ (vmList.length ? ('<br />' + trans('%n machine(s)','UIGChooserItemGroup',vmList.length).replace('%n',vmList.length)) : '');
+
+ $(header).tipped({'source':function() {
+
+ // find number of running VMs
+ var runningVMs = 0;
+
+ if(vmList.length) {
+ $(header).siblings('div.vboxChooserGroupVMs').find('td.vboxVMSessionOpen').each(function(idx,elm3) {
+ if(vboxVMStates.isRunning(vboxVMDataMediator.getVMData($(elm3).closest('table').data('vmid'))))
+ runningVMs++;
+ });
+ }
+
+ return staticTip + (runningVMs > 0 ? ' ' + trans('(%n running)','UIGChooserItemGroup',runningVMs).replace('%n', runningVMs) : '');
+ }
+ ,'position':'mouse','delay':1500});
+ })
+ .children('span.vboxChooserGroupInfo')
+ .children('span.vboxChooserGroupCounts').html(
+ (gList.length ? ('<span style="background-image:url(images/vbox/group_abstract_16px.png);" />'+gList.length) : '') +
+ (vmList.length ? ('<span style="background-image:url(images/vbox/machine_abstract_16px.png);" />'+vmList.length) : '')
+ );
+ });
+
+ }
+
+ // Save GUI group definition?
+ if(!save) return;
+
+
+ // Tell the interface we're about to save groups
+ vboxChooser._editable = false;
+ $('#vboxPane').trigger('vmGroupDefsSaving');
+
+ vboxChooser._groupDefs = allGroups;
+
+ // Save machine groups and trigger change
+ var vms = [];
+ var vmList = vboxVMDataMediator.getVMList();
+ for(var i = 0; i < vmList.length; i++) {
+
+ if(!vmList[i] || vmList[i].id == 'host') continue;
+
+ /* If a VM's groups have changed, add it to the list */
+ var eGroups = vmList[i].groups;
+ var nGroups = vboxChooser.getGroupsForVM(vmList[i].id);
+
+ if($(nGroups).not(eGroups).length || $(eGroups).not(nGroups).length) {
+
+ vms[vms.length] = {
+ 'id' : vmList[i].id,
+ 'groups' : nGroups
+ };
+ }
+ }
+
+ // Save machines groups?
+ if(vms.length) {
+
+ // Reload VMs and group definitions
+ var reloadAll = function() {
+
+ var ml = new vboxLoader();
+ ml.add('vboxGetMedia',function(d){$('#vboxPane').data('vboxMedia',d.responseData);});
+ ml.add('vboxGroupDefinitionsGet',function(d){vboxChooser._groupDefs = d.responseData;});
+
+ // Reload VM list and group definitions, something went wrong
+ ml.onLoad = function() {
+
+ // Stop vmlist from refreshing..
+ vboxChooser.stop();
+
+ // reset selections
+ $('#vboxPane').trigger('vmSelectionListChanged',[vboxChooser]);
+
+ // ask for new one
+ vboxChooser.start();
+ };
+ ml.run();
+ };
+
+ $.when(vboxAjaxRequest('machinesSaveGroups',{'vms':vms})).done(function(res){
+
+ if(res.responseData.errored) {
+ reloadAll();
+ vboxChooser._editable = true;
+ $('#vboxPane').trigger('vmGroupDefsSaved');
+ } else {
+ $.when(vboxAjaxRequest('vboxGroupDefinitionsSet',{'groupDefinitions':allGroups})).always(function(){
+ vboxChooser._editable = true;
+ $('#vboxPane').trigger('vmGroupDefsSaved');
+ });
+ }
+
+ }).fail(reloadAll);
+
+ } else {
+ $.when(vboxAjaxRequest('vboxGroupDefinitionsSet',{'groupDefinitions':allGroups})).always(function(){
+ vboxChooser._editable = true;
+ $('#vboxPane').trigger('vmGroupDefsSaved');
+ });
+ }
+
+
+ return allGroups;
+
+ },
+
+ /*
+ * Return a list of groups that VM is a member of
+ */
+ getGroupsForVM : function(vmid) {
+ var gPathList = [];
+ vboxChooser._anchor.find('table.vboxChooserItem-'+vboxChooser._anchorid+'-'+vmid+':not(.ui-draggable-dragging)').each(function(idx,elm){
+ var gParent = $(elm).closest('div.vboxChooserGroup');
+ if(!gParent.hasClass('ui-draggable-dragging'))
+ gPathList[gPathList.length] = gParent.data('vmGroupPath');
+ });
+ return gPathList;
+ },
+
+ /*
+ * Determine whether or not a group name conflicts
+ * with another group in parent
+ */
+ groupNameConflicts : function(parentGroup, name, ignoreGroupAtPath) {
+ var found = false;
+ parentGroup.children('div.vboxChooserGroup:not(.ui-draggable-dragging)').children('div.vboxChooserGroupIdentifier[title="'+name+'"]').parent().each(function(i,elm){
+
+ if(ignoreGroupAtPath && (ignoreGroupAtPath == $(elm).data('vmGroupPath')))
+ return true;
+
+ found=true;
+ return false;
+ });
+ return found;
+ },
+
+ /*
+ * Ungroup selected group
+ */
+ unGroupSelectedGroup : function() {
+
+ var target = $(vboxChooser.getSelectedGroupElements()[0]).siblings('div.vboxChooserGroupVMs');
+
+ // Groups
+ // - ignore group at path we are currently ungrouping
+ var ignoreGroup = $(vboxChooser.getSelectedGroupElements()[0]).data('vmGroupPath');
+ $(vboxChooser.getSelectedGroupElements()[0]).children('div.vboxChooserGroup').each(function(i,elm) {
+
+ // Make sure there are no conflicts
+ var newElm = $(elm).detach();
+ var groupName = $(elm).children('div.vboxChooserGroupIdentifier').attr('title');
+ var newGroupName = groupName;
+
+ var i = 2;
+ while(vboxChooser.groupNameConflicts($(target).parent(), newGroupName, ignoreGroup)) {
+ newGroupName = groupName + ' (' + (i++) + ')';
+ }
+
+ $(newElm).children('div.vboxChooserGroupIdentifier').attr({'title':newGroupName})
+ .siblings('div.vboxChooserGroupHeader')
+ .children('span.vboxChooserGroupName').text(newGroupName);
+
+ $(newElm).insertBefore(target);
+
+ });
+
+ // VMs
+ $(vboxChooser.getSelectedGroupElements()[0]).children('div.vboxChooserGroupVMs').children().each(function(i,elm){
+ $(elm).detach();
+ if(!target.children('table.vboxChooserItem-'+vboxChooser._anchorid+'-'+$(elm).data('vmid'))[0])
+ target.append(elm);
+ });
+
+
+ // ungroup selected items
+ // compose and save group definitions
+ vboxChooser.composeGroupDef(true);
+
+ // Resize chooser elements
+ vboxChooser._resizeElements();
+
+ vboxChooser.selectionListChanged();
+
+
+ },
+
+ /*
+ * Sort group sub-elements based on VirtualBox
+ * group definitions
+ */
+ sortGroup : function(gElm) {
+
+ // Find group orders
+ var gPath = $(gElm).data('vmGroupPath');
+ var groupList = vboxChooser._groupDefs;
+
+ if(!(gPath && groupList)) return;
+
+ var machineOrder = [];
+ var groupOrder = [];
+
+ // Get correct order
+ for(var i = 0; i < groupList.length; i++) {
+ if(groupList[i].path == gPath) {
+ order = groupList[i].order.split(',');
+ for(var a = 0; a < order.length; a++) {
+ kv = order[a].split('=',2);
+ if(kv[0] == 'm') machineOrder[machineOrder.length] = kv[1];
+ else groupOrder[groupOrder.length] = kv[1];
+ }
+ }
+ }
+
+ // sort groups
+ var groups = $(gElm).children('div.vboxChooserGroup').get();
+ var maxPos = groups.length;
+ groups.sort(function(a,b){
+
+ var Pos1 = jQuery.inArray($(a).children('div.vboxChooserGroupIdentifier').attr('title'), groupOrder);
+ var Pos2 = jQuery.inArray($(b).children('div.vboxChooserGroupIdentifier').attr('title'), groupOrder);
+
+ if(Pos1==-1) Pos1 = maxPos;
+ if(Pos2==-1) Pos2 = maxPos;
+
+ return (Pos1 > Pos2 || Pos1 == -1 ? -1 : (Pos2 == Pos1 ? 0 : 1));
+
+ });
+ $.each(groups, function(idx,itm) {
+ $(itm).insertAfter($(gElm).children('div.vboxChooserGroupHeader'));
+ });
+
+ // sort VMs
+ var vms = $(gElm).children('div.vboxChooserGroupVMs').children('table.vboxChooserVM').get();
+ var maxPos = vms.length;
+ vms.sort(function(a,b) {
+
+ var Pos1 = jQuery.inArray($(a).data('vmid'), machineOrder);
+ var Pos2 = jQuery.inArray($(b).data('vmid'), machineOrder);
+
+ if(Pos1==-1) Pos1 = maxPos;
+ if(Pos2==-1) Pos2 = maxPos;
+
+ return (Pos1 > Pos2 ? 1 : (Pos2 == Pos1 ? 0 : -1));
+
+ });
+ $.each(vms, function(idx,itm) {
+ $(gElm).children('div.vboxChooserGroupVMs').append(itm);
+ });
+
+
+ },
+
+ /*
+ * Sort selected group by item names
+ */
+ sortSelectedGroup : function(rootElm) {
+
+ var el = $(vboxChooser.getSelectedGroupElements()[0]);
+
+ if(rootElm || !el) {
+ el = vboxChooser._anchor.children('div.vboxChooserGroup');
+ }
+
+ // sort groups
+ var groups = $(el).children('div.vboxChooserGroup').get();
+ groups.sort(function(a,b){
+ return $(b).children('div.vboxChooserGroupIdentifier').attr('title').localeCompare($(a).children('div.vboxChooserGroupIdentifier').attr('title'));
+ });
+ $.each(groups, function(idx,itm) {
+ $(itm).insertAfter($(el).children('div.vboxChooserGroupHeader'));
+ });
+
+ // sort VMs
+ var vms = $(el).children('div.vboxChooserGroupVMs').children('table.vboxChooserVM').get();
+ vms.sort(function(a,b) {
+ return $(a).find('span.vboxVMName').text().localeCompare($(b).find('span.vboxVMName').text());
+ });
+ $.each(vms, function(idx,itm) {
+ $(el).children('div.vboxChooserGroupVMs').append(itm);
+ });
+
+ // compose and save group definitions
+ vboxChooser.composeGroupDef(true);
+
+ },
+
+ /*
+ * Rename selected group
+ */
+ renameSelectedGroup : function() {
+
+ var el = $(vboxChooser.getSelectedGroupElements()[0]);
+
+ // Function to rename group
+ var renameGroup = function(e, textbox) {
+
+ if(!textbox) textbox = $(this);
+
+ var newName = $(textbox).val().replace(/[\\\/:*?"<>,]/g,'_');
+
+ if(newName && newName != $(textbox).closest('div.vboxChooserGroup').children('div.vboxChooserGroupIdentifier').attr('title')) {
+
+ // Do not rename if it conflicts
+ var noConflict = newName;
+ var i = 2;
+ while(vboxChooser.groupNameConflicts($(textbox).parent().parent().parent().parent(), noConflict)) {
+ noConflict = newName + ' (' + (i++) + ')';
+ }
+ newName = noConflict;
+
+ $(textbox).closest('div.vboxChooserGroup')
+ .children('div.vboxChooserGroupIdentifier').attr({'title':newName})
+ .siblings('div.vboxChooserGroupHeader')
+ .children('span.vboxChooserGroupName').html(newName);
+
+ // group renamed, compose and save groups
+ vboxChooser.composeGroupDef(true);
+
+ // Write out collapsed group list
+ vboxChooser._saveCollapsedGroups();
+
+ }
+
+
+ $(textbox).parent().parent().children().css({'display':''});
+ $(textbox).parent().empty().remove();
+ };
+
+ $(el).children('div.vboxChooserGroupHeader').children().css({'display':'none'});
+ $(el).children('div.vboxChooserGroupHeader').append(
+
+ $('<form />').append(
+ $('<input />').attr({'type':'text','value':$(el).children('div.vboxChooserGroupIdentifier').attr('title')}).css({'width':'90%','padding':'0px','margin':'0px'}).on('keypress',function(e){
+ if (e.which == 13) {
+ $(this).off('blur', renameGroup);
+ renameGroup(e,this);
+ e.stopPropagation();
+ e.preventDefault();
+ $(this).trigger('blur');
+ return false;
+ }
+ })
+ )
+
+ );
+ $(el).children('div.vboxChooserGroupHeader').children('form').children('input').focus().select().blur(renameGroup);
+
+ },
+
+ /*
+ * Select a single group
+ */
+ _selectGroup : function(gelm) {
+ $(gelm).addClass('vboxVMGroupSelected');
+ },
+
+ /*
+ * Deselect a single group
+ */
+ _deselectGroup : function(gelm) {
+
+ $(gelm).removeClass('vboxVMGroupSelected');
+ },
+
+ /*
+ * Select (or unselect) an item in our list. Called onmousedown or onCLick
+ */
+ selectItem : function(e) {
+
+ // Right click selects item if it is not selected
+ if(e.which != 1) {
+
+ // Right click on group header and group is selected
+ // just return and show context menu
+ if($(this).hasClass('vboxChooserGroupHeader') && $(this).parent().hasClass('vboxVMGroupSelected')) {
+ return true;
+
+ // Right click on VM and VM is already selected
+ // just return and show context menu
+ } else if($(this).hasClass('vboxListItemSelected')) {
+ return true;
+ }
+ }
+
+ var selectedList = [];
+ var item = $(this);
+
+
+ // Group?
+ if($(item).hasClass('vboxChooserGroupHeader')) {
+
+
+ // No control key. Exclusive selection
+ if(!e.ctrlKey && !e.metaKey) {
+
+ // already selected
+ if(vboxChooser._selectedList.length == 1 && vboxChooser._selectedList[0].type == 'group' &&
+ vboxChooser._selectedList[0].groupPath == $(item).parent().data('vmGroupPath'))
+ return true;
+
+ vboxChooser._anchor.find('.vboxListItemSelected').removeClass('vboxListItemSelected');
+ vboxChooser._anchor.find('div.vboxVMGroupSelected')
+ .each(function(idx,gelm) {
+ vboxChooser._deselectGroup(gelm);
+ });
+
+
+
+ // select current group
+ vboxChooser._selectGroup($(item).parent());
+
+ selectedList = [{
+ type: 'group',
+ groupPath: $(item).parent().data('vmGroupPath')
+ }];
+
+ // Already selected, and ctrl key
+ } else if($(item).parent().hasClass('vboxVMGroupSelected')){
+
+ // Deselect item
+ selectedList = vboxChooser._selectedList.filter(function(v){
+ return (v.type != 'group' || (v.groupPath != $(item).parent().data('vmGroupPath')));
+ });
+
+ vboxChooser._deselectGroup($(item).parent());
+
+ // Not already selected, and ctrl key
+ } else {
+
+ vboxChooser._selectGroup($(item).parent());
+
+ selectedList = vboxChooser._selectedList;
+
+ selectedList[selectedList.length] = {
+ type: 'group',
+ groupPath: $(item).parent().data('vmGroupPath')
+ };
+
+ }
+
+
+ // VM
+ } else {
+
+ // No ctrl key or selection is host. Exclusive selection
+ if((!e.ctrlKey && !e.metaKey) || $(item).data('vmid') == 'host') {
+
+ vboxChooser._anchor.find('.vboxListItemSelected').removeClass('vboxListItemSelected');
+ vboxChooser._anchor.find('div.vboxVMGroupSelected').removeClass('vboxVMGroupSelected')
+ .each(function(idx,gelm){
+ vboxChooser._deselectGroup(gelm);
+ });
+
+ // Select current VM
+ $(item).addClass('vboxListItemSelected').removeClass('vboxHover');
+
+ // already selected
+ if(vboxChooser._selectedList.length == 1 && vboxChooser._selectedList[0].type == 'vm' &&
+ vboxChooser._selectedList[0].id == $(item).data('vmid'))
+ return true;
+
+ selectedList = [{
+ type: 'vm',
+ id: $(item).data('vmid'),
+ groupPath: $(item).parent().data('vmGroupPath')
+ }];
+
+ // Already selected, and ctrl key
+ } else if($(item).hasClass('vboxListItemSelected')) {
+
+ // Deselect item
+ selectedList = vboxChooser._selectedList.filter(function(v){
+ return (v.type == 'group' || (v.id != $(item).data('vmid')));
+ });
+
+ $(item).removeClass('vboxListItemSelected');
+
+ // ctrl key, but not already selected
+ } else {
+
+ $(item).addClass('vboxListItemSelected').removeClass('vboxHover');
+
+ selectedList = vboxChooser._selectedList;
+
+ selectedList[selectedList.length] = {
+ type: 'vm',
+ id: $(item).data('vmid'),
+ groupPath: $(item).parent().data('vmGroupPath')
+ };
+
+ }
+
+ }
+
+ // Remove host?
+ if(selectedList.length > 1) {
+
+ // Deselect host
+ selectedList = selectedList.filter(function(v){
+ return (v.type == 'group' || (v.id != 'host'));
+ });
+
+ vboxChooser._anchor.children('table.vboxChooserItem-'+vboxChooser._anchorid+'-host').removeClass('vboxListItemSelected');
+
+ }
+
+ vboxChooser.selectionListChanged(selectedList);
+
+ return true;
+
+
+ },
+
+ /*
+ * Show only single group element identified by gelm
+ */
+ showOnlyGroupElm : function(gelm) {
+
+ // Going backwards affects animations
+ var back = false;
+
+ // gelm is null if we're going backwards
+ if(!gelm) {
+
+
+ if(vboxChooser._showOnlyGroupHistory.length > 1) {
+ // this gets rid of current
+ vboxChooser._showOnlyGroupHistory.pop();
+ // selects previous
+ gelm = vboxChooser._showOnlyGroupHistory.pop();
+ back = true;
+ } else {
+ gelm = null;
+ }
+
+
+ } else {
+
+ // Hold history
+ vboxChooser._showOnlyGroupHistory[vboxChooser._showOnlyGroupHistory.length] = gelm;
+ }
+
+
+ // No scrolling
+ vboxChooser._anchor.css({'overflow-y':'hidden'});
+
+ if($(gelm)[0]) {
+
+
+ // Slide over or back
+ $.when(vboxChooser._anchor.hide('slide', {direction: (back ? 'right' : 'left'), distance: (vboxChooser._anchor.outerWidth()/1.5)}, 200)).always(function() {
+
+
+ /* hide host when showing only a group */
+ $('table.vboxChooserItem-'+vboxChooser._anchorid+'-host').hide();
+
+
+ /* Undo anything previously performed by this */
+ vboxChooser._anchor.find('div.vboxChooserGroupHide').removeClass('vboxChooserGroupHide vboxChooserGroupHideShowContainer');
+ vboxChooser._anchor.find('div.vboxChooserGroupShowOnly').removeClass('vboxChooserGroupShowOnly');
+
+ $(gelm).parents('div.vboxChooserGroup').addClass('vboxChooserGroupHide vboxChooserGroupHideShowContainer').siblings().addClass('vboxChooserGroupHide');
+
+ vboxChooser._anchor.find('div.vboxChooserGroupRootLevel').removeClass('vboxChooserGroupRootLevel');
+ $(gelm).addClass('vboxChooserGroupShowOnly vboxChooserGroupRootLevel').siblings().addClass('vboxChooserGroupHide');
+
+ $.when(vboxChooser._anchor.show('slide', {direction: (back ? 'left' : 'right'), distance: (vboxChooser._anchor.outerWidth()/1.5)}, 200))
+ .done(function(){
+
+ // Restore scrolling
+ vboxChooser._anchor.css({'overflow-y':'auto'});
+
+ // Hide group info
+ $(gelm).find('div.vboxChooserGroupHeader').trigger('mouseout');
+
+ // Reset title sizes
+ vboxChooser._resizeElements();
+
+ // force redraw of these
+ $(gelm).find('.vboxFitToContainer').css({'display':'none'}).css({'width':'','display':''});
+
+
+ });
+
+ });
+
+ } else {
+
+ vboxChooser._showOnlyGroupHistory = [];
+
+ // Slide back to anchor
+ $.when(vboxChooser._anchor.hide('slide', {direction: 'right', distance: (vboxChooser._anchor.outerWidth()/1.5)}, 200)).always(function() {
+
+ /* show host when going back to main list */
+ $('table.vboxChooserItem-'+vboxChooser._anchorid+'-host').show();
+
+ vboxChooser._anchor.find('div.vboxChooserGroupHide').removeClass('vboxChooserGroupHide vboxChooserGroupHideShowContainer');
+ vboxChooser._anchor.find('div.vboxChooserGroupShowOnly').removeClass('vboxChooserGroupShowOnly ');
+
+ vboxChooser._anchor.find('div.vboxChooserGroupRootLevel').removeClass('vboxChooserGroupRootLevel');
+ vboxChooser._anchor.children('div.vboxChooserGroupRoot').addClass('vboxChooserGroupRootLevel');
+
+ $.when(vboxChooser._anchor.show('slide', {direction: 'left', distance: (vboxChooser._anchor.outerWidth()/1.5)}, 200))
+ .done(function(){
+
+ // Restore scrolling
+ vboxChooser._anchor.css({'overflow-y':'auto'});
+
+ // Hide group info
+ vboxChooser._anchor.find('div.vboxChooserGroupHeader').trigger('mouseout');
+
+ // Reset title sizes
+ vboxChooser._resizeElements();
+
+ // force redraw of these
+ vboxChooser._anchor.find('.vboxFitToContainer').css({'display':'none','width':''}).css({'display':''});
+ });
+ });
+ }
+
+ },
+
+ /*
+ * Return HTML for group
+ */
+ groupHTML : function(gpath) {
+
+ if(!gpath) gpath = '/';
+ var first = gpath == '/';
+ var gname = gpath.substring(gpath.lastIndexOf('/')+1);
+ var collapsed = vboxChooser._isGroupCollapsed(gpath);
+
+ var gHTML = $('<div />').append(
+ $('<div />').addClass('vboxChooserGroupIdentifier').css({'display':'none'}).attr({'title':gname})
+ ).append(
+ $('<div />').addClass('vboxChooserGroupHeader').css({'display':(first ? 'none' : '')})
+ .attr({'title':gname})
+ .dblclick(function() {
+
+ // Already collapsed?
+ var collapsed = $(this).closest('div.vboxChooserGroup').hasClass('vboxVMGroupCollapsed');
+
+ // Button rotation function
+ var rotateButton = function(){return true;};
+
+ var vboxArrowImage = $(this).find('span.vboxChooserGroupNameArrowCollapse');
+
+ if(!($.browser.msie && $.browser.version.substring(0,1) < 9)) {
+
+ rotateButton = function() {
+
+ return $('<div />').animate({left:90},{
+ duration: 300,
+ step: function(currentStep) {
+ if(!collapsed) currentStep = (90 - currentStep);
+ vboxArrowImage.css({
+ 'transform':'rotate('+currentStep+'deg)',
+ '-moz-transform': 'rotate('+currentStep+'deg)',
+ '-webkit-transform': 'rotate('+currentStep+'deg)',
+ '-o-transform': 'rotate('+currentStep+'deg)',
+ '-ms-transform': 'rotate('+currentStep+'deg)'
+ });
+ },
+ queue: true,
+ complete: function() {
+ vboxArrowImage.css({
+ 'transform':'',
+ '-moz-transform': '',
+ '-webkit-transform': '',
+ '-o-transform': '',
+ '-ms-transform': ''
+ });
+ }
+
+ });
+ };
+ }
+
+
+ // Run button rotation and toggle class
+ $.when(rotateButton(), $(this).closest('div.vboxChooserGroup').toggleClass('vboxVMGroupCollapsed', ($.browser.msie && $.browser.version.substring(0,1) < 9) ? undefined : 300)).always(function(){
+
+ // Write out collapsed group list
+ vboxChooser._saveCollapsedGroups();
+
+ // Reset title sizes
+ vboxChooser._resizeElements();
+ });
+
+
+ })
+ .append(
+ $('<div />').addClass('vboxChooserDropTarget')
+ .addClass('vboxDropTargetTop').hover(function(){
+ if(vboxChooser._draggingGroup)
+ $(this).addClass('vboxChooserDropTargetHover' + (first ? 'ignore' : ''));
+ }, function(){
+ $(this).removeClass('vboxChooserDropTargetHover');
+ })
+ )
+ .append(
+ $('<span />').addClass('vboxChooserGroupNameArrowLeft vboxChooserGroupNameArrowCollapse vboxArrowImage')
+ .mousedown(function(e){
+ e.stopPropagation();
+ e.preventDefault();
+ return false;
+ }).mouseup(function(){
+ $(this).closest('div.vboxChooserGroupHeader').trigger('dblclick');
+ })
+
+ ).append(
+
+ $('<span />').addClass('vboxChooserGroupNameArrowLeft vboxChooserGroupShowOnlyBack vboxArrowImage')
+ .click(function(e) {
+ e.stopPropagation();
+ e.preventDefault();
+ vboxChooser.showOnlyGroupElm();
+ return false;
+
+ })
+
+ )
+ .append($('<span />').addClass('vboxChooserGroupInfo').html(
+ "<span class='vboxChooserGroupCounts' />"
+ ).append(
+ $('<span />').addClass('vboxChooserGroupShowOnly vboxArrowImage')
+ .click(function(e){
+ e.stopPropagation();
+ e.preventDefault();
+ vboxChooser.showOnlyGroupElm($(this).closest('div.vboxChooserGroup'));
+ return false;
+ })
+
+ ))
+ .append($('<span />').html(gname).addClass('vboxChooserGroupName vboxFitToContainer'))
+ .append(
+ $('<div />').addClass('vboxChooserDropTarget vboxChooserDropTargetBottom')
+ .hover(function(){
+ if(vboxChooser._draggingGroup)
+ $(this).addClass('vboxChooserDropTargetHover' + (first ? 'ignore' : ''));
+ }, function(){
+ $(this).removeClass('vboxChooserDropTargetHover');
+ })
+
+ )
+ .hover(function(){
+
+ if(vboxChooser._compact) return;
+
+ $(this).addClass('vboxHover');
+
+ // Resize title and add hover class?
+ if(!$(this).parent().hasClass('vboxChooserGroupRoot')) {
+
+ // Set width of title to -group info span width
+ var infoWidth = $(this).children('span.vboxChooserGroupInfo').width();
+ var pWidth = $(this).width();
+
+ $(this).children('span.vboxChooserGroupName').css({'max-width':(pWidth-infoWidth-20)+'px'});
+
+ }
+
+
+ },function(){
+
+ // Resize title and remove hover class
+ $(this).removeClass('vboxHover');
+
+ if(!$(this).parent().hasClass('vboxChooserGroupRoot'))
+ $(this).children('span.vboxChooserGroupName').css({'max-width':''});
+
+ }).on('mousedown',vboxChooser.selectItem)
+
+ ).addClass((first ? 'vboxChooserGroupRoot vboxChooserGroupRootLevel ' : (collapsed ? 'vboxVMGroupCollapsed ' : '')) + 'vboxChooserGroup')
+ .data({'vmGroupPath':gpath})
+ .draggable({'cursorAt':{left: -10, top: -10},'helper':function(){
+
+ return $(this).clone().addClass('vboxVMGroupCollapsed vboxVMGroupSelected')
+ .children('div.vboxChooserGroupHeader').removeClass('vboxHover').children('.vboxChooserGroupNameArrowCollapse')
+ .hide().closest('div.vboxChooserGroup').css({'width':$(this).width()+'px'});
+
+
+ },'start':function() {
+
+ if(!$('#vboxPane').data('vboxSession').admin) return false;
+
+ if(!vboxChooser._editable) return false;
+
+ vboxChooser._draggingGroup = $(this).data('vmGroupPath');
+ $(vboxChooser._anchor).disableSelection();
+
+ },'stop':function(e) {
+ vboxChooser.vmGroupDropped(e,$(this));
+
+ }}).append($('<div />').addClass('vboxChooserGroupVMs'));
+
+
+ // Bottom drop target
+ if(!first) {
+ gHTML.hover(function(){
+ $(this).addClass('vboxGroupHover'); }, function() {
+ $(this).removeClass('vboxGroupHover');
+ }).append(
+ $('<div />').addClass('vboxChooserDropTarget vboxChooserDropTargetBottom')
+ .hover(function(){
+ if(vboxChooser._draggingGroup)
+ $(this).addClass('vboxChooserDropTargetHover');
+ }, function(){
+ $(this).removeClass('vboxChooserDropTargetHover');
+ })
+ );
+ }
+
+
+
+ // Group context menu
+ $(gHTML).contextMenu({
+ menu: vboxChooser._vmGroupContextMenuObj.menuId(),
+ menusetup: function(el) {
+ $(el).children('div.vboxChooserGroupHeader').trigger('click');
+ }
+ },function(act,el,pos,d,e){
+ vboxChooser._vmGroupContextMenuObj.menuClickCallback(act, el);
+ });
+
+ return gHTML;
+
+
+
+ },
+
+ /*
+ * Return selected VM elements
+ */
+ getSelectedVMElements : function() {
+ return vboxChooser._anchor.find('table.vboxSelected');
+ },
+
+ /*
+ * Return selected group elements
+ */
+ getSelectedGroupElements : function() {
+ return vboxChooser._anchor.find('div.vboxVMGroupSelected');
+ },
+
+
+ /*
+ * Start VM list update
+ */
+ start : function(anchorid) {
+
+ // already running?
+ if(vboxChooser._running) return;
+ vboxChooser._running = true;
+
+ // Where are we drawn?
+ if(anchorid) {
+ vboxChooser._anchorid = anchorid;
+ vboxChooser._anchor = $('#'+anchorid);
+ }
+
+
+ // Set group definition key
+ vboxChooser._groupDefinitionKey = $('#vboxPane').data('vboxConfig')['groupDefinitionKey'];
+
+ // Get collapsed group list
+ vboxChooser._collapsedGroups = vboxGetLocalDataItem($('#vboxPane').data('vboxConfig').key+'-collapsedGroups', true);
+ if(!vboxChooser._collapsedGroups) vboxChooser._collapsedGroups = [];
+ else vboxChooser._collapsedGroups = vboxChooser._collapsedGroups.split(',');
+
+
+ // Get groups and machine list. datamediator will start listener
+ $.when(vboxAjaxRequest('vboxGroupDefinitionsGet')).done(function(g) {
+
+ vboxChooser._groupDefs = g.responseData;
+
+ $.when(vboxVMDataMediator.getVMList()).done(function(d) {
+ vboxChooser.updateList(d);
+ });
+ });
+
+ },
+
+ /*
+ * Stop VM list updates and clear list
+ */
+ stop : function() {
+
+ if(!vboxChooser._running) return;
+ vboxChooser._running = false;
+
+ vboxChooser._anchor.html("<div id='vboxChooserSpinner' style='text-align: center'><div><img src='images/spinner.gif' /></div></div>");
+
+ // reset vars
+ vboxChooser._versionChecked = false;
+ vboxChooser._selectedList = [];
+ vboxChooser.selectedVMs = [];
+ vboxChooser.selectionMode = vboxSelectionModeNone;
+
+ }
+
+
+
+};
+
+$(document).ready(function(){
+
+ // Calculate scrollbar width
+ vboxChooser._scrollbarWidth = getScrollbarWidth();
+
+ // "Stop" chooser
+ $('#vboxPane').on('hostChange',function(){
+
+ vboxChooser.stop();
+
+ }).on('hostChanged',function(){
+
+
+ vboxChooser.start();
+
+ // Refresh menus
+ }).on('vmGroupDefsSaving vmGroupDefsSaved vmSelectionListChanged', function() {
+
+ if(vboxChooser._vmGroupContextMenuObj)
+ vboxChooser._vmGroupContextMenuObj.update(vboxChooser);
+ if(vboxChooser._vmContextMenuObj)
+ vboxChooser._vmContextMenuObj.update(vboxChooser);
+
+
+ // Event list queue
+ }).on('vboxEvents',function(e, eventList) {
+
+ var redrawVMs = [];
+ var sortGroups = [];
+ var groupsChanged = false;
+ var selectedChanged = false;
+ var resizeElements = false;
+
+ for(var i = 0; i < eventList.length; i++) {
+
+ switch(eventList[i].eventType) {
+
+ ////////////////////////////////
+ //
+ // Machine data changed
+ //
+ ////////////////////////////////
+ case 'OnMachineDataChanged':
+
+ // Shorthand
+ var vmid = eventList[i].machineId;
+ var data = vboxVMDataMediator.getVMData(vmid);
+
+ // Update VM in list
+ if(data) {
+
+ // Enforce VM ownership
+ if($('#vboxPane').data('vboxConfig').enforceVMOwnership && !$('#vboxPane').data('vboxSession').admin && data.owner != $('#vboxPane').data('vboxSession').user) {
+ break;
+ }
+
+ redrawVMs[redrawVMs.length] = vmid;
+
+ // Make sure VM has root group at least
+ if(data.groups.length == 0) data.groups = ['/'];
+
+ // Remove from groups if they have changed
+ var currGroups = vboxChooser.getGroupsForVM(vmid);
+ var groupDiff = $(currGroups).not(data.groups);
+ groupsChanged = groupDiff.length;
+ for(var a = 0; a < groupDiff.length; a++) {
+
+ var gElm = vboxChooser.getGroupElement(groupDiff[a], false);
+ if(!$(gElm)[0]) return;
+
+ selectedChanged = (selectedChanged || $(gElm).children('div.vboxChooserGroupVMs').closest('div.vboxVMGroupSelected').length);
+
+ $(gElm).children('div.vboxChooserGroupVMs')
+ .children('table.vboxChooserItem-'+vboxChooser._anchorid+'-'+data.id).empty().remove();
+
+ }
+
+ // Add to other groups
+ var groupDiff = $(data.groups).not(currGroups);
+ groupsChanged = (groupsChanged || groupDiff.length);
+ for(var a = 0; a < groupDiff.length; a++) {
+
+ var gElm = vboxChooser.getGroupElement(groupDiff[a]);
+
+ // Skip it if it is already there
+ if($(gElm).children('div.vboxChooserGroupVMs').children('table.vboxChooserItem-'+vboxChooser._anchorid+'-'+data.id)[0])
+ continue;
+
+ $(gElm).children('div.vboxChooserGroupVMs')
+ .append(
+ vboxChooser.vmHTML(data)
+ );
+
+ selectedChanged = (selectedChanged || $(gElm).children('div.vboxChooserGroupVMs').closest('div.vboxVMGroupSelected').length);
+
+ // Sort the group this machine was added to
+ sortGroups = sortGroups.concat(data.groups);
+
+ }
+
+ resizeElements = (resizeElements || groupsChanged);
+
+
+ }
+
+ break;
+
+ /////////////////////////////////
+ //
+ // Snapshot taken / deleted / restored
+ //
+ /////////////////////////////////
+ case 'OnSnapshotDeleted':
+ case 'OnSnapshotTaken':
+ case 'OnSnapshotRestored':
+ case 'OnSnapshotChanged':
+ redrawVMs[redrawVMs.length] = eventList[i].machineId;
+ break;
+
+ /////////////////////////////////////
+ //
+ // Machine registered or unregistered
+ //
+ //////////////////////////////////////
+ case 'OnMachineRegistered':
+
+ // Shorthand
+ var vmid = eventList[i].machineId;
+
+ // Unregistered
+ if(!eventList[i].registered) {
+
+ var wasSelected = vboxChooser.isVMSelected(vmid);
+
+ $('#'+vboxChooser._anchorid +' table.vboxChooserItem-'+vboxChooser._anchorid+'-'+vmid).remove();
+
+ groupsChanged = true;
+
+ // See if VM was selected
+ if(wasSelected) {
+
+ selectedChanged = true;
+
+ vboxChooser._selectedList = vboxChooser._selectedList.filter(function(v){
+ return (v.type == 'group' || (v.id != vmid));
+ });
+
+
+ }
+
+ resizeElements = true;
+
+
+ break;
+
+ }
+
+ // Registered
+
+ // Enforce VM ownership
+ if($('#vboxPane').data('vboxConfig').enforceVMOwnership && !$('#vboxPane').data('vboxSession').admin && eventList[i].enrichmentData.owner != $('#vboxPane').data('vboxSession').user) {
+ break;
+ }
+
+ // Add to list
+ vboxChooser.updateVMElement(eventList[i].enrichmentData, true);
+
+ resizeElements = true;
+ break;
+
+
+ ///////////////////////////////////
+ //
+ // Extra data changed
+ //
+ ////////////////////////////////////
+ case 'OnExtraDataChanged':
+
+ if(!eventList[i].machineId && eventList[i].key.indexOf(vboxChooser._groupDefinitionKey) === 0) {
+
+ var path = eventList[i].key.substring(vboxChooser._groupDefinitionKey.length);
+ if(!path) path = "/";
+ var name = path.substring(path.lastIndexOf('/')+1);
+ var vboxVMGroups = vboxChooser._groupDefs;
+ var found = false;
+
+ // No current group definitions?
+ if(!vboxVMGroups) break;
+
+ // Step through each group, comparing
+ for(var a = 0; a < vboxVMGroups.length; a++) {
+ if(vboxVMGroups[a].path == path) {
+ // Sort this group if it is different
+ if(vboxVMGroups[a].order != eventList[i].value)
+ sortGroups[sortGroups.length] = path;
+ found = true;
+ vboxVMGroups[a] = {'path':path,'name':name,'order':eventList[i].value};
+ break;
+ }
+ }
+
+ // Add to group if not found
+ if(!found) {
+ vboxVMGroups[vboxVMGroups.length] = {'path':path,'name':name,'order':eventList[i].value};
+ sortGroups[sortGroups.length] = path; // sort when added
+ resizeElements = true;
+ }
+
+ } else {
+
+ switch(eventList[i].key) {
+
+ // redraw when custom icon changes
+ case 'phpvb/icon':
+ redrawVMs[redrawVMs.length] = eventList[i].machineId;
+ break;
+ }
+ }
+ break;
+
+ ////////////////////////////////////////
+ //
+ // Session or state change gets redrawn
+ //
+ ///////////////////////////////////////
+ case 'OnSessionStateChanged':
+ case 'OnMachineStateChanged':
+ redrawVMs[redrawVMs.length] = eventList[i].machineId;
+ break;
+
+ } // </ switch eventType >>
+
+
+ } // </ for each event >
+
+ // Now redraw each VM
+ ///////////////////////////
+ var redrawn = {};
+ var updateMenus = false;
+ for(var i = 0; i < redrawVMs.length; i++) {
+
+ if(redrawn[redrawVMs[i]]) continue;
+ redrawn[redrawVMs[i]] = true;
+
+ vboxChooser.updateVMElement(vboxVMDataMediator.getVMData(redrawVMs[i]));
+
+ // Update menus if the VM is selected
+ updateMenus = (updateMenus || vboxChooser.isVMSelected(redrawVMs[i]));
+
+ }
+
+ // Sort groups
+ var groupsSorted = {};
+ for(var i = 0; i < sortGroups.length; i++) {
+ if(groupsSorted[sortGroups[i]]) continue;
+ groupsSorted[sortGroups[i]] = true;
+ var gElm = $(vboxChooser.getGroupElement(sortGroups[i]),false);
+ if(gElm[0])
+ vboxChooser.sortGroup(gElm);
+
+ }
+
+ // Groups changed
+ if(groupsChanged || sortGroups.length) {
+ vboxChooser.composeGroupDef();
+ }
+
+
+ // update selection list
+ if(selectedChanged) {
+
+ vboxChooser.selectionListChanged(vboxChooser._selectedList);
+
+ } else if(updateMenus) {
+
+ if(vboxChooser._vmGroupContextMenuObj)
+ vboxChooser._vmGroupContextMenuObj.update(vboxChooser);
+
+
+ if(vboxChooser._vmContextMenuObj)
+ vboxChooser._vmContextMenuObj.update(vboxChooser);
+
+ }
+
+ if(resizeElements) vboxChooser._resizeElements(true);
+
+
+
+ });
+
+
+
}); \ No newline at end of file