').addClass('main-desc').append(
$('
').html(_l('message.select.affinity.groups'))
)
);
$step.find('.select-container').append(
makeSelects(
'affinity-groups',
args.data.affinityGroups, {
name: 'name',
desc: 'description',
id: 'id'
}, {
type: 'checkbox',
'wizard-field': 'affinity-groups'
},
args.data.selectedObj,
args.data.selectedObjNonEditable
)
);
} else {
$step.find('.select-container').append(
$('
').addClass('no-affinity-groups').html(_l('message.no.affinity.groups'))
);
}
}
}
};
},
'sshkeyPairs': function($step, formData) {
var originalValues = function(formData) {
if (formData.sshkeypair) {
$step.find('input[type=radio]').filter(function() {
return $(this).val() == formData.sshkeypair;
}).click();
} else {
$step.find('input[type=radio]:first').click();
}
};
return {
response: {
success: function(args) {
$step.find('.main-desc, p.no-sshkey-pairs').remove();
if (args.data.sshkeyPairs && args.data.sshkeyPairs.length) {
$step.prepend(
$('
').addClass('main-desc').append(
$('
').html(_l('message.please.select.ssh.key.pair.use.with.this.vm'))
)
);
$step.find('.section.no-thanks').show();
$step.find('.select-container').append(
makeSelects(
'sshkeypair',
args.data.sshkeyPairs, {
name: 'name',
id: 'name'
}, {
'wizard-field': 'sshkey-pairs'
}
)
);
originalValues(formData); // if we can select only one.
} else {
$step.find('.section.no-thanks').hide();
$step.find('.select-container').append(
$('
').addClass('no-sshkey-pairs').html(_l('You do not have any ssh key pairs. Please continue to the next step.'))
);
}
}
}
};
},
'network': function($step, formData) {
var showAddNetwork = true;
var checkShowAddNetwork = function($newNetwork) {
if (!showAddNetwork) {
$newNetwork.hide();
} else {
$newNetwork.show();
}
};
var originalValues = function(formData) {
// Default networks
$step.find('input[type=radio]').filter(function() {
return $(this).val() == formData['defaultNetwork'];
}).click();
// Optional networks
var selectedOptionalNetworks = [];
if ($.isArray(formData['shared-networks']) != -1) {
$(formData['shared-networks']).each(function() {
selectedOptionalNetworks.push(this);
});
} else {
selectedOptionalNetworks.push(formData['shared-networks']);
}
var $checkboxes = $step.find('input[name=shared-networks]');
$(selectedOptionalNetworks).each(function() {
var networkID = this;
$checkboxes.filter(function() {
return $(this).val() == networkID;
}).attr('checked', 'checked');
});
};
var $newNetwork = $step.find('.new-network');
var $newNetworkCheckbox = $newNetwork.find('input[type=checkbox]');
// Setup new network field
$newNetworkCheckbox.unbind('click');
$newNetworkCheckbox.click(function() {
$newNetwork.toggleClass('unselected');
// Select another default if hiding field
if ($newNetwork.hasClass('unselected')) {
$step.find('input[type=radio]:visible:first').click();
} else {
$newNetwork.find('input[type=radio]').click();
}
});
setTimeout(function() {
var $checkbox = $step.find('.new-network input[type=checkbox]');
var $newNetwork = $checkbox.closest('.new-network');
if ($step.find('.select.my-networks .select-container .select:visible').size()) {
$checkbox.attr('checked', false);
$newNetwork.addClass('unselected');
} else {
$newNetwork.find('input[name=defaultNetwork]').filter('[value=new-network]').click();
}
$checkbox.change();
});
// Show relevant conditional sub-step if present
$step.find('.wizard-step-conditional').hide();
if ($.isFunction(args.showAddNetwork)) {
showAddNetwork = args.showAddNetwork({
data: formData,
context: context
});
}
// Filter network list by VPC ID
var filterNetworkList = function(vpcID) {
var $selects = $step.find('.my-networks .select-container .select');
var $visibleSelects = $($.grep($selects, function(select) {
var $select = $(select);
return args.vpcFilter($select.data('json-obj'), vpcID);
}));
var $addNetworkForm = $step.find('.select.new-network');
var $addNewNetworkCheck = $addNetworkForm.find('input[name=new-network]');
// VPC networks cannot be created via instance wizard
if (vpcID != -1) {
$step.find('.my-networks .select-container').addClass('single-select');
$addNetworkForm.hide();
if ($addNewNetworkCheck.is(':checked')) {
$addNewNetworkCheck.click();
$addNewNetworkCheck.attr('checked', false);
}
} else {
$step.find('.my-networks .select-container').removeClass('single-select');
$addNetworkForm.show();
checkShowAddNetwork($addNetworkForm);
}
$selects.find('input[type=checkbox]').attr('checked', false);
$selects.hide();
$visibleSelects.show();
// Select first visible item by default
$visibleSelects.filter(':first')
.find('input[type=radio]')
.click();
cloudStack.evenOdd($visibleSelects, 'div.select', {
even: function($elem) {
$elem.removeClass('odd');
$elem.addClass('even');
},
odd: function($elem) {
$elem.removeClass('even');
$elem.addClass('odd');
}
});
};
var $vpcSelect = $step.find('select[name=vpc-filter]');
$vpcSelect.unbind('change');
$vpcSelect.change(function() {
filterNetworkList($vpcSelect.val());
});
return {
response: {
success: function(args) {
var vpcs = args.data.vpcs;
var addClass = args.addClass;
var removeClass = args.removeClass;
// Populate VPC drop-down
$vpcSelect.html('');
$(vpcs).map(function(index, vpc) {
var $option = $('');
var id = vpc.id;
var description = vpc.name;
$option.attr('value', id);
$option.html(description);
$option.appendTo($vpcSelect);
});
// 'No VPC' option
$(' ').attr('value', '-1').html(_l('ui.listView.filters.all')).prependTo($vpcSelect);
$vpcSelect.val(-1);
// Populate network offering drop-down
$(args.data.networkOfferings).each(function() {
$(' ')
.val(this.id)
.html(this.name)
.appendTo($newNetwork.find('select'));
});
if (args.type) {
$step.find('.wizard-step-conditional').filter(function() {
return $(this).hasClass(args.type);
}).show();
} else {
$step.find('.select-network').show();
}
// My networks
$step.find('.my-networks .select-container').append(
makeSelects('my-networks', args.data.networkObjs, {
name: 'name',
desc: 'type',
id: 'id'
}, {
type: 'checkbox',
'wizard-field': 'my-networks',
secondary: {
desc: 'Default',
name: 'defaultNetwork',
type: 'radio',
'wizard-field': 'default-network'
}
})
);
// Add IP/advanced option fields
$step.find('.my-networks .select-container .select, .select.new-network .select').each(function () {
var $select = $(this);
var $advancedLink = $('').addClass('advanced-options hide-if-unselected');
var $specifyIpField = $('
').addClass('specify-ip hide-if-unselected').append(
$('').html(_l('label.ip.address')),
$(' ').attr({ type: 'text' })
);
// Cleanup
if ($select.closest('.new-network').size()) {
$select.find('.advanced-options, .specify-ip').remove();
}
$select.append($advancedLink, $specifyIpField);
$advancedLink.click(function() {
$select.toggleClass('advanced');
});
});
// Show non-VPC networks by default
filterNetworkList(-1);
// Security groups (alt. page)
var $sgSelects = makeSelects('security-groups', args.data.securityGroups, {
name: 'name',
desc: 'description',
id: 'id'
}, {
type: 'checkbox',
'wizard-field': 'security-groups'
});
$step.find('.security-groups .select-container').append($sgSelects);
//If there is only one security group and the only one is 'default', make it selected by default
if ($sgSelects.length == 1) {
var $firstCheckbox = $sgSelects.eq(0);
if ($firstCheckbox.find('div .name').text() == 'default') {
$firstCheckbox.find('input:checkbox').click();
}
}
originalValues(formData);
checkShowAddNetwork($newNetwork);
}
}
};
},
'review': function($step, formData) {
$step.find('[wizard-field]').each(function() {
var field = $(this).attr('wizard-field');
var fieldName;
var $input = $wizard.find('[wizard-field=' + field + ']').filter(function() {
return ($(this).is(':selected') ||
$(this).is(':checked') ||
$(this).attr('type') == 'hidden') &&
$(this).is(':not(:disabled)');
});
if ($input.is('option')) {
fieldName = $input.html();
} else if ($input.is('input[type=radio]')) {
// Choosen New network as default
if ($input.parents('div.new-network').size()) {
fieldName = $input.closest('div.new-network').find('input[name="new-network-name"]').val();
// Choosen Network from existed
} else if ($input.parents('div.my-networks').size()) {
fieldName = $input.closest('div.select').find('.select-desc .name').html();
} else {
fieldName = $input.parent().find('.select-desc .name').html();
}
} else if ($input.eq(0).is('input[type=checkbox]')) {
fieldName = '';
$input.each(function(index) {
if (index != 0) fieldName += ' ';
fieldName += $(this).next('div.select-desc').find('.name').html();
});
} else if ($input.is('input[type=hidden]')) {
fieldName = $input.val();
}
if (fieldName) {
$(this).html(fieldName);
} else {
$(this).html('(' + _l('label.none') + ')');
}
var conditionalFieldFrom = $(this).attr('conditional-field');
if (conditionalFieldFrom) {
if ($wizard.find('.' + conditionalFieldFrom).css('display') == 'block') {
$(this).closest('div.select').show();
} else {
$(this).closest('div.select').hide();
}
}
});
}
};
$wizard.bind('cloudStack.instanceWizard.showStep', function(e, args) {
showStep(args.index, { refresh: true });
});
// Go to specified step in wizard,
// updating nav items and diagram
var showStep = function(index, options) {
if (!options) options = {};
var targetIndex = index - 1;
if (index <= 1) targetIndex = 0;
if (targetIndex == $steps.size()) {
completeAction();
return;
}
var $targetStep = $($steps.hide()[targetIndex]).show();
var stepID = $targetStep.attr('wizard-step-id');
var formData = cloudStack.serializeForm($form);
if (options.refresh) {
$targetStep.removeClass('loaded');
}
if (!$targetStep.hasClass('loaded')) {
// Remove previous content
if (!$targetStep.hasClass('review')) { // Review row content is not autogenerated
$targetStep.find('.select-container:not(.fixed) div, option:not(:disabled)').remove();
}
dataProvider(
index,
dataGenerators[stepID](
$targetStep,
formData
)
);
if (!$targetStep.hasClass('repeat') && !$targetStep.hasClass('always-load')) $targetStep.addClass('loaded');
}
// Show launch vm button if last step
var $nextButton = $wizard.find('.button.next');
$nextButton.find('span').html(_l('label.next'));
$nextButton.removeClass('final');
if ($targetStep.hasClass('review')) {
$nextButton.find('span').html(_l('label.launch.vm'));
$nextButton.addClass('final');
}
// Hide previous button on first step
var $previousButton = $wizard.find('.button.previous');
if (index == 1) $previousButton.hide();
else $previousButton.show();
// Update progress bar
var $targetProgress = $progress.removeClass('active').filter(function() {
return $(this).index() <= targetIndex;
}).toggleClass('active');
// Update diagram; show/hide as necessary
$diagramParts.filter(function() {
return $(this).index() <= targetIndex;
}).fadeIn('slow');
$diagramParts.filter(function() {
return $(this).index() > targetIndex;
}).fadeOut('slow');
setTimeout(function() {
if (!$targetStep.find('input[type=radio]:checked').size()) {
$targetStep.find('input[type=radio]:first').click();
}
}, 50);
};
// Events
$wizard.click(function(event) {
var $target = $(event.target);
var $activeStep = $form.find('.step:visible');
// Next button
if ($target.closest('div.button.next').size()) {
//step 2 - select template/ISO
if($activeStep.hasClass('select-iso')) {
if ($activeStep.find('.content:visible input:checked').size() == 0) {
cloudStack.dialog.notice({
message: 'message.step.1.continue'
});
return false;
}
$(window).trigger("cloudStack.module.instanceWizard.clickNextButton", {
$form: $form,
currentStep: 2
});
}
//step 6 - select network
if ($activeStep.find('.wizard-step-conditional.select-network:visible').size() > 0) {
var data = $activeStep.data('my-networks');
if (!data) {
$activeStep.closest('form').data('my-networks', cloudStack.serializeForm(
$activeStep.closest('form')
)['my-networks']);
}
if ($activeStep.find('input[type=checkbox]:checked').size() == 0) { //if no checkbox is checked
cloudStack.dialog.notice({
message: 'message.step.4.continue'
});
return false;
}
if ($activeStep.hasClass('next-use-security-groups')) {
var advSGFilter = args.advSGFilter({
data: cloudStack.serializeForm($form)
});
if (advSGFilter == 0) { //when total number of selected sg networks is 0, then 'Select Security Group' is skipped, go to step 6 directly
showStep(6);
} else { //when total number of selected sg networks > 0
if ($activeStep.find('input[type=checkbox]:checked').size() > 1) { //when total number of selected networks > 1
cloudStack.dialog.notice({
message: "Can't create a vm with multiple networks one of which is Security Group enabled"
});
return false;
}
}
}
}
//step 6 - review (spcifiy displyname, group as well)
if ($activeStep.hasClass('review')) {
if ($activeStep.find('input[name=displayname]').size() > 0 && $activeStep.find('input[name=displayname]').val().length > 0) {
//validate
var b = cloudStack.validate.vmHostName($activeStep.find('input[name=displayname]').val());
if (b == false)
return false;
}
}
if (!$form.valid()) {
if ($form.find('input.error:visible, select.error:visible').size()) {
return false;
}
}
if ($activeStep.hasClass('repeat')) {
showStep($steps.filter(':visible').index() + 1);
} else {
showStep($steps.filter(':visible').index() + 2);
}
return false;
}
// Previous button
if ($target.closest('div.button.previous').size()) {
var $step = $steps.filter(':visible');
var $networkStep = $steps.filter('.network');
var index = $step.index();
$networkStep.removeClass('next-use-security-groups');
if (index) {
if (index == $steps.size() - 1 && $networkStep.hasClass('next-use-security-groups')) {
showStep(5);
} else if ($activeStep.find('.select-security-group:visible').size() &&
$activeStep.find('.select-network.no-add-network').size()) {
showStep(5);
} else {
showStep(index);
}
}
return false;
}
// Close button
if ($target.closest('div.button.cancel').size()) {
close();
return false;
}
// Edit link
if ($target.closest('div.edit').size()) {
var $edit = $target.closest('div.edit');
showStep($edit.find('a').attr('href'));
return false;
}
return true;
});
showStep(1);
$wizard.bind('change', function(event) {
var $target = $(event.target);
var $step = $target.closest('.step');
var $futureSteps = $step.siblings().filter(function() {
return $(this).index() > $step.index();
});
// Reset all fields in futher steps
$futureSteps.removeClass('loaded');
});
var minCustomDiskSize = args.minDiskOfferingSize ?
args.minDiskOfferingSize() : 1;
var maxCustomDiskSize = args.maxDiskOfferingSize ?
args.maxDiskOfferingSize() : 100;
// Setup tabs and slider
$wizard.find('.section.custom-size.custom-disk-size .size.min span').html(minCustomDiskSize);
$wizard.find('.section.custom-size.custom-disk-size input[type=text]').val(minCustomDiskSize);
$wizard.find('.section.custom-size.custom-disk-size .size.max span').html(maxCustomDiskSize);
$wizard.find('.tab-view').tabs();
$wizard.find('.slider').each(function() {
var $slider = $(this);
$slider.slider({
min: minCustomDiskSize,
max: maxCustomDiskSize,
start: function(event) {
$slider.closest('.section.custom-size').find('input[type=radio]').click();
},
slide: function(event, ui) {
$slider.closest('.section.custom-size').find('input[type=text]').val(
ui.value
);
$slider.closest('.step').find('span.custom-disk-size').html(
ui.value
);
}
});
});
$wizard.find('div.data-disk-offering div.custom-size input[type=text]').bind('change', function() {
var old = $wizard.find('div.data-disk-offering div.custom-size input[type=text]').val();
$wizard.find('div.data-disk-offering span.custom-disk-size').html(_s(old));
});
return $wizard.dialog({
title: _l('label.vm.add'),
width: 896,
height: 570,
closeOnEscape: false,
zIndex: 5000
})
.closest('.ui-dialog').overlay();
};
instanceWizard(args);
};
};
})(jQuery, cloudStack);