No changes
This commit is contained in:
parent
8680a02b13
commit
b6b398f5bf
17374 changed files with 2475441 additions and 0 deletions
2380
ControlPanel/themes/MasterControlProgram/js/bootstrap.js
vendored
Normal file
2380
ControlPanel/themes/MasterControlProgram/js/bootstrap.js
vendored
Normal file
File diff suppressed because it is too large
Load diff
12
ControlPanel/themes/MasterControlProgram/js/bootstrap.min.js
vendored
Normal file
12
ControlPanel/themes/MasterControlProgram/js/bootstrap.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
452
ControlPanel/themes/MasterControlProgram/js/main.js
Normal file
452
ControlPanel/themes/MasterControlProgram/js/main.js
Normal file
|
|
@ -0,0 +1,452 @@
|
|||
$(document).ready(function() {
|
||||
|
||||
/* *** Call Theme Config Driver *** */
|
||||
$.get('themes/MasterControlProgram/conf/sbs_conf.php',
|
||||
function(data){
|
||||
console.log(data);
|
||||
}
|
||||
);
|
||||
|
||||
/* *** Cutting Title *** */
|
||||
$('.logo h2').text($('.logo h2').text().substring(0, $('.logo h2').text().lastIndexOf(" [") + 1));
|
||||
|
||||
/* *** Remove CSS and JS Files *** */
|
||||
$('link[href="css/global.css"]').remove();
|
||||
$('link[href="js/bootstrap/css/bootstrap-combined.min.css"]').remove();
|
||||
|
||||
/* *** Removing Chars from Links *** */
|
||||
$('a:not(.user_menu_link), a span').each(function(){
|
||||
$(this).html($(this).html().replace('[','').replace(']',''));
|
||||
});
|
||||
|
||||
/* *** Several Class and Style Stuff *** */
|
||||
$(window).load(function () {
|
||||
$('tr, td, div:not([class*="nicEdit"])').css("background-color", "");
|
||||
$('div:not([class*="nicEdit"], #refreshed-0)').css("border", "").css("height", "");
|
||||
$('input').css("width", "");
|
||||
if($.trim($("div").text()) == "") {
|
||||
$(this).remove();
|
||||
}
|
||||
$('.footer.center').removeClass('center');
|
||||
// $('input[type="submit"]').each(function(){
|
||||
// $(this).replaceWith('<button type="submit" name="'+$(this).attr('name')+'" value="'+$(this).attr('value')+'" class="btn btn-primary btn-sm">'+$(this).attr('value')+'</button>');
|
||||
// });
|
||||
});
|
||||
|
||||
$('table .first_row > td').each(function(){
|
||||
$(this).replaceWith('<th>'+$(this).html()+'</th>');
|
||||
});
|
||||
|
||||
$('.magnificContentsDiv').bind("DOMSubtreeModified",function(){
|
||||
$('.updateLink, .ogpAPIActions').addClass('form-control').css('display','inline-block');
|
||||
$('.copyButton').addClass('btn').addClass('btn-sm').addClass('btn-primary');
|
||||
});
|
||||
|
||||
/* *** Submit Button Replacement *** */
|
||||
$('input[type="submit"]').each(function(){
|
||||
var oSubmitButton = $(this);
|
||||
var oForm = oSubmitButton.closest('form');
|
||||
var sOriginAttrs = '';
|
||||
|
||||
$.each(oSubmitButton[0].attributes, function() {
|
||||
if (this.specified) {
|
||||
sOriginAttrs += ' ' + this.name + '="' + this.value + '"';
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
// File Style Hack
|
||||
$.fn.input_file_styling = function() {
|
||||
$('input[type="file"]').each(function(){
|
||||
if($(this).parent().hasClass('btn-file')==false){
|
||||
$(this).css('display', 'none');
|
||||
$(this).wrap('<div class="input-group">').wrap('<label class="input-group-btn">').wrap('<span class="btn btn-sm btn-primary btn-file">');
|
||||
$(this).parent('span').parent('label').parent('.input-group').append('<input type="text" class="form-control" readonly="">');
|
||||
$(this).parent('span').prepend('<i class="fa fa-search"></i> Browse...');
|
||||
}
|
||||
});
|
||||
$(document).on('change', ':file', function() {
|
||||
var input = $(this),
|
||||
numFiles = input.get(0).files ? input.get(0).files.length : 1,
|
||||
label = input.val().replace(/\\/g, '/').replace(/.*\//, '');
|
||||
input.trigger('fileselect', [numFiles, label]);
|
||||
});
|
||||
$(':file').on('fileselect', function(event, numFiles, label) {
|
||||
var input = $(this).parents('.input-group').find(':text'),
|
||||
log = numFiles > 1 ? numFiles + ' files selected' : label;
|
||||
if( input.length ) {
|
||||
input.val(log);
|
||||
} else {
|
||||
if( log ) alert(log);
|
||||
}
|
||||
});
|
||||
}
|
||||
// Init Call of the Function
|
||||
$.fn.input_file_styling();
|
||||
// Restyle after Adding a File Input
|
||||
$('#add_file_attachment').click(function(){
|
||||
setTimeout($.fn.input_file_styling, 1);
|
||||
});
|
||||
|
||||
$('.main .redirectLink').prepend('<i class="fa fa-arrow-right" aria-hidden="true"></i> ');
|
||||
|
||||
var inputs = $('input, textarea, select').not('input[type=button], input[type="submit"], input[type="SUBMIT"], input[type=reset], input[type=radio], input[type=checkbox], input[type=image], input[type="file"]');
|
||||
$(inputs).addClass('form-control').removeAttr('style');
|
||||
var buttons = $('button, input[type="button"], input[type="submit"], input[type="SUBMIT"], input[type="reset"], .redirectLink, [href^="?m=gamemanager&p=update&update=refresh"], .main [href="?m=modulemanager&p=update"], .main [href="?m=simple-billing&p=shop"], .main [href^="home.php?m=TS3Admin&changevServer"], .main [href^="?m=gamemanager&p=game_monitor&home_id="], .serverIdToggle, .main [href="?m=settings&p=api_hosts"]');
|
||||
$(buttons).addClass('btn').addClass('btn-sm').addClass('btn-primary');
|
||||
$('.main [href^="?m=modulemanager&p=del&id="]').addClass('btn').addClass('btn-xs').addClass('btn-danger');
|
||||
$('.main [href^="?m=modulemanager&p=add&module="]').addClass('btn').addClass('btn-xs').addClass('btn-success');
|
||||
|
||||
$('em').each(function(){
|
||||
$(this).replaceWith('<div class="label label-warning inline-block">'+$(this).html()+'</div>');
|
||||
});
|
||||
|
||||
$('.monitorbutton, .administration-buttons').addClass('btn-primary');
|
||||
$('.administration-buttons').removeClass('administration-buttons').addClass('admin-buttons');
|
||||
$('form').addClass('form-group').css('float', '');
|
||||
$('.main #search').parent('form').css('margin-bottom', '10px');
|
||||
$('table').addClass('table').addClass('table-sm').addClass('table-striped').removeAttr('style');
|
||||
$('tfoot, input').removeAttr('style');
|
||||
$('tfoot .bloc').removeClass('bloc');
|
||||
$('.main input[name="remove"], .main input[name="removeJob"]').removeClass('btn-primary').addClass('btn-danger');
|
||||
|
||||
$('.online').addClass('label').addClass('label-success').addClass('label-size');
|
||||
$('.offline').addClass('label').addClass('label-danger').addClass('label-size');
|
||||
$('.success').addClass('alert').addClass('alert-success');
|
||||
$('.attachment_info').addClass('alert').addClass('alert-info');
|
||||
$('td b.success').removeClass('alert').removeClass('alert-success');
|
||||
$('.failure:not(b)').addClass('alert').addClass('alert-danger');
|
||||
|
||||
$('img[src="modules/addonsmanager/loading.gif"]').replaceWith('<i class="fa fa-spinner fa-pulse fa-3x fa-fw loadinggif"></i>');
|
||||
$('img[src="images/online.png"], img[src$="icon_online.gif"]').replaceWith('<i class="fa fa-circle online" aria-hidden="true"></i>');
|
||||
$('img[src="images/offline.png"], img[src$="icon_offline.gif"]').replaceWith('<i class="fa fa-circle offline" aria-hidden="true"></i>');
|
||||
|
||||
$('.main img, .main input[type="image"]').error(function () {
|
||||
$(this).unbind("error").attr("src", "themes/MasterControlProgram/images/image_not_found.png").attr("style", "max-width:250px;").removeAttr('height');
|
||||
});
|
||||
|
||||
|
||||
/* *** MENU *** */
|
||||
$('.menu ul[id^=submenu] span').each(function() {
|
||||
var img_url = $(this).attr('data-icon_path');
|
||||
$(this).before("<img src='"+img_url+"'/>");
|
||||
});
|
||||
|
||||
$('.menu a').click(function(){
|
||||
if($(this).attr('aria-expanded')=="true"){
|
||||
window.location = $(this).attr('link');
|
||||
}
|
||||
});
|
||||
|
||||
$('.menu [class$="menu_link_selected"]').attr('aria-expanded', 'true').next('ul').addClass('collapse').addClass('in').attr('aria-expanded', 'true');
|
||||
|
||||
$('.menu > ul').attr('id', 'menu');
|
||||
$('.menu ul').each(function() {
|
||||
if($(this).prev('a').length){
|
||||
var data_parent = '#'+$(this).parent('li').parent('ul').attr('id');
|
||||
var link_id = $(this).prev('a').attr('href').replace(/[^a-z0-9\s]/gi, '');
|
||||
if(!$(this).parent().hasClass('menu')){
|
||||
$(this).addClass('collapse');
|
||||
}
|
||||
$(this).parent('li').addClass('panel');
|
||||
$(this).attr('id', link_id);
|
||||
$(this).prev('a').attr({
|
||||
'link': $(this).prev('a').attr('href'),
|
||||
'href': '#'+$(this).attr('id'),
|
||||
'data-parent': data_parent,
|
||||
'data-toggle': 'collapse'
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
/* *** Menu -> Check & Remove wrong active Links *** */
|
||||
$('.menu [class$="menu_link_selected"]').each(function(){
|
||||
if($(this).attr('href')!=window.location.href.slice(window.location.href.indexOf('?'))){
|
||||
var checkLink = $(this).attr('link');
|
||||
var thisClass = $(this).attr('class');
|
||||
if(typeof checkLink == 'undefined') {
|
||||
$(this).removeClass(thisClass).addClass(thisClass.replace(/_selected/g,'')).removeAttr('aria-expanded');
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
/* *** Pagination *** */
|
||||
$('#pagination').each(function(){
|
||||
$(this).replaceWith('<ul class="pagination">'+$(this).html()+'</ul>');
|
||||
var pm = $('.pagination');
|
||||
|
||||
var ps = $(pm).find('[class$="_paginationStart"]');
|
||||
var pp = $(pm).find('[class$="_paginationPages"]');
|
||||
var pe = $(pm).find('[class$="_paginationEnd"]');
|
||||
|
||||
if($(ps).length){
|
||||
if($(ps).find('span').length){ console.log('divider!'); }
|
||||
$(ps).find('a').each(function(){
|
||||
var tl = $(this).attr('href');
|
||||
var tc = $(this).text();
|
||||
$(pm).append('<li><span><a href="'+tl+'">'+tc+'</a></li>');
|
||||
});
|
||||
if($(ps).find('span').length){
|
||||
$(pm).append('<li><span><a>...</a></span></li>');
|
||||
}
|
||||
$(ps).remove();
|
||||
}
|
||||
$(pp).find('a').each(function(){
|
||||
var tl = $(this).attr('href');
|
||||
var tc = $(this).text().replace('[','').replace(']','');
|
||||
if($(this).is('[class$="_currentPageLink"]')){
|
||||
$(pm).append('<li class="active"><span><a href="'+tl+'">'+tc+'</a></li>');
|
||||
}else{
|
||||
$(pm).append('<li><span><a href="'+tl+'">'+tc+'</a></li>');
|
||||
}
|
||||
});
|
||||
$(pp).remove();
|
||||
|
||||
if($(pe).length){
|
||||
if($(pe).find('span').length){
|
||||
$(pm).append('<li><span><a>...</a></span></li>');
|
||||
}
|
||||
$(pe).find('a').each(function(){
|
||||
var tl = $(this).attr('href');
|
||||
var tc = $(this).text();
|
||||
$(pm).append('<li><span><a href="'+tl+'">'+tc+'</a></li>');
|
||||
});
|
||||
$(pe).remove();
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
|
||||
/* *** Removing CSS File from FTP Page *** */
|
||||
if(window.location.href.indexOf("home.php?m=TS3Admin") != -1 ){
|
||||
$('link[href="modules/TS3Admin/webinterface.css"]').remove();
|
||||
}
|
||||
|
||||
|
||||
/* *** Tooltip *** */
|
||||
$(window).load(function(){
|
||||
$('.image-tip').each(function(){
|
||||
var tip_text = $(this).find('.tip').text();
|
||||
$(this).replaceWith('<i class="fa fa-question-circle-o" aria-hidden="true" data-toggle="tooltip" data-placement="left" title="'+tip_text+'"></i>');
|
||||
});
|
||||
$('[data-toggle="tooltip"]').each(function(){
|
||||
$(this).tooltip({
|
||||
animated: 'fade',
|
||||
html: true
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
/* *** Login Redirect Size *** */
|
||||
if(location.pathname.substring(location.pathname.length-1) == "/" || location.pathname.substring(location.pathname.length-9) == "index.php"){
|
||||
if($('#refresh-manual').length){
|
||||
$('.main').removeClass('col-md-12').addClass('col-md-6').addClass('col-md-offset-3');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* *** Login Page Mod *** */
|
||||
if(location.pathname.substring(location.pathname.length-1) == "/" || location.pathname.substring(location.pathname.length-9) == "index.php"){
|
||||
|
||||
if($('form[name="login_form"]').length > 0) {
|
||||
if ($('.g-recaptcha').length > 0) {
|
||||
var recaptcha_pubkey = $('.g-recaptcha').attr('data-sitekey');
|
||||
var recaptcha = "<div class='text-center' style='margin-bottom: 10px;'><script src='//www.google.com/recaptcha/api.js'></script><div style='display: inline-block;' class='g-recaptcha' data-sitekey='"+recaptcha_pubkey+"' data-theme='dark'></div></div>";
|
||||
}else{
|
||||
var recaptcha = "";
|
||||
}
|
||||
|
||||
var title = $('.main h4').text();
|
||||
var lang = $('[name="login_form"] tr:nth-child(1) td:first-child').text().replace(':', '');
|
||||
var user = $('[name="login_form"] tr:nth-child(2) td:first-child').text().replace(':', '');
|
||||
var pass = $('[name="login_form"] tr:nth-child(3) td:first-child').text().replace(':', '');
|
||||
var forgot = $('[href="?m=lostpwd"]').text();
|
||||
var lbtn = $('[name="login"]').val();
|
||||
var optns = $('[name="lang"]').html();
|
||||
|
||||
if($('[href="?m=register&p=form"]').length > 0) {
|
||||
//<input type="submit" name="login" value="'+lbtn+'" class="btn btn-primary btn-block btn-sm">\
|
||||
var buttons = '\
|
||||
<div class="row" style="margin-bottom: 10px;">\
|
||||
<div class="col-xs-6">\
|
||||
<button type="submit" name="login" value="'+lbtn+'" class="btn btn-primary btn-block btn-sm">'+lbtn+'</button>\
|
||||
</div>\
|
||||
<div class="col-xs-6">\
|
||||
<a href="?m=register&p=form" class="btn btn-primary btn-block btn-sm">'+$('[href="?m=register&p=form"] > span').text()+'</a>\
|
||||
</div>\
|
||||
</div>\
|
||||
';
|
||||
}else{
|
||||
//<input type="submit" name="login" value="'+lbtn+'" class="btn btn-primary btn-block btn-sm">\
|
||||
var buttons = '\
|
||||
<div class="row" style="margin-bottom: 10px;">\
|
||||
<div class="col-xs-12">\
|
||||
<button type="submit" name="login" value="'+lbtn+'" class="btn btn-primary btn-block btn-sm">'+lbtn+'</button>\
|
||||
</div>\
|
||||
</div>\
|
||||
';
|
||||
}
|
||||
|
||||
|
||||
var new_form = '\
|
||||
<div class="login-container">\
|
||||
<h3>'+title+'</h3>\
|
||||
<form action="index.php" name="login_form" method="post" class="form-group">\
|
||||
<div class="input-group">\
|
||||
<span class="input-group-addon"><i class="fa fa-user" aria-hidden="true"></i></span>\
|
||||
<input type="text" name="ulogin" id="ulogin" class="form-control" placeholder="'+user+'">\
|
||||
</div>\
|
||||
<div class="input-group">\
|
||||
<span class="input-group-addon"><i class="fa fa-lock" aria-hidden="true"></i></span>\
|
||||
<input type="password" name="upassword" class="form-control" placeholder="'+pass+'">\
|
||||
</div>\
|
||||
<div class="input-group">\
|
||||
<span class="input-group-addon"><i class="fa fa-language" aria-hidden="true"></i></span>\
|
||||
<select name="lang" onchange="this.form.submit();" class="form-control">'+optns+'</select>\
|
||||
</div>\
|
||||
'+recaptcha+'\
|
||||
'+buttons+'\
|
||||
</form>\
|
||||
<div class="row">\
|
||||
<div class="col-xs-12">\
|
||||
<a class="pull-right label" href="?m=lostpwd">'+forgot+'</a>\
|
||||
</div>\
|
||||
</div>\
|
||||
<div class="clearfix"></div>\
|
||||
</div>';
|
||||
|
||||
$('.main').empty().html(new_form);
|
||||
$('select[name=lang] > option:first-child').replaceWith('<option value="-" selected="selected">'+lang+'</option>');
|
||||
}
|
||||
|
||||
// *** Lost Password Form ***
|
||||
if(window.location.href.indexOf('?m=lostpwd') > -1) {
|
||||
var title = $('.main h2').text();
|
||||
|
||||
if ($('.main > strong').length > 0 || $('.main > p').text().toLowerCase().indexOf('smtp')>=0) {
|
||||
// *** Error Message ***
|
||||
|
||||
var err = $('.main strong').text();
|
||||
var err_msg = $('.main p').text();
|
||||
|
||||
var new_form = '\
|
||||
<div class="login-container">\
|
||||
<h3>'+title+'</h3>\
|
||||
<div class="alert alert-danger" role="alert"><strong>'+err+'</strong><p>'+err_msg+'</p></div>\
|
||||
<a href="?m=lostpwd" class="btn btn-primary btn-sm"><< Back</a>\
|
||||
</div>';
|
||||
}else if ($('.main > p > b[style="color:red;"]').length > 0) {
|
||||
// *** Sent Password ***
|
||||
|
||||
var msgb = $('.main > p > b[style="color:red;"]').text();
|
||||
$('.main > p > b[style="color:red;"]').remove();
|
||||
var msg = $('.main > p').text();
|
||||
|
||||
var new_form = '\
|
||||
<div class="login-container">\
|
||||
<h3>'+title+'</h3>\
|
||||
<div class="alert alert-success" role="alert"><p>'+msg+'</p><p>'+msgb+'</p></div>\
|
||||
<a href="?m=lostpwd" class="btn btn-primary btn-sm"><< Back</a>\
|
||||
</div>';
|
||||
}else{
|
||||
|
||||
if ($('.main td > p').length > 0) {
|
||||
if($('.main td > p').attr('style')=='color: red;'){
|
||||
var alert = '<div class="alert alert-danger" role="alert">';
|
||||
}else{
|
||||
var alert = '<div class="alert alert-success" role="alert">';
|
||||
}
|
||||
$('.main td > p').each(function() {
|
||||
alert += '<p>'+$(this).text()+'</p>';
|
||||
});
|
||||
alert += '</div>';
|
||||
} else {
|
||||
var alert = "";
|
||||
}
|
||||
|
||||
var email = $('.main label[for="email_address"]').text();
|
||||
var lbtn = $('td > [type="submit"]').val();
|
||||
var bbtn = $('[action="index.php"] > input[type="submit"]').val();
|
||||
|
||||
var new_form = '\
|
||||
<div class="login-container">\
|
||||
<h3>'+title+'</h3>\
|
||||
'+alert+'\
|
||||
<form action="?m=lostpwd" method="post" class="form-group">\
|
||||
<input type="text" name="email_address" class="form-control" placeholder="Email">\
|
||||
<button type="submit" name="login" value="'+lbtn+'" class="btn btn-primary btn-block btn-sm">'+lbtn+'</button>\
|
||||
</form>\
|
||||
<a href="index.php" class="label" style="display: block;text-align: right;margin-top: 10px;">'+bbtn+'</a>\
|
||||
</div>';
|
||||
|
||||
}
|
||||
$('.main').empty().html(new_form);
|
||||
}
|
||||
|
||||
|
||||
$('.main').removeClass('col-md-10').addClass('col-md-12');
|
||||
|
||||
$('nav.navbar').addClass('navbar-default');
|
||||
$('#navbar ul').addClass('nav').addClass('navbar-nav');
|
||||
$('#navbar [class*="selected"]').parent('li').addClass('active');
|
||||
|
||||
$('.navigation').removeClass('col-md-2').addClass('col-md-12').css('padding-right','15px')
|
||||
$('.collapse').css('padding','0px 5px');
|
||||
$('.menu').css('margin-bottom','0px');
|
||||
$('body > .container-fluid > .row:first-of-type').remove();
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
$(window).load(function(){
|
||||
$("body > .container-fluid").fadeIn(50);
|
||||
|
||||
$(':file').on('fileselect', function(event, numFiles, label) {
|
||||
var input = $(this).parents('.input-group').find(':text'),
|
||||
log = numFiles > 1 ? numFiles + ' files selected' : label;
|
||||
if(input.length){
|
||||
input.val(log);
|
||||
}else{
|
||||
if(log) alert(log);
|
||||
}
|
||||
});
|
||||
|
||||
/*
|
||||
$('input[src$="remove.gif"]').each(function(){
|
||||
var NewButton = $("<button />");
|
||||
$.each(this.attributes, function(i, attrib){
|
||||
// Change Type to Submit Mod
|
||||
if(attrib.name=='type'){
|
||||
attrval = 'submit';
|
||||
}else{
|
||||
attrval = attrib.value;
|
||||
}
|
||||
// Skip src Attribute
|
||||
if(attrib.name=='src'){
|
||||
return false;
|
||||
}
|
||||
// Change Stop Update Value for "Cancel Update" Fix
|
||||
if(attrib.value=='stop_update'){
|
||||
attrval = 'stop_update_x';
|
||||
}
|
||||
$(NewButton).attr(attrib.name, attrval);
|
||||
});
|
||||
$(NewButton).attr('class', 'btn btn-xs btn-danger btn-sm btn-primary');
|
||||
$(this).replaceWith(function () {
|
||||
return $(NewButton).append($(this).contents()).prepend('<i class="fa fa-times" aria-hidden="true"></i>');
|
||||
});
|
||||
});
|
||||
*/
|
||||
|
||||
});
|
||||
|
||||
|
||||
$(document).on('change', ':file', function() {
|
||||
var input = $(this),
|
||||
numFiles = input.get(0).files ? input.get(0).files.length : 1,
|
||||
label = input.val().replace(/\\/g, '/').replace(/.*\//, '');
|
||||
input.trigger('fileselect', [numFiles, label]);
|
||||
});
|
||||
|
||||
2
ControlPanel/themes/MasterControlProgram/js/pace.min.js
vendored
Normal file
2
ControlPanel/themes/MasterControlProgram/js/pace.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
450
ControlPanel/themes/MasterControlProgram/js/radialIndicator.js
Normal file
450
ControlPanel/themes/MasterControlProgram/js/radialIndicator.js
Normal file
|
|
@ -0,0 +1,450 @@
|
|||
/*
|
||||
radialIndicator.js v 1.3.1
|
||||
Author: Sudhanshu Yadav
|
||||
Copyright (c) 2015,2016 Sudhanshu Yadav - ignitersworld.com , released under the MIT license.
|
||||
Demo on: ignitersworld.com/lab/radialIndicator.html
|
||||
*/
|
||||
;(function (factory) {
|
||||
/** support UMD ***/
|
||||
var global = Function('return this')() || (42, eval)('this');
|
||||
if (typeof define === "function" && define.amd) {
|
||||
define(["jquery"], function ($) {
|
||||
return (global.radialIndicator = factory($, global));
|
||||
});
|
||||
} else if (typeof module === "object" && module.exports) {
|
||||
module.exports = global.document ?
|
||||
factory(require("jquery"), global) :
|
||||
function (w) {
|
||||
if (!w.document) {
|
||||
throw new Error("radialIndiactor requires a window with a document");
|
||||
}
|
||||
return factory(require("jquery")(w), w);
|
||||
};
|
||||
} else {
|
||||
global.radialIndicator = factory(global.jQuery, global);
|
||||
}
|
||||
}(function ($, window, undefined) {
|
||||
|
||||
var document = window.document;
|
||||
|
||||
"use strict";
|
||||
//circumfence and quart value to start bar from top
|
||||
var circ = Math.PI * 2,
|
||||
quart = Math.PI / 2;
|
||||
|
||||
|
||||
//function to smooth canvas drawing for ratina devices
|
||||
|
||||
//method to manage device pixel ratio in ratina devices
|
||||
var smoothCanvas = (function() {
|
||||
var ctx = document.createElement("canvas").getContext("2d"),
|
||||
dpr = window.devicePixelRatio || 1,
|
||||
bsr = ctx.webkitBackingStorePixelRatio ||
|
||||
ctx.mozBackingStorePixelRatio ||
|
||||
ctx.msBackingStorePixelRatio ||
|
||||
ctx.oBackingStorePixelRatio ||
|
||||
ctx.backingStorePixelRatio || 1,
|
||||
|
||||
ratio = dpr / bsr; //PIXEL RATIO
|
||||
|
||||
return function(w, h, canvasElm) {
|
||||
var can = canvasElm || document.createElement("canvas");
|
||||
can.width = w * ratio;
|
||||
can.height = h * ratio;
|
||||
can.style.width = w + "px";
|
||||
can.style.height = h + "px";
|
||||
can.getContext("2d").setTransform(ratio, 0, 0, ratio, 0, 0);
|
||||
return can;
|
||||
}
|
||||
}());
|
||||
|
||||
//function to convert hex to rgb
|
||||
function hexToRgb(hex) {
|
||||
// Expand shorthand form (e.g. "03F") to full form (e.g. "0033FF")
|
||||
var shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i;
|
||||
hex = hex.replace(shorthandRegex, function(m, r, g, b) {
|
||||
return r + r + g + g + b + b;
|
||||
});
|
||||
|
||||
var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
|
||||
return result ? [parseInt(result[1], 16), parseInt(result[2], 16), parseInt(result[3], 16)] : null;
|
||||
}
|
||||
|
||||
function getPropVal(curShift, perShift, bottomRange, topRange) {
|
||||
return Math.round(bottomRange + ((topRange - bottomRange) * curShift / perShift));
|
||||
}
|
||||
|
||||
|
||||
//function to get current color in case of
|
||||
function getCurrentColor(curPer, bottomVal, topVal, bottomColor, topColor) {
|
||||
var rgbAryTop = topColor.indexOf('#') != -1 ? hexToRgb(topColor) : topColor.match(/\d+/g),
|
||||
rgbAryBottom = bottomColor.indexOf('#') != -1 ? hexToRgb(bottomColor) : bottomColor.match(/\d+/g),
|
||||
perShift = topVal - bottomVal,
|
||||
curShift = curPer - bottomVal;
|
||||
|
||||
if (!rgbAryTop || !rgbAryBottom) return null;
|
||||
|
||||
return 'rgb(' + getPropVal(curShift, perShift, rgbAryBottom[0], rgbAryTop[0]) + ',' + getPropVal(curShift, perShift, rgbAryBottom[1], rgbAryTop[1]) + ',' + getPropVal(curShift, perShift, rgbAryBottom[2], rgbAryTop[2]) + ')';
|
||||
}
|
||||
|
||||
//to merge object
|
||||
function merge() {
|
||||
var arg = arguments,
|
||||
target = arg[0];
|
||||
for (var i = 1, ln = arg.length; i < ln; i++) {
|
||||
var obj = arg[i];
|
||||
for (var k in obj) {
|
||||
if (obj.hasOwnProperty(k)) {
|
||||
target[k] = obj[k];
|
||||
}
|
||||
}
|
||||
}
|
||||
return target;
|
||||
}
|
||||
|
||||
//function to apply formatting on number depending on parameter
|
||||
function formatter(pattern) {
|
||||
return function(num) {
|
||||
if (!pattern) return num.toString();
|
||||
num = num || 0
|
||||
var numRev = num.toString().split('').reverse(),
|
||||
output = pattern.split("").reverse(),
|
||||
i = 0,
|
||||
lastHashReplaced = 0;
|
||||
|
||||
//changes hash with numbers
|
||||
for (var ln = output.length; i < ln; i++) {
|
||||
if (!numRev.length) break;
|
||||
if (output[i] == "#") {
|
||||
lastHashReplaced = i;
|
||||
output[i] = numRev.shift();
|
||||
}
|
||||
}
|
||||
|
||||
//add overflowing numbers before prefix
|
||||
output.splice(lastHashReplaced + 1, output.lastIndexOf('#') - lastHashReplaced, numRev.reverse().join(""));
|
||||
|
||||
return output.reverse().join('');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//circle bar class
|
||||
function Indicator(container, indOption) {
|
||||
var self = this;
|
||||
|
||||
indOption = indOption || {};
|
||||
indOption = merge({}, radialIndicator.defaults, indOption);
|
||||
|
||||
this.indOption = indOption;
|
||||
|
||||
//create a queryselector if a selector string is passed in container
|
||||
if (typeof container == "string")
|
||||
container = document.querySelector(container);
|
||||
|
||||
//get the first element if container is a node list
|
||||
if (container.length)
|
||||
container = container[0];
|
||||
|
||||
this.container = container;
|
||||
|
||||
//create a canvas element
|
||||
var canElm = document.createElement("canvas");
|
||||
container.appendChild(canElm);
|
||||
|
||||
this.canElm = canElm; // dom object where drawing will happen
|
||||
|
||||
this.ctx = canElm.getContext('2d'); //get 2d canvas context
|
||||
|
||||
//add intial value
|
||||
this.current_value = indOption.initValue || indOption.minValue || 0;
|
||||
|
||||
|
||||
//handeling user interaction
|
||||
var startListener = function(e) {
|
||||
if (!indOption.interaction) return;
|
||||
|
||||
var touchMove = e.type == "touchstart" ? "touchmove" : "mousemove",
|
||||
touchEnd = e.type == "touchstart" ? "touchend" : "mouseup",
|
||||
position = canElm.getBoundingClientRect(),
|
||||
cy = position.top + canElm.offsetHeight / 2,
|
||||
cx = position.left + canElm.offsetWidth / 2;
|
||||
|
||||
var moveListener = function(e) {
|
||||
e.preventDefault();
|
||||
|
||||
//get the cordinates
|
||||
var mx = e.clientX || e.touches[0].clientX,
|
||||
my = e.clientY || e.touches[0].clientY,
|
||||
radian = (circ + quart + Math.atan2((my - cy), (mx - cx))) % (circ + 0.0175),
|
||||
radius = (indOption.radius - 1 + indOption.barWidth / 2),
|
||||
circum = circ * radius,
|
||||
precision = indOption.precision != null ? indOption.precision : 0,
|
||||
precisionNo = Math.pow(10, precision),
|
||||
val = Math.round(precisionNo * radian * radius * (indOption.maxValue - indOption.minValue) / circum) / precisionNo;
|
||||
|
||||
self.value(val);
|
||||
};
|
||||
|
||||
var endListener = function() {
|
||||
document.removeEventListener(touchMove, moveListener, false);
|
||||
document.removeEventListener(touchEnd, endListener, false);
|
||||
};
|
||||
|
||||
document.addEventListener(touchMove, moveListener, false);
|
||||
document.addEventListener(touchEnd, endListener, false);
|
||||
};
|
||||
|
||||
canElm.addEventListener('touchstart', startListener, false);
|
||||
canElm.addEventListener('mousedown', startListener, false);
|
||||
|
||||
|
||||
canElm.addEventListener("mousewheel", MouseWheelHandler, false);
|
||||
canElm.addEventListener("DOMMouseScroll", MouseWheelHandler, false);
|
||||
|
||||
function MouseWheelHandler(e) {
|
||||
if (!indOption.interaction) return;
|
||||
e.preventDefault();
|
||||
|
||||
// cross-browser wheel delta
|
||||
var delta = -(Math.max(-1, Math.min(1, (e.wheelDelta || -e.detail)))),
|
||||
precision = indOption.precision != null ? indOption.precision : 0,
|
||||
precisionNo = Math.pow(10, precision),
|
||||
diff = indOption.maxValue - indOption.minValue,
|
||||
val = self.current_value + Math.round(precisionNo * delta * diff / Math.min(diff, 100)) / precisionNo;
|
||||
|
||||
self.value(val);
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Indicator.prototype = {
|
||||
constructor: radialIndicator,
|
||||
_init: function() {
|
||||
var indOption = this.indOption,
|
||||
canElm = this.canElm,
|
||||
ctx = this.ctx,
|
||||
dim = (indOption.radius + indOption.barWidth) * 2; //elm width and height
|
||||
|
||||
//create a formatter function
|
||||
this.formatter = typeof indOption.format == "function" ? indOption.format : formatter(indOption.format);
|
||||
|
||||
//maximum text length;
|
||||
this.maxLength = indOption.percentage ? 4 : this.formatter(indOption.maxValue).length;
|
||||
|
||||
//smooth the canvas elm for ratina display
|
||||
smoothCanvas(dim, dim, canElm);
|
||||
|
||||
//draw background bar
|
||||
this._drawBarBg();
|
||||
|
||||
//put the initial value if defined
|
||||
this.value(this.current_value);
|
||||
|
||||
return this;
|
||||
},
|
||||
//draw background bar
|
||||
_drawBarBg: function() {
|
||||
var indOption = this.indOption,
|
||||
ctx = this.ctx,
|
||||
dim = (indOption.radius + indOption.barWidth) * 2, //elm width and height
|
||||
center = dim / 2; //center point in both x and y axis
|
||||
|
||||
//draw nackground circle
|
||||
ctx.strokeStyle = indOption.barBgColor; //background circle color
|
||||
ctx.lineWidth = indOption.barWidth;
|
||||
if (indOption.barBgColor != "transparent") {
|
||||
ctx.beginPath();
|
||||
ctx.arc(center, center, indOption.radius - 1 + indOption.barWidth / 2, 0, 2 * Math.PI);
|
||||
ctx.stroke();
|
||||
}
|
||||
},
|
||||
//update the value of indicator without animation
|
||||
value: function(val) {
|
||||
//return the val if val is not provided
|
||||
if (val === undefined || isNaN(val)) {
|
||||
return this.current_value;
|
||||
}
|
||||
|
||||
val = parseFloat(val);
|
||||
|
||||
var ctx = this.ctx,
|
||||
indOption = this.indOption,
|
||||
curColor = indOption.barColor,
|
||||
dim = (indOption.radius + indOption.barWidth) * 2,
|
||||
minVal = indOption.minValue,
|
||||
maxVal = indOption.maxValue,
|
||||
center = dim / 2;
|
||||
|
||||
//limit the val in range of minumum and maximum value
|
||||
val = val < minVal ? minVal : val > maxVal ? maxVal : val;
|
||||
|
||||
var precision = indOption.precision != null ? indOption.precision : 0,
|
||||
precisionNo = Math.pow(10, precision),
|
||||
perVal = Math.round(((val - minVal) * precisionNo / (maxVal - minVal)) * 100) / precisionNo, //percentage value tp two decimal precision
|
||||
dispVal = indOption.percentage ? perVal + '%' : this.formatter(val); //formatted value
|
||||
|
||||
//save val on object
|
||||
this.current_value = val;
|
||||
|
||||
|
||||
//draw the bg circle
|
||||
ctx.clearRect(0, 0, dim, dim);
|
||||
this._drawBarBg();
|
||||
|
||||
//get current color if color range is set
|
||||
if (typeof curColor == "object") {
|
||||
var range = Object.keys(curColor);
|
||||
|
||||
for (var i = 1, ln = range.length; i < ln; i++) {
|
||||
var bottomVal = range[i - 1],
|
||||
topVal = range[i],
|
||||
bottomColor = curColor[bottomVal],
|
||||
topColor = curColor[topVal],
|
||||
newColor = val == bottomVal ? bottomColor : val == topVal ? topColor : val > bottomVal && val < topVal ? indOption.interpolate ? getCurrentColor(val, bottomVal, topVal, bottomColor, topColor) : topColor : false;
|
||||
|
||||
if (newColor != false) {
|
||||
curColor = newColor;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//draw th circle value
|
||||
ctx.strokeStyle = curColor;
|
||||
|
||||
//add linecap if value setted on options
|
||||
if (indOption.roundCorner) ctx.lineCap = "round";
|
||||
|
||||
ctx.beginPath();
|
||||
ctx.arc(center, center, indOption.radius - 1 + indOption.barWidth / 2, -(quart), ((circ) * perVal / 100) - quart, false);
|
||||
ctx.stroke();
|
||||
|
||||
//add percentage text
|
||||
if (indOption.displayNumber) {
|
||||
var cFont = ctx.font.split(' '),
|
||||
weight = indOption.fontWeight,
|
||||
fontSize = indOption.fontSize || (dim / (this.maxLength - (Math.floor(this.maxLength * 1.4 / 4) - 1)));
|
||||
|
||||
cFont = indOption.fontFamily || cFont[cFont.length - 1];
|
||||
|
||||
ctx.shadowColor = "rgba(0,0,0,.5)";
|
||||
ctx.shadowOffsetX = 0;
|
||||
ctx.shadowOffsetY = 1;
|
||||
ctx.shadowBlur = 3;
|
||||
ctx.fillStyle = indOption.fontColor || curColor;
|
||||
ctx.font = weight + " " + fontSize + "px " + cFont;
|
||||
ctx.textAlign = "center";
|
||||
ctx.textBaseline = indOption.textBaseline;
|
||||
ctx.fillText(dispVal, center, center);
|
||||
}
|
||||
|
||||
//call onChange callback
|
||||
indOption.onChange.call(this.container,val);
|
||||
|
||||
return this;
|
||||
},
|
||||
//animate progressbar to the value
|
||||
animate: function(val) {
|
||||
var indOption = this.indOption,
|
||||
counter = this.current_value || indOption.minValue,
|
||||
self = this,
|
||||
minVal = indOption.minValue,
|
||||
maxVal = indOption.maxValue,
|
||||
frameNum = indOption.frameNum || (indOption.percentage ? 100 : 500),
|
||||
precision = indOption.precision != null ? indOption.precision : Math.ceil(Math.log(maxVal - minVal / frameNum)),
|
||||
precisionNo = Math.pow(10, precision),
|
||||
incBy = (maxVal - minVal) / frameNum ; //increment by .2% on every tick and 1% if showing as percentage
|
||||
|
||||
//limit the val in range of minumum and maximum value
|
||||
val = val < minVal ? minVal : val > maxVal ? maxVal : val;
|
||||
|
||||
var back = val < counter;
|
||||
|
||||
//clear interval function if already started
|
||||
if (this.intvFunc) clearInterval(this.intvFunc);
|
||||
|
||||
this.intvFunc = setInterval(function() {
|
||||
|
||||
if ((!back && counter >= val) || (back && counter <= val)) {
|
||||
if (self.current_value == counter) {
|
||||
clearInterval(self.intvFunc);
|
||||
if (indOption.onAnimationComplete) indOption.onAnimationComplete(self.current_value);
|
||||
return;
|
||||
} else {
|
||||
counter = val;
|
||||
}
|
||||
}
|
||||
|
||||
self.value(counter); //dispaly the value
|
||||
|
||||
if (counter != val) {
|
||||
counter = Math.round((counter + (back ? -incBy : incBy)) * precisionNo) / precisionNo;
|
||||
} //increment or decrement till counter does not reach to value
|
||||
}, indOption.frameTime);
|
||||
|
||||
return this;
|
||||
},
|
||||
//method to update options
|
||||
option: function(key, val) {
|
||||
if (val === undefined) return this.option[key];
|
||||
|
||||
if (['radius', 'barWidth', 'barBgColor', 'format', 'maxValue', 'percentage'].indexOf(key) != -1) {
|
||||
this.indOption[key] = val;
|
||||
this._init().value(this.current_value);
|
||||
}
|
||||
this.indOption[key] = val;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/** Initializer function **/
|
||||
function radialIndicator(container, options) {
|
||||
var progObj = new Indicator(container, options);
|
||||
progObj._init();
|
||||
return progObj;
|
||||
}
|
||||
|
||||
//radial indicator defaults
|
||||
radialIndicator.defaults = {
|
||||
radius: 50, //inner radius of indicator
|
||||
barWidth: 5, //bar width
|
||||
barBgColor: '#eeeeee', //unfilled bar color
|
||||
barColor: '#99CC33', //filled bar color , can be a range also having different colors on different value like {0 : "#ccc", 50 : '#333', 100: '#000'}
|
||||
format: null, //format indicator numbers, can be a # formator ex (##,###.##) or a function
|
||||
frameTime: 10, //miliseconds to move from one frame to another
|
||||
frameNum: null, //Defines numbers of frame in indicator, defaults to 100 when showing percentage and 500 for other values
|
||||
fontColor: null, //font color
|
||||
fontFamily: null, //defines font family
|
||||
fontWeight: 'bold', //defines font weight
|
||||
fontSize: null, //define the font size of indicator number
|
||||
textBaseline: 'middle', //define the text base line of indicator number
|
||||
interpolate: true, //interpolate color between ranges
|
||||
percentage: false, //show percentage of value
|
||||
precision: null, //default value for precision depend on difference between min and max divided by number of frames
|
||||
displayNumber: true, //display indicator number
|
||||
roundCorner: false, //have round corner in filled bar
|
||||
minValue: 0, //minimum value
|
||||
maxValue: 100, //maximum value
|
||||
initValue: 0, //define initial value of indicator,
|
||||
interaction: false, //if true it allows to change radial indicator value using mouse or touch interaction
|
||||
onChange: function() {}
|
||||
};
|
||||
|
||||
window.radialIndicator = radialIndicator;
|
||||
|
||||
//add as a jquery plugin
|
||||
if ($) {
|
||||
$.fn.radialIndicator = function(options) {
|
||||
return this.each(function() {
|
||||
var newPCObj = radialIndicator(this, options);
|
||||
$.data(this, 'radialIndicator', newPCObj);
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
return radialIndicator;
|
||||
|
||||
}));
|
||||
Loading…
Add table
Add a link
Reference in a new issue