mirror of
				https://github.com/apache/cloudstack.git
				synced 2025-10-26 08:42:29 +01:00 
			
		
		
		
	-Fixes case where 1 existing network is present, but cannot be unchecked when 'add new network' is checked -Fixes regression with multiple networks and VPC tiers present, where unchecking all regular networks will select the hidden VPC network reviewed-by: jessica
		
			
				
	
	
		
			869 lines
		
	
	
		
			32 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			869 lines
		
	
	
		
			32 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');
 | |
| 
 | |
|           args.action({
 | |
|             // Populate data
 | |
|             context: context,
 | |
|             data: data,
 | |
|             response: {
 | |
|               success: function(args) {
 | |
|                 var $listView = $('.list-view.instances');
 | |
| 
 | |
|                 if ($listView.size()) {
 | |
|                   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.size()? $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) {
 | |
|           var $selects = $('<div>');
 | |
|           options = options ? options : {};
 | |
| 
 | |
|           $(data).each(function() {
 | |
|             var id = this[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 $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';
 | |
|                         var isSingleSelect = $(this).closest('.select-container').hasClass('single-select');
 | |
| 
 | |
|                         if (isCheckbox) {
 | |
|                           if ((isSingleSelect || !$otherSelects.size()) &&
 | |
|                               $newNetwork.find('input[type=checkbox]').is(':unchecked')) {
 | |
|                             $otherSelects.find('input[type=checkbox]').attr('checked', false);
 | |
| 
 | |
|                             // 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(this[fields.name]))
 | |
|                       .append($('<div>').addClass('desc').html(this[fields.desc]))
 | |
|                   )
 | |
|                   .data('json-obj', this);
 | |
| 
 | |
|             $selects.append($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);
 | |
|                     }
 | |
|                   })
 | |
|                   .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) {
 | |
|               $step.find('select').val(
 | |
|                 formData.zoneid
 | |
|               );
 | |
| 
 | |
|               $step.find('input[type=radio]').filter(function() {
 | |
|                 return $(this).val() == formData['select-template'];
 | |
|               }).click();
 | |
|             };
 | |
| 
 | |
|             return {
 | |
|               response: {
 | |
|                 success: function(args) {
 | |
|                   // Zones
 | |
|                   $(args.data.zones).each(function() {
 | |
|                     $step.find('.select-zone select').append(
 | |
|                       $('<option>')
 | |
|                         .attr({
 | |
|                           value: this.id,
 | |
|                           'wizard-field': 'zone'
 | |
|                         })
 | |
|                         .html(this.name)
 | |
|                     );
 | |
|                   });
 | |
| 
 | |
|                   originalValues(formData);
 | |
|                 }
 | |
|               }
 | |
|             };
 | |
|           },
 | |
| 
 | |
|           'select-iso': function($step, formData) {
 | |
|             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.size()) {
 | |
|                 $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'
 | |
|                     });
 | |
| 
 | |
|                     if (type == 'featuredisos' || type == 'communityisos' || type == 'myisos') {
 | |
|                       // 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();
 | |
| 
 | |
|                         $select.addClass('selected').append(
 | |
|                           $('<div>').addClass('hypervisor')
 | |
|                             .append($('<label>').html('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
 | |
|                   $(
 | |
|                     [
 | |
|                       ['featuredtemplates', 'instance-wizard-featured-templates'],
 | |
|                       ['communitytemplates', 'instance-wizard-community-templates'],
 | |
|                       ['mytemplates', 'instance-wizard-my-templates'],
 | |
| 
 | |
|                       ['featuredisos', 'instance-wizard-featured-isos'],
 | |
|                       ['communityisos', 'instance-wizard-community-isos'],
 | |
|                       ['myisos', 'instance-wizard-my-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);
 | |
|                     });
 | |
|                   });
 | |
| 
 | |
|                   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'
 | |
|                     })
 | |
|                   );
 | |
| 
 | |
|                   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.size()) {
 | |
|                 $step.find('input[type=radio]:visible').filter(':first').click();
 | |
|               }
 | |
|             };
 | |
| 
 | |
|             $step.find('.section.custom-size').hide();
 | |
| 
 | |
|             return {
 | |
|               response: {
 | |
|                 success: function(args) {
 | |
|                   $step.removeClass('custom-disk-size');
 | |
|                   if (args.required) {
 | |
|                     $step.find('.section.no-thanks').hide();
 | |
|                     $step.addClass('required');
 | |
|                   } else {
 | |
|                     $step.find('.section.no-thanks').show();
 | |
|                     $step.removeClass('required');
 | |
|                   }
 | |
| 
 | |
|                   $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];
 | |
| 
 | |
|                     if (!item) return true;
 | |
| 
 | |
|                     var custom = item[args.customFlag];
 | |
| 
 | |
|                     $step.find('.custom-size-label').remove();
 | |
| 
 | |
|                     if (custom) {
 | |
|                       $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 {
 | |
|                       $step.find('.section.custom-size').hide();
 | |
|                       $step.removeClass('custom-disk-size');
 | |
|                     }
 | |
| 
 | |
|                     return true;
 | |
|                   });
 | |
| 
 | |
|                   originalValues(formData);
 | |
|                 }
 | |
|               }
 | |
|             };
 | |
|           },
 | |
| 
 | |
|           'network': function($step, formData) {
 | |
|             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();
 | |
| 
 | |
|             // 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();
 | |
|               }
 | |
|               
 | |
|               $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;
 | |
| 
 | |
|                   // 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('None').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', $.merge(args.data.myNetworks, args.data.sharedNetworks), {
 | |
|                       name: 'name',
 | |
|                       desc: 'type',
 | |
|                       id: 'id'
 | |
|                     }, {
 | |
|                       type: 'checkbox',
 | |
|                       'wizard-field': 'my-networks',
 | |
|                       secondary: {
 | |
|                         desc: 'Default',
 | |
|                         name: 'defaultNetwork',
 | |
|                         type: 'radio',
 | |
|                         'wizard-field': 'default-network'
 | |
|                       }
 | |
|                     })
 | |
|                   );
 | |
| 
 | |
|                   // Show non-VPC networks by default
 | |
|                   filterNetworkList(-1);
 | |
| 
 | |
|                   // Security groups (alt. page)
 | |
|                   $step.find('.security-groups .select-container').append(
 | |
|                     makeSelects('security-groups', args.data.securityGroups, {
 | |
|                       name: 'name',
 | |
|                       desc: 'description',
 | |
|                       id: 'id'
 | |
|                     }, {
 | |
|                       type: 'checkbox',
 | |
|                       'wizard-field': 'security-groups'
 | |
|                     })
 | |
|                   );
 | |
| 
 | |
|                   originalValues(formData);
 | |
|                 }
 | |
|               }
 | |
|             };
 | |
|           },
 | |
| 
 | |
|           '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');
 | |
|                     });
 | |
| 
 | |
|                     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 += '<br />';
 | |
|                   fieldName += $(this).next('div.select-desc').find('.name').html();
 | |
|                 });
 | |
|               }
 | |
| 
 | |
|                     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();
 | |
|                 }
 | |
|               }
 | |
|             });
 | |
|           }
 | |
|         };
 | |
| 
 | |
|         // 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 (!$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
 | |
|               )
 | |
|             );
 | |
| 
 | |
|             $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()) {
 | |
|             // Make sure ISO or template is selected
 | |
|             if ($activeStep.hasClass('select-iso') &&
 | |
|                 !$activeStep.find('.content:visible input:checked').size()) {
 | |
|               cloudStack.dialog.notice({ message: 'message.step.1.continue' });
 | |
|               return false;
 | |
|             }
 | |
| 
 | |
|             //step 5 - select network
 | |
|             if($activeStep.find('.wizard-step-conditional.select-network:visible').size() > 0) {
 | |
|               if($activeStep.find('input[type=checkbox]:checked').size() == 0) {  //if no checkbox is checked
 | |
|                 cloudStack.dialog.notice({ message: 'message.step.4.continue' });
 | |
|                 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;
 | |
|               }
 | |
|             }
 | |
| 
 | |
|             showStep($steps.filter(':visible').index() + 2);
 | |
| 
 | |
|             return false;
 | |
|           }
 | |
| 
 | |
|           // Previous button
 | |
|           if ($target.closest('div.button.previous').size()) {
 | |
|             var index = $steps.filter(':visible').index();
 | |
|             if (index) 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 maxCustomDiskSize = args.maxDiskOfferingSize ?
 | |
|               args.maxDiskOfferingSize() : 100;
 | |
| 
 | |
|         // Setup tabs and slider
 | |
|         $wizard.find('.section.custom-size .size.max span').html(maxCustomDiskSize);
 | |
|         $wizard.find('.tab-view').tabs();
 | |
|         $wizard.find('.slider').slider({
 | |
|           min: 1,
 | |
|           max: maxCustomDiskSize,
 | |
|           start: function(event) {
 | |
|             $wizard.find('div.data-disk-offering div.custom-size input[type=radio]').click();
 | |
|           },
 | |
|           slide: function(event, ui) {
 | |
|             $wizard.find('div.data-disk-offering div.custom-size input[type=text]').val(
 | |
|               ui.value
 | |
|             );
 | |
|             $wizard.find('div.data-disk-offering span.custom-disk-size').html(
 | |
|               ui.value
 | |
|             );
 | |
|           }
 | |
|         });
 | |
| 
 | |
|         return $wizard.dialog({
 | |
|           title: _l('label.vm.add'),
 | |
|           width: 800,
 | |
|           height: 570,
 | |
|           closeOnEscape: false,
 | |
|           zIndex: 5000
 | |
|         })
 | |
|           .closest('.ui-dialog').overlay();
 | |
|       };
 | |
| 
 | |
|       instanceWizard(args);
 | |
|     };
 | |
|   };
 | |
| })(jQuery, cloudStack);
 |