// Copyright 2012 Citrix Systems, Inc. Licensed under the // Apache License, Version 2.0 (the "License"); you may not use this // file except in compliance with the License. Citrix Systems, Inc. // reserves all rights not expressly granted by 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. // // Automatically generated by addcopyright.py at 04/03/2012 (function($, cloudStack) { /** * Serialize form data as object */ var getData = function($wizard, options) { if (!options) options = {}; var $forms = $wizard.find('form').filter(function() { return !options.all ? !$(this).closest('.multi-edit').size() : true; }); var $physicalNetworkItems = $wizard.find( '.steps .setup-physical-network .select-container.multi' ).filter(':not(.disabled)'); var $publicTrafficItems = $wizard.find( '.steps .setup-public-traffic .data-body .data-item'); var $storageTrafficItems = $wizard.find( '.steps .setup-storage-traffic .data-body .data-item'); var groupedForms = {}; if ($physicalNetworkItems.find('li.traffic-type-draggable.storage').size()) { $wizard.find('li.conditional.storage-traffic').show(); } else { $wizard.find('li.conditional.storage-traffic').hide(); } if (options.all) { return cloudStack.serializeForm($forms, { escapeSlashes: true }); } // Group form fields together, by form ID $forms.each(function() { var $form = $(this); var id = $form.attr('rel'); if (!id) return true; groupedForms[id] = cloudStack.serializeForm($form, { escapeSlashes: true }); return true; }); // Get physical network data groupedForms.physicalNetworks = $.map( $physicalNetworkItems, function(network) { var $network = $(network); var $guestForm = $wizard.find('form[guest-network-id=' + $network.index() + ']'); var trafficTypeConfiguration = {}; $network.find('.traffic-type-draggable').each(function() { var $trafficType = $(this); var trafficTypeID = $trafficType.attr('traffic-type-id'); trafficTypeConfiguration[trafficTypeID] = $trafficType.data('traffic-type-data'); }); return { id: $network.index(), name: $network.find('.field.name input[type=text]').val(), // Traffic type list trafficTypes: $.map( $network.find('.traffic-type-draggable'), function(trafficType) { var $trafficType = $(trafficType); return $trafficType.attr('traffic-type-id'); } ), // Traffic type configuration data trafficTypeConfiguration: trafficTypeConfiguration, guestConfiguration: $guestForm.size() ? cloudStack.serializeForm($guestForm) : null }; } ); // Get public traffic data (multi-edit) groupedForms.publicTraffic = $.map( $publicTrafficItems, function(publicTrafficItem) { var $publicTrafficItem = $(publicTrafficItem); var publicTrafficData = {}; var fields = [ 'gateway', 'netmask', 'vlanid', 'startip', 'endip' ]; $(fields).each(function() { publicTrafficData[this] = $publicTrafficItem.find('td.' + this + ' span').html(); }); return publicTrafficData; } ); // Get storage traffic data (multi-edit) groupedForms.storageTraffic = $.map( $storageTrafficItems, function(storageTrafficItem) { var $storageTrafficItem = $(storageTrafficItem); var storageTrafficData = {}; var fields = [ 'gateway', 'netmask', 'vlanid', 'startip', 'endip' ]; $(fields).each(function() { storageTrafficData[this] = $storageTrafficItem.find('td.' + this + ' span').html(); }); return storageTrafficData; } ); // Hack to fix forward slash JS error $.each(groupedForms, function(key1, value1) { $.each(value1, function(key2, value2) { if (typeof value2 == 'string') { groupedForms[key1][key2] = value2.replace(/__forwardSlash__/g, '\/'); } }); }); // Include zone network type if (groupedForms.zone) { groupedForms.zone.networkType = $forms.find('input[name=network-model]:checked').val(); } return groupedForms; }; /** * Handles validation for custom UI components */ var customValidation = { networkRanges: function($form) { if ($form.closest('.multi-edit').find('.data-item').size()) { return true; } cloudStack.dialog.notice({ message: dictionary['message.please.add.at.lease.one.traffic.range'] }); return false; }, physicalNetworks: function($form) { var $enabledPhysicalNetworks = $form.filter(':not(.disabled)').filter(function() { return $(this).find('.traffic-type-draggable').size(); }); var $trafficTypes = $enabledPhysicalNetworks.find('.traffic-type-draggable'); var $configuredTrafficTypes = $trafficTypes.filter(function() { var $trafficType = $(this); return $trafficType.data('traffic-type-data') && $trafficType.data('traffic-type-data').label.length >= 1; }); if ($enabledPhysicalNetworks.size() > 1 && $configuredTrafficTypes.size() != $trafficTypes.size()) { cloudStack.dialog.notice({ message: _l('message.configure.all.traffic.types') }); return false; } return true; } }; /** * Determine if UI components in step should be custom-validated * (i.e., not a standard form) */ var checkCustomValidation = function($step) { var $multiEditForm = $step.find('.multi-edit form'); var $physicalNetworks = $step.find('.select-container.multi'); var isCustomValidated; if ($multiEditForm.size()) { isCustomValidated = customValidation.networkRanges($multiEditForm); } else if ($physicalNetworks.size()) { isCustomValidated = customValidation.physicalNetworks($physicalNetworks); } else { isCustomValidated = true; } return isCustomValidated; }; var isAdvancedNetwork = function($wizard) { return getData($wizard, { all: true })['network-model'] == 'Advanced'; }; /** * Setup physical network wizard UI */ var physicalNetwork = { init: function($wizard) { var $existingPhysicalNetworks = physicalNetwork.getNetworks($wizard); // Initialize physical networks if (!$existingPhysicalNetworks.size()) { physicalNetwork.add($wizard); } else if (!isAdvancedNetwork($wizard)) { $existingPhysicalNetworks.filter(':first').siblings().each(function() { physicalNetwork.remove($(this)); }); } physicalNetwork.updateNetworks(physicalNetwork.getNetworks($wizard)); $wizard.find('.traffic-types-drag-area ul li').removeClass('required disabled clone'); // Setup clone traffic types $(physicalNetwork.cloneTrafficTypes($wizard)).each(function() { var trafficTypeID = this; $wizard.find('.traffic-types-drag-area ul li').filter(function() { return $(this).hasClass(trafficTypeID); }).addClass('clone'); }); // Setup required traffic types $(physicalNetwork.requiredTrafficTypes($wizard)).each(function () { var trafficTypeID = this; var $firstPhysicalNetwork = physicalNetwork.getNetworks($wizard).filter(':first'); // First physical network gets required traffic types physicalNetwork.assignTrafficType(trafficTypeID, $firstPhysicalNetwork); $wizard.find('.traffic-types-drag-area ul li').filter(function() { return $(this).hasClass(trafficTypeID); }).addClass('required'); }); // Setup disabled traffic types $(physicalNetwork.disabledTrafficTypes($wizard)).each(function() { var trafficTypeID = this; var $trafficType = physicalNetwork.getTrafficType(this, $wizard); physicalNetwork.unassignTrafficType($trafficType); $wizard.find('.traffic-types-drag-area ul li').filter(function() { return $(this).hasClass(trafficTypeID); }).addClass('disabled'); }); }, /** * Traffic type edit dialog */ editTrafficTypeDialog: function($trafficType) { var trafficData = $trafficType.data('traffic-type-data') ? $trafficType.data('traffic-type-data') : {}; var hypervisor = getData($trafficType.closest('.zone-wizard')).zone.hypervisor; cloudStack.dialog.createForm({ form: { title: _l('label.edit.traffic.type'), desc: _l('message.edit.traffic.type'), fields: { label: { label: hypervisor + ' ' + _l('label.traffic.label'), defaultValue: trafficData.label } } }, after: function(args) { $trafficType.data('traffic-type-data', args.data); } }); }, /** * Get required traffic type IDs for proper validation */ requiredTrafficTypes: function($wizard) { return cloudStack.zoneWizard.requiredTrafficTypes({ data: getData($wizard) }); }, /** * Get required traffic type IDs for proper validation */ disabledTrafficTypes: function($wizard) { return cloudStack.zoneWizard.disabledTrafficTypes({ data: getData($wizard) }); }, /** * Get clone-type traffic type IDs for proper validation */ cloneTrafficTypes: function($wizard) { return cloudStack.zoneWizard.cloneTrafficTypes({ data: getData($wizard) }); }, /** * Physical network step: Renumber network form items */ renumberFormItems: function($container) { var $items = $container.find('.select-container.multi'); $items.each(function() { var $item = $(this); var $networkName = $item.find('.field.name input[type=text]'); var $networkId = $item.find('input[name=id]'); var $networkTypes = $item.find('.field.network-types input'); var index = $item.index(); $networkId.val(index); $networkName.attr('name', 'physicalNetworks[' + index + ']' + '.name'); $networkTypes.val(index); }); }, /** * Get main physical network wizard step container * * @param $elem Any elem within the container */ getMainContainer: function($elem) { return $elem.closest('.steps .setup-physical-network'); }, /** * Returns traffic elem * * @param trafficTypeID ID of desired traffic type */ getTrafficType: function(trafficTypeID, $container) { var $trafficType = $container.find('li.traffic-type-draggable').filter(function() { return $(this).attr('traffic-type-id') == trafficTypeID; }); if (physicalNetwork.isTrafficTypeClone($trafficType) && !$container.closest('.select-container.multi').size()) { // Get traffic type from original container return $trafficType.filter(function() { return $(this).closest( physicalNetwork.getOriginalTrafficContainer($trafficType) ).size(); }); } return $trafficType; }, /** * Get original drag container for traffic type elem * * @param $trafficType Traffic type elem */ getOriginalTrafficContainer: function($trafficType) { var $dragContainer = physicalNetwork.getMainContainer($trafficType) .find('.traffic-types-drag-area ul > li') .filter(function() { return $(this).hasClass($trafficType.attr('traffic-type-id')); }) .find('ul'); return $dragContainer; }, /** * Get all physical networks * * @param $container Physical network step - main container */ getNetworks: function($container) { return $container.find('.select-container.multi'); }, /** * Determine if traffic type is a 'cloned' type * * @param $trafficType */ isTrafficTypeClone: function($trafficType) { return physicalNetwork.getOriginalTrafficContainer($trafficType).parent().hasClass('clone'); }, /** * Assigns traffic type to specified physical network * * @param trafficTypeID ID of desired traffic type * @param $physicalNetwork Physical network elem */ assignTrafficType: function(trafficTypeID, $physicalNetwork, data) { var $container = physicalNetwork.getMainContainer($physicalNetwork); var $trafficType = physicalNetwork.getTrafficType(trafficTypeID, $container); var $dropArea = $physicalNetwork.find('.drop-container ul'); if ($physicalNetwork.find('.traffic-type-draggable[traffic-type-id=' + trafficTypeID + ']').size()) return false; if (physicalNetwork.isTrafficTypeClone($trafficType)) { if (!physicalNetwork.getTrafficType(trafficTypeID, $physicalNetwork).size()) { $trafficType = $trafficType.clone() .removeClass('disabled') .appendTo($dropArea) .draggable(physicalNetwork.draggableOptions($physicalNetwork.closest('.zone-wizard'))); } else { return false; } } else { $trafficType.appendTo($dropArea); } if (data) { $trafficType.data('traffic-type-data', data); } physicalNetwork.updateNetworks($.merge($physicalNetwork, $physicalNetwork.siblings())); return $trafficType; }, /** * Assigns traffic type to original drag container * * @param trafficTypeID ID of desired traffic type * @param $container Physical network wizard step container * @param $physicalNetwork (optional) Specific physical network to remove from -- only for clones */ unassignTrafficType: function($trafficType) { var $wizard = $trafficType.closest('.zone-wizard'); var $originalContainer = physicalNetwork.getOriginalTrafficContainer($trafficType); var $physicalNetworks = physicalNetwork.getNetworks($wizard); var trafficTypeID = $trafficType.attr('traffic-type-id'); if (!physicalNetwork.isTrafficTypeClone($trafficType) && $.inArray(trafficTypeID, physicalNetwork.requiredTrafficTypes($wizard)) == -1) { $trafficType.appendTo($originalContainer); } else { physicalNetwork.assignTrafficType( trafficTypeID, $physicalNetworks.filter(':first') ); if (physicalNetwork.isTrafficTypeClone($trafficType) && $physicalNetworks.find('.traffic-type-draggable[traffic-type-id=' + trafficTypeID + ']').size() > 1) { $trafficType.remove(); } } return $trafficType; }, /** * Returns true if new physical network item needs to be added */ needsNewNetwork: function($containers) { // Basic zones do not have multiple physical networks if (!isAdvancedNetwork($containers.closest('.zone-wizard'))) return false; var $emptyContainers = $containers.filter(function() { return !$(this).find('li').size(); }); return !$emptyContainers.size() ? $containers.size() : false; }, /** * Cleanup physical network containers */ updateNetworks: function($containers) { var $mainContainer = physicalNetwork.getMainContainer($containers); var $allPhysicalNetworks = physicalNetwork.getNetworks($mainContainer); var containerTotal = isAdvancedNetwork($containers.closest('.zone-wizard')) ? 2 : 1; $allPhysicalNetworks.each(function() { var $ul = $(this).find('.drop-container ul'); if (!$(this).find('li').size()) { $(this).addClass('disabled'); $ul.fadeOut(); } else { $(this).removeClass('disabled'); $ul.show(); } }); $containers.each(function() { var $currentContainer = $(this); if (!$currentContainer.find('li').size() && $containers.size() > containerTotal) { $currentContainer.remove(); } }); $containers = $containers.closest('.setup-physical-network') .find('.select-container.multi'); if (physicalNetwork.needsNewNetwork($containers)) { physicalNetwork.add($mainContainer.parent()); } $containers.filter(':first').find('.remove.physical-network').remove(); return $containers; }, /** * Default options for initializing traffic type draggables */ draggableOptions: function($wizard) { return { appendTo: $wizard, helper: 'clone', // Events start: function(event, ui) { $(this).addClass('disabled'); }, stop: function(event, ui) { $(this).removeClass('disabled'); }, cancel: '.edit-traffic-type' }; }, /** * Physical network step: Generate new network element */ add: function($wizard) { var $container = $wizard.find('.setup-physical-network .content.input-area form'); var $physicalNetworkItem = $('
').addClass('select-container multi'); var $deleteButton = $('
').addClass('button remove physical-network') .attr({ title: 'Remove this physical network' }) .append('').addClass('icon').html(' '); var $icon = $('
').addClass('physical-network-icon'); var $nameField = $('
').addClass('field name').append( $('
').addClass('name').append( $('').html('Physical network name') ), $('
').addClass('value').append( $('').attr({ type: 'text' }).addClass('required') ) ); var $dropContainer = $('
').addClass('drop-container').append( $('').addClass('empty-message').html( 'Drag and drop traffic types you would like to add here.' ), $('
    ').hide() ).droppable({ over: function(event, ui) { var $ul = $(this).find('ul'); $ul.addClass('active'); if (!$ul.find('li').size()) { $(this).closest('.select-container.multi').removeClass('disabled'); $ul.fadeIn(); } }, out: function(event, ui) { var $ul = $(this).find('ul'); $ul.removeClass('active'); physicalNetwork.updateNetworks($(this).closest('.select-container.multi')); }, drop: function(event, ui) { var trafficTypeID = ui.draggable.attr('traffic-type-id'); var $physicalNetwork = $(this).closest('.select-container.multi'); var trafficTypeData = ui.draggable.data('traffic-type-data'); if (trafficTypeID == 'guest' && ui.draggable.closest('.select-container.multi').size()) { ui.draggable.remove(); } physicalNetwork.assignTrafficType(trafficTypeID, $physicalNetwork, trafficTypeData); } }); var $idField = $('').attr({ type: 'hidden', name: 'id', value: 0 }); // Initialize new default network form elem $physicalNetworkItem.append( $icon, $nameField, $idField, $dropContainer ); // Only advanced zones can remove physical network if (isAdvancedNetwork($wizard)) { $physicalNetworkItem.prepend($deleteButton); } $physicalNetworkItem.hide().appendTo($container).fadeIn('fast'); $physicalNetworkItem.find('.name input').val('Physical Network ' + parseInt($physicalNetworkItem.index() + 1)); physicalNetwork.renumberFormItems($container); // Remove network action $physicalNetworkItem.find('.button.remove.physical-network').click(function() { physicalNetwork.remove($physicalNetworkItem); }); $physicalNetworkItem.addClass('disabled'); // Since there are no traffic types yet return $physicalNetworkItem; }, /** * Physical network step: Remove specified network element * * @param $physicalNetworkItem Physical network container to remove */ remove: function($physicalNetworkItem) { var $container = $physicalNetworkItem.closest('.setup-physical-network .content.input-area form'); var $trafficTypes = $physicalNetworkItem.find('li.traffic-type-draggable'); $trafficTypes.each(function() { var trafficTypeID = $(this).attr('traffic-type-id'); physicalNetwork.assignTrafficType( trafficTypeID, $physicalNetworkItem.prev() ); }); $trafficTypes.filter('.clone').remove(); physicalNetwork.updateNetworks($physicalNetworkItem.parent().find('.multi')); $container.validate('refresh'); } }; /** * Configure guest traffic UI */ var guestTraffic = { init: function($wizard, args) { var $physicalNetworks = physicalNetwork.getNetworks($wizard); var $tabs = guestTraffic.makeTabs($physicalNetworks, args); var $container = guestTraffic.getMainContainer($wizard); // Cleanup guestTraffic.remove($wizard); $container.find('.content form').hide(); $tabs.appendTo($container.find('.content .select-container')); var $subnav = $container.find('ul.subnav').remove(); // Fix to avoid subnav becoming tab ul $container.tabs(); $container.prepend($subnav); $container.find('.field').hide(); $container.find('[rel=vlanRange]').show(); }, /** * Cleanup */ remove: function($wizard) { var $container = guestTraffic.getMainContainer($wizard); // Cleanup $container.tabs('destroy'); $container.find('.physical-network-item').remove(); $container.find('.content form').show(); }, getMainContainer: function($wizard) { return $wizard.find('.steps .setup-guest-traffic'); }, makeTabs: function($physicalNetworks, args) { var $tabs = $('
      ').addClass('physical-network-item'); var $content = $(); // Only use networks w/ guest traffic type $physicalNetworks = $physicalNetworks.filter(function() { return $(this).find('li.guest').size(); return true; }); $physicalNetworks.each(function() { var $network = $(this); var $form = makeForm(args, 'guestTraffic', {}); var refID = $network.find('input[name=id]').val(); var networkID = 'physical-network-' + refID; $form.attr('guest-network-id', refID); $tabs.append($('
    • ').append( $('') .attr({ href: '#' + networkID }) .html($network.find('.field.name input').val()) )); $.merge( $content, $('
      ') .addClass('physical-network-item') .attr({ id: networkID }) .append($form) ); $form.validate(); }); $tabs.find('li:first').addClass('first'); $tabs.find('li:last').addClass('last'); return $.merge($tabs, $content); } }; /** * Generate dynamic form, based on ID of form object given */ var makeForm = function(args, id, formState) { var form = cloudStack.dialog.createForm({ noDialog: true, context: $.extend(true, {}, cloudStack.context, { zones: [formState] }), form: { title: '', desc: '', fields: args.forms[id].fields }, after: function(args) {} }); var $form = form.$formContainer.find('form'); // Cleanup form to follow zone wizard CSS naming $form.attr('rel', id); $form.find('input[type=submit]').remove(); $form.find('.form-item').addClass('field').removeClass('form-item'); $form.find('label.error').hide(); $form.find('.form-item .name').each(function() { $(this).html($(this).find('label')); }); $form.find('select, input').change(function() { cloudStack.evenOdd($form, '.field:visible', { even: function($row) { $row.removeClass('odd'); }, odd: function($row) { $row.addClass('odd'); } }); }); return $form; }; cloudStack.uiCustom.zoneWizard = function(args) { return function() { var $wizard = $('#template').find('div.zone-wizard').clone(); var $progress = $wizard.find('div.progress ul li'); var $steps = $wizard.find('div.steps').children().hide().filter(':not(.disabled)'); $wizard.data('startfn', null); // Close wizard var close = function() { $wizard.dialog('destroy'); $('div.overlay').fadeOut(function() { $('div.overlay').remove(); }); }; // Save and close wizard var completeAction = function() { var $launchStep = $wizard.find('.steps .review'); var data = getData($wizard); var enableZoneAction = args.enableZoneAction; // Convert last step to launch appearance $launchStep.find('.main-desc').hide(); $launchStep.find('.main-desc.launch').show(); $launchStep.find('.launch-container').show(); $launchStep.find('ul').html(''); $wizard.find('.buttons').hide(); $wizard.find('.button.previous').remove(); var makeMessage = function(message, isError) { var $li = $('
    • ') .addClass(!isError ? 'loading' : 'info') .append( $('').addClass('icon').html(' '), $('').addClass('text').html(message) ); var $launchContainer = $launchStep.find('.launch-container'); $launchStep.find('ul').append($li); $li.prev().removeClass('loading'); $launchContainer.scrollTop($launchContainer.height()); if (isError) { $li.prev().addClass('error'); } }; args.action({ data: data, startFn: $wizard.data('startfn'), uiSteps: $.map( $wizard.find('.steps > div'), function(step) { return $(step).attr('zone-wizard-step-id'); } ), response: { success: function(args) { $launchStep.find('ul li').removeClass('loading'); var closeWindow = function() { close(); $(window).trigger('cloudStack.fullRefresh'); }; var enableZone = function() { makeMessage(dictionary['message.enabling.zone']); enableZoneAction({ formData: data, data: data, launchData: args.data, response: { success: function(args) { closeWindow(); }, error: function(message) { cloudStack.dialog.notice({ message: dictionary['error.could.not.enable.zone'] + ':
      ' + message }); } } }); }; cloudStack.dialog.confirm({ message: dictionary['message.zone.creation.complete.would.you.like.to.enable.this.zone'], action: function() { enableZone(); }, cancelAction: function() { closeWindow(); } }); }, error: function(stepID, message, start) { var goNextOverride = function(event) { $(this).unbind('click', goNextOverride); showStep(stepID, false, { nextStep: 'launch' }); return false; }; $wizard.find('.buttons').show(); $wizard.find('.buttons .button.next') .removeClass('final') .html('Fix errors') .click(goNextOverride); makeMessage(dictionary['error.something.went.wrong.please.correct.the.following'] + ':
      ' + message, true); $wizard.data('startfn', start); }, message: makeMessage } }); }; // Go to specified step in wizard, // updating nav items and diagram var showStep = function(index, goBack, options) { if (!options) options = {}; if (typeof index == 'string') { index = $wizard.find('[zone-wizard-step-id=' + index + ']').index() + 1; } var targetIndex = index - 1; if (index <= 1) targetIndex = 0; if (targetIndex == $steps.size()) { completeAction(); } $steps.hide(); $wizard.find('.buttons').show(); var $targetStep = $($steps[targetIndex]).show(); var $uiCustom = $targetStep.find('[ui-custom]'); var formState = getData($wizard, { all: true }); var groupedFormState = getData($wizard); var formID = $targetStep.attr('zone-wizard-form'); var stepPreFilter = cloudStack.zoneWizard.preFilters[ $targetStep.attr('zone-wizard-prefilter') ]; // Bypass step check if (stepPreFilter && !stepPreFilter({ data: formState, groupedData: groupedFormState })) { return showStep( !goBack ? index + 1 : index - 1, goBack ); } if (formID) { if (!$targetStep.find('form').size()) { makeForm(args, formID, formState).appendTo($targetStep.find('.content.input-area .select-container')); setTimeout(function() { cloudStack.evenOdd($targetStep, '.field:visible', { even: function() {}, odd: function($row) { $row.addClass('odd'); } }); }, 50); } else { // Always re-activate selects $targetStep.find('form select').each(function() { var $select = $(this); var selectFn = $select.data('dialog-select-fn'); var originalVal = $select.val(); if (selectFn) { $select.html(''); selectFn({ context: { zones: [formState] } }); $select.val(originalVal); $select.trigger('change'); } }); } if (args.forms[formID].preFilter) { var preFilter = args.forms[formID].preFilter({ $form: $targetStep.find('form'), data: formState }); } } // Custom UI manipulations for specific steps switch($targetStep.attr('zone-wizard-step-id')) { case 'configureGuestTraffic': if (formState['network-model'] == 'Advanced') { guestTraffic.init($wizard, args); } else { guestTraffic.remove($wizard); } break; case 'setupPhysicalNetwork': physicalNetwork.init($wizard); } if ($uiCustom.size()) { $uiCustom.each(function() { var $item = $(this); var id = $item.attr('ui-custom'); $item.replaceWith( args.customUI[id]({ data: formState, context: cloudStack.context }) ) }); } if (!targetIndex) { $wizard.find('.button.previous').hide(); } else { $wizard.find('.button.previous').show(); } var $nextButton = $wizard.find('.button.next'); $nextButton.find('span').html('Next'); $nextButton.removeClass('final post-launch'); // Show launch button if last step if ($targetStep.index() == $steps.size() - 1 || options.nextStep) { $nextButton.find('span').html(options.nextStep ? 'Save changes' : 'Launch zone'); $nextButton.addClass('final'); if (options.nextStep) { $nextButton.addClass('post-launch'); } } // Update progress bar var $targetProgress = $progress.removeClass('active').filter(function() { return $(this).index() <= targetIndex; }).toggleClass('active'); setTimeout(function() { if (!$targetStep.find('input[type=radio]:checked').size()) { $targetStep.find('input[type=radio]:first').click(); } }, 50); $targetStep.find('form').validate(); }; // Events $wizard.find('select').change(function(event) { // Conditional selects (on step 4 mainly) var $target = $(this); var $tagged = $wizard.find('.conditional.vlan-type-tagged'); var $untagged = $wizard.find('.conditional.vlan-type-untagged'); var $accountSpecific = $wizard.find('.field.conditional.ip-scope-account-specific'); // VLAN - tagged if ($target.is('[name=vlan-type]')) { $tagged.hide(); $untagged.hide(); $accountSpecific.hide(); if ($target.val() == 'tagged') { $untagged.hide(); $tagged.show(); } else if ($target.val() == 'untagged') { $tagged.hide(); $untagged.show(); } $.merge($tagged, $untagged).find('select:visible').trigger('change'); cloudStack.evenOdd($wizard, '.field:visible', { even: function($elem) { $elem.removeClass('odd'); $elem.addClass('even'); }, odd: function($elem) { $elem.removeClass('even'); $elem.addClass('odd'); } }); return true; } // IP Scope - acct. specific if ($target.is('select.ip-scope')) { $accountSpecific.hide(); if ($target.val() == 'account-specific') $accountSpecific.show(); cloudStack.evenOdd($wizard, '.field:visible', { even: function($elem) { $elem.removeClass('odd'); $elem.addClass('even'); }, odd: function($elem) { $elem.removeClass('even'); $elem.addClass('odd'); } }); } return true; }); $wizard.click(function(event) { var $target = $(event.target); // Radio button if ($target.is('[type=radio]')) { if ($target.attr('name') == 'network-model') { var $inputs = $wizard.find('.isolation-mode').find('input[name=isolation-mode]').attr({ disabled: 'disabled' }); if ($target.val() == 'Advanced') { $inputs.attr('disabled', false); } } return true; } // Checkbox if ($target.is('[type=checkbox]:checked')) { $('div.conditional.' + $target.attr('name')).hide(); return true; } else if ($target.is('[type=checkbox]:unchecked')) { $('div.conditional.' + $target.attr('name')).show(); return true; } // Next button if ($target.closest('div.button.next').size()) { var $step = $steps.filter(':visible'); // Validation var $form = $('form:visible').filter(function() { // Don't include multi-edit (validation happens separately) return !$(this).closest('.multi-edit').size(); }); // Handle validation for custom UI components var isCustomValidated = checkCustomValidation($step); if (($form.size() && !$form.valid()) || !isCustomValidated) { if (($form && $form.find('.error:visible').size()) || !isCustomValidated) return false; } if (!$target.closest('.button.next.final').size()) showStep($steps.filter(':visible').index() + 2); else { if ($target.closest('.button.next.final.post-launch').size()) { showStep('launch'); } completeAction(); } return false; } // Previous button if ($target.closest('div.button.previous').size()) { showStep($steps.filter(':visible').index(), true); 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; } // Edit traffic type button var $editTrafficTypeButton = $target.closest('.drop-container .traffic-type-draggable .edit-traffic-type'); var $trafficType = $editTrafficTypeButton.closest('.traffic-type-draggable'); if ($editTrafficTypeButton.size()) { physicalNetwork.editTrafficTypeDialog($trafficType); return false; } return true; }); // Add/remove network action $wizard.find('.button.add.new-physical-network').click(function() { addPhysicalNetwork($wizard); }); // Traffic type draggables $wizard.find('.traffic-type-draggable').draggable(physicalNetwork.draggableOptions($wizard)); // For removing traffic types from physical network $wizard.find('.traffic-types-drag-area').droppable({ drop: function(event, ui) { physicalNetwork.unassignTrafficType(ui.draggable); return true; } }); showStep(1); return $wizard.dialog({ title: 'Add zone', closeOnEscape: false, width: 750, height: 665, zIndex: 5000, resizable: false }).closest('.ui-dialog').overlay(); }; }; })(jQuery, cloudStack);