mirror of
https://github.com/apache/cloudstack
synced 2026-08-10 00:16:08 +00:00
If in a section with multiple subsections, show active subsection in the breadcrumb. For example, if in storage->snapshots, display 'Storage - Snapshots' based on the 'title' attribute for the main section and subsetion. -- Note: this disables the 'fixSize' functionality which resizes long breadcrumb trails, due to incompatibility with this new feature. It is going to be reimplemented anyway, as it is fairly glitchy in its current incarnation.
445 lines
14 KiB
JavaScript
445 lines
14 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) {
|
|
$.extend(cloudStack, {
|
|
ui: {
|
|
widgets: {} // Defines API methods for UI widgets
|
|
},
|
|
uiCustom: {}
|
|
});
|
|
|
|
/**
|
|
* Generate navigation <li>s
|
|
*
|
|
* @param args cloudStack data args
|
|
*/
|
|
var makeNavigation = function(args) {
|
|
var $navList = $('<ul>');
|
|
var preFilter = cloudStack.sectionPreFilter ?
|
|
cloudStack.sectionPreFilter({
|
|
context: $.extend(true, {}, args.context, {
|
|
sections: $.map(cloudStack.sections, function(value, key) {
|
|
return key;
|
|
})
|
|
})
|
|
}) : null;
|
|
|
|
$.each(args.sections, function(sectionID, args) {
|
|
if (preFilter && $.inArray(sectionID, preFilter) == -1) {
|
|
return true;
|
|
}
|
|
|
|
var $li = $('<li>')
|
|
.addClass('navigation-item')
|
|
.addClass(sectionID)
|
|
.append($('<span>').addClass('icon').html(' '))
|
|
.append($('<span>').html(_l(args.title)))
|
|
.data('cloudStack-section-id', sectionID);
|
|
|
|
$li.appendTo($navList);
|
|
|
|
return true;
|
|
});
|
|
|
|
// Special classes for first and last items
|
|
$navList.find('li:first').addClass('first');
|
|
$navList.find('li:last').addClass('last');
|
|
|
|
return $navList;
|
|
};
|
|
|
|
/**
|
|
* Create section contents
|
|
*
|
|
* @param sectionID Section's ID to show
|
|
* @param args CloudStack3 configuration
|
|
*/
|
|
var showSection = function(sectionID, args, $browser) {
|
|
var $navItem = $('#navigation').find('li').filter(function() {
|
|
return $(this).hasClass(sectionID);
|
|
});
|
|
var data = args.sections[sectionID];
|
|
|
|
data.$browser = $browser;
|
|
$navItem.siblings().removeClass('active');
|
|
$navItem.addClass('active');
|
|
|
|
// Reset browser panels
|
|
$browser.cloudBrowser('removeAllPanels');
|
|
$browser.cloudBrowser('addPanel', {
|
|
title: '<span class="section">' + _l(data.title) + '</span>' + '<span class="subsection"></span>',
|
|
data: '',
|
|
complete: function($panel, $breadcrumb) {
|
|
$breadcrumb.attr('title', _l(data.title));
|
|
data.$breadcrumb = $breadcrumb;
|
|
|
|
// Hide breadcrumb if this is the home section
|
|
if (args.home === sectionID) {
|
|
$('#breadcrumbs').find('li:first, div.end:last').hide();
|
|
}
|
|
|
|
// Append specified widget to view
|
|
if (data.show)
|
|
$panel.append(data.show(data));
|
|
else if (data.treeView)
|
|
$panel.treeView(data, { context: args.context });
|
|
else
|
|
$panel.listView(data, { context: args.context });
|
|
}
|
|
});
|
|
|
|
return $navItem;
|
|
};
|
|
|
|
// Define page element generation fns
|
|
var pageElems = {
|
|
header: function(args) {
|
|
// Make notification area
|
|
var $notificationArea = $('<div>').addClass('button notifications')
|
|
.append(
|
|
$('<div>').addClass('total')
|
|
// Total notifications
|
|
.append($('<span>').html(0))
|
|
)
|
|
.append($('<span>').html(_l('label.notifications')))
|
|
.notifications();
|
|
|
|
// Project switcher
|
|
var $viewSwitcher = $('<div>').addClass('button view-switcher')
|
|
.append(
|
|
// Default View
|
|
$('<div>').addClass('select default-view active')
|
|
.html(_l('label.default.view'))
|
|
.prepend(
|
|
$('<span>').addClass('icon').html(' ')
|
|
)
|
|
)
|
|
.append(
|
|
// Project View
|
|
$('<div>').addClass('select project-view')
|
|
.html(_l('label.project.view'))
|
|
.prepend(
|
|
$('<span>').addClass('icon').html(' ')
|
|
)
|
|
)
|
|
.click(function(event) {
|
|
var $target = $(event.target);
|
|
var $projectSwitcher = $(this);
|
|
var $container = $('html body');
|
|
var $navDisabled = $(
|
|
$.map([
|
|
'projects',
|
|
'accounts',
|
|
'domains',
|
|
'system',
|
|
'global-settings',
|
|
'configuration'
|
|
], function(id) {
|
|
return '#navigation li.' + id;
|
|
}).join(',')
|
|
);
|
|
|
|
if ($target.closest('.select.project-view').size()) {
|
|
$('#cloudStack3-container').addClass('project-view');
|
|
$projectSwitcher.addClass('alt');
|
|
$projectSwitcher.find('.select.project-view').addClass('active')
|
|
.siblings().removeClass('active');
|
|
|
|
// Activate project view
|
|
$navDisabled.hide();
|
|
cloudStack.uiCustom.projects({
|
|
$projectSelect: $projectSelect.hide().find('select')
|
|
});
|
|
} else {
|
|
$navDisabled.show();
|
|
$('#cloudStack3-container').removeClass('project-view');
|
|
$projectSwitcher.removeClass('alt');
|
|
$projectSelect.hide();
|
|
$projectSwitcher.find('.select.default-view').addClass('active')
|
|
.siblings().removeClass('active');
|
|
|
|
// Put project name in header
|
|
$('.select.project-view').html(
|
|
'<span class="icon"> </span>' + _l('label.project.view')
|
|
).attr('title', '');
|
|
|
|
// Clear out project
|
|
cloudStack.context.projects = null;
|
|
}
|
|
|
|
$('#navigation li.dashboard').click();
|
|
|
|
return false;
|
|
});
|
|
var $projectSelect = $('<div>').addClass('view-switcher').hide()
|
|
.append($('<select>'));
|
|
|
|
// User status area
|
|
var userLabel = args.context.users[0].name ?
|
|
args.context.users[0].name : args.context.users[0].login;
|
|
var $userInfo = $('<div>').attr({ id: 'user' }).addClass('button')
|
|
.append(
|
|
$('<div>').addClass('name').html(
|
|
args.context && args.context.users ?
|
|
cloudStack.concat(userLabel, 14) : 'Invalid User'
|
|
)
|
|
)
|
|
.append(
|
|
$('<div>').addClass('icon options')
|
|
.append(
|
|
$('<div>').addClass('icon arrow')
|
|
)
|
|
);
|
|
$userInfo.attr('title', userLabel);
|
|
|
|
return [
|
|
$('<div>').addClass('logo'),
|
|
$('<div>').addClass('controls')
|
|
.append($notificationArea)
|
|
.append($viewSwitcher)
|
|
.append($projectSelect)
|
|
.append($userInfo)
|
|
];
|
|
},
|
|
|
|
'main-area': function(args) {
|
|
var $navigation = $('<div>').attr({ id: 'navigation' });
|
|
var $browser = $('<div>').attr({ id: 'browser' })
|
|
.append(
|
|
// Home breadcrumb
|
|
$('<div>').attr({ id: 'breadcrumbs' })
|
|
.append($('<div>').addClass('home'))
|
|
.append($('<div>').addClass('end'))
|
|
)
|
|
|
|
.append(
|
|
// Panel container
|
|
$('<div>').addClass('container')
|
|
);
|
|
|
|
makeNavigation(args).appendTo($navigation);
|
|
|
|
return [
|
|
$navigation, $browser
|
|
];
|
|
}
|
|
};
|
|
|
|
$.fn.cloudStack = function(args) {
|
|
var $container = $('<div>')
|
|
.attr({
|
|
id: 'container',
|
|
'cloudStack-container': true
|
|
})
|
|
.data('cloudStack-args', args)
|
|
.appendTo(this);
|
|
var context = args.context;
|
|
|
|
// Create pageElems
|
|
$.each(pageElems, function(id, fn) {
|
|
var $elem = $('<div>').attr({ id: id });
|
|
|
|
$(fn(args)).each(function() {
|
|
$elem.append($(this));
|
|
});
|
|
|
|
$elem.appendTo($container);
|
|
});
|
|
|
|
// User options
|
|
var $options = $('<div>').attr({ id: 'user-options' })
|
|
.appendTo($('#header'));
|
|
|
|
$(['label.logout', 'label.help', 'About']).each(function() {
|
|
var $link = $('<a>')
|
|
.attr({ href: '#' })
|
|
.html(_l(this.toString()))
|
|
.appendTo($options);
|
|
|
|
if (this == 'label.help') {
|
|
$link.click(function() {
|
|
var helpURL = 'http://docs.cloud.com/CloudStack_Documentation';
|
|
|
|
window.open(helpURL, '_blank');
|
|
|
|
return false;
|
|
});
|
|
}
|
|
if (this == 'About') {
|
|
$link.click(function() {
|
|
var $logo = $('<div>').addClass('logo').html('CloudStack'),
|
|
$version = $('<div>').addClass('version').html(g_cloudstackversion),
|
|
$about = $('<div>').addClass('about').append($logo).append($version);
|
|
$about.dialog({
|
|
modal: true,
|
|
width: 300,
|
|
title: 'About CloudStack',
|
|
closeOnEscape: false,
|
|
dialogClass: 'dialog-about',
|
|
buttons: {
|
|
'Close': function() {
|
|
$( this ).dialog( "close" );
|
|
$(':ui-dialog, .overlay').remove();
|
|
}
|
|
}
|
|
}).closest('.ui-dialog').overlay();
|
|
|
|
return false;
|
|
});
|
|
}
|
|
});
|
|
|
|
// Initialize browser
|
|
$container.find('#browser div.container').cloudBrowser();
|
|
$container.find('#navigation li')
|
|
.filter(function() {
|
|
return $(this).hasClass(args.home);
|
|
})
|
|
.click();
|
|
|
|
// Validation
|
|
$.extend($.validator.messages, { required: _l('label.required') });
|
|
|
|
$.validator.addMethod(
|
|
"disallowSpecialCharacters",
|
|
function(value, element) {
|
|
return (value.indexOf("<") == -1 && value.indexOf(">") == -1);
|
|
},
|
|
jQuery.format("Disallowed characters: <, >")
|
|
);
|
|
|
|
// Check for pending project invitations
|
|
if (args.projects) {
|
|
args.projects.invitationCheck({
|
|
context: cloudStack.context,
|
|
response: {
|
|
success: function(args) {
|
|
if (!args.data.length) return;
|
|
|
|
var projectList = $.map(args.data, function(invitation) {
|
|
return '<li>' + invitation.project + '</li>';
|
|
}).join('');
|
|
|
|
cloudStack.dialog.notice({
|
|
message: _l('message.pending.projects.1') +
|
|
'<ul>' + projectList + '</ul>' +
|
|
'<p>' + _l('message.pending.projects.2') + '</p>'
|
|
});
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
// Hide logo conditionally
|
|
if (!args.hasLogo) $('#header, #header .controls').addClass('nologo');
|
|
|
|
return this;
|
|
};
|
|
|
|
// Events
|
|
$(function() {
|
|
// Check if target should be hovered
|
|
function checkHoveredLabel($target) {
|
|
var $multiWizard = $('div.ui-dialog div.multi-wizard');
|
|
if (($target.is('label[for]') && !$target.parents('body.login')) ||
|
|
($multiWizard.size() &&
|
|
($target.is('.multi-wizard label') && $target.prev('input[type="radio"],input[type="checkbox"]').size()) ||
|
|
($target.is('.multi-wizard .select-desc div.name') && $target.parent('div.select-desc').prev('input[type="radio"],input[type="checkbox"]').size())
|
|
))
|
|
return true;
|
|
|
|
return false;
|
|
}
|
|
|
|
// Rollover behavior for user options
|
|
$(document).bind('mouseover', function(event) {
|
|
var $target = $(event.target);
|
|
if (checkHoveredLabel($target)) {
|
|
$target.addClass('label-hovered');
|
|
}
|
|
if ($target.closest('#user, #user-options').size()) {
|
|
return false;
|
|
}
|
|
else $('#user-options').hide();
|
|
|
|
return false;
|
|
});
|
|
|
|
$(document).bind('mouseout', function(event) {
|
|
var $target = $(event.target);
|
|
if (checkHoveredLabel($target)) {
|
|
$target.removeClass('label-hovered');
|
|
}
|
|
});
|
|
|
|
$(document).bind('click', function(event) {
|
|
var $target = $(event.target);
|
|
var $container = $target.closest('[cloudStack-container]');
|
|
var args = $container.data('cloudStack-args');
|
|
var $browser = $container.find('#browser .container');
|
|
var $multiWizard = $('div.ui-dialog div.multi-wizard');
|
|
|
|
// Wizard: trigger click event for input when click it label
|
|
if ($multiWizard.size()) {
|
|
if ($target.is('.multi-wizard label') && $target.prev('input[type="radio"],input[type="checkbox"]').size()) {
|
|
$target.prev('input').trigger('click');
|
|
}
|
|
if ($target.is('.multi-wizard .select-desc div.name') && $target.parent('div.select-desc').prev('input[type="radio"],input[type="checkbox"]').size()) {
|
|
$target.parent('div.select-desc').prev('input').trigger('click');
|
|
}
|
|
}
|
|
|
|
if (!$container.size()) return true;
|
|
|
|
// Navigation items
|
|
if ($target.closest('li.navigation-item').size() && $target.closest('#navigation').size()) {
|
|
var $navItem = $target.closest('li.navigation-item');
|
|
|
|
if ($navItem.is('.disabled')) return false;
|
|
showSection($navItem.data('cloudStack-section-id'), args, $browser);
|
|
|
|
return false;
|
|
}
|
|
|
|
// Browser expand
|
|
if ($target.hasClass('control expand') && $target.closest('div.panel div.toolbar').size()) {
|
|
$browser.cloudBrowser('toggleMaximizePanel', {
|
|
panel: $target.closest('div.panel')
|
|
});
|
|
|
|
return false;
|
|
}
|
|
|
|
// Home breadcrumb
|
|
if ($target.is('#breadcrumbs div.home')) {
|
|
showSection(args.home, args, $browser);
|
|
return false;
|
|
}
|
|
|
|
// User options
|
|
if ($target.closest('#user div.icon.options').size()) {
|
|
$('#user-options').toggle();
|
|
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
});
|
|
});
|
|
})(window.jQuery,
|
|
window.cloudStack ? window.cloudStack : window.cloudStack = {});
|