mirror of
https://github.com/apache/cloudstack.git
synced 2025-10-26 08:42:29 +01:00
* Add jQuery ui stylings to the project * Adapt stylings to jquery ui stylings - remove unnecessary (empty) style definitions * Check if jquery autocomplete is initialized before destroying it * Use dialog modal option instead of setting z-index styling - set minimum heigth of dialog * Swap removeAttr() for prop() since it's not longer recommended as of jQuery 3.0 * Fix reccuring snapshots modal view * Further style improvements * More improvements on the instance-wizard (and multi-wizard in general) * Raise input hints over modal z-index * Adapt/fix stylings - center buttons of create form modals - fix width of select menu in service offerings - fix width of modal in Network -> VPC -> configure -> static NAT -> aquire new Ip -> enable static nat * Adapt width of dynamic-input container
1384 lines
73 KiB
JavaScript
1384 lines
73 KiB
JavaScript
// Licensed to the Apache Software Foundation (ASF) under one
|
|
// or more contributor license agreements. See the NOTICE file
|
|
// distributed with this work for additional information
|
|
// regarding copyright ownership. The ASF licenses this file
|
|
// to you under the Apache License, Version 2.0 (the
|
|
// "License"); you may not use this file except in compliance
|
|
// with the License. You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing,
|
|
// software distributed under the License is distributed on an
|
|
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
// KIND, either express or implied. See the License for the
|
|
// specific language governing permissions and limitations
|
|
// under the License.
|
|
|
|
(function($, cloudStack) {
|
|
/**
|
|
* Instance wizard
|
|
*/
|
|
cloudStack.uiCustom.instanceWizard = function(args) {
|
|
return function(listViewArgs) {
|
|
var context = listViewArgs.context;
|
|
|
|
var instanceWizard = function(data) {
|
|
var $wizard = $('#template').find('div.instance-wizard').clone();
|
|
var $progress = $wizard.find('div.progress ul li');
|
|
var $steps = $wizard.find('div.steps').children().hide();
|
|
var $diagramParts = $wizard.find('div.diagram').children().hide();
|
|
var $form = $wizard.find('form');
|
|
|
|
$form.validate();
|
|
|
|
// Close instance wizard
|
|
var close = function() {
|
|
$wizard.dialog('destroy');
|
|
$('div.overlay').fadeOut(function() {
|
|
$('div.overlay').remove();
|
|
});
|
|
};
|
|
|
|
// Save instance and close wizard
|
|
var completeAction = function() {
|
|
var data = cloudStack.serializeForm($form);
|
|
var $wizardLoading = $('<div>').addClass('loading-overlay').appendTo($wizard).css('z-index', '10000');
|
|
|
|
// Pass network IPs
|
|
data['my-network-ips'] = [];
|
|
$form.find('.my-networks .select .specify-ip input[type=text]').each(function() {
|
|
var $input = $(this);
|
|
|
|
if (!$input.closest('.select').find('input[type=checkbox]').is(':checked')) return true;
|
|
|
|
data['my-network-ips'].push(
|
|
$input.closest('.select').hasClass('advanced') ?
|
|
$input.val() : null
|
|
);
|
|
});
|
|
data['new-network-ip'] = $form.find('.new-network .select.advanced .specify-ip input[type=text]').val();
|
|
|
|
// Handle multi-disk service offerings
|
|
if ($form.find('.multi-disk-select-container').length) {
|
|
data['disk-offerings-multi'] = [];
|
|
|
|
var $diskGroups = $form.find('.disk-select-group');
|
|
var $selectedDisks = $.grep($diskGroups, function (diskGroup) {
|
|
return $(diskGroup).find('input[type=checkbox]:checked').length;
|
|
});
|
|
|
|
$selectedDisks.map(function (disk) {
|
|
data['disk-offerings-multi'].push(
|
|
$.extend($(disk).data('json-obj'), {
|
|
_diskOfferingId: $(disk).find('input[type=radio]:checked').val()
|
|
})
|
|
);
|
|
});
|
|
}
|
|
|
|
args.action({
|
|
// Populate data
|
|
context: context,
|
|
data: data,
|
|
$wizard: $wizard,
|
|
response: {
|
|
success: function(args) {
|
|
var $listView = $('.list-view.instances');
|
|
|
|
if ($listView.length) {
|
|
var $loading = $('.list-view.instances').listView('prependItem', {
|
|
data: [{
|
|
name: data.displayname ? data.displayname : _l('label.new.vm'),
|
|
zonename: $wizard.find('select[name=zoneid] option').filter(function() {
|
|
return $(this).val() == data.zoneid;
|
|
}).html(),
|
|
state: 'Creating'
|
|
}],
|
|
actionFilter: function(args) {
|
|
return [];
|
|
}
|
|
});
|
|
}
|
|
|
|
listViewArgs.complete({
|
|
_custom: args._custom,
|
|
messageArgs: cloudStack.serializeForm($form),
|
|
$item: $listView.length ? $loading : $('<div>')
|
|
});
|
|
|
|
close();
|
|
},
|
|
error: function(message) {
|
|
$wizard.remove();
|
|
$('div.overlay').remove();
|
|
|
|
if (message) {
|
|
cloudStack.dialog.notice({
|
|
message: message
|
|
});
|
|
}
|
|
}
|
|
}
|
|
});
|
|
};
|
|
|
|
var makeSelects = function(name, data, fields, options, selectedObj, selectedObjNonEditable) {
|
|
var $selects = $('<div>');
|
|
options = options ? options : {};
|
|
|
|
$(data).each(function() {
|
|
var item = this;
|
|
var id = item[fields.id];
|
|
|
|
var $select = $('<div>')
|
|
.addClass('select')
|
|
.append(
|
|
$('<input>')
|
|
.attr({
|
|
type: (function(type) {
|
|
return type ? type : 'radio';
|
|
})(options ? options.type : null),
|
|
name: name,
|
|
'wizard-field': options['wizard-field']
|
|
})
|
|
.val(id)
|
|
.click(function() {
|
|
var $select = $(this).closest('.select');
|
|
var isSingleSelect = $select.hasClass('single-select');
|
|
var $radio = $select.find('input[type=radio]');
|
|
var $newNetwork = $(this).closest('.content').find('.select.new-network');
|
|
var $otherSelects = $select.siblings().filter(':visible');
|
|
var isCheckbox = $(this).attr('type') == 'checkbox';
|
|
|
|
if (isCheckbox) {
|
|
if (isSingleSelect) {
|
|
$select.siblings('.single-select:visible').find('input[type=checkbox]')
|
|
.attr('checked', false);
|
|
|
|
var $checkedOtherSelect = $otherSelects.filter(function() {
|
|
return $(this).not('.single-select') &&
|
|
$(this).find('input[type=checkbox]:checked').length &&
|
|
$(this).find('input[type=radio]:checked').length;
|
|
});
|
|
|
|
if (!$checkedOtherSelect.length &&
|
|
!$('.new-network:visible input[type=radio]:checked').length) {
|
|
$(this).closest('.select').find('input[type=radio]').click();
|
|
}
|
|
}
|
|
|
|
if ((!$otherSelects.length) &&
|
|
$newNetwork.find('input[type=checkbox]').is(':unchecked')) {
|
|
// Set as default
|
|
$(this).closest('.select').find('input[type=radio]').click();
|
|
}
|
|
}
|
|
|
|
if ($radio.is(':checked') && !$(this).is(':checked')) {
|
|
if (!$radio.closest('.select').index()) {
|
|
return false;
|
|
} else {
|
|
$otherSelects.filter(':first')
|
|
.find('input[type=radio]').click();
|
|
}
|
|
}
|
|
|
|
return true;
|
|
})
|
|
)
|
|
.append(
|
|
$('<div>').addClass('select-desc')
|
|
.append($('<div>').addClass('name').html(_s(this[fields.name])))
|
|
.append($('<div>').addClass('desc').html(_s(this[fields.desc])))
|
|
)
|
|
.data('json-obj', this);
|
|
|
|
if (selectedObj != null && selectedObj.id == item.id) {
|
|
$select.find('input[type=checkbox]').attr('checked', 'checked');
|
|
|
|
if (selectedObjNonEditable) {
|
|
$select.find('input[type=checkbox]').attr('disabled', 'disabled');
|
|
$select.find('input[type=checkbox]').clone().attr({
|
|
type: 'hidden',
|
|
disabled: false
|
|
}).appendTo($selects);
|
|
}
|
|
}
|
|
|
|
$selects.append($select);
|
|
|
|
if (item._singleSelect) {
|
|
$select.addClass('single-select');
|
|
}
|
|
|
|
if (options.secondary) {
|
|
var $secondary = $('<div>').addClass('secondary-input').append(
|
|
$('<input>')
|
|
.attr({
|
|
type: options.secondary.type,
|
|
name: options.secondary.name,
|
|
'wizard-field': options.secondary['wizard-field']
|
|
})
|
|
.val(id)
|
|
.click(function() {
|
|
var $checkbox = $(this).closest('.select').find('input[type=checkbox]');
|
|
|
|
if (!$checkbox.is(':checked')) {
|
|
$checkbox.attr('checked', true);
|
|
}
|
|
|
|
if ($(this).closest('.select-container').hasClass('single-select')) {
|
|
$(this).closest('.select').siblings().find('input[type=checkbox]')
|
|
.attr('checked', false);
|
|
}
|
|
|
|
if ($select.hasClass('single-select')) {
|
|
$select.siblings('.single-select:visible').find('input[type=checkbox]')
|
|
.attr('checked', false);
|
|
}
|
|
})
|
|
.after(
|
|
$('<div>').addClass('name').html(options.secondary.desc)
|
|
)
|
|
).appendTo($select);
|
|
}
|
|
});
|
|
|
|
cloudStack.evenOdd($selects, 'div.select', {
|
|
even: function($elem) {
|
|
$elem.addClass('even');
|
|
},
|
|
odd: function($elem) {
|
|
$elem.addClass('odd');
|
|
}
|
|
});
|
|
|
|
return $selects.children();
|
|
};
|
|
|
|
var dataProvider = function(step, providerArgs, callback) {
|
|
// Call appropriate data provider
|
|
args.steps[step - 1]($.extend(providerArgs, {
|
|
currentData: cloudStack.serializeForm($form),
|
|
initArgs: args,
|
|
context: context
|
|
}));
|
|
};
|
|
|
|
var dataGenerators = {
|
|
setup: function($step, formData) {
|
|
var originalValues = function(formData, initialValue) {
|
|
var selectedValue = formData.zoneid || initialValue;
|
|
$step.find('select').val(selectedValue);
|
|
|
|
$step.find('input[type=radio]').filter(function() {
|
|
return $(this).val() == formData['select-template'];
|
|
}).click();
|
|
};
|
|
|
|
return {
|
|
response: {
|
|
success: function(args) {
|
|
// Zones
|
|
var initialValue = '';
|
|
$(args.data.zones).each(function( index ) {
|
|
if(index == 0){
|
|
initialValue = this.id;
|
|
}
|
|
$step.find('.select-zone select').append(
|
|
$('<option>')
|
|
.attr({
|
|
value: this.id,
|
|
'wizard-field': 'zone'
|
|
})
|
|
.html(this.name)
|
|
);
|
|
});
|
|
|
|
originalValues(formData, initialValue);
|
|
}
|
|
}
|
|
};
|
|
},
|
|
|
|
'select-iso': function($step, formData) {
|
|
$step.find('.section.custom-size').hide();
|
|
|
|
var originalValues = function(formData) {
|
|
var $inputs = $step.find('.wizard-step-conditional:visible')
|
|
.find('input[type=radio]');
|
|
var $selected = $inputs.filter(function() {
|
|
return $(this).val() == formData.templateid;
|
|
});
|
|
|
|
if (!$selected.length) {
|
|
$inputs.filter(':first').click();
|
|
} else {
|
|
$selected.click();
|
|
}
|
|
$step.find('select[name=hypervisorid]:visible').val(
|
|
formData.hypervisorid
|
|
);
|
|
};
|
|
|
|
$step.find('.wizard-step-conditional').hide();
|
|
|
|
return {
|
|
response: {
|
|
success: function(args) {
|
|
if (formData['select-template']) {
|
|
$step.find('.wizard-step-conditional').filter(function() {
|
|
return $(this).hasClass(formData['select-template']);
|
|
}).show();
|
|
} else {
|
|
$step.find('.select-iso').show();
|
|
}
|
|
var makeIsos = function(type, append) {
|
|
var $selects = makeSelects('templateid', args.data.templates[type], {
|
|
name: 'name',
|
|
desc: 'displaytext',
|
|
id: 'id'
|
|
}, {
|
|
'wizard-field': 'template'
|
|
});
|
|
var $templateHypervisor = $step.find('input[type=hidden][wizard-field=hypervisor]');
|
|
|
|
// Get hypervisor from template
|
|
if (type == 'featuredtemplates' || type == 'communitytemplates' || type == 'mytemplates' || type == 'sharedtemplates') {
|
|
$selects.each(function() {
|
|
var $select = $(this);
|
|
var template = $.grep(args.data.templates[type], function(tmpl, v) {
|
|
return tmpl.id == $select.find('input').val();
|
|
})[0];
|
|
|
|
$select.change(function() {
|
|
$templateHypervisor
|
|
.attr('disabled', false)
|
|
.val(template.hypervisor);
|
|
});
|
|
});
|
|
} else {
|
|
$templateHypervisor.attr('disabled', 'disabled');
|
|
}
|
|
|
|
if (type == 'featuredisos' || type == 'communityisos' || type == 'myisos' || type == 'sharedisos') {
|
|
// Create hypervisor select
|
|
$selects.find('input').bind('click', function() {
|
|
var $select = $(this).closest('.select');
|
|
|
|
//$select.siblings().removeClass('selected').find('.hypervisor').remove(); //SelectISO has 3 tabs now. This line only remove hypervisor div in the same tab, not enough. The following 3 lines will remove hypervisor div in all of 3 tabs.
|
|
$("#instance-wizard-featured-isos .select-container div.selected").removeClass('selected').find('div.hypervisor').remove();
|
|
$("#instance-wizard-community-isos .select-container div.selected").removeClass('selected').find('div.hypervisor').remove();
|
|
$("#instance-wizard-my-isos .select-container div.selected").removeClass('selected').find('div.hypervisor').remove();
|
|
$("#instance-wizard-shared-isos .select-container div.selected").removeClass('selected').find('div.hypervisor').remove();
|
|
|
|
$select.addClass('selected').append(
|
|
$('<div>').addClass('hypervisor')
|
|
.append($('<label>').html(_l('label.hypervisor') + ':'))
|
|
.append($('<select>').attr({
|
|
name: 'hypervisorid'
|
|
}))
|
|
);
|
|
|
|
// Get hypervisor data
|
|
$(args.data.hypervisors).each(function() {
|
|
$select.find('select').append(
|
|
$('<option>').attr({
|
|
value: this[args.hypervisor.idField],
|
|
'wizard-field': 'hypervisor'
|
|
})
|
|
.html(this[args.hypervisor.nameField])
|
|
);
|
|
});
|
|
});
|
|
}
|
|
|
|
append($selects);
|
|
};
|
|
|
|
// Featured ISOs
|
|
$(
|
|
[
|
|
// Templates
|
|
['featuredtemplates', 'instance-wizard-featured-templates'],
|
|
['communitytemplates', 'instance-wizard-community-templates'],
|
|
['mytemplates', 'instance-wizard-my-templates'],
|
|
['sharedtemplates', 'instance-wizard-shared-templates'],
|
|
|
|
// ISOs
|
|
['featuredisos', 'instance-wizard-featured-isos'],
|
|
['communityisos', 'instance-wizard-community-isos'],
|
|
['myisos', 'instance-wizard-my-isos'],
|
|
['sharedisos', 'instance-wizard-shared-isos']
|
|
//['isos', 'instance-wizard-all-isos']
|
|
]
|
|
).each(function() {
|
|
var item = this;
|
|
var $selectContainer = $wizard.find('#' + item[1]).find('.select-container');
|
|
|
|
makeIsos(item[0], function($elem) {
|
|
$selectContainer.append($elem);
|
|
});
|
|
});
|
|
|
|
var custom = args.customHidden({
|
|
context: context,
|
|
data: args.data
|
|
});
|
|
|
|
$step.find('.custom-size-label').remove();
|
|
|
|
if (custom) {
|
|
$step.find('.section.custom-size').hide();
|
|
$step.removeClass('custom-disk-size');
|
|
}
|
|
|
|
$step.find('input[type=radio]').bind('change', function() {
|
|
var $target = $(this);
|
|
var val = $target.val();
|
|
var item = null;
|
|
if (item == null && args.data.templates.featuredtemplates != undefined) {
|
|
item = $.grep(args.data.templates.featuredtemplates, function(elem) {
|
|
return elem.id == val;
|
|
})[0];
|
|
}
|
|
if (item == null && args.data.templates.communitytemplates != undefined) {
|
|
item = $.grep(args.data.templates.communitytemplates, function(elem) {
|
|
return elem.id == val;
|
|
})[0];
|
|
}
|
|
if (item == null && args.data.templates.mytemplates!=undefined) {
|
|
item = $.grep(args.data.templates.mytemplates, function(elem) {
|
|
return elem.id == val;
|
|
})[0];
|
|
}
|
|
if (item == null && args.data.templates.sharedtemplates!=undefined) {
|
|
item = $.grep(args.data.templates.sharedtemplates, function(elem) {
|
|
return elem.id == val;
|
|
})[0];
|
|
}
|
|
|
|
if (!item) return true;
|
|
|
|
var hypervisor = item['hypervisor'];
|
|
if (hypervisor == 'KVM' || hypervisor == 'XenServer' || hypervisor == 'VMware') {
|
|
$step.find('.section.custom-size').show();
|
|
$step.addClass('custom-disk-size');
|
|
} else {
|
|
$step.find('.section.custom-size').hide();
|
|
$step.removeClass('custom-disk-size');
|
|
}
|
|
|
|
return true;
|
|
});
|
|
|
|
originalValues(formData);
|
|
|
|
}
|
|
}
|
|
};
|
|
},
|
|
|
|
'service-offering': function($step, formData) {
|
|
var originalValues = function(formData) {
|
|
if (formData.serviceofferingid) {
|
|
$step.find('input[type=radio]').filter(function() {
|
|
return $(this).val() == formData.serviceofferingid;
|
|
}).click();
|
|
} else {
|
|
$step.find('input[type=radio]:first').click();
|
|
}
|
|
};
|
|
|
|
return {
|
|
response: {
|
|
success: function(args) {
|
|
$step.find('.content .select-container').append(
|
|
makeSelects('serviceofferingid', args.data.serviceOfferings, {
|
|
name: 'name',
|
|
desc: 'displaytext',
|
|
id: 'id'
|
|
}, {
|
|
'wizard-field': 'service-offering'
|
|
})
|
|
);
|
|
|
|
$step.find('input[type=radio]').bind('change', function() {
|
|
var $target = $(this);
|
|
var val = $target.val();
|
|
var item = $.grep(args.data.serviceOfferings, function(elem) {
|
|
return elem.id == val;
|
|
})[0];
|
|
|
|
if (!item) return true;
|
|
|
|
var custom = item[args.customFlag];
|
|
|
|
if (custom) {
|
|
$step.addClass('custom-size');
|
|
} else {
|
|
$step.removeClass('custom-size');
|
|
}
|
|
|
|
var customIops = item[args.customIopsFlag];
|
|
|
|
if (customIops && args.canShowCustomIops) {
|
|
$step.addClass('custom-iops');
|
|
} else {
|
|
$step.removeClass('custom-iops');
|
|
}
|
|
|
|
return true;
|
|
});
|
|
|
|
originalValues(formData);
|
|
}
|
|
}
|
|
};
|
|
},
|
|
|
|
'data-disk-offering': function($step, formData) {
|
|
var originalValues = function(formData) {
|
|
var $targetInput = $step.find('input[type=radio]').filter(function() {
|
|
return $(this).val() == formData.diskofferingid;
|
|
}).click();
|
|
|
|
if (!$targetInput.length) {
|
|
$step.find('input[type=radio]:visible').filter(':first').click();
|
|
}
|
|
};
|
|
|
|
$step.find('.section.custom-size').hide();
|
|
|
|
return {
|
|
response: {
|
|
success: function(args) {
|
|
var multiDisk = args.multiDisk;
|
|
|
|
$step.find('.multi-disk-select-container').remove();
|
|
$step.removeClass('custom-disk-size');
|
|
$step.find('.main-desc, p.no-datadisk').remove();
|
|
|
|
if (!multiDisk){
|
|
if (args.required) {
|
|
$step.find('.section.no-thanks')
|
|
.hide();
|
|
$step.addClass('required');
|
|
} else {
|
|
$step.find('.section.no-thanks')
|
|
.show();
|
|
$step.removeClass('required');
|
|
}
|
|
} else {
|
|
$step.find('.section.no-thanks').hide();
|
|
$step.addClass('required');
|
|
}
|
|
|
|
var $selectContainer = $step.find('.content .select-container:not(.multi-disk)');
|
|
|
|
if (multiDisk) { // Render as multiple groups for each disk
|
|
if (multiDisk[0].id == "none"){
|
|
$step.find('.select-container').append(
|
|
$('<p>').addClass('no-datadisk').html(_l('message.no.datadisk'))
|
|
);
|
|
return;
|
|
}
|
|
var $multiDiskSelect = $('<div>').addClass('multi-disk-select-container');
|
|
|
|
$(multiDisk).map(function(index, disk) {
|
|
var array_do = [];
|
|
$.each(args.data.diskOfferings, function( key, value ) {
|
|
if (value){
|
|
if (value.disksize >= disk.size && value.name != "Custom"){
|
|
array_do.push(value);
|
|
}
|
|
}
|
|
})
|
|
var $group = $('<div>').addClass('disk-select-group');
|
|
var $header = $('<div>').addClass('disk-select-header').append(
|
|
$('<div>').addClass('title').html(disk.label)
|
|
).appendTo($group);
|
|
var $checkbox = $('<input>').addClass('multi-disk-select')
|
|
.attr({
|
|
type: 'checkbox',
|
|
'disk-id': disk.id
|
|
})
|
|
.prependTo($header);
|
|
var $multiSelectContainer = $selectContainer.clone().append(
|
|
makeSelects('diskofferingid.' + disk.id, array_do, {
|
|
id: 'id',
|
|
name: 'name',
|
|
desc: 'displaytext'
|
|
}, {
|
|
'wizard-field': 'disk-offering'
|
|
})
|
|
).appendTo($group).addClass('multi-disk');
|
|
|
|
$group.appendTo($multiDiskSelect);
|
|
$group.data('json-obj', disk);
|
|
|
|
// Show-hide disk group selects
|
|
$checkbox.click(function() {
|
|
$group.toggleClass('selected');
|
|
$group.find('.select:first input[type=radio]').click();
|
|
|
|
if (!$multiDiskSelect.find('input[type=checkbox]:checked').length) {
|
|
$step.find('.no-thanks input[type=radio]').click();
|
|
} else {
|
|
$step.find('.no-thanks input[type=radio]').attr('checked', false);
|
|
}
|
|
});
|
|
|
|
// Add custom disk size box
|
|
$step.find('.section.custom-size').clone().hide().appendTo($group);
|
|
});
|
|
|
|
$multiDiskSelect.insertAfter($selectContainer);
|
|
$selectContainer.hide();
|
|
|
|
// Fix issue with containers always showing after reload
|
|
$multiDiskSelect.find('.select-container').attr('style', null);
|
|
} else {
|
|
$selectContainer.show();
|
|
$step.find('.content .select-container').append(
|
|
makeSelects('diskofferingid', args.data.diskOfferings, {
|
|
id: 'id',
|
|
name: 'name',
|
|
desc: 'displaytext'
|
|
}, {
|
|
'wizard-field': 'disk-offering'
|
|
})
|
|
);
|
|
}
|
|
|
|
$step.find('input[type=radio]').bind('change', function() {
|
|
var $target = $(this);
|
|
var val = $target.val();
|
|
var item = $.grep(args.data.diskOfferings, function(elem) {
|
|
return elem.id == val;
|
|
})[0];
|
|
var isMultiDisk = $step.find('.multi-disk-select').length;
|
|
|
|
// Uncheck any multi-select groups
|
|
if ($target.closest('.no-thanks').length && isMultiDisk) {
|
|
$step.find('.disk-select-group input[type=checkbox]:checked').click();
|
|
$(this).attr('checked', true);
|
|
|
|
return true;
|
|
}
|
|
|
|
if (!item) {
|
|
if (isMultiDisk) {
|
|
$(this).closest('.disk-select-group .section.custom-size').hide();
|
|
$(this).closest('.disk-select-group').removeClass('custom-size');
|
|
} else {
|
|
// handle removal of custom size controls
|
|
$step.find('.section.custom-size').hide();
|
|
$step.removeClass('custom-disk-size');
|
|
|
|
// handle removal of custom IOPS controls
|
|
$step.removeClass('custom-iops-do');
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
var custom = item[args.customFlag];
|
|
|
|
if (!isMultiDisk) $step.find('.custom-size-label').remove();
|
|
|
|
if (custom && !isMultiDisk) {
|
|
$target.parent().find('.name')
|
|
.append(
|
|
$('<span>').addClass('custom-size-label')
|
|
.append(': ')
|
|
.append(
|
|
$('<span>').addClass('custom-disk-size').html(
|
|
$step.find('.custom-size input[name=size]').val()
|
|
)
|
|
)
|
|
.append(' GB')
|
|
);
|
|
$target.parent().find('.select-desc .desc')
|
|
.append(
|
|
$('<span>').addClass('custom-size-label')
|
|
.append(', ')
|
|
.append(
|
|
$('<span>').addClass('custom-disk-size').html(
|
|
$step.find('.custom-size input[name=size]').val()
|
|
)
|
|
)
|
|
.append(' GB')
|
|
);
|
|
$step.find('.section.custom-size').show();
|
|
$step.addClass('custom-disk-size');
|
|
$target.closest('.select-container').scrollTop(
|
|
$target.position().top
|
|
);
|
|
} else if (custom && isMultiDisk) {
|
|
$(this).closest('.disk-select-group').addClass('custom-size');
|
|
} else {
|
|
if (isMultiDisk) {
|
|
$(this).closest('.disk-select-group').removeClass('custom-size');
|
|
} else {
|
|
$step.find('.section.custom-size').hide();
|
|
$step.removeClass('custom-disk-size');
|
|
}
|
|
}
|
|
|
|
var customIops = item[args.customIopsDoFlag];
|
|
|
|
if (customIops) {
|
|
$step.addClass('custom-iops-do');
|
|
} else {
|
|
$step.removeClass('custom-iops-do');
|
|
}
|
|
|
|
return true;
|
|
});
|
|
|
|
originalValues(formData);
|
|
}
|
|
}
|
|
};
|
|
},
|
|
|
|
'affinity': function($step, formData) {
|
|
return {
|
|
response: {
|
|
success: function(args) {
|
|
// Cleanup
|
|
$step.find('.main-desc, p.no-affinity-groups').remove();
|
|
|
|
if (args.data.affinityGroups && args.data.affinityGroups.length) {
|
|
$step.prepend(
|
|
$('<div>').addClass('main-desc').append(
|
|
$('<p>').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(
|
|
$('<p>').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(
|
|
$('<div>').addClass('main-desc').append(
|
|
$('<p>').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(
|
|
$('<p>').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').length) {
|
|
$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 = $('<option>');
|
|
var id = vpc.id;
|
|
var description = vpc.name;
|
|
|
|
$option.attr('value', id);
|
|
$option.html(description);
|
|
$option.appendTo($vpcSelect);
|
|
});
|
|
|
|
// 'No VPC' option
|
|
$('<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() {
|
|
$('<option>')
|
|
.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 = $('<div>').addClass('advanced-options hide-if-unselected');
|
|
var $specifyIpField = $('<div>').addClass('specify-ip hide-if-unselected').append(
|
|
$('<label>').html(_l('label.ip.address')),
|
|
$('<input>').attr({ type: 'text' })
|
|
);
|
|
|
|
// Cleanup
|
|
if ($select.closest('.new-network').length) {
|
|
$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').length) {
|
|
fieldName = $input.closest('div.new-network').find('input[name="new-network-name"]').val();
|
|
// Choosen Network from existed
|
|
} else if ($input.parents('div.my-networks').length) {
|
|
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 += '<br />';
|
|
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.length) {
|
|
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').length) {
|
|
$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').length) {
|
|
//step 2 - select template/ISO
|
|
if($activeStep.hasClass('select-iso')) {
|
|
if ($activeStep.find('.content:visible input:checked').length == 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').length > 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').length == 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').length > 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]').length > 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').length) {
|
|
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').length) {
|
|
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.length - 1 && $networkStep.hasClass('next-use-security-groups')) {
|
|
showStep(5);
|
|
} else if ($activeStep.find('.select-security-group:visible').length &&
|
|
$activeStep.find('.select-network.no-add-network').length) {
|
|
showStep(5);
|
|
} else {
|
|
showStep(index);
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
// Close button
|
|
if ($target.closest('div.button.cancel').length) {
|
|
close();
|
|
|
|
return false;
|
|
}
|
|
|
|
// Edit link
|
|
if ($target.closest('div.edit').length) {
|
|
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));
|
|
});
|
|
|
|
|
|
var wizardDialog = $wizard.dialog({
|
|
title: _l('label.vm.add'),
|
|
width: 896,
|
|
minHeight: 600,
|
|
height: 'auto',
|
|
closeOnEscape: false,
|
|
modal: true
|
|
});
|
|
var wizardDialogDiv = wizardDialog.closest('.ui-dialog');
|
|
|
|
$('button.ui-dialog-titlebar-close').remove();
|
|
return wizardDialogDiv.overlay();
|
|
};
|
|
|
|
instanceWizard(args);
|
|
};
|
|
};
|
|
})(jQuery, cloudStack);
|