blob: 247f9d019ae9a2aebd7493916c32f5a2c79da80f [file]
/* $Id$ */
/**
* 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.
*/
'use strict';
//Make sure jQuery has been loaded before app.js
if (typeof jQuery === "undefined")
{
throw new Error("ManifoldCF requires jQuery");
}
/* ManifoldCF
*
* @type Object
* @description $.ManifoldCF is the main object for the template's app.
* It's used for implementing functions and options related
* to the template. Keeping everything wrapped in an object
* prevents conflict with other plugins and is a better
* way to organize our code.
*/
$.ManifoldCF={};
/* --------------------
* - ManifoldCF Options -
* --------------------
* Modify these options to suit your implementation
*/
$.ManifoldCF.options={
//Sidebar push menu toggle button selector
sidebarToggleSelector: "[data-toggle='offcanvas']",
//Activate sidebar slimscroll if the fixed layout is set (requires SlimScroll Plugin)
sidebarSlimScroll: true,
BSTooltipSelector: '[data-toggle="tooltip"]',
//The standard screen sizes that bootstrap uses.
//If you change these in the variables.less file, change
//them here too.
screenSizes: {
xs: 480,
sm: 768,
md: 992,
lg: 1200
}
};
/* ------------------
* - Implementation -
* ------------------
* The next block of code implements ManifoldCF's
* functions and plugins as specified by the
* options above.
*/
$(function ()
{
//Easy access to options
var o=$.ManifoldCF.options;
//Set up the object
_init();
//Activate the layout maker
$.ManifoldCF.layout.activate();
//Enable sidebar tree view controls
$.ManifoldCF.tree('.sidebar');
//Activate sidebar push menu
$.ManifoldCF.pushMenu.activate(o.sidebarToggleSelector);
//Activate Bootstrap tooltip
$(o.BSTooltipSelector).tooltip({
trigger: 'hover',
container: 'body'
});
/*
* INITIALIZE BUTTON TOGGLE
* ------------------------
*/
$('.btn-group[data-toggle="btn-toggle"]').each(function ()
{
var group=$(this);
$(this).find(".btn").click(function (e)
{
group.find(".btn.active").removeClass("active");
$(this).addClass("active");
e.preventDefault();
});
});
});
/* ----------------------------------
* - Initialize the ManifoldCF Object -
* ----------------------------------
* All ManifoldCF functions are implemented below.
*/
function _init()
{
/* Layout
* ======
* Fixes the layout height in case min-height fails.
*
* @type Object
* @usage $.ManifoldCF.layout.activate()
* $.ManifoldCF.layout.fix()
* $.ManifoldCF.layout.fixSidebar()
*/
$.ManifoldCF.layout={
activate: function ()
{
var _this=this;
_this.fix();
_this.fixSidebar();
$(window,".wrapper").resize(function ()
{
_this.fix();
_this.fixSidebar();
});
},
fix: function ()
{
//Get window height and the wrapper height
var neg=$('.main-header').outerHeight() + $('.main-footer').outerHeight();
var window_height=$(window).height();
var sidebar_height=$(".sidebar").height();
//Set the min-height of the content and sidebar based on the
//the height of the document.
if ($("body").hasClass("fixed"))
{
$(".content-wrapper, .right-side").css('min-height',window_height - $('.main-footer').outerHeight());
} else
{
var postSetWidth;
if (window_height >= sidebar_height)
{
$(".content-wrapper, .right-side").css('min-height',window_height - neg);
postSetWidth=window_height - neg;
} else
{
$(".content-wrapper, .right-side").css('min-height',sidebar_height);
postSetWidth=sidebar_height;
}
}
$('.main-footer').show();
},
fixSidebar: function ()
{
//Make sure the body tag has the .fixed class
if (!$("body").hasClass("fixed"))
{
if (typeof $.fn.slimScroll != 'undefined')
{
$(".sidebar").slimScroll({destroy: true}).height("auto");
}
return;
} else if (typeof $.fn.slimScroll == 'undefined' && console)
{
console.error("Error: the fixed layout requires the slimscroll plugin!");
}
//Enable slimscroll for fixed layout
if ($.ManifoldCF.options.sidebarSlimScroll)
{
if (typeof $.fn.slimScroll != 'undefined')
{
//Destroy if it exists
$(".sidebar").slimScroll({destroy: true}).height("auto");
//Add slimscroll
$(".sidebar").slimscroll({
height: ($(window).height() - $(".main-header").height()) + "px",
color: "rgba(255,255,255,0.8)",
size: "5px"
});
}
}
}
};
/* PushMenu()
* ==========
* Adds the push menu functionality to the sidebar.
*
* @type Function
* @usage: $.ManifoldCF.pushMenu("[data-toggle='offcanvas']")
*/
$.ManifoldCF.pushMenu={
activate: function (toggleBtn)
{
//Get the screen sizes
var screenSizes=$.ManifoldCF.options.screenSizes;
//Enable sidebar toggle
$(toggleBtn).on('click',function (e)
{
e.preventDefault();
//Enable sidebar push menu
if ($(window).width() > (screenSizes.sm - 1))
{
$("body").toggleClass('sidebar-collapse');
}
//Handle sidebar push menu for small screens
else
{
if ($("body").hasClass('sidebar-open'))
{
$("body").removeClass('sidebar-open');
$("body").removeClass('sidebar-collapse')
} else
{
$("body").addClass('sidebar-open');
}
}
});
$(".content-wrapper").click(function ()
{
//Enable hide menu when clicking on the content-wrapper on small screens
if ($(window).width() <= (screenSizes.sm - 1) && $("body").hasClass("sidebar-open"))
{
$("body").removeClass('sidebar-open');
}
});
//Enable expand on hover for sidebar mini
if ($.ManifoldCF.options.sidebarExpandOnHover
|| ($('body').hasClass('fixed')
&& $('body').hasClass('sidebar-mini')))
{
this.expandOnHover();
}
},
expandOnHover: function ()
{
var _this=this;
var screenWidth=$.ManifoldCF.options.screenSizes.sm - 1;
//Expand sidebar on hover
$('.main-sidebar').hover(function ()
{
if ($('body').hasClass('sidebar-mini')
&& $("body").hasClass('sidebar-collapse')
&& $(window).width() > screenWidth)
{
_this.expand();
}
},function ()
{
if ($('body').hasClass('sidebar-mini')
&& $('body').hasClass('sidebar-expanded-on-hover')
&& $(window).width() > screenWidth)
{
_this.collapse();
}
});
},
expand: function ()
{
$("body").removeClass('sidebar-collapse').addClass('sidebar-expanded-on-hover');
},
collapse: function ()
{
if ($('body').hasClass('sidebar-expanded-on-hover'))
{
$('body').removeClass('sidebar-expanded-on-hover').addClass('sidebar-collapse');
}
}
};
/* Tree()
* ======
* Converts the sidebar into a multilevel
* tree view menu.
*
* @type Function
* @Usage: $.ManifoldCF.tree('.sidebar')
*/
$.ManifoldCF.tree=function (menu)
{
var _this=this;
$("li a",$(menu)).on('click',function (e)
{
//Get the clicked link and the next element
var $this=$(this);
var checkElement=$this.next();
//Check if the next element is a menu and is visible
if ((checkElement.is('.treeview-menu')) && (checkElement.is(':visible')))
{
//Close the menu
checkElement.slideUp('normal',function ()
{
checkElement.removeClass('menu-open');
//Fix the layout in case the sidebar stretches over the height of the window
//_this.layout.fix();
});
checkElement.parent("li").removeClass("active");
}
//If the menu is not visible
else if ((checkElement.is('.treeview-menu')) && (!checkElement.is(':visible')))
{
//Get the parent menu
var parent=$this.parents('ul').first();
//Close all open menus within the parent
var ul=parent.find('ul:visible').slideUp('normal');
//Remove the menu-open class from the parent
ul.removeClass('menu-open');
//Get the parent li
var parent_li=$this.parent("li");
//Open the target menu and add the menu-open class
checkElement.slideDown('normal',function ()
{
//Add the class active to the parent li
checkElement.addClass('menu-open');
parent.find('li.active').removeClass('active');
parent_li.addClass('active');
//Fix the layout in case the sidebar stretches over the height of the window
_this.layout.fix();
});
}
//if this isn't a link, prevent the page from being redirected
if (checkElement.is('.treeview-menu'))
{
e.preventDefault();
}
});
};
}
$.ManifoldCF.setTitle=function (title,header,activeMenu)
{
document.title=title;
$(".content-header #heading").text(header);
activeMenu=typeof activeMenu !== 'undefined'?activeMenu:'outputs';
$("." + activeMenu).addClass("active");
$(".selectpicker").selectpicker({iconBase:'fa',tickIcon:'fa-check'});
};
function displayError(xhr)
{
$(".content-header #heading").text('Error!');
document.title='Error';
var msg = xhr.status + " " + xhr.statusText;
//Proper error message, if the server is down.
if(xhr.status === 0)
{
msg = MCFError.ServerDown;
}
else if(xhr.status === 500)
{
msg = MCFError.InternalServerError;
}
var errorTemplate = '<div class="box box-solid">' +
'<div class="box-body">' +
'<div class="alert alert-danger">' +
'<h3><i class="fa fa-ban fa-fw"></i> Error!</h3>' +
'<h4>' + msg +'</h4>' +
'</div>' +
'</div>' +
'<div class="box-footer with-border">' +
'<div class="btn-group">' +
'<a class="btn btn-default" href="index.jsp" title="Return" data-toggle="tooltip">' +
'<i class="fa fa-check fa-fw" aria-hidden="true"></i>OK' +
'</a>';
if(xhr.status === 500)
{
errorTemplate += '<button type="button" class="btn btn-default" data-toggle="modal" data-target="#exceptionModal">' +
'<i class="fa fa-exclamation-triangle fa-fw" aria-hidden="true"></i>See Exception</button>';
$('#exceptionModal .modal-body').empty();
$('#exceptionModal .modal-body').html(xhr.responseText);
}
errorTemplate += '</div>' +
'</div>' +
'</div>';
$("#content").html(errorTemplate);
}
function _endsWith(str, suffix) {
return str.indexOf(suffix, str.length - suffix.length) !== -1;
}
function _preLoadContent()
{
console.log('_preLoadContent');
$($.ManifoldCF.options.BSTooltipSelector).tooltip('destroy');
//Temporary fix for Javascript bug, when loading connector javascript.
//Get all the global methods
var methods = Object.keys(window);
for(var i=0; i<=methods.length; i++){
var method = methods[i];
if (method && (_endsWith(method, 'checkConfig') ||
_endsWith(method, 'checkConfigForSave') ||
_endsWith(method, 'checkSpecification') ||
_endsWith(method, 'checkSpecificationForSave'))) {
delete window[method];
}
}
}
function _postLoadContent()
{
console.log('_postLoadContent');
//Activate Bootstrap tooltip
$($.ManifoldCF.options.BSTooltipSelector).tooltip({
trigger: 'hover',
container: 'body'
});
}
$.ManifoldCF.loadContent=function (url)
{
$('.overlay,#loader').show();
console.log("URL: " + url);
_preLoadContent();
//Add Client Timezone Offset
var timezone_offset = new Date().getTimezoneOffset();
var timezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
$('#content').load(decodeURIComponent(url), { client_timezone_offset : timezone_offset, client_timezone : timezone } ,function (response,status,xhr)
{
if (status == 'error')
{
displayError(xhr);
}
_postLoadContent();
$('.overlay,#loader').hide();
});
};
$.ManifoldCF.submit=function (form)
{
$('.overlay,#loader').show();
var formData = new FormData(form),
$form = $(form),
action = $form.attr('action'),
method = $form.attr('method');
_preLoadContent();
//Add Client Timezone Offset
var timezone_offset = new Date().getTimezoneOffset();
var timezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
formData.append('client_timezone_offset',timezone_offset);
formData.append('client_timezone',timezone);
$.ajax({
type: method,
url: action,
data: formData,
cache: false,
contentType: false,
processData: false
}).done(function (data,textStatus,jqXHR)
{
var page=jqXHR.getResponseHeader("page");
console.log("page: " + page)
if (typeof page != 'undefined')
{
window.history.replaceState({urlPath: encodeURI(page)},null,'?p=' + page + '#execute');
}
else
{
window.history.replaceState({urlPath: encodeURI(action)},null,'#execute_' + form.name);
}
console.log("textStatus: " + textStatus);
$('#content').html(data);
}).fail(function (xhr,opts,error)
{
displayError(xhr);
}).always(function ()
{
_postLoadContent();
$('.overlay,#loader').hide();
});
}
window.onpopstate = function (event) {
console.log('historyEvent:',event);
if (event.state) {
// history changed because of pushState/replaceState
var state=window.history.state;
if (typeof state != 'undefined')
{
if (!state.urlPath.startsWith('execute'))
{
$.ManifoldCF.loadContent(state.urlPath);
}
}
}
else
{
console.log('history changed because of a page load');
}
}
$(function(){
// navigation link handler
$(document.body).on("click",'.link',function (e)
{
e.preventDefault();
var urlPath = $(this).attr('data-href') || $(this).attr('href');
var title=$(this).text();
$.ManifoldCF.loadContent(urlPath);
var data = {urlPath: encodeURIComponent(urlPath)};
window.history.pushState(data,title,'?p=' + encodeURIComponent(urlPath) + '&_' + new Date().getTime());
});
//Prevent from submit on Enter
$(window).keydown(function(e){
var key = e.charCode || e.keyCode || 0;
var node = (e.target) ? e.target : ((e.srcElement) ? e.srcElement : null);
if(key == 13 && node.nodeName !== "TEXTAREA") {
console.log("Enter on input fields is disabled.");
e.preventDefault();
return false;
}
});
});