mirror of https://github.com/apache/cloudstack.git
458 lines
14 KiB
JavaScript
458 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) {
|
|
if (!(args.preFilter && args.preFilter())) {
|
|
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);
|
|
|
|
if (args.customIcon) {
|
|
$li.addClass('custom-icon').find('span.icon').html('').append(
|
|
$('<img>').attr({ src: args.customIcon })
|
|
);
|
|
}
|
|
|
|
$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');
|
|
|
|
$(window).trigger('cloudStack.ready');
|
|
|
|
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 = {});
|