Merge branch 'master' of git://phpmyadmin.git.sourceforge.net/gitroot/phpmyadmin/phpmyadmin into OpenGIS
This commit is contained in:
commit
db06c5a912
@ -14,6 +14,8 @@
|
||||
+ rfe #3310562 Wording about Column
|
||||
+ AJAX for Add a user in Database privileges
|
||||
+ Patch #3271804 for rfe #3177495, new DisableMultiTableMaintenance directive
|
||||
+ [interface] Reorganised server status page.
|
||||
+ [interface] Changed way of generating charts.
|
||||
|
||||
3.4.3.0 (not yet released)
|
||||
- bug #3311170 [sync] Missing helper icons in Synchronize
|
||||
@ -23,6 +25,7 @@
|
||||
- patch #3311539 [edit] Inline edit does not escape backslashes
|
||||
- bug #3313210 [interface] Columns class sometimes changed for nothing
|
||||
- patch #3313326 [interface] Some tooltips do not disappear
|
||||
- bug #3315720 [search] Fix search in non unicode tables
|
||||
|
||||
3.4.2.0 (2011-06-07)
|
||||
- bug #3301249 [interface] Iconic table operations does not remove inline edit label
|
||||
|
||||
34
chart_export.php
Normal file
34
chart_export.php
Normal file
@ -0,0 +1,34 @@
|
||||
<?php
|
||||
/* vim: set expandtab sw=4 ts=4 sts=4: */
|
||||
/**
|
||||
* "Echo" service to allow force downloading of exported charts (png or svg)
|
||||
*
|
||||
* @package phpMyAdmin
|
||||
*/
|
||||
|
||||
|
||||
define('PMA_MINIMUM_COMMON',true);
|
||||
|
||||
require_once './libraries/common.inc.php';
|
||||
|
||||
if(isset($_REQUEST['filename']) && isset($_REQUEST['image'])) {
|
||||
$allowed = Array( 'image/png'=>'png', 'image/svg+xml'=>'svg');
|
||||
|
||||
if(!isset($allowed[$_REQUEST['type']])) exit('Invalid export type');
|
||||
|
||||
if(!preg_match("/(".implode("|",$allowed).")$/i",$_REQUEST['filename']))
|
||||
$_REQUEST['filename'].='.'.$allowed[$_REQUEST['type']];
|
||||
|
||||
header("Cache-Control: public");
|
||||
header("Content-Description: File Transfer");
|
||||
header("Content-Disposition: attachment; filename=".$_REQUEST['filename']);
|
||||
header("Content-Type: ".$_REQUEST['type']);
|
||||
header("Content-Transfer-Encoding: binary");
|
||||
|
||||
if($allowed[$_REQUEST['type']]!='svg')
|
||||
echo base64_decode(substr($_REQUEST['image'],strpos($_REQUEST['image'],',')+1));
|
||||
else
|
||||
echo $_REQUEST['image'];
|
||||
|
||||
} else exit('Invalid request');
|
||||
?>
|
||||
@ -178,7 +178,7 @@ if (isset($_REQUEST['submit_search'])) {
|
||||
$thefieldlikevalue = array();
|
||||
foreach ($tblfields as $tblfield) {
|
||||
if (! isset($field) || strlen($field) == 0 || $tblfield == $field) {
|
||||
$thefieldlikevalue[] = PMA_backquote($tblfield)
|
||||
$thefieldlikevalue[] = 'CONVERT(' . PMA_backquote($tblfield) . ' USING utf8)'
|
||||
. ' ' . $like_or_regex . ' '
|
||||
. "'" . $automatic_wildcard
|
||||
. $search_word
|
||||
|
||||
22
js/canvg/MIT-LICENSE.txt
Normal file
22
js/canvg/MIT-LICENSE.txt
Normal file
@ -0,0 +1,22 @@
|
||||
Copyright (c) 2010-2011 Gabe Lerner (gabelerner@gmail.com) - http://code.google.com/p/canvg/
|
||||
|
||||
Permission is hereby granted, free of charge, to any person
|
||||
obtaining a copy of this software and associated documentation
|
||||
files (the "Software"), to deal in the Software without
|
||||
restriction, including without limitation the rights to use,
|
||||
copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the
|
||||
Software is furnished to do so, subject to the following
|
||||
conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
OTHER DEALINGS IN THE SOFTWARE.
|
||||
2221
js/canvg/canvg.js
Normal file
2221
js/canvg/canvg.js
Normal file
File diff suppressed because it is too large
Load Diff
288
js/canvg/rgbcolor.js
Normal file
288
js/canvg/rgbcolor.js
Normal file
@ -0,0 +1,288 @@
|
||||
/**
|
||||
* A class to parse color values
|
||||
* @author Stoyan Stefanov <sstoo@gmail.com>
|
||||
* @link http://www.phpied.com/rgb-color-parser-in-javascript/
|
||||
* @license Use it if you like it
|
||||
*/
|
||||
function RGBColor(color_string)
|
||||
{
|
||||
this.ok = false;
|
||||
|
||||
// strip any leading #
|
||||
if (color_string.charAt(0) == '#') { // remove # if any
|
||||
color_string = color_string.substr(1,6);
|
||||
}
|
||||
|
||||
color_string = color_string.replace(/ /g,'');
|
||||
color_string = color_string.toLowerCase();
|
||||
|
||||
// before getting into regexps, try simple matches
|
||||
// and overwrite the input
|
||||
var simple_colors = {
|
||||
aliceblue: 'f0f8ff',
|
||||
antiquewhite: 'faebd7',
|
||||
aqua: '00ffff',
|
||||
aquamarine: '7fffd4',
|
||||
azure: 'f0ffff',
|
||||
beige: 'f5f5dc',
|
||||
bisque: 'ffe4c4',
|
||||
black: '000000',
|
||||
blanchedalmond: 'ffebcd',
|
||||
blue: '0000ff',
|
||||
blueviolet: '8a2be2',
|
||||
brown: 'a52a2a',
|
||||
burlywood: 'deb887',
|
||||
cadetblue: '5f9ea0',
|
||||
chartreuse: '7fff00',
|
||||
chocolate: 'd2691e',
|
||||
coral: 'ff7f50',
|
||||
cornflowerblue: '6495ed',
|
||||
cornsilk: 'fff8dc',
|
||||
crimson: 'dc143c',
|
||||
cyan: '00ffff',
|
||||
darkblue: '00008b',
|
||||
darkcyan: '008b8b',
|
||||
darkgoldenrod: 'b8860b',
|
||||
darkgray: 'a9a9a9',
|
||||
darkgreen: '006400',
|
||||
darkkhaki: 'bdb76b',
|
||||
darkmagenta: '8b008b',
|
||||
darkolivegreen: '556b2f',
|
||||
darkorange: 'ff8c00',
|
||||
darkorchid: '9932cc',
|
||||
darkred: '8b0000',
|
||||
darksalmon: 'e9967a',
|
||||
darkseagreen: '8fbc8f',
|
||||
darkslateblue: '483d8b',
|
||||
darkslategray: '2f4f4f',
|
||||
darkturquoise: '00ced1',
|
||||
darkviolet: '9400d3',
|
||||
deeppink: 'ff1493',
|
||||
deepskyblue: '00bfff',
|
||||
dimgray: '696969',
|
||||
dodgerblue: '1e90ff',
|
||||
feldspar: 'd19275',
|
||||
firebrick: 'b22222',
|
||||
floralwhite: 'fffaf0',
|
||||
forestgreen: '228b22',
|
||||
fuchsia: 'ff00ff',
|
||||
gainsboro: 'dcdcdc',
|
||||
ghostwhite: 'f8f8ff',
|
||||
gold: 'ffd700',
|
||||
goldenrod: 'daa520',
|
||||
gray: '808080',
|
||||
green: '008000',
|
||||
greenyellow: 'adff2f',
|
||||
honeydew: 'f0fff0',
|
||||
hotpink: 'ff69b4',
|
||||
indianred : 'cd5c5c',
|
||||
indigo : '4b0082',
|
||||
ivory: 'fffff0',
|
||||
khaki: 'f0e68c',
|
||||
lavender: 'e6e6fa',
|
||||
lavenderblush: 'fff0f5',
|
||||
lawngreen: '7cfc00',
|
||||
lemonchiffon: 'fffacd',
|
||||
lightblue: 'add8e6',
|
||||
lightcoral: 'f08080',
|
||||
lightcyan: 'e0ffff',
|
||||
lightgoldenrodyellow: 'fafad2',
|
||||
lightgrey: 'd3d3d3',
|
||||
lightgreen: '90ee90',
|
||||
lightpink: 'ffb6c1',
|
||||
lightsalmon: 'ffa07a',
|
||||
lightseagreen: '20b2aa',
|
||||
lightskyblue: '87cefa',
|
||||
lightslateblue: '8470ff',
|
||||
lightslategray: '778899',
|
||||
lightsteelblue: 'b0c4de',
|
||||
lightyellow: 'ffffe0',
|
||||
lime: '00ff00',
|
||||
limegreen: '32cd32',
|
||||
linen: 'faf0e6',
|
||||
magenta: 'ff00ff',
|
||||
maroon: '800000',
|
||||
mediumaquamarine: '66cdaa',
|
||||
mediumblue: '0000cd',
|
||||
mediumorchid: 'ba55d3',
|
||||
mediumpurple: '9370d8',
|
||||
mediumseagreen: '3cb371',
|
||||
mediumslateblue: '7b68ee',
|
||||
mediumspringgreen: '00fa9a',
|
||||
mediumturquoise: '48d1cc',
|
||||
mediumvioletred: 'c71585',
|
||||
midnightblue: '191970',
|
||||
mintcream: 'f5fffa',
|
||||
mistyrose: 'ffe4e1',
|
||||
moccasin: 'ffe4b5',
|
||||
navajowhite: 'ffdead',
|
||||
navy: '000080',
|
||||
oldlace: 'fdf5e6',
|
||||
olive: '808000',
|
||||
olivedrab: '6b8e23',
|
||||
orange: 'ffa500',
|
||||
orangered: 'ff4500',
|
||||
orchid: 'da70d6',
|
||||
palegoldenrod: 'eee8aa',
|
||||
palegreen: '98fb98',
|
||||
paleturquoise: 'afeeee',
|
||||
palevioletred: 'd87093',
|
||||
papayawhip: 'ffefd5',
|
||||
peachpuff: 'ffdab9',
|
||||
peru: 'cd853f',
|
||||
pink: 'ffc0cb',
|
||||
plum: 'dda0dd',
|
||||
powderblue: 'b0e0e6',
|
||||
purple: '800080',
|
||||
red: 'ff0000',
|
||||
rosybrown: 'bc8f8f',
|
||||
royalblue: '4169e1',
|
||||
saddlebrown: '8b4513',
|
||||
salmon: 'fa8072',
|
||||
sandybrown: 'f4a460',
|
||||
seagreen: '2e8b57',
|
||||
seashell: 'fff5ee',
|
||||
sienna: 'a0522d',
|
||||
silver: 'c0c0c0',
|
||||
skyblue: '87ceeb',
|
||||
slateblue: '6a5acd',
|
||||
slategray: '708090',
|
||||
snow: 'fffafa',
|
||||
springgreen: '00ff7f',
|
||||
steelblue: '4682b4',
|
||||
tan: 'd2b48c',
|
||||
teal: '008080',
|
||||
thistle: 'd8bfd8',
|
||||
tomato: 'ff6347',
|
||||
turquoise: '40e0d0',
|
||||
violet: 'ee82ee',
|
||||
violetred: 'd02090',
|
||||
wheat: 'f5deb3',
|
||||
white: 'ffffff',
|
||||
whitesmoke: 'f5f5f5',
|
||||
yellow: 'ffff00',
|
||||
yellowgreen: '9acd32'
|
||||
};
|
||||
for (var key in simple_colors) {
|
||||
if (color_string == key) {
|
||||
color_string = simple_colors[key];
|
||||
}
|
||||
}
|
||||
// emd of simple type-in colors
|
||||
|
||||
// array of color definition objects
|
||||
var color_defs = [
|
||||
{
|
||||
re: /^rgb\((\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3})\)$/,
|
||||
example: ['rgb(123, 234, 45)', 'rgb(255,234,245)'],
|
||||
process: function (bits){
|
||||
return [
|
||||
parseInt(bits[1]),
|
||||
parseInt(bits[2]),
|
||||
parseInt(bits[3])
|
||||
];
|
||||
}
|
||||
},
|
||||
{
|
||||
re: /^(\w{2})(\w{2})(\w{2})$/,
|
||||
example: ['#00ff00', '336699'],
|
||||
process: function (bits){
|
||||
return [
|
||||
parseInt(bits[1], 16),
|
||||
parseInt(bits[2], 16),
|
||||
parseInt(bits[3], 16)
|
||||
];
|
||||
}
|
||||
},
|
||||
{
|
||||
re: /^(\w{1})(\w{1})(\w{1})$/,
|
||||
example: ['#fb0', 'f0f'],
|
||||
process: function (bits){
|
||||
return [
|
||||
parseInt(bits[1] + bits[1], 16),
|
||||
parseInt(bits[2] + bits[2], 16),
|
||||
parseInt(bits[3] + bits[3], 16)
|
||||
];
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
// search through the definitions to find a match
|
||||
for (var i = 0; i < color_defs.length; i++) {
|
||||
var re = color_defs[i].re;
|
||||
var processor = color_defs[i].process;
|
||||
var bits = re.exec(color_string);
|
||||
if (bits) {
|
||||
channels = processor(bits);
|
||||
this.r = channels[0];
|
||||
this.g = channels[1];
|
||||
this.b = channels[2];
|
||||
this.ok = true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// validate/cleanup values
|
||||
this.r = (this.r < 0 || isNaN(this.r)) ? 0 : ((this.r > 255) ? 255 : this.r);
|
||||
this.g = (this.g < 0 || isNaN(this.g)) ? 0 : ((this.g > 255) ? 255 : this.g);
|
||||
this.b = (this.b < 0 || isNaN(this.b)) ? 0 : ((this.b > 255) ? 255 : this.b);
|
||||
|
||||
// some getters
|
||||
this.toRGB = function () {
|
||||
return 'rgb(' + this.r + ', ' + this.g + ', ' + this.b + ')';
|
||||
}
|
||||
this.toHex = function () {
|
||||
var r = this.r.toString(16);
|
||||
var g = this.g.toString(16);
|
||||
var b = this.b.toString(16);
|
||||
if (r.length == 1) r = '0' + r;
|
||||
if (g.length == 1) g = '0' + g;
|
||||
if (b.length == 1) b = '0' + b;
|
||||
return '#' + r + g + b;
|
||||
}
|
||||
|
||||
// help
|
||||
this.getHelpXML = function () {
|
||||
|
||||
var examples = new Array();
|
||||
// add regexps
|
||||
for (var i = 0; i < color_defs.length; i++) {
|
||||
var example = color_defs[i].example;
|
||||
for (var j = 0; j < example.length; j++) {
|
||||
examples[examples.length] = example[j];
|
||||
}
|
||||
}
|
||||
// add type-in colors
|
||||
for (var sc in simple_colors) {
|
||||
examples[examples.length] = sc;
|
||||
}
|
||||
|
||||
var xml = document.createElement('ul');
|
||||
xml.setAttribute('id', 'rgbcolor-examples');
|
||||
for (var i = 0; i < examples.length; i++) {
|
||||
try {
|
||||
var list_item = document.createElement('li');
|
||||
var list_color = new RGBColor(examples[i]);
|
||||
var example_div = document.createElement('div');
|
||||
example_div.style.cssText =
|
||||
'margin: 3px; '
|
||||
+ 'border: 1px solid black; '
|
||||
+ 'background:' + list_color.toHex() + '; '
|
||||
+ 'color:' + list_color.toHex()
|
||||
;
|
||||
example_div.appendChild(document.createTextNode('test'));
|
||||
var list_item_value = document.createTextNode(
|
||||
' ' + examples[i] + ' -> ' + list_color.toRGB() + ' -> ' + list_color.toHex()
|
||||
);
|
||||
list_item.appendChild(example_div);
|
||||
list_item.appendChild(list_item_value);
|
||||
xml.appendChild(list_item);
|
||||
|
||||
} catch(e){}
|
||||
}
|
||||
return xml;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
131
js/functions.js
131
js/functions.js
@ -25,6 +25,13 @@ var ajax_message_init = false;
|
||||
*/
|
||||
var codemirror_editor = false;
|
||||
|
||||
/**
|
||||
* @var chart_activeTimeouts object active timeouts that refresh the charts. When disabling a realtime chart, this can be used to stop the continuous ajax requests
|
||||
*/
|
||||
var chart_activeTimeouts = new Object();
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Add a hidden field to the form to indicate that this will be an
|
||||
* Ajax request (only if this hidden field does not exist)
|
||||
@ -1237,6 +1244,7 @@ $(document).ready(function(){
|
||||
* optional, defaults to 'Loading...'
|
||||
* @param var timeout number of milliseconds for the message to be visible
|
||||
* optional, defaults to 5000
|
||||
* @return jQuery object jQuery Element that holds the message div
|
||||
*/
|
||||
|
||||
function PMA_ajaxShowMessage(message, timeout) {
|
||||
@ -1301,7 +1309,7 @@ function PMA_ajaxShowMessage(message, timeout) {
|
||||
})
|
||||
}
|
||||
|
||||
return $("#loading");
|
||||
return $("#loading");
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1332,7 +1340,7 @@ function PMA_showNoticeForEnum(selectElement) {
|
||||
/**
|
||||
* Generates a dialog box to pop up the create_table form
|
||||
*/
|
||||
function PMA_createTableDialog( div, url , target){
|
||||
function PMA_createTableDialog( div, url , target) {
|
||||
/**
|
||||
* @var button_options Object that stores the options passed to jQueryUI
|
||||
* dialog
|
||||
@ -1376,6 +1384,119 @@ function PMA_createTableDialog( div, url , target){
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a highcharts chart in the given container
|
||||
*
|
||||
* @param var settings object with highcharts properties that should be applied. (See also http://www.highcharts.com/ref/)
|
||||
* requires at least settings.chart.renderTo and settings.series to be set.
|
||||
* In addition there may be an additional property object 'realtime' that allows for realtime charting:
|
||||
* realtime: {
|
||||
* url: adress to get the data from (will always add token, ajax_request=1 and chart_data=1 to the GET request)
|
||||
* type: the GET request will also add type=[value of the type property] to the request
|
||||
* callback: Callback function that should draw the point, it's called with 4 parameters in this order:
|
||||
* - the chart object
|
||||
* - the current response value of the GET request, JSON parsed
|
||||
* - the previous response value of the GET request, JSON parsed
|
||||
* - the number of added points
|
||||
*
|
||||
* @return object The created highcharts instance
|
||||
*/
|
||||
function PMA_createChart(passedSettings) {
|
||||
var container = passedSettings.chart.renderTo;
|
||||
|
||||
var settings = {
|
||||
chart: {
|
||||
type: 'spline',
|
||||
marginRight: 10,
|
||||
events: {
|
||||
load: function() {
|
||||
var thisChart = this;
|
||||
var lastValue=null, curValue=null;
|
||||
var numLoadedPoints=0, otherSum=0;
|
||||
var diff;
|
||||
// No realtime updates for graphs that are being exported, and disabled when no callback is set
|
||||
if(thisChart.options.chart.forExport==true || !passedSettings.realtime || !passedSettings.realtime.callback) return;
|
||||
|
||||
thisChart.options.realtime.timeoutCallBack = function() {
|
||||
$.get(passedSettings.realtime.url,{ajax_request:1, chart_data:1, type:passedSettings.realtime.type},function(data) {
|
||||
if(chart_activeTimeouts[container]==null) return;
|
||||
|
||||
curValue = jQuery.parseJSON(data);
|
||||
//if(lastValue==null) lastValue = curValue;
|
||||
|
||||
if(lastValue==null) diff = curValue.x - thisChart.xAxis[0].getExtremes().max;
|
||||
else diff = parseInt(curValue.x - lastValue.x);
|
||||
|
||||
thisChart.xAxis[0].setExtremes(thisChart.xAxis[0].getExtremes().min+diff, thisChart.xAxis[0].getExtremes().max+diff, false);
|
||||
|
||||
passedSettings.realtime.callback(thisChart,curValue,lastValue,numLoadedPoints);
|
||||
|
||||
lastValue = curValue;
|
||||
numLoadedPoints++;
|
||||
chart_activeTimeouts[container] = setTimeout(thisChart.options.realtime.timeoutCallBack, thisChart.options.realtime.refreshRate);
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
chart_activeTimeouts[container] = setTimeout(thisChart.options.realtime.timeoutCallBack, 0);
|
||||
}
|
||||
}
|
||||
},
|
||||
plotOptions: {
|
||||
series: {
|
||||
marker: {
|
||||
radius: 3
|
||||
}
|
||||
}
|
||||
},
|
||||
credits: {
|
||||
enabled:false
|
||||
},
|
||||
xAxis: {
|
||||
type: 'datetime',
|
||||
},
|
||||
yAxis: {
|
||||
min: 0,
|
||||
title: {
|
||||
text: PMA_messages['strTotalCount']
|
||||
},
|
||||
plotLines: [{
|
||||
value: 0,
|
||||
width: 1,
|
||||
color: '#808080'
|
||||
}]
|
||||
},
|
||||
tooltip: {
|
||||
formatter: function() {
|
||||
return '<b>'+ this.series.name +'</b><br/>'+
|
||||
Highcharts.dateFormat('%Y-%m-%d %H:%M:%S', this.x) +'<br/>'+
|
||||
Highcharts.numberFormat(this.y, 2);
|
||||
}
|
||||
},
|
||||
exporting: {
|
||||
enabled: true
|
||||
},
|
||||
series: []
|
||||
}
|
||||
|
||||
/* Set/Get realtime chart default values */
|
||||
if(passedSettings.realtime) {
|
||||
if(!passedSettings.realtime.refreshRate)
|
||||
passedSettings.realtime.refreshRate = 5000;
|
||||
|
||||
if(!passedSettings.realtime.numMaxPoints)
|
||||
passedSettings.realtime.numMaxPoints = 32;
|
||||
|
||||
settings.xAxis.min = new Date().getTime() - passedSettings.realtime.numMaxPoints * passedSettings.realtime.refreshRate;
|
||||
settings.xAxis.max = new Date().getTime() + passedSettings.realtime.refreshRate / 2;
|
||||
}
|
||||
|
||||
// Overwrite/Merge default settings with passedsettings
|
||||
$.extend(true,settings,passedSettings);
|
||||
|
||||
return new Highcharts.Chart(settings);
|
||||
}
|
||||
|
||||
/**
|
||||
* jQuery function that uses jQueryUI's dialogs to confirm with user. Does not
|
||||
* return a jQuery object yet and hence cannot be chained
|
||||
@ -2007,8 +2128,10 @@ $(document).ready(function() {
|
||||
}
|
||||
});
|
||||
|
||||
$(document).ready(initTooltips);
|
||||
|
||||
/* Displays tooltips */
|
||||
$(document).ready(function() {
|
||||
function initTooltips() {
|
||||
// Hide the footnotes from the footer (which are displayed for
|
||||
// JavaScript-disabled browsers) since the tooltip is sufficient
|
||||
$(".footnotes").hide();
|
||||
@ -2034,7 +2157,7 @@ $(document).ready(function() {
|
||||
style: { background: '#ffffcc' }
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function menuResize()
|
||||
{
|
||||
|
||||
690
js/highcharts/exporting.js
Normal file
690
js/highcharts/exporting.js
Normal file
@ -0,0 +1,690 @@
|
||||
/**
|
||||
* @license Highcharts JS v2.1.4 (2011-03-02)
|
||||
* Exporting module
|
||||
*
|
||||
* (c) 2010 Torstein Hønsi
|
||||
*
|
||||
* License: www.highcharts.com/license
|
||||
*/
|
||||
|
||||
// JSLint options:
|
||||
/*global Highcharts, document, window, Math, setTimeout */
|
||||
|
||||
(function() { // encapsulate
|
||||
|
||||
// create shortcuts
|
||||
var HC = Highcharts,
|
||||
Chart = HC.Chart,
|
||||
addEvent = HC.addEvent,
|
||||
createElement = HC.createElement,
|
||||
discardElement = HC.discardElement,
|
||||
css = HC.css,
|
||||
merge = HC.merge,
|
||||
each = HC.each,
|
||||
extend = HC.extend,
|
||||
math = Math,
|
||||
mathMax = math.max,
|
||||
doc = document,
|
||||
win = window,
|
||||
hasTouch = 'ontouchstart' in doc.documentElement,
|
||||
M = 'M',
|
||||
L = 'L',
|
||||
DIV = 'div',
|
||||
HIDDEN = 'hidden',
|
||||
NONE = 'none',
|
||||
PREFIX = 'highcharts-',
|
||||
ABSOLUTE = 'absolute',
|
||||
PX = 'px',
|
||||
|
||||
|
||||
|
||||
// Add language and get the defaultOptions
|
||||
defaultOptions = HC.setOptions({
|
||||
lang: {
|
||||
downloadPNG: 'Download PNG image',
|
||||
downloadJPEG: 'Download JPEG image',
|
||||
downloadPDF: 'Download PDF document',
|
||||
downloadSVG: 'Download SVG vector image',
|
||||
exportButtonTitle: 'Export to raster or vector image',
|
||||
printButtonTitle: 'Print the chart'
|
||||
}
|
||||
});
|
||||
|
||||
// Buttons and menus are collected in a separate config option set called 'navigation'.
|
||||
// This can be extended later to add control buttons like zoom and pan right click menus.
|
||||
defaultOptions.navigation = {
|
||||
menuStyle: {
|
||||
border: '1px solid #A0A0A0',
|
||||
background: '#FFFFFF'
|
||||
},
|
||||
menuItemStyle: {
|
||||
padding: '0 5px',
|
||||
background: NONE,
|
||||
color: '#303030',
|
||||
fontSize: hasTouch ? '14px' : '11px'
|
||||
},
|
||||
menuItemHoverStyle: {
|
||||
background: '#4572A5',
|
||||
color: '#FFFFFF'
|
||||
},
|
||||
|
||||
buttonOptions: {
|
||||
align: 'right',
|
||||
backgroundColor: {
|
||||
linearGradient: [0, 0, 0, 20],
|
||||
stops: [
|
||||
[0.4, '#F7F7F7'],
|
||||
[0.6, '#E3E3E3']
|
||||
]
|
||||
},
|
||||
borderColor: '#B0B0B0',
|
||||
borderRadius: 3,
|
||||
borderWidth: 1,
|
||||
//enabled: true,
|
||||
height: 20,
|
||||
hoverBorderColor: '#909090',
|
||||
hoverSymbolFill: '#81A7CF',
|
||||
hoverSymbolStroke: '#4572A5',
|
||||
symbolFill: '#E0E0E0',
|
||||
//symbolSize: 12,
|
||||
symbolStroke: '#A0A0A0',
|
||||
//symbolStrokeWidth: 1,
|
||||
symbolX: 11.5,
|
||||
symbolY: 10.5,
|
||||
verticalAlign: 'top',
|
||||
width: 24,
|
||||
y: 10
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
// Add the export related options
|
||||
defaultOptions.exporting = {
|
||||
//enabled: true,
|
||||
//filename: 'chart',
|
||||
type: 'image/png',
|
||||
url: 'chart_export.php',
|
||||
width: 800,
|
||||
buttons: {
|
||||
exportButton: {
|
||||
//enabled: true,
|
||||
symbol: 'exportIcon',
|
||||
x: -10,
|
||||
symbolFill: '#A8BF77',
|
||||
hoverSymbolFill: '#768F3E',
|
||||
_titleKey: 'exportButtonTitle',
|
||||
menuItems: [{
|
||||
textKey: 'downloadPNG',
|
||||
onclick: function() {
|
||||
this.exportChart();
|
||||
}
|
||||
},/* {
|
||||
textKey: 'downloadJPEG',
|
||||
onclick: function() {
|
||||
this.exportChart({
|
||||
type: 'image/jpeg'
|
||||
});
|
||||
}
|
||||
}, {
|
||||
textKey: 'downloadPDF',
|
||||
onclick: function() {
|
||||
this.exportChart({
|
||||
type: 'application/pdf'
|
||||
});
|
||||
}
|
||||
}, */{
|
||||
textKey: 'downloadSVG',
|
||||
onclick: function() {
|
||||
this.exportChart({
|
||||
type: 'image/svg+xml'
|
||||
});
|
||||
}
|
||||
}/*, {
|
||||
text: 'View SVG',
|
||||
onclick: function() {
|
||||
var svg = this.getSVG()
|
||||
.replace(/</g, '\n<')
|
||||
.replace(/>/g, '>');
|
||||
|
||||
doc.body.innerHTML = '<pre>'+ svg +'</pre>';
|
||||
}
|
||||
}*/]
|
||||
|
||||
},
|
||||
printButton: {
|
||||
//enabled: true,
|
||||
symbol: 'printIcon',
|
||||
x: -36,
|
||||
symbolFill: '#B5C9DF',
|
||||
hoverSymbolFill: '#779ABF',
|
||||
_titleKey: 'printButtonTitle',
|
||||
onclick: function() {
|
||||
this.print();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
extend(Chart.prototype, {
|
||||
/**
|
||||
* Return an SVG representation of the chart
|
||||
*
|
||||
* @param additionalOptions {Object} Additional chart options for the generated SVG representation
|
||||
*/
|
||||
getSVG: function(additionalOptions) {
|
||||
var chart = this,
|
||||
chartCopy,
|
||||
sandbox,
|
||||
svg,
|
||||
seriesOptions,
|
||||
config,
|
||||
pointOptions,
|
||||
pointMarker,
|
||||
options = merge(chart.options, additionalOptions); // copy the options and add extra options
|
||||
|
||||
// IE compatibility hack for generating SVG content that it doesn't really understand
|
||||
if (!doc.createElementNS) {
|
||||
doc.createElementNS = function(ns, tagName) {
|
||||
var elem = doc.createElement(tagName);
|
||||
elem.getBBox = function() {
|
||||
return chart.renderer.Element.prototype.getBBox.apply({ element: elem });
|
||||
};
|
||||
return elem;
|
||||
};
|
||||
}
|
||||
|
||||
// create a sandbox where a new chart will be generated
|
||||
sandbox = createElement(DIV, null, {
|
||||
position: ABSOLUTE,
|
||||
top: '-9999em',
|
||||
width: chart.chartWidth + PX,
|
||||
height: chart.chartHeight + PX
|
||||
}, doc.body);
|
||||
|
||||
// override some options
|
||||
extend(options.chart, {
|
||||
renderTo: sandbox,
|
||||
forExport: true
|
||||
});
|
||||
options.exporting.enabled = false; // hide buttons in print
|
||||
options.chart.plotBackgroundImage = null; // the converter doesn't handle images
|
||||
// prepare for replicating the chart
|
||||
options.series = [];
|
||||
each(chart.series, function(serie) {
|
||||
seriesOptions = serie.options;
|
||||
|
||||
seriesOptions.animation = false; // turn off animation
|
||||
seriesOptions.showCheckbox = false;
|
||||
|
||||
// remove image markers
|
||||
if (seriesOptions && seriesOptions.marker && /^url\(/.test(seriesOptions.marker.symbol)) {
|
||||
seriesOptions.marker.symbol = 'circle';
|
||||
}
|
||||
|
||||
seriesOptions.data = [];
|
||||
|
||||
each(serie.data, function(point) {
|
||||
|
||||
// extend the options by those values that can be expressed in a number or array config
|
||||
config = point.config;
|
||||
pointOptions = {
|
||||
x: point.x,
|
||||
y: point.y,
|
||||
name: point.name
|
||||
};
|
||||
|
||||
if (typeof config == 'object' && point.config && config.constructor != Array) {
|
||||
extend(pointOptions, config);
|
||||
}
|
||||
|
||||
seriesOptions.data.push(pointOptions); // copy fresh updated data
|
||||
|
||||
// remove image markers
|
||||
pointMarker = point.config && point.config.marker;
|
||||
if (pointMarker && /^url\(/.test(pointMarker.symbol)) {
|
||||
delete pointMarker.symbol;
|
||||
}
|
||||
});
|
||||
|
||||
options.series.push(seriesOptions);
|
||||
});
|
||||
|
||||
// generate the chart copy
|
||||
chartCopy = new Highcharts.Chart(options);
|
||||
|
||||
// get the SVG from the container's innerHTML
|
||||
svg = chartCopy.container.innerHTML;
|
||||
|
||||
// free up memory
|
||||
options = null;
|
||||
chartCopy.destroy();
|
||||
discardElement(sandbox);
|
||||
|
||||
// sanitize
|
||||
svg = svg
|
||||
.replace(/zIndex="[^"]+"/g, '')
|
||||
.replace(/isShadow="[^"]+"/g, '')
|
||||
.replace(/symbolName="[^"]+"/g, '')
|
||||
.replace(/jQuery[0-9]+="[^"]+"/g, '')
|
||||
.replace(/isTracker="[^"]+"/g, '')
|
||||
.replace(/url\([^#]+#/g, 'url(#')
|
||||
/*.replace(/<svg /, '<svg xmlns:xlink="http://www.w3.org/1999/xlink" ')
|
||||
.replace(/ href=/, ' xlink:href=')
|
||||
.replace(/preserveAspectRatio="none">/g, 'preserveAspectRatio="none"/>')*/
|
||||
/* This fails in IE < 8
|
||||
.replace(/([0-9]+)\.([0-9]+)/g, function(s1, s2, s3) { // round off to save weight
|
||||
return s2 +'.'+ s3[0];
|
||||
})*/
|
||||
|
||||
// IE specific
|
||||
.replace(/id=([^" >]+)/g, 'id="$1"')
|
||||
.replace(/class=([^" ]+)/g, 'class="$1"')
|
||||
.replace(/ transform /g, ' ')
|
||||
.replace(/:(path|rect)/g, '$1')
|
||||
.replace(/style="([^"]+)"/g, function(s) {
|
||||
return s.toLowerCase();
|
||||
});
|
||||
|
||||
// IE9 beta bugs with innerHTML. Test again with final IE9.
|
||||
svg = svg.replace(/(url\(#highcharts-[0-9]+)"/g, '$1')
|
||||
.replace(/"/g, "'");
|
||||
if (svg.match(/ xmlns="/g).length == 2) {
|
||||
svg = svg.replace(/xmlns="[^"]+"/, '');
|
||||
}
|
||||
|
||||
return svg;
|
||||
},
|
||||
|
||||
/**
|
||||
* Submit the SVG representation of the chart to the server
|
||||
* @param {Object} options Exporting options. Possible members are url, type and width.
|
||||
* @param {Object} chartOptions Additional chart options for the SVG representation of the chart
|
||||
*/
|
||||
exportChart: function(options, chartOptions) {
|
||||
var form,
|
||||
chart = this,
|
||||
canvas=createElement('canvas');
|
||||
|
||||
$('body').append(canvas);
|
||||
$(canvas).hide();
|
||||
|
||||
var submitData = function(chartData) {
|
||||
// merge the options
|
||||
options = merge(chart.options.exporting, options);
|
||||
|
||||
// create the form
|
||||
form = createElement('form', {
|
||||
method: 'post',
|
||||
action: options.url
|
||||
}, {
|
||||
display: NONE
|
||||
}, doc.body);
|
||||
|
||||
// add the values
|
||||
each(['filename', 'type', 'width', 'image','token'], function(name) {
|
||||
createElement('input', {
|
||||
type: HIDDEN,
|
||||
name: name,
|
||||
value: {
|
||||
filename: options.filename || 'chart',
|
||||
type: options.type,
|
||||
width: options.width,
|
||||
image: chartData,
|
||||
token: pma_token
|
||||
}[name]
|
||||
}, null, form);
|
||||
});
|
||||
|
||||
// submit
|
||||
form.submit();
|
||||
|
||||
// clean up
|
||||
discardElement(form);
|
||||
}
|
||||
|
||||
if(options && options.type=='image/svg+xml') {
|
||||
submitData(chart.getSVG(chartOptions));
|
||||
} else {
|
||||
// Generate data uri and submit once done
|
||||
canvg(canvas, chart.getSVG(chartOptions),{
|
||||
ignoreAnimation:true,
|
||||
ignoreMouse:true,
|
||||
renderCallback:function() { submitData(canvas.toDataURL()); }
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Print the chart
|
||||
*/
|
||||
print: function() {
|
||||
|
||||
var chart = this,
|
||||
container = chart.container,
|
||||
origDisplay = [],
|
||||
origParent = container.parentNode,
|
||||
body = doc.body,
|
||||
childNodes = body.childNodes;
|
||||
|
||||
if (chart.isPrinting) { // block the button while in printing mode
|
||||
return;
|
||||
}
|
||||
|
||||
chart.isPrinting = true;
|
||||
|
||||
// hide all body content
|
||||
each(childNodes, function(node, i) {
|
||||
if (node.nodeType == 1) {
|
||||
origDisplay[i] = node.style.display;
|
||||
node.style.display = NONE;
|
||||
}
|
||||
});
|
||||
|
||||
// pull out the chart
|
||||
body.appendChild(container);
|
||||
|
||||
// print
|
||||
win.print();
|
||||
|
||||
// allow the browser to prepare before reverting
|
||||
setTimeout(function() {
|
||||
|
||||
// put the chart back in
|
||||
origParent.appendChild(container);
|
||||
|
||||
// restore all body content
|
||||
each(childNodes, function(node, i) {
|
||||
if (node.nodeType == 1) {
|
||||
node.style.display = origDisplay[i];
|
||||
}
|
||||
});
|
||||
|
||||
chart.isPrinting = false;
|
||||
|
||||
}, 1000);
|
||||
|
||||
},
|
||||
|
||||
/**
|
||||
* Display a popup menu for choosing the export type
|
||||
*
|
||||
* @param {String} name An identifier for the menu
|
||||
* @param {Array} items A collection with text and onclicks for the items
|
||||
* @param {Number} x The x position of the opener button
|
||||
* @param {Number} y The y position of the opener button
|
||||
* @param {Number} width The width of the opener button
|
||||
* @param {Number} height The height of the opener button
|
||||
*/
|
||||
contextMenu: function(name, items, x, y, width, height) {
|
||||
var chart = this,
|
||||
navOptions = chart.options.navigation,
|
||||
menuItemStyle = navOptions.menuItemStyle,
|
||||
chartWidth = chart.chartWidth,
|
||||
chartHeight = chart.chartHeight,
|
||||
cacheName = 'cache-'+ name,
|
||||
menu = chart[cacheName],
|
||||
menuPadding = mathMax(width, height), // for mouse leave detection
|
||||
boxShadow = '3px 3px 10px #888',
|
||||
innerMenu,
|
||||
hide,
|
||||
menuStyle;
|
||||
|
||||
// create the menu only the first time
|
||||
if (!menu) {
|
||||
|
||||
// create a HTML element above the SVG
|
||||
chart[cacheName] = menu = createElement(DIV, {
|
||||
className: PREFIX + name
|
||||
}, {
|
||||
position: ABSOLUTE,
|
||||
zIndex: 1000,
|
||||
padding: menuPadding + PX
|
||||
}, chart.container);
|
||||
|
||||
innerMenu = createElement(DIV, null,
|
||||
extend({
|
||||
MozBoxShadow: boxShadow,
|
||||
WebkitBoxShadow: boxShadow,
|
||||
boxShadow: boxShadow
|
||||
}, navOptions.menuStyle) , menu);
|
||||
|
||||
// hide on mouse out
|
||||
hide = function() {
|
||||
css(menu, { display: NONE });
|
||||
};
|
||||
|
||||
addEvent(menu, 'mouseleave', hide);
|
||||
|
||||
|
||||
// create the items
|
||||
each(items, function(item) {
|
||||
if (item) {
|
||||
var div = createElement(DIV, {
|
||||
onmouseover: function() {
|
||||
css(this, navOptions.menuItemHoverStyle);
|
||||
},
|
||||
onmouseout: function() {
|
||||
css(this, menuItemStyle);
|
||||
},
|
||||
innerHTML: item.text || HC.getOptions().lang[item.textKey]
|
||||
}, extend({
|
||||
cursor: 'pointer'
|
||||
}, menuItemStyle), innerMenu);
|
||||
|
||||
div[hasTouch ? 'ontouchstart' : 'onclick'] = function() {
|
||||
hide();
|
||||
item.onclick.apply(chart, arguments);
|
||||
};
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
chart.exportMenuWidth = menu.offsetWidth;
|
||||
chart.exportMenuHeight = menu.offsetHeight;
|
||||
}
|
||||
|
||||
menuStyle = { display: 'block' };
|
||||
|
||||
// if outside right, right align it
|
||||
if (x + chart.exportMenuWidth > chartWidth) {
|
||||
menuStyle.right = (chartWidth - x - width - menuPadding) + PX;
|
||||
} else {
|
||||
menuStyle.left = (x - menuPadding) + PX;
|
||||
}
|
||||
// if outside bottom, bottom align it
|
||||
if (y + height + chart.exportMenuHeight > chartHeight) {
|
||||
menuStyle.bottom = (chartHeight - y - menuPadding) + PX;
|
||||
} else {
|
||||
menuStyle.top = (y + height - menuPadding) + PX;
|
||||
}
|
||||
|
||||
css(menu, menuStyle);
|
||||
},
|
||||
|
||||
/**
|
||||
* Add the export button to the chart
|
||||
*/
|
||||
addButton: function(options) {
|
||||
var chart = this,
|
||||
renderer = chart.renderer,
|
||||
btnOptions = merge(chart.options.navigation.buttonOptions, options),
|
||||
onclick = btnOptions.onclick,
|
||||
menuItems = btnOptions.menuItems,
|
||||
/*position = chart.getAlignment(btnOptions),
|
||||
buttonLeft = position.x,
|
||||
buttonTop = position.y,*/
|
||||
buttonWidth = btnOptions.width,
|
||||
buttonHeight = btnOptions.height,
|
||||
box,
|
||||
symbol,
|
||||
button,
|
||||
borderWidth = btnOptions.borderWidth,
|
||||
boxAttr = {
|
||||
stroke: btnOptions.borderColor
|
||||
|
||||
},
|
||||
symbolAttr = {
|
||||
stroke: btnOptions.symbolStroke,
|
||||
fill: btnOptions.symbolFill
|
||||
};
|
||||
|
||||
if (btnOptions.enabled === false) {
|
||||
return;
|
||||
}
|
||||
|
||||
// element to capture the click
|
||||
function revert() {
|
||||
symbol.attr(symbolAttr);
|
||||
box.attr(boxAttr);
|
||||
}
|
||||
|
||||
// the box border
|
||||
box = renderer.rect(
|
||||
0,
|
||||
0,
|
||||
buttonWidth,
|
||||
buttonHeight,
|
||||
btnOptions.borderRadius,
|
||||
borderWidth
|
||||
)
|
||||
//.translate(buttonLeft, buttonTop) // to allow gradients
|
||||
.align(btnOptions, true)
|
||||
.attr(extend({
|
||||
fill: btnOptions.backgroundColor,
|
||||
'stroke-width': borderWidth,
|
||||
zIndex: 19
|
||||
}, boxAttr)).add();
|
||||
|
||||
// the invisible element to track the clicks
|
||||
button = renderer.rect(
|
||||
0,
|
||||
0,
|
||||
buttonWidth,
|
||||
buttonHeight,
|
||||
0
|
||||
)
|
||||
.align(btnOptions)
|
||||
.attr({
|
||||
fill: 'rgba(255, 255, 255, 0.001)',
|
||||
title: HC.getOptions().lang[btnOptions._titleKey],
|
||||
zIndex: 21
|
||||
}).css({
|
||||
cursor: 'pointer'
|
||||
})
|
||||
.on('mouseover', function() {
|
||||
symbol.attr({
|
||||
stroke: btnOptions.hoverSymbolStroke,
|
||||
fill: btnOptions.hoverSymbolFill
|
||||
});
|
||||
box.attr({
|
||||
stroke: btnOptions.hoverBorderColor
|
||||
});
|
||||
})
|
||||
.on('mouseout', revert)
|
||||
.on('click', revert)
|
||||
.add();
|
||||
|
||||
//addEvent(button.element, 'click', revert);
|
||||
|
||||
// add the click event
|
||||
if (menuItems) {
|
||||
onclick = function(e) {
|
||||
revert();
|
||||
var bBox = button.getBBox();
|
||||
chart.contextMenu('export-menu', menuItems, bBox.x, bBox.y, buttonWidth, buttonHeight);
|
||||
};
|
||||
}
|
||||
/*addEvent(button.element, 'click', function() {
|
||||
onclick.apply(chart, arguments);
|
||||
});*/
|
||||
button.on('click', function() {
|
||||
onclick.apply(chart, arguments);
|
||||
});
|
||||
|
||||
// the icon
|
||||
symbol = renderer.symbol(
|
||||
btnOptions.symbol,
|
||||
btnOptions.symbolX,
|
||||
btnOptions.symbolY,
|
||||
(btnOptions.symbolSize || 12) / 2
|
||||
)
|
||||
.align(btnOptions, true)
|
||||
.attr(extend(symbolAttr, {
|
||||
'stroke-width': btnOptions.symbolStrokeWidth || 1,
|
||||
zIndex: 20
|
||||
})).add();
|
||||
|
||||
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
// Create the export icon
|
||||
HC.Renderer.prototype.symbols.exportIcon = function(x, y, radius) {
|
||||
return [
|
||||
M, // the disk
|
||||
x - radius, y + radius,
|
||||
L,
|
||||
x + radius, y + radius,
|
||||
x + radius, y + radius * 0.5,
|
||||
x - radius, y + radius * 0.5,
|
||||
'Z',
|
||||
M, // the arrow
|
||||
x, y + radius * 0.5,
|
||||
L,
|
||||
x - radius * 0.5, y - radius / 3,
|
||||
x - radius / 6, y - radius / 3,
|
||||
x - radius / 6, y - radius,
|
||||
x + radius / 6, y - radius,
|
||||
x + radius / 6, y - radius / 3,
|
||||
x + radius * 0.5, y - radius / 3,
|
||||
'Z'
|
||||
];
|
||||
};
|
||||
// Create the print icon
|
||||
HC.Renderer.prototype.symbols.printIcon = function(x, y, radius) {
|
||||
return [
|
||||
M, // the printer
|
||||
x - radius, y + radius * 0.5,
|
||||
L,
|
||||
x + radius, y + radius * 0.5,
|
||||
x + radius, y - radius / 3,
|
||||
x - radius, y - radius / 3,
|
||||
'Z',
|
||||
M, // the upper sheet
|
||||
x - radius * 0.5, y - radius / 3,
|
||||
L,
|
||||
x - radius * 0.5, y - radius,
|
||||
x + radius * 0.5, y - radius,
|
||||
x + radius * 0.5, y - radius / 3,
|
||||
'Z',
|
||||
M, // the lower sheet
|
||||
x - radius * 0.5, y + radius * 0.5,
|
||||
L,
|
||||
x - radius * 0.75, y + radius,
|
||||
x + radius * 0.75, y + radius,
|
||||
x + radius * 0.5, y + radius * 0.5,
|
||||
'Z'
|
||||
];
|
||||
};
|
||||
|
||||
|
||||
// Add the buttons on chart load
|
||||
Chart.prototype.callbacks.push(function(chart) {
|
||||
var n,
|
||||
exportingOptions = chart.options.exporting,
|
||||
buttons = exportingOptions.buttons;
|
||||
|
||||
if (exportingOptions.enabled !== false) {
|
||||
|
||||
for (n in buttons) {
|
||||
chart.addButton(buttons[n]);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
})();
|
||||
10671
js/highcharts/highcharts.js
Normal file
10671
js/highcharts/highcharts.js
Normal file
File diff suppressed because it is too large
Load Diff
91
js/jquery/jquery.cookie.js
Normal file
91
js/jquery/jquery.cookie.js
Normal file
@ -0,0 +1,91 @@
|
||||
/*jslint browser: true */ /*global jQuery: true */
|
||||
|
||||
/**
|
||||
* jQuery Cookie plugin
|
||||
*
|
||||
* Copyright (c) 2010 Klaus Hartl (stilbuero.de)
|
||||
* Dual licensed under the MIT and GPL licenses:
|
||||
* http://www.opensource.org/licenses/mit-license.php
|
||||
* http://www.gnu.org/licenses/gpl.html
|
||||
*
|
||||
*/
|
||||
|
||||
// TODO JsDoc
|
||||
|
||||
/**
|
||||
* Create a cookie with the given key and value and other optional parameters.
|
||||
*
|
||||
* @example $.cookie('the_cookie', 'the_value');
|
||||
* @desc Set the value of a cookie.
|
||||
* @example $.cookie('the_cookie', 'the_value', { expires: 7, path: '/', domain: 'jquery.com', secure: true });
|
||||
* @desc Create a cookie with all available options.
|
||||
* @example $.cookie('the_cookie', 'the_value');
|
||||
* @desc Create a session cookie.
|
||||
* @example $.cookie('the_cookie', null);
|
||||
* @desc Delete a cookie by passing null as value. Keep in mind that you have to use the same path and domain
|
||||
* used when the cookie was set.
|
||||
*
|
||||
* @param String key The key of the cookie.
|
||||
* @param String value The value of the cookie.
|
||||
* @param Object options An object literal containing key/value pairs to provide optional cookie attributes.
|
||||
* @option Number|Date expires Either an integer specifying the expiration date from now on in days or a Date object.
|
||||
* If a negative value is specified (e.g. a date in the past), the cookie will be deleted.
|
||||
* If set to null or omitted, the cookie will be a session cookie and will not be retained
|
||||
* when the the browser exits.
|
||||
* @option String path The value of the path atribute of the cookie (default: path of page that created the cookie).
|
||||
* @option String domain The value of the domain attribute of the cookie (default: domain of page that created the cookie).
|
||||
* @option Boolean secure If true, the secure attribute of the cookie will be set and the cookie transmission will
|
||||
* require a secure protocol (like HTTPS).
|
||||
* @type undefined
|
||||
*
|
||||
* @name $.cookie
|
||||
* @cat Plugins/Cookie
|
||||
* @author Klaus Hartl/klaus.hartl@stilbuero.de
|
||||
*/
|
||||
|
||||
/**
|
||||
* Get the value of a cookie with the given key.
|
||||
*
|
||||
* @example $.cookie('the_cookie');
|
||||
* @desc Get the value of a cookie.
|
||||
*
|
||||
* @param String key The key of the cookie.
|
||||
* @return The value of the cookie.
|
||||
* @type String
|
||||
*
|
||||
* @name $.cookie
|
||||
* @cat Plugins/Cookie
|
||||
* @author Klaus Hartl/klaus.hartl@stilbuero.de
|
||||
*/
|
||||
jQuery.cookie = function (key, value, options) {
|
||||
|
||||
// key and at least value given, set cookie...
|
||||
if (arguments.length > 1 && String(value) !== "[object Object]") {
|
||||
options = jQuery.extend({}, options);
|
||||
|
||||
if (value === null || value === undefined) {
|
||||
options.expires = -1;
|
||||
}
|
||||
|
||||
if (typeof options.expires === 'number') {
|
||||
var days = options.expires, t = options.expires = new Date();
|
||||
t.setDate(t.getDate() + days);
|
||||
}
|
||||
|
||||
value = String(value);
|
||||
|
||||
return (document.cookie = [
|
||||
encodeURIComponent(key), '=',
|
||||
options.raw ? value : encodeURIComponent(value),
|
||||
options.expires ? '; expires=' + options.expires.toUTCString() : '', // use expires attribute, max-age is not supported by IE
|
||||
options.path ? '; path=' + options.path : '',
|
||||
options.domain ? '; domain=' + options.domain : '',
|
||||
options.secure ? '; secure' : ''
|
||||
].join(''));
|
||||
}
|
||||
|
||||
// key and possibly options given, get cookie...
|
||||
options = value || {};
|
||||
var result, decode = options.raw ? function (s) { return s; } : decodeURIComponent;
|
||||
return (result = new RegExp('(?:^|; )' + encodeURIComponent(key) + '=([^;]*)').exec(document.cookie)) ? decode(result[1]) : null;
|
||||
};
|
||||
1031
js/jquery/jquery.tablesorter.js
Normal file
1031
js/jquery/jquery.tablesorter.js
Normal file
File diff suppressed because it is too large
Load Diff
@ -46,6 +46,10 @@ $js_messages['strBLOBRepositoryDisableAreYouSure'] = sprintf(__('Are you sure yo
|
||||
$js_messages['strFormEmpty'] = __('Missing value in the form!');
|
||||
$js_messages['strNotNumber'] = __('This is not a number!');
|
||||
|
||||
/* Charts */
|
||||
/* l10n: Default description for the y-Axis of Charts */
|
||||
$js_messages['strTotalCount'] = __('Total count');
|
||||
|
||||
/* For server_privileges.js */
|
||||
$js_messages['strHostEmpty'] = __('The host name is empty!');
|
||||
$js_messages['strUserEmpty'] = __('The user name is empty!');
|
||||
@ -56,6 +60,18 @@ $js_messages['strReloadingPrivileges'] = __('Reloading Privileges');
|
||||
$js_messages['strRemovingSelectedUsers'] = __('Removing Selected Users');
|
||||
$js_messages['strClose'] = __('Close');
|
||||
|
||||
/* for server_status.js */
|
||||
$js_messages['strRealtimeChart'] = __('Realtime chart');
|
||||
$js_messages['strStaticData'] = __('Static data');
|
||||
/* l10n: Total number of queries */
|
||||
$js_messages['strTotal'] = __('Total');
|
||||
/* l10n: Other, small valued, queries */
|
||||
$js_messages['strOther'] = __('Other');
|
||||
/* l10n: Thousands separator */
|
||||
$js_messages['strThousandsSeperator'] = __(',');
|
||||
/* l10n: Decimal separator */
|
||||
$js_messages['strDecimalSeperator'] = __('.');
|
||||
|
||||
/* For inline query editing */
|
||||
$js_messages['strGo'] = __('Go');
|
||||
$js_messages['strCancel'] = __('Cancel');
|
||||
|
||||
164
js/pMap.js
164
js/pMap.js
@ -1,164 +0,0 @@
|
||||
/**
|
||||
* Holds the definition and the creation of the imageMap object
|
||||
* @author Martynas Mickevicius <mmartynas@gmail.com>
|
||||
* @package phpMyAdmin
|
||||
*/
|
||||
|
||||
/**
|
||||
* responsible for showing tooltips above the image chart
|
||||
*/
|
||||
var imageMap = {
|
||||
'mouseMoved': function(event, cont) {
|
||||
// return if no imageMap set
|
||||
// this can happen if server has no json
|
||||
if (!this.imageMap) {
|
||||
return;
|
||||
}
|
||||
|
||||
// get mouse coordinated relative to image
|
||||
var mouseX = event.pageX - cont.offsetLeft;
|
||||
var mouseY = event.pageY - cont.offsetTop;
|
||||
|
||||
//console.log("X: " + mouseX + ", Y: " + mouseY);
|
||||
|
||||
/* Check if we are flying over a map zone
|
||||
* Lets use the following method to check if a given
|
||||
* point is in any convex polygon.
|
||||
* http://www.programmingforums.org/post168124-3.html
|
||||
*/
|
||||
var found = false;
|
||||
for (var key = 0; key < this.imageMap.length; key++)
|
||||
{
|
||||
var seriesName = this.imageMap[key]['n'];
|
||||
var seriesValue = this.imageMap[key]['v'];
|
||||
|
||||
var signSum = 0;
|
||||
for (var i = 0; i < this.imageMap[key]['p'].length; i++)
|
||||
{
|
||||
var index1;
|
||||
var index2;
|
||||
|
||||
if (i == this.imageMap[key]['p'].length - 1)
|
||||
{
|
||||
index1 = i;
|
||||
index2 = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
index1 = i;
|
||||
index2 = i+1;
|
||||
}
|
||||
var result = this.getDeterminant(
|
||||
this.imageMap[key]['p'][index1][0],
|
||||
this.imageMap[key]['p'][index1][1],
|
||||
this.imageMap[key]['p'][index2][0],
|
||||
this.imageMap[key]['p'][index2][1],
|
||||
mouseX,
|
||||
mouseY
|
||||
);
|
||||
if (result > 0) { signSum += 1; } else { signSum += -1; }
|
||||
}
|
||||
|
||||
if (Math.abs(signSum) == this.imageMap[key]['p'].length)
|
||||
{
|
||||
found = true;
|
||||
if (this.currentKey != key)
|
||||
{
|
||||
this.tooltip.show();
|
||||
this.tooltip.title(seriesName);
|
||||
this.tooltip.text(seriesValue);
|
||||
this.currentKey = key;
|
||||
}
|
||||
this.tooltip.move(mouseX + 20, mouseY + 20);
|
||||
}
|
||||
}
|
||||
if (!found && this.currentKey != -1 )
|
||||
{
|
||||
this.tooltip.hide();
|
||||
this.currentKey = -1;
|
||||
}
|
||||
},
|
||||
|
||||
'getDeterminant': function (X1, Y1, X2, Y2, X3, Y3) {
|
||||
return (X2*Y3 - X3*Y2) - (X1*Y3 - X3*Y1) + (X1*Y2 - X2*Y1);
|
||||
},
|
||||
|
||||
'loadImageMap': function(map) {
|
||||
this.imageMap = JSON.parse(map);
|
||||
for (key in this.imageMap)
|
||||
{
|
||||
// FIXME
|
||||
// without this loop image map does not work
|
||||
// on IE8 in the status page
|
||||
}
|
||||
},
|
||||
|
||||
'init': function() {
|
||||
this.tooltip.init();
|
||||
|
||||
$("div#chart").bind('mousemove',function(e) {
|
||||
imageMap.mouseMoved(e, this);
|
||||
});
|
||||
|
||||
this.tooltip.attach("div#chart");
|
||||
|
||||
this.currentKey = -1;
|
||||
},
|
||||
|
||||
'tooltip': {
|
||||
'init': function () {
|
||||
this.el = $('<div></div>');
|
||||
this.el.css('position', 'absolute');
|
||||
this.el.css('font-family', 'tahoma');
|
||||
this.el.css('background-color', '#373737');
|
||||
this.el.css('color', '#BEBEBE');
|
||||
this.el.css('padding', '3px');
|
||||
|
||||
var title = $('<p></p>');
|
||||
title.attr('id', 'title');
|
||||
title.css('margin', '0px');
|
||||
title.css('padding', '3px');
|
||||
title.css('background-color', '#606060');
|
||||
title.css('text-align', 'center');
|
||||
title.html('Title');
|
||||
this.el.append(title);
|
||||
|
||||
var text = $('<p></p>');
|
||||
text.attr('id', 'text');
|
||||
text.css('margin', '0');
|
||||
text.html('Text');
|
||||
this.el.append(text);
|
||||
|
||||
this.hide();
|
||||
},
|
||||
|
||||
'attach': function (element) {
|
||||
$(element).prepend(this.el);
|
||||
},
|
||||
|
||||
'move': function (x, y) {
|
||||
this.el.css('margin-left', x);
|
||||
this.el.css('margin-top', y);
|
||||
},
|
||||
|
||||
'hide': function () {
|
||||
this.el.css('display', 'none');
|
||||
},
|
||||
|
||||
'show': function () {
|
||||
this.el.css('display', 'block');
|
||||
},
|
||||
|
||||
'title': function (title) {
|
||||
this.el.find("p#title").html(title);
|
||||
},
|
||||
|
||||
'text': function (text) {
|
||||
this.el.find("p#text").html(text.replace(/;/g, "<br />"));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
$(document).ready(function() {
|
||||
imageMap.init();
|
||||
});
|
||||
373
js/server_status.js
Normal file
373
js/server_status.js
Normal file
@ -0,0 +1,373 @@
|
||||
/* vim: set expandtab sw=4 ts=4 sts=4: */
|
||||
/**
|
||||
* @fileoverview functions used in server status pages
|
||||
* @name Server Status
|
||||
*
|
||||
* @requires jQuery
|
||||
* @requires jQueryUI
|
||||
* @requires jQueryCookie
|
||||
* @requires jQueryTablesorter
|
||||
* @requires Highcharts
|
||||
* @requires canvg
|
||||
* @requires js/functions.js
|
||||
*
|
||||
*/
|
||||
|
||||
// Add a tablesorter parser to properly handle thousands seperated numbers and SI prefixes
|
||||
$(function() {
|
||||
jQuery.tablesorter.addParser({
|
||||
id: "fancyNumber",
|
||||
is: function(s) {
|
||||
return /^[0-9]?[0-9,\.]*\s?(k|M|G|T|%)?$/.test(s);
|
||||
},
|
||||
format: function(s) {
|
||||
var num = jQuery.tablesorter.formatFloat( s.replace(PMA_messages['strThousandsSeperator'],'').replace(PMA_messages['strDecimalSeperator'],'.') );
|
||||
var factor = 1;
|
||||
switch (s.charAt(s.length-1)) {
|
||||
case '%': factor = -2; break;
|
||||
// Todo: Complete this list (as well as in the regexp a few lines up)
|
||||
case 'k': factor = 3; break;
|
||||
case 'M': factor = 6; break;
|
||||
case 'G': factor = 9; break;
|
||||
case 'T': factor = 12; break;
|
||||
}
|
||||
return num*Math.pow(10,factor);
|
||||
},
|
||||
type: "numeric"
|
||||
});
|
||||
});
|
||||
|
||||
$(function() {
|
||||
// Filters for status variables
|
||||
var textFilter=null;
|
||||
var alertFilter = false;
|
||||
var categoryFilter='';
|
||||
var odd_row=false;
|
||||
var text=''; // Holds filter text
|
||||
var queryPieChart = null;
|
||||
/* Chart configuration */
|
||||
|
||||
// Defines what the tabs are currently displaying (realtime or data)
|
||||
var tabStatus = new Object();
|
||||
// Holds the current chart instances for each tab
|
||||
var tabChart = new Object();
|
||||
|
||||
// Add tabs
|
||||
$('#serverStatusTabs').tabs({
|
||||
// Tab persistence
|
||||
cookie: { name: 'pma_serverStatusTabs', expires: 1 },
|
||||
// Fixes line break in the menu bar when the page overflows and scrollbar appears
|
||||
show: function() { menuResize(); }
|
||||
});
|
||||
|
||||
// Fixes wrong tab height with floated elements. See also http://bugs.jqueryui.com/ticket/5601
|
||||
$(".ui-widget-content:not(.ui-tabs):not(.ui-helper-clearfix)").addClass("ui-helper-clearfix");
|
||||
|
||||
// Initialize each tab
|
||||
$('div.ui-tabs-panel').each(function() { initTab($(this),null); });
|
||||
|
||||
$('.statuslinks select').change(function() {
|
||||
var chart=tabChart[$(this).parents('div.ui-tabs-panel').attr('id')];
|
||||
chart.options.realtime.refreshRate = 1000*parseInt(this.value);
|
||||
chart.xAxis[0].setExtremes(new Date().getTime() - chart.options.realtime.numMaxPoints * chart.options.realtime.refreshRate, chart.xAxis[0].getExtremes().max, true);
|
||||
clearTimeout(chart_activeTimeouts[chart.options.chart.renderTo]);
|
||||
chart_activeTimeouts[chart.options.chart.renderTo] = setTimeout(chart.options.realtime.timeoutCallBack, chart.options.realtime.refreshRate);
|
||||
});
|
||||
|
||||
// Ajax refresh of variables (always the first element in each tab)
|
||||
$('.statuslinks a.tabRefresh').click(function() {
|
||||
// ui-tabs-panel class is added by the jquery tabs feature
|
||||
var tab=$(this).parents('div.ui-tabs-panel');
|
||||
var that = this;
|
||||
|
||||
// Show ajax load icon
|
||||
$(this).find('img').show();
|
||||
|
||||
$.get($(this).attr('href'),{ajax_request:1},function(data) {
|
||||
$(that).find('img').hide();
|
||||
initTab(tab,data);
|
||||
});
|
||||
|
||||
tabStatus[tab.attr('id')]='data';
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
/** Realtime charting of variables (always the third element) **/
|
||||
$('.statuslinks a.tabChart').click(function() {
|
||||
// ui-tabs-panel class is added by the jquery tabs feature
|
||||
var tab=$(this).parents('div.ui-tabs-panel');
|
||||
|
||||
if(tabStatus[tab.attr('id')]!='realtime') {
|
||||
var series, title;
|
||||
var settings = new Object();
|
||||
|
||||
switch(tab.attr('id')) {
|
||||
case 'statustabs_traffic':
|
||||
settings = {
|
||||
series: [{name:'Connections since last refresh', data:[]},{name:'Processes', data:[]}],
|
||||
title: {text:'Connections / Processes'},
|
||||
realtime:{ url:'server_status.php?'+url_query,
|
||||
type: 'proc',
|
||||
callback: function(chartObj, curVal, lastVal,numLoadedPoints) {
|
||||
if(lastVal==null) return;
|
||||
chartObj.series[0].addPoint(
|
||||
{ x:curVal.x, y:curVal.y_conn-lastVal.y_conn },
|
||||
false, numLoadedPoints >= chartObj.options.realtime.numMaxPoints
|
||||
);
|
||||
chartObj.series[1].addPoint(
|
||||
{ x:curVal.x, y:curVal.y_proc },
|
||||
true, numLoadedPoints >= chartObj.options.realtime.numMaxPoints
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
||||
break;
|
||||
case 'statustabs_queries':
|
||||
settings = {
|
||||
series: [{name:'Issued queries since last refresh', data:[]}],
|
||||
title: {text:'Issued queries'},
|
||||
tooltip: { formatter:function() { return this.point.name; } },
|
||||
realtime:{ url:'server_status.php?'+url_query,
|
||||
type: 'queries',
|
||||
callback: function(chartObj, curVal, lastVal,numLoadedPoints) {
|
||||
if(lastVal==null) return;
|
||||
chartObj.series[0].addPoint(
|
||||
{ x:curVal.x, y:curVal.y-lastVal.y, name:sortedQueriesPointInfo(curVal,lastVal) },
|
||||
true, numLoadedPoints >= chartObj.options.realtime.numMaxPoints
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
||||
break;
|
||||
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
if(!settings.chart) settings.chart = {};
|
||||
settings.chart.renderTo=tab.attr('id')+"_chart_cnt";
|
||||
|
||||
tab.find('.tabInnerContent')
|
||||
.hide()
|
||||
.after('<div style="clear:both; min-width:500px; height:400px; padding-bottom:80px;" id="'+tab.attr('id')+'_chart_cnt"></div>');
|
||||
tabStatus[tab.attr('id')]='realtime';
|
||||
tabChart[tab.attr('id')]=PMA_createChart(settings);
|
||||
$(this).html(PMA_messages['strStaticData']);
|
||||
tab.find('.statuslinks a.tabRefresh').hide();
|
||||
tab.find('.statuslinks select').show();
|
||||
} else {
|
||||
clearTimeout(chart_activeTimeouts[tab.attr('id')+"_chart_cnt"]);
|
||||
chart_activeTimeouts[tab.attr('id')+"_chart_cnt"]=null;
|
||||
tab.find('.tabInnerContent').show();
|
||||
tab.find('div#'+tab.attr('id')+'_chart_cnt').remove();
|
||||
tabStatus[tab.attr('id')]='data';
|
||||
tabChart[tab.attr('id')].destroy();
|
||||
$(this).html(PMA_messages['strRealtimeChart']);
|
||||
tab.find('.statuslinks a.tabRefresh').show();
|
||||
tab.find('.statuslinks select').hide();
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
|
||||
/* 3 Filtering functions */
|
||||
$('#filterAlert').change(function() {
|
||||
alertFilter = this.checked;
|
||||
filterVariables();
|
||||
});
|
||||
|
||||
$('#filterText').keyup(function(e) {
|
||||
if($(this).val().length==0) textFilter=null;
|
||||
else textFilter = new RegExp("(^|_)"+$(this).val(),'i');
|
||||
text=$(this).val();
|
||||
filterVariables();
|
||||
});
|
||||
|
||||
$('#filterCategory').change(function() {
|
||||
categoryFilter = $(this).val();
|
||||
filterVariables();
|
||||
});
|
||||
|
||||
/* Adjust DOM / Add handlers to the tabs */
|
||||
function initTab(tab,data) {
|
||||
switch(tab.attr('id')) {
|
||||
case 'statustabs_traffic':
|
||||
if(data!=null) tab.find('.tabInnerContent').html(data);
|
||||
initTooltips();
|
||||
break;
|
||||
case 'statustabs_queries':
|
||||
if(data!=null) {
|
||||
queryPieChart.destroy();
|
||||
tab.find('.tabInnerContent').html(data);
|
||||
}
|
||||
|
||||
// Build query statistics chart
|
||||
var cdata = new Array();
|
||||
$.each(jQuery.parseJSON($('#serverstatusquerieschart').html()),function(key,value) {
|
||||
cdata.push([key,parseInt(value)]);
|
||||
});
|
||||
|
||||
queryPieChart=PMA_createChart({
|
||||
chart: {
|
||||
renderTo: 'serverstatusquerieschart'
|
||||
|
||||
},
|
||||
title: {
|
||||
text:'',
|
||||
margin:0
|
||||
},
|
||||
series: [{
|
||||
type:'pie',
|
||||
name: 'Query statistics',
|
||||
data: cdata
|
||||
}],
|
||||
plotOptions: {
|
||||
pie: {
|
||||
allowPointSelect: true,
|
||||
cursor: 'pointer',
|
||||
dataLabels: {
|
||||
enabled: true,
|
||||
formatter: function() {
|
||||
return '<b>'+ this.point.name +'</b><br> '+ Highcharts.numberFormat(this.percentage, 2) +' %';
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
tooltip: {
|
||||
formatter: function() { return '<b>'+ this.point.name +'</b><br/>'+Highcharts.numberFormat(this.y, 2)+'<br/>('+Highcharts.numberFormat(this.percentage, 2) +' %)'; }
|
||||
}
|
||||
});
|
||||
break;
|
||||
|
||||
case 'statustabs_allvars':
|
||||
if(data!=null) {
|
||||
tab.find('.tabInnerContent').html(data);
|
||||
filterVariables();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
initTableSorter(tab.attr('id'));
|
||||
}
|
||||
|
||||
function initTableSorter(tabid) {
|
||||
switch(tabid) {
|
||||
case 'statustabs_queries':
|
||||
$('#serverstatusqueriesdetails').tablesorter({
|
||||
sortList: [[3,1]],
|
||||
widgets: ['zebra'],
|
||||
headers: {
|
||||
1: { sorter: 'fancyNumber' },
|
||||
2: { sorter: 'fancyNumber' }
|
||||
}
|
||||
});
|
||||
|
||||
$('#serverstatusqueriesdetails tr:first th')
|
||||
.append('<img class="sortableIcon" src="'+pma_theme_image+'cleardot.gif" alt="">');
|
||||
|
||||
break;
|
||||
|
||||
case 'statustabs_allvars':
|
||||
$('#serverstatusvariables').tablesorter({
|
||||
sortList: [[0,0]],
|
||||
widgets: ['zebra'],
|
||||
headers: {
|
||||
1: { sorter: 'fancyNumber' }
|
||||
}
|
||||
});
|
||||
|
||||
$('#serverstatusvariables tr:first th')
|
||||
.append('<img class="sortableIcon" src="'+pma_theme_image+'cleardot.gif" alt="">');
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Filters the status variables by name/category/alert in the variables tab */
|
||||
function filterVariables() {
|
||||
var useful_links=0;
|
||||
var section = text;
|
||||
|
||||
if(categoryFilter.length>0) section = categoryFilter;
|
||||
|
||||
if(section.length>1) {
|
||||
$('#linkSuggestions span').each(function() {
|
||||
if($(this).attr('class').indexOf('status_'+section)!=-1) {
|
||||
useful_links++;
|
||||
$(this).css('display','');
|
||||
} else {
|
||||
$(this).css('display','none');
|
||||
}
|
||||
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
if(useful_links>0)
|
||||
$('#linkSuggestions').css('display','');
|
||||
else $('#linkSuggestions').css('display','none');
|
||||
|
||||
odd_row=false;
|
||||
$('#serverstatusvariables th.name').each(function() {
|
||||
if((textFilter==null || textFilter.exec($(this).text()))
|
||||
&& (!alertFilter || $(this).next().find('span.attention').length>0)
|
||||
&& (categoryFilter.length==0 || $(this).parent().hasClass('s_'+categoryFilter))) {
|
||||
odd_row = !odd_row;
|
||||
$(this).parent().css('display','');
|
||||
if(odd_row) {
|
||||
$(this).parent().addClass('odd');
|
||||
$(this).parent().removeClass('even');
|
||||
} else {
|
||||
$(this).parent().addClass('even');
|
||||
$(this).parent().removeClass('odd');
|
||||
}
|
||||
} else {
|
||||
$(this).parent().css('display','none');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Provides a nicely formatted and sorted tooltip of each datapoint of the query statistics
|
||||
function sortedQueriesPointInfo(queries, lastQueries){
|
||||
var max, maxIdx, num=0;
|
||||
var queryKeys = new Array();
|
||||
var queryValues = new Array();
|
||||
var sumOther=0;
|
||||
var sumTotal=0;
|
||||
|
||||
// Separate keys and values, then sort them
|
||||
$.each(queries.pointInfo, function(key,value) {
|
||||
if(value-lastQueries.pointInfo[key] > 0) {
|
||||
queryKeys.push(key);
|
||||
queryValues.push(value-lastQueries.pointInfo[key]);
|
||||
sumTotal+=value-lastQueries.pointInfo[key];
|
||||
}
|
||||
});
|
||||
var numQueries = queryKeys.length;
|
||||
var pointInfo = '<b>' + PMA_messages['strTotal'] + ': ' + sumTotal + '</b><br>';
|
||||
|
||||
while(queryKeys.length > 0) {
|
||||
max=0;
|
||||
for(var i=0; i<queryKeys.length; i++) {
|
||||
if(queryValues[i] > max) {
|
||||
max = queryValues[i];
|
||||
maxIdx = i;
|
||||
}
|
||||
}
|
||||
if(numQueries > 8 && num>=6)
|
||||
sumOther+=queryValues[maxIdx];
|
||||
else pointInfo += queryKeys[maxIdx].substr(4).replace('_',' ') + ': ' + queryValues[maxIdx] + '<br>';
|
||||
|
||||
queryKeys.splice(maxIdx,1);
|
||||
queryValues.splice(maxIdx,1);
|
||||
num++;
|
||||
}
|
||||
|
||||
if(sumOther>0)
|
||||
pointInfo += PMA_messages['strOther'] + ': ' + sumOther;
|
||||
|
||||
return pointInfo;
|
||||
}
|
||||
|
||||
});
|
||||
42
js/server_variables.js
Normal file
42
js/server_variables.js
Normal file
@ -0,0 +1,42 @@
|
||||
$(function() {
|
||||
var textFilter=null;
|
||||
var odd_row=false;
|
||||
|
||||
// Filter options are invisible for disabled js users
|
||||
$('fieldset#tableFilter').css('display','');
|
||||
|
||||
$('#filterText').keyup(function(e) {
|
||||
if($(this).val().length==0) textFilter=null;
|
||||
else textFilter = new RegExp("(^| )"+$(this).val(),'i');
|
||||
filterVariables();
|
||||
});
|
||||
|
||||
function filterVariables() {
|
||||
odd_row=false;
|
||||
var mark_next=false;
|
||||
var firstCell;
|
||||
|
||||
$('table.filteredData tbody tr').each(function() {
|
||||
firstCell = $(this).children(':first');
|
||||
|
||||
if(mark_next || textFilter==null || textFilter.exec(firstCell.text())) {
|
||||
// If current row is 'marked', also display next row
|
||||
if($(this).hasClass('marked') && !mark_next)
|
||||
mark_next=true;
|
||||
else mark_next=false;
|
||||
|
||||
odd_row = !odd_row;
|
||||
$(this).css('display','');
|
||||
if(odd_row) {
|
||||
$(this).addClass('odd');
|
||||
$(this).removeClass('even');
|
||||
} else {
|
||||
$(this).addClass('even');
|
||||
$(this).removeClass('odd');
|
||||
}
|
||||
} else {
|
||||
$(this).css('display','none');
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
47
js/sql.js
47
js/sql.js
@ -1155,6 +1155,51 @@ $(document).ready(function() {
|
||||
$('.column_heading.marker').live('click', function() {
|
||||
PMA_changeClassForColumn($(this), 'marked');
|
||||
});
|
||||
})
|
||||
});
|
||||
|
||||
/*
|
||||
* Profiling Chart
|
||||
*/
|
||||
function createProfilingChart() {
|
||||
if($('#profilingchart').length==0) return;
|
||||
|
||||
var cdata = new Array();
|
||||
$.each(jQuery.parseJSON($('#profilingchart').html()),function(key,value) {
|
||||
cdata.push([key,parseFloat(value)]);
|
||||
});
|
||||
|
||||
// Prevent the user from seeing the JSON code
|
||||
$('div#profilingchart').html('').show();
|
||||
|
||||
PMA_createChart({
|
||||
chart: {
|
||||
renderTo: 'profilingchart',
|
||||
backgroundColor: $('#sqlqueryresults fieldset').css('background-color')
|
||||
},
|
||||
title: { text:'', margin:0 },
|
||||
series: [{
|
||||
type:'pie',
|
||||
name: 'Query execution time',
|
||||
data: cdata
|
||||
}],
|
||||
plotOptions: {
|
||||
pie: {
|
||||
allowPointSelect: true,
|
||||
cursor: 'pointer',
|
||||
dataLabels: {
|
||||
enabled: true,
|
||||
distance: 35,
|
||||
formatter: function() {
|
||||
return '<b>'+ this.point.name +'</b><br/>'+ Highcharts.numberFormat(this.percentage, 2) +' %';
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
tooltip: {
|
||||
formatter: function() { return '<b>'+ this.point.name +'</b><br/>'+this.y+'s<br/>('+Highcharts.numberFormat(this.percentage, 2) +' %)'; }
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/**#@- */
|
||||
|
||||
236
js/tbl_chart.js
Normal file
236
js/tbl_chart.js
Normal file
@ -0,0 +1,236 @@
|
||||
var chart_xaxis_idx = -1;
|
||||
var chart_series;
|
||||
var chart_series_index = -1;
|
||||
|
||||
$(document).ready(function() {
|
||||
var currentChart=null;
|
||||
var chart_data = jQuery.parseJSON($('#querychart').html());
|
||||
chart_series = 'columns';
|
||||
chart_xaxis_idx = $('select[name="chartXAxis"]').attr('value');
|
||||
|
||||
$('#resizer').resizable({
|
||||
minHeight:240,
|
||||
minWidth:300,
|
||||
// On resize, set the chart size to that of the
|
||||
// resizer minus padding. If your chart has a lot of data or other
|
||||
// content, the redrawing might be slow. In that case, we recommend
|
||||
// that you use the 'stop' event instead of 'resize'.
|
||||
resize: function() {
|
||||
currentChart.setSize(
|
||||
this.offsetWidth - 20,
|
||||
this.offsetHeight - 20,
|
||||
false
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
var currentSettings = {
|
||||
chart: {
|
||||
type:'line',
|
||||
width:$('#resizer').width()-20,
|
||||
height:$('#resizer').height()-20
|
||||
},
|
||||
xAxis: {
|
||||
title: { text: $('input[name="xaxis_label"]').attr('value') }
|
||||
},
|
||||
yAxis: {
|
||||
title: { text: $('input[name="yaxis_label"]').attr('value') }
|
||||
},
|
||||
title: { text: $('input[name="chartTitle"]').attr('value'), margin:20 },
|
||||
plotOptions: {
|
||||
series: {}
|
||||
}
|
||||
}
|
||||
|
||||
$('#querychart').html('');
|
||||
|
||||
$('input[name="chartType"]').click(function() {
|
||||
currentSettings.chart.type=$(this).attr('value');
|
||||
|
||||
drawChart();
|
||||
|
||||
if($(this).attr('value')=='bar' || $(this).attr('value')=='column')
|
||||
$('span.barStacked').show();
|
||||
else
|
||||
$('span.barStacked').hide();
|
||||
});
|
||||
|
||||
$('input[name="barStacked"]').click(function() {
|
||||
if(this.checked)
|
||||
$.extend(true,currentSettings,{ plotOptions: { series: { stacking:'normal' } } });
|
||||
else
|
||||
$.extend(true,currentSettings,{ plotOptions: { series: { stacking:null } } });
|
||||
drawChart();
|
||||
});
|
||||
|
||||
$('input[name="chartTitle"]').keyup(function() {
|
||||
var title=$(this).attr('value');
|
||||
if(title.length==0) title=' ';
|
||||
currentChart.setTitle({text: title});
|
||||
});
|
||||
|
||||
$('select[name="chartXAxis"]').change(function() {
|
||||
chart_xaxis_idx = this.value;
|
||||
drawChart();
|
||||
});
|
||||
$('select[name="chartSeries"]').change(function() {
|
||||
chart_series = this.value;
|
||||
chart_series_index = this.selectedIndex;
|
||||
drawChart();
|
||||
});
|
||||
|
||||
/* Sucks, we cannot just set axis labels, we have to redraw the chart completely */
|
||||
$('input[name="xaxis_label"]').keyup(function() {
|
||||
currentSettings.xAxis.title.text = $(this).attr('value');
|
||||
drawChart(true);
|
||||
});
|
||||
$('input[name="yaxis_label"]').keyup(function() {
|
||||
currentSettings.yAxis.title.text = $(this).attr('value');
|
||||
drawChart(true);
|
||||
});
|
||||
|
||||
function drawChart(noAnimation) {
|
||||
currentSettings.chart.width=$('#resizer').width()-20;
|
||||
currentSettings.chart.height=$('#resizer').height()-20;
|
||||
|
||||
if(currentChart!=null) currentChart.destroy();
|
||||
|
||||
if(noAnimation) currentSettings.plotOptions.series.animation = false;
|
||||
currentChart = PMA_queryChart(chart_data,currentSettings);
|
||||
if(noAnimation) currentSettings.plotOptions.series.animation = true;
|
||||
}
|
||||
|
||||
drawChart();
|
||||
$('#querychart').show();
|
||||
});
|
||||
|
||||
function in_array(element,array) {
|
||||
for(var i=0; i<array.length; i++)
|
||||
if(array[i]==element) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
function PMA_queryChart(data,passedSettings) {
|
||||
if($('#querychart').length==0) return;
|
||||
|
||||
var columnNames = Array();
|
||||
|
||||
var series = new Array();
|
||||
var xaxis = new Object();
|
||||
var yaxis = new Object();
|
||||
|
||||
$.each(data[0],function(index,element) {
|
||||
columnNames.push(index);
|
||||
});
|
||||
|
||||
switch(passedSettings.chart.type) {
|
||||
case 'column':
|
||||
case 'spline':
|
||||
case 'line':
|
||||
case 'bar':
|
||||
xaxis.categories = new Array();
|
||||
|
||||
if(chart_series=='columns') {
|
||||
var j=0;
|
||||
for(var i=0; i<columnNames.length; i++)
|
||||
if(i!=chart_xaxis_idx) {
|
||||
series[j] = new Object();
|
||||
series[j].data = new Array();
|
||||
series[j].name = columnNames[i];
|
||||
$.each(data,function(key,value) {
|
||||
series[j].data.push(parseFloat(value[columnNames[i]]));
|
||||
if(j==0 && chart_xaxis_idx!=-1 && !xaxis.categories[value[columnNames[chart_xaxis_idx]]])
|
||||
xaxis.categories.push(value[columnNames[chart_xaxis_idx]]);
|
||||
});
|
||||
j++;
|
||||
}
|
||||
} else {
|
||||
var j=0;
|
||||
var seriesIndex = new Object();
|
||||
// Get series types and build series object from the query data
|
||||
$.each(data,function(index,element) {
|
||||
var contains=false;
|
||||
for(var i=0; i<series.length; i++)
|
||||
if(series[i].name == element[chart_series]) contains=true;
|
||||
|
||||
if(!contains) {
|
||||
seriesIndex[element[chart_series]] = j;
|
||||
series[j] = new Object();
|
||||
series[j].data = new Array();
|
||||
series[j].name = element[chart_series]; // columnNames[i];
|
||||
j++;
|
||||
}
|
||||
});
|
||||
|
||||
var type;
|
||||
// Get series points from query data
|
||||
$.each(data,function(key,value) {
|
||||
type = value[chart_series];
|
||||
series[seriesIndex[type]].data.push(parseFloat(value[columnNames[0]]));
|
||||
if(!in_array(value[columnNames[chart_xaxis_idx]],xaxis.categories))
|
||||
xaxis.categories.push(value[columnNames[chart_xaxis_idx]]);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
if(columnNames.length==2)
|
||||
yaxis.title = { text: columnNames[0] };
|
||||
break;
|
||||
|
||||
case 'pie':
|
||||
series[0] = new Object();
|
||||
series[0].data = new Array();
|
||||
$.each(data,function(key,value) {
|
||||
series[0].data.push({name:value[columnNames[chart_xaxis_idx]],y:parseFloat(value[columnNames[0]])});
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
||||
// Prevent the user from seeing the JSON code
|
||||
$('div#profilingchart').html('').show();
|
||||
|
||||
var settings = {
|
||||
chart: {
|
||||
renderTo: 'querychart',
|
||||
backgroundColor: $('fieldset').css('background-color')
|
||||
},
|
||||
title: { text:'', margin:0 },
|
||||
series: series,
|
||||
xAxis: xaxis,
|
||||
yAxis: yaxis,
|
||||
plotOptions: {
|
||||
pie: {
|
||||
allowPointSelect: true,
|
||||
cursor: 'pointer',
|
||||
dataLabels: {
|
||||
enabled: true,
|
||||
distance: 35,
|
||||
formatter: function() {
|
||||
return '<b>'+ this.point.name +'</b><br/>'+ Highcharts.numberFormat(this.percentage, 2) +' %';
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
credits: {
|
||||
enabled:false
|
||||
},
|
||||
exporting: {
|
||||
enabled: true
|
||||
},
|
||||
tooltip: {
|
||||
formatter: function() {
|
||||
if(this.point.name) return '<b>'+this.series.name+'</b><br/>'+this.point.name+'<br/>'+this.y;
|
||||
return '<b>'+this.series.name+'</b><br/>'+this.y;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if(passedSettings.chart.type=='pie')
|
||||
settings.tooltip.formatter = function() { return '<b>'+columnNames[0]+'</b><br/>'+this.y; }
|
||||
|
||||
// Overwrite/Merge default settings with passedsettings
|
||||
$.extend(true,settings,passedSettings);
|
||||
|
||||
return new Highcharts.Chart(settings);
|
||||
}
|
||||
@ -1,256 +0,0 @@
|
||||
<?php
|
||||
/* vim: set expandtab sw=4 ts=4 sts=4: */
|
||||
/**
|
||||
* Chart functions used to generate various types of charts.
|
||||
* @package phpMyAdmin
|
||||
*/
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
define('ERR_NO_GD', 0);
|
||||
define('ERR_NO_JSON', 1);
|
||||
|
||||
require_once './libraries/chart/pma_pchart_pie.php';
|
||||
require_once './libraries/chart/pma_pchart_single_bar.php';
|
||||
require_once './libraries/chart/pma_pchart_multi_bar.php';
|
||||
require_once './libraries/chart/pma_pchart_stacked_bar.php';
|
||||
require_once './libraries/chart/pma_pchart_single_line.php';
|
||||
require_once './libraries/chart/pma_pchart_multi_line.php';
|
||||
require_once './libraries/chart/pma_pchart_single_radar.php';
|
||||
require_once './libraries/chart/pma_pchart_multi_radar.php';
|
||||
|
||||
/**
|
||||
* Formats a chart for the status page.
|
||||
* @param array $data data for the status chart
|
||||
* @return string HTML and JS code for the chart
|
||||
*/
|
||||
function PMA_chart_status($data)
|
||||
{
|
||||
// format keys which will be shown in the chart
|
||||
$chartData = array();
|
||||
foreach($data as $dataKey => $dataValue) {
|
||||
$key = ucwords(str_replace(array('Com_', '_'), array('', ' '), $dataKey));
|
||||
$value = (int)$dataValue;
|
||||
$chartData[$key] = $value;
|
||||
}
|
||||
|
||||
$chart = new PMA_pChart_Pie(
|
||||
$chartData,
|
||||
array('titleText' => __('Query statistics'))
|
||||
);
|
||||
$chartCode = $chart->toString();
|
||||
PMA_handle_chart_err($chart->getErrors());
|
||||
echo $chartCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats a chart for the profiling page.
|
||||
* @param array $data data for the status chart
|
||||
* @return string HTML and JS code for the chart
|
||||
*/
|
||||
function PMA_chart_profiling($data)
|
||||
{
|
||||
$chartData = array();
|
||||
foreach($data as $dataValue) {
|
||||
$value = (int)($dataValue['Duration'] * 1000000);
|
||||
$key = ucwords($dataValue['Status']);
|
||||
$chartData[$key] = $value;
|
||||
}
|
||||
|
||||
$chart = new PMA_pChart_Pie(
|
||||
$chartData,
|
||||
array('titleText' => __('Query execution time comparison (in microseconds)'))
|
||||
);
|
||||
$chartCode = $chart->toString();
|
||||
PMA_handle_chart_err($chart->getErrors());
|
||||
echo $chartCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats a chart for the query results page.
|
||||
* @param array $data data for the status chart
|
||||
* @param array $chartSettings settings used to generate the chart
|
||||
* @return string HTML and JS code for the chart
|
||||
*/
|
||||
function PMA_chart_results($data, &$chartSettings)
|
||||
{
|
||||
$chartData = array();
|
||||
$chart = null;
|
||||
|
||||
// set default title if not already set
|
||||
if (empty($chartSettings['titleText'])) {
|
||||
$chartSettings['titleText'] = __('Query results');
|
||||
}
|
||||
|
||||
// set default type if not already set
|
||||
if (empty($chartSettings['type'])) {
|
||||
$chartSettings['type'] = 'bar';
|
||||
}
|
||||
|
||||
// set default type if not already set
|
||||
if (empty($chartSettings['continuous'])) {
|
||||
$chartSettings['continuous'] = 'off';
|
||||
}
|
||||
|
||||
// set default bar type if needed
|
||||
if ($chartSettings['type'] == 'bar' && empty($chartSettings['barType'])) {
|
||||
$chartSettings['barType'] = 'stacked';
|
||||
}
|
||||
|
||||
// default for legend
|
||||
$chartSettings['legend'] = false;
|
||||
|
||||
// default for muti series
|
||||
$chartSettings['multi'] = false;
|
||||
|
||||
if (! isset($data[0])) {
|
||||
// empty data
|
||||
return __('No data found for the chart.');
|
||||
}
|
||||
|
||||
if (count($data[0]) == 1 || count($data[0]) == 2) {
|
||||
// One or two columns in every row.
|
||||
// This data is suitable for a simple bar chart.
|
||||
|
||||
if ($chartSettings['type'] == 'pie') {
|
||||
// loop through the rows, data for pie chart has to be formated
|
||||
// in a different way then in other charts.
|
||||
foreach ($data as $rowKey => $row) {
|
||||
$values = array_values($row);
|
||||
|
||||
if (count($row) == 1) {
|
||||
$chartData[$rowKey] = $values[0];
|
||||
}
|
||||
else {
|
||||
$chartData[$values[1]] = $values[0];
|
||||
}
|
||||
}
|
||||
|
||||
$chartSettings['legend'] = true;
|
||||
$chart = new PMA_pChart_pie($chartData, $chartSettings);
|
||||
}
|
||||
else {
|
||||
// loop through the rows
|
||||
foreach ($data as $rowKey => $row) {
|
||||
|
||||
// loop through the columns in the row
|
||||
foreach ($row as $valueKey => $value) {
|
||||
$chartData[$valueKey][] = $value;
|
||||
}
|
||||
|
||||
// if only one column, we need to add
|
||||
// placeholder data for x axis
|
||||
if (count($row) == 1) {
|
||||
$chartData[''][] = $rowKey;
|
||||
}
|
||||
}
|
||||
|
||||
switch ($chartSettings['type']) {
|
||||
case 'bar':
|
||||
default:
|
||||
$chart = new PMA_pChart_single_bar($chartData, $chartSettings);
|
||||
break;
|
||||
case 'line':
|
||||
$chart = new PMA_pChart_single_line($chartData, $chartSettings);
|
||||
break;
|
||||
case 'radar':
|
||||
$chart = new PMA_pChart_single_radar($chartData, $chartSettings);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (count($data[0]) == 3) {
|
||||
// Three columns (x axis, y axis, series) in every row.
|
||||
// This data is suitable for a stacked bar chart.
|
||||
$chartSettings['multi'] = true;
|
||||
|
||||
$keys = array_keys($data[0]);
|
||||
$yAxisKey = $keys[0];
|
||||
$xAxisKey = $keys[1];
|
||||
$seriesKey = $keys[2];
|
||||
|
||||
// get all the series labels
|
||||
$seriesLabels = array();
|
||||
foreach ($data as $row) {
|
||||
$seriesLabels[] = $row[$seriesKey];
|
||||
}
|
||||
$seriesLabels = array_unique($seriesLabels);
|
||||
|
||||
// loop through the rows
|
||||
$currentXLabel = $data[0][$xAxisKey];
|
||||
foreach ($data as $row) {
|
||||
|
||||
// save the label
|
||||
// use the same value as the key and the value to get rid of duplicate results
|
||||
$chartData[$xAxisKey][$row[$xAxisKey]] = $row[$xAxisKey];
|
||||
|
||||
// make sure to set value to every serie
|
||||
$currentSeriesLabel = (string)$row[$seriesKey];
|
||||
foreach ($seriesLabels as $seriesLabelsValue) {
|
||||
if ($currentSeriesLabel == $seriesLabelsValue) {
|
||||
// the value os for this serie
|
||||
$chartData[$yAxisKey][$seriesLabelsValue][$row[$xAxisKey]] = (int)$row[$yAxisKey];
|
||||
}
|
||||
else if (! isset($chartData[$yAxisKey][$seriesLabelsValue][$row[$xAxisKey]])) {
|
||||
// if the value for this serie is not set, set it to 0
|
||||
$chartData[$yAxisKey][$seriesLabelsValue][$row[$xAxisKey]] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$chartSettings['legend'] = true;
|
||||
|
||||
// determine the chart type
|
||||
switch ($chartSettings['type']) {
|
||||
case 'bar':
|
||||
default:
|
||||
|
||||
// determine the bar chart type
|
||||
switch ($chartSettings['barType']) {
|
||||
case 'stacked':
|
||||
default:
|
||||
$chart = new PMA_pChart_stacked_bar($chartData, $chartSettings);
|
||||
break;
|
||||
case 'multi':
|
||||
$chart = new PMA_pChart_multi_bar($chartData, $chartSettings);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'line':
|
||||
$chart = new PMA_pChart_multi_line($chartData, $chartSettings);
|
||||
break;
|
||||
case 'radar':
|
||||
$chart = new PMA_pChart_multi_radar($chartData, $chartSettings);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// unknown data format
|
||||
return '';
|
||||
}
|
||||
|
||||
$chartCode = $chart->toString();
|
||||
$chartSettings = $chart->getSettings();
|
||||
$chartErrors = $chart->getErrors();
|
||||
PMA_handle_chart_err($chartErrors);
|
||||
|
||||
return $chartCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Simple handler of chart errors.
|
||||
* @param array $errors all occured errors
|
||||
*/
|
||||
function PMA_handle_chart_err($errors)
|
||||
{
|
||||
if (in_array(ERR_NO_GD, $errors)) {
|
||||
PMA_warnMissingExtension('GD', false, __('GD extension is needed for charts.'));
|
||||
}
|
||||
else if (in_array(ERR_NO_JSON, $errors)) {
|
||||
PMA_warnMissingExtension('JSON', false, __('JSON encoder is needed for chart tooltips.'));
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
Binary file not shown.
@ -1,99 +0,0 @@
|
||||
Fonts are (c) Bitstream (see below). DejaVu changes are in public domain.
|
||||
Glyphs imported from Arev fonts are (c) Tavmjong Bah (see below)
|
||||
|
||||
Bitstream Vera Fonts Copyright
|
||||
------------------------------
|
||||
|
||||
Copyright (c) 2003 by Bitstream, Inc. All Rights Reserved. Bitstream Vera is
|
||||
a trademark of Bitstream, Inc.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of the fonts accompanying this license ("Fonts") and associated
|
||||
documentation files (the "Font Software"), to reproduce and distribute the
|
||||
Font Software, including without limitation the rights to use, copy, merge,
|
||||
publish, distribute, and/or sell copies of the Font Software, and to permit
|
||||
persons to whom the Font Software is furnished to do so, subject to the
|
||||
following conditions:
|
||||
|
||||
The above copyright and trademark notices and this permission notice shall
|
||||
be included in all copies of one or more of the Font Software typefaces.
|
||||
|
||||
The Font Software may be modified, altered, or added to, and in particular
|
||||
the designs of glyphs or characters in the Fonts may be modified and
|
||||
additional glyphs or characters may be added to the Fonts, only if the fonts
|
||||
are renamed to names not containing either the words "Bitstream" or the word
|
||||
"Vera".
|
||||
|
||||
This License becomes null and void to the extent applicable to Fonts or Font
|
||||
Software that has been modified and is distributed under the "Bitstream
|
||||
Vera" names.
|
||||
|
||||
The Font Software may be sold as part of a larger software package but no
|
||||
copy of one or more of the Font Software typefaces may be sold by itself.
|
||||
|
||||
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT,
|
||||
TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL BITSTREAM OR THE GNOME
|
||||
FOUNDATION BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING
|
||||
ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES,
|
||||
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
|
||||
THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE
|
||||
FONT SOFTWARE.
|
||||
|
||||
Except as contained in this notice, the names of Gnome, the Gnome
|
||||
Foundation, and Bitstream Inc., shall not be used in advertising or
|
||||
otherwise to promote the sale, use or other dealings in this Font Software
|
||||
without prior written authorization from the Gnome Foundation or Bitstream
|
||||
Inc., respectively. For further information, contact: fonts at gnome dot
|
||||
org.
|
||||
|
||||
Arev Fonts Copyright
|
||||
------------------------------
|
||||
|
||||
Copyright (c) 2006 by Tavmjong Bah. All Rights Reserved.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of the fonts accompanying this license ("Fonts") and
|
||||
associated documentation files (the "Font Software"), to reproduce
|
||||
and distribute the modifications to the Bitstream Vera Font Software,
|
||||
including without limitation the rights to use, copy, merge, publish,
|
||||
distribute, and/or sell copies of the Font Software, and to permit
|
||||
persons to whom the Font Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright and trademark notices and this permission notice
|
||||
shall be included in all copies of one or more of the Font Software
|
||||
typefaces.
|
||||
|
||||
The Font Software may be modified, altered, or added to, and in
|
||||
particular the designs of glyphs or characters in the Fonts may be
|
||||
modified and additional glyphs or characters may be added to the
|
||||
Fonts, only if the fonts are renamed to names not containing either
|
||||
the words "Tavmjong Bah" or the word "Arev".
|
||||
|
||||
This License becomes null and void to the extent applicable to Fonts
|
||||
or Font Software that has been modified and is distributed under the
|
||||
"Tavmjong Bah Arev" names.
|
||||
|
||||
The Font Software may be sold as part of a larger software package but
|
||||
no copy of one or more of the Font Software typefaces may be sold by
|
||||
itself.
|
||||
|
||||
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
|
||||
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL
|
||||
TAVMJONG BAH BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
|
||||
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
|
||||
OTHER DEALINGS IN THE FONT SOFTWARE.
|
||||
|
||||
Except as contained in this notice, the name of Tavmjong Bah shall not
|
||||
be used in advertising or otherwise to promote the sale, use or other
|
||||
dealings in this Font Software without prior written authorization
|
||||
from Tavmjong Bah. For further information, contact: tavmjong @ free
|
||||
. fr.
|
||||
|
||||
$Id: LICENSE 2133 2007-11-28 02:46:28Z lechimp $
|
||||
@ -1,6 +0,0 @@
|
||||
|
||||
The tahoma.ttf file which is bundled with pChart 1.27d was replaced due to uncertainty with it's licence.
|
||||
|
||||
As a replacement the DejaVuSans.ttf font file was extracted from the DejaVu fonts 2.32 package available from dejavu-fonts.org
|
||||
|
||||
For license information see LICENSE.
|
||||
@ -1,119 +0,0 @@
|
||||
<?php
|
||||
/*
|
||||
pCache - Faster renderding using data cache
|
||||
Copyright (C) 2008 Jean-Damien POGOLOTTI
|
||||
Version 1.1.2 last updated on 06/17/08
|
||||
|
||||
http://pchart.sourceforge.net
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 1,2,3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Class initialisation :
|
||||
pCache($CacheFolder="Cache/")
|
||||
Cache management :
|
||||
IsInCache($Data)
|
||||
GetFromCache($ID,$Data)
|
||||
WriteToCache($ID,$Data,$Picture)
|
||||
DeleteFromCache($ID,$Data)
|
||||
ClearCache()
|
||||
Inner functions :
|
||||
GetHash($ID,$Data)
|
||||
*/
|
||||
|
||||
/* pCache class definition */
|
||||
class pCache
|
||||
{
|
||||
var $HashKey = "";
|
||||
var $CacheFolder = "Cache/";
|
||||
|
||||
/* Create the pCache object */
|
||||
function pCache($CacheFolder="Cache/")
|
||||
{
|
||||
$this->CacheFolder = $CacheFolder;
|
||||
}
|
||||
|
||||
/* This function is clearing the cache folder */
|
||||
function ClearCache()
|
||||
{
|
||||
if ($handle = opendir($this->CacheFolder))
|
||||
{
|
||||
while (false !== ($file = readdir($handle)))
|
||||
{
|
||||
if ( $file != "." && $file != ".." )
|
||||
unlink($this->CacheFolder.$file);
|
||||
}
|
||||
closedir($handle);
|
||||
}
|
||||
}
|
||||
|
||||
/* This function is checking if we have an offline version of this chart */
|
||||
function IsInCache($ID,$Data,$Hash="")
|
||||
{
|
||||
if ( $Hash == "" )
|
||||
$Hash = $this->GetHash($ID,$Data);
|
||||
|
||||
if ( file_exists($this->CacheFolder.$Hash) )
|
||||
return(TRUE);
|
||||
else
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
/* This function is making a copy of drawn chart in the cache folder */
|
||||
function WriteToCache($ID,$Data,$Picture)
|
||||
{
|
||||
$Hash = $this->GetHash($ID,$Data);
|
||||
$FileName = $this->CacheFolder.$Hash;
|
||||
|
||||
imagepng($Picture->Picture,$FileName);
|
||||
}
|
||||
|
||||
/* This function is removing any cached copy of this chart */
|
||||
function DeleteFromCache($ID,$Data)
|
||||
{
|
||||
$Hash = $this->GetHash($ID,$Data);
|
||||
$FileName = $this->CacheFolder.$Hash;
|
||||
|
||||
if ( file_exists($FileName ) )
|
||||
unlink($FileName);
|
||||
}
|
||||
|
||||
/* This function is retrieving the cached picture if applicable */
|
||||
function GetFromCache($ID,$Data)
|
||||
{
|
||||
$Hash = $this->GetHash($ID,$Data);
|
||||
if ( $this->IsInCache("","",$Hash ) )
|
||||
{
|
||||
$FileName = $this->CacheFolder.$Hash;
|
||||
|
||||
header('Content-type: image/png');
|
||||
@readfile($FileName);
|
||||
exit();
|
||||
}
|
||||
}
|
||||
|
||||
/* This function is building the graph unique hash key */
|
||||
function GetHash($ID,$Data)
|
||||
{
|
||||
$mKey = "$ID";
|
||||
foreach($Data as $key => $Values)
|
||||
{
|
||||
$tKey = "";
|
||||
foreach($Values as $Serie => $Value)
|
||||
$tKey = $tKey.$Serie.$Value;
|
||||
$mKey = $mKey.md5($tKey);
|
||||
}
|
||||
return(md5($mKey));
|
||||
}
|
||||
}
|
||||
?>
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,260 +0,0 @@
|
||||
<?php
|
||||
/*
|
||||
pData - Simplifying data population for pChart
|
||||
Copyright (C) 2008 Jean-Damien POGOLOTTI
|
||||
Version 1.13 last updated on 08/17/08
|
||||
|
||||
http://pchart.sourceforge.net
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 1,2,3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Class initialisation :
|
||||
pData()
|
||||
Data populating methods :
|
||||
ImportFromCSV($FileName,$Delimiter=",",$DataColumns=-1,$HasHeader=FALSE,$DataName=-1)
|
||||
AddPoint($Value,$Serie="Serie1",$Description="")
|
||||
Series manipulation methods :
|
||||
AddSerie($SerieName="Serie1")
|
||||
AddAllSeries()
|
||||
RemoveSerie($SerieName="Serie1")
|
||||
SetAbsciseLabelSerie($SerieName = "Name")
|
||||
SetSerieName($Name,$SerieName="Serie1")
|
||||
+ SetSerieSymbol($Name,$Symbol)
|
||||
SetXAxisName($Name="X Axis")
|
||||
SetYAxisName($Name="Y Axis")
|
||||
SetXAxisFormat($Format="number")
|
||||
SetYAxisFormat($Format="number")
|
||||
SetXAxisUnit($Unit="")
|
||||
SetYAxisUnit($Unit="")
|
||||
removeSerieName($SerieName)
|
||||
removeAllSeries()
|
||||
Data retrieval methods :
|
||||
GetData()
|
||||
GetDataDescription()
|
||||
*/
|
||||
|
||||
/* pData class definition */
|
||||
class pData
|
||||
{
|
||||
var $Data;
|
||||
var $DataDescription;
|
||||
|
||||
function pData()
|
||||
{
|
||||
$this->Data = array();
|
||||
$this->DataDescription = "";
|
||||
$this->DataDescription["Position"] = "Name";
|
||||
$this->DataDescription["Format"]["X"] = "number";
|
||||
$this->DataDescription["Format"]["Y"] = "number";
|
||||
$this->DataDescription["Unit"]["X"] = NULL;
|
||||
$this->DataDescription["Unit"]["Y"] = NULL;
|
||||
}
|
||||
|
||||
function ImportFromCSV($FileName,$Delimiter=",",$DataColumns=-1,$HasHeader=FALSE,$DataName=-1)
|
||||
{
|
||||
$handle = @fopen($FileName,"r");
|
||||
if ($handle)
|
||||
{
|
||||
$HeaderParsed = FALSE;
|
||||
while (!feof($handle))
|
||||
{
|
||||
$buffer = fgets($handle, 4096);
|
||||
$buffer = str_replace(chr(10),"",$buffer);
|
||||
$buffer = str_replace(chr(13),"",$buffer);
|
||||
$Values = split($Delimiter,$buffer);
|
||||
|
||||
if ( $buffer != "" )
|
||||
{
|
||||
if ( $HasHeader == TRUE && $HeaderParsed == FALSE )
|
||||
{
|
||||
if ( $DataColumns == -1 )
|
||||
{
|
||||
$ID = 1;
|
||||
foreach($Values as $key => $Value)
|
||||
{ $this->SetSerieName($Value,"Serie".$ID); $ID++; }
|
||||
}
|
||||
else
|
||||
{
|
||||
$SerieName = "";
|
||||
|
||||
foreach($DataColumns as $key => $Value)
|
||||
$this->SetSerieName($Values[$Value],"Serie".$Value);
|
||||
}
|
||||
$HeaderParsed = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( $DataColumns == -1 )
|
||||
{
|
||||
$ID = 1;
|
||||
foreach($Values as $key => $Value)
|
||||
{ $this->AddPoint(intval($Value),"Serie".$ID); $ID++; }
|
||||
}
|
||||
else
|
||||
{
|
||||
$SerieName = "";
|
||||
if ( $DataName != -1 )
|
||||
$SerieName = $Values[$DataName];
|
||||
|
||||
foreach($DataColumns as $key => $Value)
|
||||
$this->AddPoint($Values[$Value],"Serie".$Value,$SerieName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
fclose($handle);
|
||||
}
|
||||
}
|
||||
|
||||
function AddPoint($Value,$Serie="Serie1",$Description="")
|
||||
{
|
||||
if (is_array($Value) && count($Value) == 1)
|
||||
$Value = array_pop($Value);
|
||||
|
||||
$ID = 0;
|
||||
for($i=0;$i<=count($this->Data);$i++)
|
||||
{ if(isset($this->Data[$i][$Serie])) { $ID = $i+1; } }
|
||||
|
||||
if ( count($Value) == 1 )
|
||||
{
|
||||
$this->Data[$ID][$Serie] = $Value;
|
||||
if ( $Description != "" )
|
||||
$this->Data[$ID]["Name"] = $Description;
|
||||
elseif (!isset($this->Data[$ID]["Name"]))
|
||||
$this->Data[$ID]["Name"] = $ID;
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach($Value as $key => $Val)
|
||||
{
|
||||
$this->Data[$ID][$Serie] = $Val;
|
||||
if (!isset($this->Data[$ID]["Name"]))
|
||||
$this->Data[$ID]["Name"] = $ID;
|
||||
$ID++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function AddSerie($SerieName="Serie1")
|
||||
{
|
||||
if ( !isset($this->DataDescription["Values"]) )
|
||||
{
|
||||
$this->DataDescription["Values"][] = $SerieName;
|
||||
}
|
||||
else
|
||||
{
|
||||
$Found = FALSE;
|
||||
foreach($this->DataDescription["Values"] as $key => $Value )
|
||||
if ( $Value == $SerieName ) { $Found = TRUE; }
|
||||
|
||||
if ( !$Found )
|
||||
$this->DataDescription["Values"][] = $SerieName;
|
||||
}
|
||||
}
|
||||
|
||||
function AddAllSeries()
|
||||
{
|
||||
unset($this->DataDescription["Values"]);
|
||||
|
||||
if ( isset($this->Data[0]) )
|
||||
{
|
||||
foreach($this->Data[0] as $Key => $Value)
|
||||
{
|
||||
if ( $Key != "Name" )
|
||||
$this->DataDescription["Values"][] = $Key;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function RemoveSerie($SerieName="Serie1")
|
||||
{
|
||||
if ( !isset($this->DataDescription["Values"]) )
|
||||
return(0);
|
||||
|
||||
$Found = FALSE;
|
||||
foreach($this->DataDescription["Values"] as $key => $Value )
|
||||
{
|
||||
if ( $Value == $SerieName )
|
||||
unset($this->DataDescription["Values"][$key]);
|
||||
}
|
||||
}
|
||||
|
||||
function SetAbsciseLabelSerie($SerieName = "Name")
|
||||
{
|
||||
$this->DataDescription["Position"] = $SerieName;
|
||||
}
|
||||
|
||||
function SetSerieName($Name,$SerieName="Serie1")
|
||||
{
|
||||
$this->DataDescription["Description"][$SerieName] = $Name;
|
||||
}
|
||||
|
||||
function SetXAxisName($Name="X Axis")
|
||||
{
|
||||
$this->DataDescription["Axis"]["X"] = $Name;
|
||||
}
|
||||
|
||||
function SetYAxisName($Name="Y Axis")
|
||||
{
|
||||
$this->DataDescription["Axis"]["Y"] = $Name;
|
||||
}
|
||||
|
||||
function SetXAxisFormat($Format="number")
|
||||
{
|
||||
$this->DataDescription["Format"]["X"] = $Format;
|
||||
}
|
||||
|
||||
function SetYAxisFormat($Format="number")
|
||||
{
|
||||
$this->DataDescription["Format"]["Y"] = $Format;
|
||||
}
|
||||
|
||||
function SetXAxisUnit($Unit="")
|
||||
{
|
||||
$this->DataDescription["Unit"]["X"] = $Unit;
|
||||
}
|
||||
|
||||
function SetYAxisUnit($Unit="")
|
||||
{
|
||||
$this->DataDescription["Unit"]["Y"] = $Unit;
|
||||
}
|
||||
|
||||
function SetSerieSymbol($Name,$Symbol)
|
||||
{
|
||||
$this->DataDescription["Symbol"][$Name] = $Symbol;
|
||||
}
|
||||
|
||||
function removeSerieName($SerieName)
|
||||
{
|
||||
if ( isset($this->DataDescription["Description"][$SerieName]) )
|
||||
unset($this->DataDescription["Description"][$SerieName]);
|
||||
}
|
||||
|
||||
function removeAllSeries()
|
||||
{
|
||||
foreach($this->DataDescription["Values"] as $Key => $Value)
|
||||
unset($this->DataDescription["Values"][$Key]);
|
||||
}
|
||||
|
||||
function GetData()
|
||||
{
|
||||
return($this->Data);
|
||||
}
|
||||
|
||||
function GetDataDescription()
|
||||
{
|
||||
return($this->DataDescription);
|
||||
}
|
||||
}
|
||||
?>
|
||||
@ -1,183 +0,0 @@
|
||||
<?php
|
||||
/* vim: set expandtab sw=4 ts=4 sts=4: */
|
||||
/**
|
||||
* Holds the base class that all charts inherit from and some widely used
|
||||
* constants.
|
||||
* @package phpMyAdmin
|
||||
*/
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
define('RED', 0);
|
||||
define('GREEN', 1);
|
||||
define('BLUE', 2);
|
||||
|
||||
/**
|
||||
* The base class that all charts inherit from.
|
||||
* @abstract
|
||||
* @package phpMyAdmin
|
||||
*/
|
||||
abstract class PMA_chart
|
||||
{
|
||||
/**
|
||||
* @var array All the default settigs values are here.
|
||||
*/
|
||||
protected $settings = array(
|
||||
|
||||
// Default title for every chart.
|
||||
'titleText' => 'Chart',
|
||||
|
||||
// The style of the chart title.
|
||||
'titleColor' => '#FAFAFA',
|
||||
|
||||
// Colors for the different slices in the pie chart.
|
||||
'colors' => array(
|
||||
'#BCE02E',
|
||||
'#E0642E',
|
||||
'#E0D62E',
|
||||
'#2E97E0',
|
||||
'#B02EE0',
|
||||
'#E02E75',
|
||||
'#5CE02E',
|
||||
'#E0B02E',
|
||||
'#000000',
|
||||
'#0022E0',
|
||||
'#726CB1',
|
||||
'#481A36',
|
||||
'#BAC658',
|
||||
'#127224',
|
||||
'#825119',
|
||||
'#238C74',
|
||||
'#4C489B',
|
||||
'#87C9BF',
|
||||
),
|
||||
|
||||
// Chart background color.
|
||||
'bgColor' => '#84AD83',
|
||||
|
||||
// The width of the chart.
|
||||
'width' => 520,
|
||||
|
||||
// The height of the chart.
|
||||
'height' => 325,
|
||||
|
||||
// Default X Axis label. If empty, label will be taken from the data.
|
||||
'xLabel' => '',
|
||||
|
||||
// Default Y Axis label. If empty, label will be taken from the data.
|
||||
'yLabel' => '',
|
||||
);
|
||||
|
||||
/**
|
||||
* @var array Options that the user has specified
|
||||
*/
|
||||
private $userSpecifiedSettings = null;
|
||||
|
||||
/**
|
||||
* @var array Error codes will be stored here
|
||||
*/
|
||||
protected $errors = array();
|
||||
|
||||
/**
|
||||
* Store user specified options
|
||||
* @param array $options users specified options
|
||||
*/
|
||||
function __construct($options = null)
|
||||
{
|
||||
$this->userSpecifiedSettings = $options;
|
||||
}
|
||||
|
||||
/**
|
||||
* All the variable initialization has to be done here.
|
||||
*/
|
||||
protected function init()
|
||||
{
|
||||
$this->handleOptions();
|
||||
}
|
||||
|
||||
/**
|
||||
* A function which handles passed parameters. Useful if desired
|
||||
* chart needs to be a little bit different from the default one.
|
||||
*/
|
||||
private function handleOptions()
|
||||
{
|
||||
if (is_null($this->userSpecifiedSettings)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->settings = array_merge($this->settings, $this->userSpecifiedSettings);
|
||||
}
|
||||
|
||||
protected function getTitleText()
|
||||
{
|
||||
return $this->settings['titleText'];
|
||||
}
|
||||
|
||||
protected function getTitleColor($component)
|
||||
{
|
||||
return $this->hexStrToDecComp($this->settings['titleColor'], $component);
|
||||
}
|
||||
|
||||
protected function getColors()
|
||||
{
|
||||
return $this->settings['colors'];
|
||||
}
|
||||
|
||||
protected function getWidth()
|
||||
{
|
||||
return $this->settings['width'];
|
||||
}
|
||||
|
||||
protected function getHeight()
|
||||
{
|
||||
return $this->settings['height'];
|
||||
}
|
||||
|
||||
protected function getBgColor($component)
|
||||
{
|
||||
return $this->hexStrToDecComp($this->settings['bgColor'], $component);
|
||||
}
|
||||
|
||||
protected function setXLabel($label)
|
||||
{
|
||||
$this->settings['xLabel'] = $label;
|
||||
}
|
||||
|
||||
protected function getXLabel()
|
||||
{
|
||||
return $this->settings['xLabel'];
|
||||
}
|
||||
|
||||
protected function setYLabel($label)
|
||||
{
|
||||
$this->settings['yLabel'] = $label;
|
||||
}
|
||||
|
||||
protected function getYLabel()
|
||||
{
|
||||
return $this->settings['yLabel'];
|
||||
}
|
||||
|
||||
public function getSettings()
|
||||
{
|
||||
return $this->settings;
|
||||
}
|
||||
|
||||
public function getErrors()
|
||||
{
|
||||
return $this->errors;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get one the dec color component from the hex color string
|
||||
* @param string $colorString color string, i.e. #5F22A99
|
||||
* @param int $component color component to get, i.e. 0 gets red.
|
||||
*/
|
||||
protected function hexStrToDecComp($colorString, $component)
|
||||
{
|
||||
return hexdec(substr($colorString, ($component * 2) + 1, 2));
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
@ -1,402 +0,0 @@
|
||||
<?php
|
||||
/* vim: set expandtab sw=4 ts=4 sts=4: */
|
||||
/**
|
||||
* Holds the base class that all charts using pChart inherit from and some
|
||||
* widely used constants
|
||||
* @package phpMyAdmin
|
||||
*/
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
define('TOP', 0);
|
||||
define('RIGHT', 1);
|
||||
define('BOTTOM', 2);
|
||||
define('LEFT', 3);
|
||||
|
||||
require_once 'pma_chart.php';
|
||||
|
||||
require_once 'pChart/pData.class';
|
||||
require_once 'pChart/pChart.class';
|
||||
|
||||
/**
|
||||
* Base class for every chart implemented using pChart.
|
||||
* @abstract
|
||||
* @package phpMyAdmin
|
||||
*/
|
||||
abstract class PMA_pChart_chart extends PMA_chart
|
||||
{
|
||||
/**
|
||||
* @var String title text
|
||||
*/
|
||||
protected $titleText;
|
||||
|
||||
/**
|
||||
* @var array data for the chart
|
||||
*/
|
||||
protected $data;
|
||||
|
||||
/**
|
||||
* @var object pData object that holds the description of the data
|
||||
*/
|
||||
protected $dataSet;
|
||||
|
||||
/**
|
||||
* @var object pChart object that holds the chart
|
||||
*/
|
||||
protected $chart;
|
||||
|
||||
/**
|
||||
* @var array holds base64 encoded chart image parts
|
||||
*/
|
||||
protected $partsEncoded = array();
|
||||
|
||||
public function __construct($data, $options = null)
|
||||
{
|
||||
parent::__construct($options);
|
||||
|
||||
$this->data = $data;
|
||||
|
||||
$this->settings['fontPath'] = './libraries/chart/pChart/fonts/';
|
||||
|
||||
$this->settings['scale'] = SCALE_ADDALLSTART0;
|
||||
|
||||
$this->settings['labelHeight'] = 20;
|
||||
|
||||
$this->settings['fontSize'] = 8;
|
||||
|
||||
$this->settings['continuous'] = 'off';
|
||||
|
||||
// as in CSS (top, right, bottom, left)
|
||||
$this->setAreaMargins(array(20, 20, 40, 60));
|
||||
|
||||
// Get color settings from theme
|
||||
$this->settings = array_merge($this->settings,$GLOBALS['cfg']['chartColor']);
|
||||
}
|
||||
|
||||
protected function init()
|
||||
{
|
||||
parent::init();
|
||||
|
||||
// create pChart object
|
||||
$this->chart = new pChart($this->getWidth(), $this->getHeight());
|
||||
|
||||
// create pData object
|
||||
$this->dataSet = new pData;
|
||||
|
||||
$this->chart->reportWarnings('GD');
|
||||
$this->chart->ErrorFontName = $this->getFontPath().'DejaVuSans.ttf';
|
||||
|
||||
// initialize colors
|
||||
foreach ($this->getColors() as $key => $color) {
|
||||
$this->chart->setColorPalette(
|
||||
$key,
|
||||
hexdec(substr($color, 1, 2)),
|
||||
hexdec(substr($color, 3, 2)),
|
||||
hexdec(substr($color, 5, 2))
|
||||
);
|
||||
}
|
||||
|
||||
$this->chart->setFontProperties($this->getFontPath().'DejaVuSans.ttf', $this->getFontSize());
|
||||
|
||||
$this->chart->setImageMap(true, 'mapid');
|
||||
}
|
||||
|
||||
/**
|
||||
* data is put to the $dataSet object according to what type chart is
|
||||
* @abstract
|
||||
*/
|
||||
abstract protected function prepareDataSet();
|
||||
|
||||
/**
|
||||
* all components of the chart are drawn
|
||||
*/
|
||||
protected function prepareChart()
|
||||
{
|
||||
$this->drawBackground();
|
||||
$this->drawChart();
|
||||
}
|
||||
|
||||
/**
|
||||
* draws the background
|
||||
*/
|
||||
protected function drawBackground()
|
||||
{
|
||||
$this->drawCommon();
|
||||
$this->drawTitle();
|
||||
$this->setGraphAreaDimensions();
|
||||
$this->drawGraphArea();
|
||||
}
|
||||
|
||||
/**
|
||||
* draws the part of the background which is common to most of the charts
|
||||
*/
|
||||
protected function drawCommon()
|
||||
{
|
||||
$this->chart->drawGraphAreaGradient(
|
||||
$this->getBgColor(RED),
|
||||
$this->getBgColor(GREEN),
|
||||
$this->getBgColor(BLUE),
|
||||
// With a gradientIntensity of 0 the background does't draw, oddly
|
||||
($this->settings['gradientIntensity']==0)?1:$this->settings['gradientIntensity'],TARGET_BACKGROUND);
|
||||
|
||||
if(is_string($this->settings['border']))
|
||||
$this->chart->addBorder(1,$this->getBorderColor(RED),$this->getBorderColor(GREEN),$this->getBorderColor(BLUE));
|
||||
}
|
||||
|
||||
/**
|
||||
* draws the chart title
|
||||
*/
|
||||
protected function drawTitle()
|
||||
{
|
||||
// Draw the title
|
||||
$this->chart->drawTextBox(
|
||||
0,
|
||||
0,
|
||||
$this->getWidth(),
|
||||
$this->getLabelHeight(),
|
||||
$this->getTitleText(),
|
||||
0,
|
||||
$this->getTitleColor(RED),
|
||||
$this->getTitleColor(GREEN),
|
||||
$this->getTitleColor(BLUE),
|
||||
ALIGN_CENTER,
|
||||
false,
|
||||
$this->getTitleBgColor(RED),
|
||||
$this->getTitleBgColor(GREEN),
|
||||
$this->getTitleBgColor(BLUE)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* calculates and sets the dimensions that will be used for the actual graph
|
||||
*/
|
||||
protected function setGraphAreaDimensions()
|
||||
{
|
||||
$this->chart->setGraphArea(
|
||||
$this->getAreaMargin(LEFT),
|
||||
$this->getLabelHeight() + $this->getAreaMargin(TOP),
|
||||
$this->getWidth() - $this->getAreaMargin(RIGHT),
|
||||
$this->getHeight() - $this->getAreaMargin(BOTTOM)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* draws graph area (the area where all bars, lines, points will be seen)
|
||||
*/
|
||||
protected function drawGraphArea()
|
||||
{
|
||||
$this->chart->drawGraphArea(
|
||||
$this->getGraphAreaColor(RED),
|
||||
$this->getGraphAreaColor(GREEN),
|
||||
$this->getGraphAreaColor(BLUE),
|
||||
false
|
||||
);
|
||||
$this->chart->drawScale(
|
||||
$this->dataSet->GetData(),
|
||||
$this->dataSet->GetDataDescription(),
|
||||
$this->getScale(),
|
||||
$this->getScaleColor(RED),
|
||||
$this->getScaleColor(GREEN),
|
||||
$this->getScaleColor(BLUE),
|
||||
true,0,2,true
|
||||
);
|
||||
|
||||
if($this->settings['gradientIntensity']>0)
|
||||
$this->chart->drawGraphAreaGradient(
|
||||
$this->getGraphAreaGradientColor(RED),
|
||||
$this->getGraphAreaGradientColor(GREEN),
|
||||
$this->getGraphAreaGradientColor(BLUE),
|
||||
$this->settings['gradientIntensity']
|
||||
);
|
||||
else
|
||||
$this->chart->drawGraphArea(
|
||||
$this->getGraphAreaGradientColor(RED),
|
||||
$this->getGraphAreaGradientColor(GREEN),
|
||||
$this->getGraphAreaGradientColor(BLUE)
|
||||
);
|
||||
|
||||
$this->chart->drawGrid(
|
||||
4,
|
||||
true,
|
||||
$this->getGridColor(RED),
|
||||
$this->getGridColor(GREEN),
|
||||
$this->getGridColor(BLUE),
|
||||
20
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* draws the chart
|
||||
* @abstract
|
||||
*/
|
||||
protected abstract function drawChart();
|
||||
|
||||
/**
|
||||
* Renders the chart, base 64 encodes the output and puts it into
|
||||
* array partsEncoded.
|
||||
*
|
||||
* Parameter can be used to slice the chart vertically into parts. This
|
||||
* solves an issue where some browsers (IE8) accept base64 images only up
|
||||
* to some length.
|
||||
*
|
||||
* @param integer $parts number of parts to render.
|
||||
* Default value 1 means that all the
|
||||
* chart will be in one piece.
|
||||
*/
|
||||
protected function render($parts = 1)
|
||||
{
|
||||
$fullWidth = 0;
|
||||
|
||||
for ($i = 0; $i < $parts; $i++) {
|
||||
|
||||
// slicing is vertical so part height is the full height
|
||||
$partHeight = $this->chart->YSize;
|
||||
|
||||
// there will be some rounding erros, will compensate later
|
||||
$partWidth = round($this->chart->XSize / $parts);
|
||||
$fullWidth += $partWidth;
|
||||
$partX = $partWidth * $i;
|
||||
|
||||
if ($i == $parts - 1) {
|
||||
// if this is the last part, compensate for the rounding errors
|
||||
$partWidth += $this->chart->XSize - $fullWidth;
|
||||
}
|
||||
|
||||
// get a part from the full chart image
|
||||
$part = imagecreatetruecolor($partWidth, $partHeight);
|
||||
imagecopy($part, $this->chart->Picture, 0, 0, $partX, 0, $partWidth, $partHeight);
|
||||
|
||||
// render part and save it to variable
|
||||
ob_start();
|
||||
imagepng($part, NULL, 9, PNG_ALL_FILTERS);
|
||||
$output = ob_get_contents();
|
||||
ob_end_clean();
|
||||
|
||||
// base64 encode the current part
|
||||
$partEncoded = base64_encode($output);
|
||||
$this->partsEncoded[$i] = $partEncoded;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* get the HTML and JS code for the configured chart
|
||||
* @return string HTML and JS code for the chart
|
||||
*/
|
||||
public function toString()
|
||||
{
|
||||
if (!function_exists('gd_info')) {
|
||||
array_push($this->errors, ERR_NO_GD);
|
||||
return '';
|
||||
}
|
||||
|
||||
$this->init();
|
||||
$this->prepareDataSet();
|
||||
$this->prepareChart();
|
||||
|
||||
//$this->chart->debugImageMap();
|
||||
//$this->chart->printErrors('GD');
|
||||
|
||||
// check if a user wanted a chart in one part
|
||||
if ($this->isContinuous()) {
|
||||
$this->render(1);
|
||||
}
|
||||
else {
|
||||
$this->render(20);
|
||||
}
|
||||
|
||||
$returnData = '<div id="chart">';
|
||||
foreach ($this->partsEncoded as $part) {
|
||||
$returnData .= '<img src="data:image/png;base64,'.$part.'" />';
|
||||
}
|
||||
$returnData .= '</div>';
|
||||
|
||||
// add tooltips only if json is available
|
||||
if (function_exists('json_encode')) {
|
||||
$returnData .= '
|
||||
<script type="text/javascript">
|
||||
//<![CDATA[
|
||||
imageMap.loadImageMap(\''.json_encode($this->getImageMap()).'\');
|
||||
//]]>
|
||||
</script>
|
||||
';
|
||||
}
|
||||
else {
|
||||
array_push($this->errors, ERR_NO_JSON);
|
||||
}
|
||||
|
||||
return $returnData;
|
||||
}
|
||||
|
||||
protected function getLabelHeight()
|
||||
{
|
||||
return $this->settings['labelHeight'];
|
||||
}
|
||||
|
||||
protected function setAreaMargins($areaMargins)
|
||||
{
|
||||
$this->settings['areaMargins'] = $areaMargins;
|
||||
}
|
||||
|
||||
protected function getAreaMargin($side)
|
||||
{
|
||||
return $this->settings['areaMargins'][$side];
|
||||
}
|
||||
|
||||
protected function getFontPath()
|
||||
{
|
||||
return $this->settings['fontPath'];
|
||||
}
|
||||
|
||||
protected function getScale()
|
||||
{
|
||||
return $this->settings['scale'];
|
||||
}
|
||||
|
||||
protected function getFontSize()
|
||||
{
|
||||
return $this->settings['fontSize'];
|
||||
}
|
||||
|
||||
protected function isContinuous()
|
||||
{
|
||||
return $this->settings['continuous'] == 'on';
|
||||
}
|
||||
|
||||
protected function getImageMap()
|
||||
{
|
||||
return $this->chart->getImageMap();
|
||||
}
|
||||
|
||||
protected function getGraphAreaColor($component)
|
||||
{
|
||||
return $this->hexStrToDecComp($this->settings['graphAreaColor'], $component);
|
||||
}
|
||||
|
||||
protected function getGraphAreaGradientColor($component)
|
||||
{
|
||||
return $this->hexStrToDecComp($this->settings['graphAreaGradientColor'], $component);
|
||||
}
|
||||
|
||||
protected function getGridColor($component)
|
||||
{
|
||||
return $this->hexStrToDecComp($this->settings['gridColor'], $component);
|
||||
}
|
||||
|
||||
protected function getScaleColor($component)
|
||||
{
|
||||
return $this->hexStrToDecComp($this->settings['scaleColor'], $component);
|
||||
}
|
||||
|
||||
protected function getTitleBgColor($component)
|
||||
{
|
||||
return $this->hexStrToDecComp($this->settings['titleBgColor'], $component);
|
||||
}
|
||||
|
||||
protected function getBorderColor($component)
|
||||
{
|
||||
return $this->hexStrToDecComp($this->settings['border'], $component);
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
@ -1,117 +0,0 @@
|
||||
<?php
|
||||
/* vim: set expandtab sw=4 ts=4 sts=4: */
|
||||
/**
|
||||
* @package phpMyAdmin
|
||||
*/
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
require_once 'pma_pchart_chart.php';
|
||||
|
||||
/**
|
||||
* Base class for every chart that uses multiple series.
|
||||
* All of these charts will require legend box.
|
||||
* @abstract
|
||||
* @package phpMyAdmin
|
||||
*/
|
||||
abstract class PMA_pChart_multi extends PMA_pChart_chart
|
||||
{
|
||||
public function __construct($data, $options = null)
|
||||
{
|
||||
parent::__construct($data, $options);
|
||||
|
||||
// as in CSS (top, right, bottom, left)
|
||||
$this->setLegendMargins(array(20, 10, 0, 0));
|
||||
}
|
||||
|
||||
/**
|
||||
* data set preparation for multi serie graphs
|
||||
*/
|
||||
protected function prepareDataSet()
|
||||
{
|
||||
$values = array_values($this->data);
|
||||
$keys = array_keys($this->data);
|
||||
|
||||
// Dataset definition
|
||||
$this->dataSet->AddPoint($values[0], "Keys");
|
||||
|
||||
$i = 0;
|
||||
foreach ($values[1] as $seriesName => $seriesData) {
|
||||
$this->dataSet->AddPoint($seriesData, "Values".$i);
|
||||
$this->dataSet->SetSerieName($seriesName, "Values".$i);
|
||||
$i++;
|
||||
}
|
||||
$this->dataSet->AddAllSeries();
|
||||
|
||||
$this->dataSet->RemoveSerie("Keys");
|
||||
$this->dataSet->SetAbsciseLabelSerie("Keys");
|
||||
|
||||
$xLabel = $this->getXLabel();
|
||||
if (empty($xLabel)) {
|
||||
$this->setXLabel($keys[0]);
|
||||
}
|
||||
$yLabel = $this->getYLabel();
|
||||
if (empty($yLabel)) {
|
||||
$this->setYLabel($keys[1]);
|
||||
}
|
||||
|
||||
$this->dataSet->SetXAxisName($this->getXLabel());
|
||||
$this->dataSet->SetYAxisName($this->getYLabel());
|
||||
}
|
||||
|
||||
/**
|
||||
* set graph area dimensions with respect to legend box size
|
||||
*/
|
||||
protected function setGraphAreaDimensions()
|
||||
{
|
||||
$this->chart->setGraphArea(
|
||||
$this->getAreaMargin(LEFT),
|
||||
$this->getLabelHeight() + $this->getAreaMargin(TOP),
|
||||
$this->getWidth() - $this->getAreaMargin(RIGHT) - $this->getLegendBoxWidth() - $this->getLegendMargin(LEFT) - $this->getLegendMargin(RIGHT),
|
||||
$this->getHeight() - $this->getAreaMargin(BOTTOM)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* multi serie charts need a legend. draw it
|
||||
*/
|
||||
protected function drawChart()
|
||||
{
|
||||
$this->drawLegend();
|
||||
}
|
||||
|
||||
/**
|
||||
* draws a legend
|
||||
*/
|
||||
protected function drawLegend()
|
||||
{
|
||||
// Draw the legend
|
||||
$this->chart->drawLegend(
|
||||
$this->getWidth() - $this->getLegendMargin(RIGHT) - $this->getLegendBoxWidth(),
|
||||
$this->getLabelHeight() + $this->getLegendMargin(TOP),
|
||||
$this->dataSet->GetDataDescription(),
|
||||
250,250,250,50,50,50
|
||||
);
|
||||
}
|
||||
|
||||
protected function setLegendMargins($legendMargins)
|
||||
{
|
||||
if (!isset($this->settings['legendMargins'])) {
|
||||
$this->settings['legendMargins'] = $legendMargins;
|
||||
}
|
||||
}
|
||||
|
||||
protected function getLegendMargin($side)
|
||||
{
|
||||
return $this->settings['legendMargins'][$side];
|
||||
}
|
||||
|
||||
protected function getLegendBoxWidth()
|
||||
{
|
||||
$legendSize = $this->chart->getLegendBoxSize($this->dataSet->GetDataDescription());
|
||||
return $legendSize[0];
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
@ -1,37 +0,0 @@
|
||||
<?php
|
||||
/* vim: set expandtab sw=4 ts=4 sts=4: */
|
||||
/**
|
||||
* @package phpMyAdmin
|
||||
*/
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
require_once 'pma_pchart_multi.php';
|
||||
|
||||
/**
|
||||
* implements multi bar chart
|
||||
* @package phpMyAdmin
|
||||
*/
|
||||
class PMA_pChart_multi_bar extends PMA_pChart_multi
|
||||
{
|
||||
public function __construct($data, $options = null)
|
||||
{
|
||||
parent::__construct($data, $options);
|
||||
|
||||
$this->settings['scale'] = SCALE_NORMAL;
|
||||
}
|
||||
|
||||
/**
|
||||
* draws multi bar graph
|
||||
*/
|
||||
protected function drawChart()
|
||||
{
|
||||
parent::drawChart();
|
||||
|
||||
// Draw the bar chart
|
||||
$this->chart->drawBarGraph($this->dataSet->GetData(), $this->dataSet->GetDataDescription(), 70);
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
@ -1,38 +0,0 @@
|
||||
<?php
|
||||
/* vim: set expandtab sw=4 ts=4 sts=4: */
|
||||
/**
|
||||
* @package phpMyAdmin
|
||||
*/
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
require_once 'pma_pchart_multi.php';
|
||||
|
||||
/**
|
||||
* implements multi line chart
|
||||
* @package phpMyAdmin
|
||||
*/
|
||||
class PMA_pChart_multi_line extends PMA_pChart_multi
|
||||
{
|
||||
public function __construct($data, $options = null)
|
||||
{
|
||||
parent::__construct($data, $options);
|
||||
|
||||
$this->settings['scale'] = SCALE_NORMAL;
|
||||
}
|
||||
|
||||
/**
|
||||
* draws multi line chart
|
||||
*/
|
||||
protected function drawChart()
|
||||
{
|
||||
parent::drawChart();
|
||||
|
||||
// Draw the bar chart
|
||||
$this->chart->drawLineGraph($this->dataSet->GetData(), $this->dataSet->GetDataDescription());
|
||||
$this->chart->drawPlotGraph($this->dataSet->GetData(), $this->dataSet->GetDataDescription(), 3, 1, -1, -1, -1, true);
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
@ -1,107 +0,0 @@
|
||||
<?php
|
||||
/* vim: set expandtab sw=4 ts=4 sts=4: */
|
||||
/**
|
||||
* @package phpMyAdmin
|
||||
*/
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
require_once 'pma_pchart_multi.php';
|
||||
|
||||
/**
|
||||
* implements multi radar chart
|
||||
* @package phpMyAdmin
|
||||
*/
|
||||
class PMA_pChart_multi_radar extends PMA_pChart_multi
|
||||
{
|
||||
public function __construct($data, $options = null)
|
||||
{
|
||||
parent::__construct($data, $options);
|
||||
|
||||
$this->normalizeValues();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the largest value from the data and normalize all the other values.
|
||||
*/
|
||||
private function normalizeValues()
|
||||
{
|
||||
$maxValue = 0;
|
||||
$keys = array_keys($this->data);
|
||||
$valueKey = $keys[1];
|
||||
|
||||
// get the max value
|
||||
foreach ($this->data[$valueKey] as $values) {
|
||||
if (max($values) > $maxValue) {
|
||||
$maxValue = max($values);
|
||||
}
|
||||
}
|
||||
|
||||
// normalize all the values according to the max value
|
||||
foreach ($this->data[$valueKey] as &$values) {
|
||||
foreach ($values as &$value) {
|
||||
$value = $value / $maxValue * 10;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* graph area for the radar chart does not include grid lines
|
||||
*/
|
||||
protected function drawGraphArea()
|
||||
{
|
||||
$this->chart->drawGraphArea(
|
||||
$this->getGraphAreaColor(RED),
|
||||
$this->getGraphAreaColor(GREEN),
|
||||
$this->getGraphAreaColor(BLUE),
|
||||
false
|
||||
);
|
||||
|
||||
if($this->settings['gradientIntensity']>0)
|
||||
$this->chart->drawGraphAreaGradient(
|
||||
$this->getGraphAreaGradientColor(RED),
|
||||
$this->getGraphAreaGradientColor(GREEN),
|
||||
$this->getGraphAreaGradientColor(BLUE),
|
||||
$this->settings['gradientIntensity']
|
||||
);
|
||||
else
|
||||
$this->chart->drawGraphArea(
|
||||
$this->getGraphAreaGradientColor(RED),
|
||||
$this->getGraphAreaGradientColor(GREEN),
|
||||
$this->getGraphAreaGradientColor(BLUE)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* draw multi radar chart
|
||||
*/
|
||||
protected function drawChart()
|
||||
{
|
||||
parent::drawChart();
|
||||
|
||||
// when drawing radar graph we can specify the border from the top of
|
||||
// graph area. We want border to be dynamic, so that either the top
|
||||
// or the side of the radar is some distance away from the top or the
|
||||
// side of the graph area.
|
||||
$areaWidth = $this->chart->GArea_X2 - $this->chart->GArea_X1;
|
||||
$areaHeight = $this->chart->GArea_Y2 - $this->chart->GArea_Y1;
|
||||
|
||||
if ($areaHeight > $areaWidth) {
|
||||
$borderOffset = ($areaHeight - $areaWidth) / 2;
|
||||
}
|
||||
else {
|
||||
$borderOffset = 0;
|
||||
}
|
||||
|
||||
// the least ammount that radar is away from the graph area side.
|
||||
$borderOffset += 40;
|
||||
|
||||
// Draw the radar chart
|
||||
$this->chart->drawRadarAxis($this->dataSet->GetData(), $this->dataSet->GetDataDescription(), true, $borderOffset,
|
||||
120, 120, 120, 230, 230, 230, -1, 2);
|
||||
$this->chart->drawFilledRadar($this->dataSet->GetData(), $this->dataSet->GetDataDescription(), 50, $borderOffset);
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
@ -1,109 +0,0 @@
|
||||
<?php
|
||||
/* vim: set expandtab sw=4 ts=4 sts=4: */
|
||||
/**
|
||||
* @package phpMyAdmin
|
||||
*/
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
require_once 'pma_pchart_multi.php';
|
||||
|
||||
/**
|
||||
* implements pie chart
|
||||
* @package phpMyAdmin
|
||||
*/
|
||||
class PMA_pChart_Pie extends PMA_pChart_multi
|
||||
{
|
||||
public function __construct($data, $options = null)
|
||||
{
|
||||
// limit data size, no more than 18 pie slices
|
||||
$data = array_slice($data, 0, 18, true);
|
||||
parent::__construct($data, $options);
|
||||
|
||||
$this->setAreaMargins(array(20, 10, 20, 20));
|
||||
}
|
||||
|
||||
/**
|
||||
* prepare data set for the pie chart
|
||||
*/
|
||||
protected function prepareDataSet()
|
||||
{
|
||||
// Dataset definition
|
||||
$this->dataSet->AddPoint(array_values($this->data), "Values");
|
||||
$this->dataSet->AddPoint(array_keys($this->data), "Keys");
|
||||
$this->dataSet->AddAllSeries();
|
||||
$this->dataSet->SetAbsciseLabelSerie("Keys");
|
||||
}
|
||||
|
||||
/**
|
||||
* graph area for the pie chart does not include grid lines
|
||||
*/
|
||||
protected function drawGraphArea()
|
||||
{
|
||||
$this->chart->drawGraphArea(
|
||||
$this->getGraphAreaColor(RED),
|
||||
$this->getGraphAreaColor(GREEN),
|
||||
$this->getGraphAreaColor(BLUE),
|
||||
false
|
||||
);
|
||||
|
||||
if($this->settings['gradientIntensity']>0)
|
||||
$this->chart->drawGraphAreaGradient(
|
||||
$this->getGraphAreaGradientColor(RED),
|
||||
$this->getGraphAreaGradientColor(GREEN),
|
||||
$this->getGraphAreaGradientColor(BLUE),
|
||||
$this->settings['gradientIntensity']
|
||||
);
|
||||
else
|
||||
$this->chart->drawGraphArea(
|
||||
$this->getGraphAreaGradientColor(RED),
|
||||
$this->getGraphAreaGradientColor(GREEN),
|
||||
$this->getGraphAreaGradientColor(BLUE)
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* draw the pie chart
|
||||
*/
|
||||
protected function drawChart()
|
||||
{
|
||||
parent::drawChart();
|
||||
|
||||
// draw pie chart in the middle of graph area
|
||||
$middleX = ($this->chart->GArea_X1 + $this->chart->GArea_X2) / 2;
|
||||
$middleY = ($this->chart->GArea_Y1 + $this->chart->GArea_Y2) / 2;
|
||||
|
||||
$this->chart->drawPieGraph(
|
||||
$this->dataSet->GetData(),
|
||||
$this->dataSet->GetDataDescription(),
|
||||
$middleX,
|
||||
// pie graph is skewed. Upper part is shorter than the
|
||||
// lower part. This is why we set an offset to the
|
||||
// Y middle coordiantes.
|
||||
$middleY - 15,
|
||||
120, PIE_PERCENTAGE, false, 60, 30, 10, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* draw legend for the pie chart
|
||||
*/
|
||||
protected function drawLegend()
|
||||
{
|
||||
$this->chart->drawPieLegend(
|
||||
$this->getWidth() - $this->getLegendMargin(RIGHT) - $this->getLegendBoxWidth(),
|
||||
$this->getLabelHeight() + $this->getLegendMargin(TOP),
|
||||
$this->dataSet->GetData(),
|
||||
$this->dataSet->GetDataDescription(),
|
||||
250, 250, 250);
|
||||
}
|
||||
|
||||
protected function getLegendBoxWidth()
|
||||
{
|
||||
$legendSize = $this->chart->getPieLegendBoxSize($this->dataSet->GetData());
|
||||
return $legendSize[0];
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
@ -1,56 +0,0 @@
|
||||
<?php
|
||||
/* vim: set expandtab sw=4 ts=4 sts=4: */
|
||||
/**
|
||||
* @package phpMyAdmin
|
||||
*/
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
require_once 'pma_pchart_chart.php';
|
||||
|
||||
/**
|
||||
* Base class for every chart that uses only one series.
|
||||
* @abstract
|
||||
* @package phpMyAdmin
|
||||
*/
|
||||
abstract class PMA_pChart_single extends PMA_pChart_chart
|
||||
{
|
||||
public function __construct($data, $options = null)
|
||||
{
|
||||
parent::__construct($data, $options);
|
||||
}
|
||||
|
||||
/**
|
||||
* data set preparation for single serie charts
|
||||
*/
|
||||
protected function prepareDataSet()
|
||||
{
|
||||
$values = array_values($this->data);
|
||||
$keys = array_keys($this->data);
|
||||
|
||||
// Dataset definition
|
||||
$this->dataSet->AddPoint($values[0], "Values");
|
||||
$this->dataSet->AddPoint($values[1], "Keys");
|
||||
|
||||
//$this->dataSet->AddAllSeries();
|
||||
$this->dataSet->AddSerie("Values");
|
||||
|
||||
$this->dataSet->SetAbsciseLabelSerie("Keys");
|
||||
|
||||
$yLabel = $this->getYLabel();
|
||||
if (empty($yLabel)) {
|
||||
$this->setYLabel($keys[0]);
|
||||
}
|
||||
$xLabel = $this->getXLabel();
|
||||
if (empty($xLabel)) {
|
||||
$this->setXLabel($keys[1]);
|
||||
}
|
||||
|
||||
$this->dataSet->SetXAxisName($this->getXLabel());
|
||||
$this->dataSet->SetYAxisName($this->getYLabel());
|
||||
$this->dataSet->SetSerieName($this->getYLabel(), "Values");
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
@ -1,34 +0,0 @@
|
||||
<?php
|
||||
/* vim: set expandtab sw=4 ts=4 sts=4: */
|
||||
/**
|
||||
* @package phpMyAdmin
|
||||
*/
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
require_once 'pma_pchart_single.php';
|
||||
|
||||
/**
|
||||
* implements single bar chart
|
||||
* @package phpMyAdmin
|
||||
*/
|
||||
class PMA_pChart_single_bar extends PMA_pChart_single
|
||||
{
|
||||
public function __construct($data, $options = null)
|
||||
{
|
||||
parent::__construct($data, $options);
|
||||
}
|
||||
|
||||
/**
|
||||
* draws single bar chart
|
||||
*/
|
||||
protected function drawChart()
|
||||
{
|
||||
// Draw the bar chart
|
||||
// use stacked bar graph function, because it gives bars with alpha
|
||||
$this->chart->drawStackedBarGraph($this->dataSet->GetData(), $this->dataSet->GetDataDescription(), 70);
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
@ -1,34 +0,0 @@
|
||||
<?php
|
||||
/* vim: set expandtab sw=4 ts=4 sts=4: */
|
||||
/**
|
||||
* @package phpMyAdmin
|
||||
*/
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
require_once 'pma_pchart_single.php';
|
||||
|
||||
/**
|
||||
* implements single line chart
|
||||
* @package phpMyAdmin
|
||||
*/
|
||||
class PMA_pChart_single_line extends PMA_pChart_single
|
||||
{
|
||||
public function __construct($data, $options = null)
|
||||
{
|
||||
parent::__construct($data, $options);
|
||||
}
|
||||
|
||||
/**
|
||||
* draws single line chart
|
||||
*/
|
||||
protected function drawChart()
|
||||
{
|
||||
// Draw the line chart
|
||||
$this->chart->drawLineGraph($this->dataSet->GetData(), $this->dataSet->GetDataDescription());
|
||||
$this->chart->drawPlotGraph($this->dataSet->GetData(), $this->dataSet->GetDataDescription(), 3, 1, -1, -1, -1, true);
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
@ -1,96 +0,0 @@
|
||||
<?php
|
||||
/* vim: set expandtab sw=4 ts=4 sts=4: */
|
||||
/**
|
||||
* @package phpMyAdmin
|
||||
*/
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
require_once 'pma_pchart_single.php';
|
||||
|
||||
/**
|
||||
* implements single radar chart
|
||||
* @package phpMyAdmin
|
||||
*/
|
||||
class PMA_pChart_single_radar extends PMA_pChart_single
|
||||
{
|
||||
public function __construct($data, $options = null)
|
||||
{
|
||||
parent::__construct($data, $options);
|
||||
|
||||
$this->normalizeValues();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the largest value from the data and normalize all the other values.
|
||||
*/
|
||||
private function normalizeValues()
|
||||
{
|
||||
$maxValue = 0;
|
||||
$keys = array_keys($this->data);
|
||||
$valueKey = $keys[0];
|
||||
$maxValue = max($this->data[$valueKey]);
|
||||
|
||||
foreach ($this->data[$valueKey] as &$value) {
|
||||
$value = $value / $maxValue * 10;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* graph area for the radar chart does not include grid lines
|
||||
*/
|
||||
protected function drawGraphArea()
|
||||
{
|
||||
$this->chart->drawGraphArea(
|
||||
$this->getGraphAreaColor(RED),
|
||||
$this->getGraphAreaColor(GREEN),
|
||||
$this->getGraphAreaColor(BLUE),
|
||||
false
|
||||
);
|
||||
|
||||
if($this->settings['gradientIntensity']>0)
|
||||
$this->chart->drawGraphAreaGradient(
|
||||
$this->getGraphAreaGradientColor(RED),
|
||||
$this->getGraphAreaGradientColor(GREEN),
|
||||
$this->getGraphAreaGradientColor(BLUE),
|
||||
$this->settings['gradientIntensity']
|
||||
);
|
||||
else
|
||||
$this->chart->drawGraphArea(
|
||||
$this->getGraphAreaGradientColor(RED),
|
||||
$this->getGraphAreaGradientColor(GREEN),
|
||||
$this->getGraphAreaGradientColor(BLUE)
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* draws the radar chart
|
||||
*/
|
||||
protected function drawChart()
|
||||
{
|
||||
// when drawing radar graph we can specify the border from the top of
|
||||
// graph area. We want border to be dynamic, so that either the top
|
||||
// or the side of the radar is some distance away from the top or the
|
||||
// side of the graph area.
|
||||
$areaWidth = $this->chart->GArea_X2 - $this->chart->GArea_X1;
|
||||
$areaHeight = $this->chart->GArea_Y2 - $this->chart->GArea_Y1;
|
||||
|
||||
if ($areaHeight > $areaWidth) {
|
||||
$borderOffset = ($areaHeight - $areaWidth) / 2;
|
||||
}
|
||||
else {
|
||||
$borderOffset = 0;
|
||||
}
|
||||
|
||||
// the least ammount that radar is away from the graph area side.
|
||||
$borderOffset += 40;
|
||||
|
||||
$this->chart->drawRadarAxis($this->dataSet->GetData(), $this->dataSet->GetDataDescription(),
|
||||
true, $borderOffset, 120, 120, 120, 230, 230, 230, -1, 2);
|
||||
$this->chart->drawFilledRadar($this->dataSet->GetData(), $this->dataSet->GetDataDescription(), 50, $borderOffset);
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
@ -1,35 +0,0 @@
|
||||
<?php
|
||||
/* vim: set expandtab sw=4 ts=4 sts=4: */
|
||||
/**
|
||||
* @package phpMyAdmin
|
||||
*/
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
require_once 'pma_pchart_multi.php';
|
||||
|
||||
/**
|
||||
* implements stacked bar chart
|
||||
* @package phpMyAdmin
|
||||
*/
|
||||
class PMA_pChart_stacked_bar extends PMA_pChart_multi
|
||||
{
|
||||
public function __construct($data, $options = null)
|
||||
{
|
||||
parent::__construct($data, $options);
|
||||
}
|
||||
|
||||
/**
|
||||
* draws stacked bar chart
|
||||
*/
|
||||
protected function drawChart()
|
||||
{
|
||||
parent::drawChart();
|
||||
|
||||
// Draw the bar chart
|
||||
$this->chart->drawStackedBarGraph($this->dataSet->GetData(), $this->dataSet->GetDataDescription(), 70);
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
@ -1302,43 +1302,6 @@ function PMA_profilingCheckbox($sql_query)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays the results of SHOW PROFILE
|
||||
*
|
||||
* @param array the results
|
||||
* @param boolean show chart
|
||||
* @access public
|
||||
*
|
||||
*/
|
||||
function PMA_profilingResults($profiling_results, $show_chart = false)
|
||||
{
|
||||
echo '<fieldset><legend>' . __('Profiling') . '</legend>' . "\n";
|
||||
echo '<div style="float: left;">';
|
||||
echo '<table>' . "\n";
|
||||
echo ' <tr>' . "\n";
|
||||
echo ' <th>' . __('Status') . '</th>' . "\n";
|
||||
echo ' <th>' . __('Time') . '</th>' . "\n";
|
||||
echo ' </tr>' . "\n";
|
||||
|
||||
foreach($profiling_results as $one_result) {
|
||||
echo ' <tr>' . "\n";
|
||||
echo '<td>' . $one_result['Status'] . '</td>' . "\n";
|
||||
echo '<td>' . $one_result['Duration'] . '</td>' . "\n";
|
||||
}
|
||||
|
||||
echo '</table>' . "\n";
|
||||
echo '</div>';
|
||||
|
||||
if ($show_chart) {
|
||||
require_once './libraries/chart.lib.php';
|
||||
echo '<div style="float: left;">';
|
||||
PMA_chart_profiling($profiling_results);
|
||||
echo '</div>';
|
||||
}
|
||||
|
||||
echo '</fieldset>' . "\n";
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats $value to byte view
|
||||
*
|
||||
@ -1402,7 +1365,6 @@ function PMA_localizeNumber($value)
|
||||
|
||||
/**
|
||||
* Formats $value to the given length and appends SI prefixes
|
||||
* $comma is not substracted from the length
|
||||
* with a $length of 0 no truncation occurs, number is only formated
|
||||
* to the current locale
|
||||
*
|
||||
@ -1416,10 +1378,11 @@ function PMA_localizeNumber($value)
|
||||
* echo PMA_formatNumber(0, 6); // 0
|
||||
*
|
||||
* </code>
|
||||
* @param double $value the value to format
|
||||
* @param integer $length the max length
|
||||
* @param integer $comma the number of decimals to retain
|
||||
* @param boolean $only_down do not reformat numbers below 1
|
||||
* @param double $value the value to format
|
||||
* @param integer $digits_left number of digits left of the comma
|
||||
* @param integer $digits_right number of digits right of the comma
|
||||
* @param boolean $only_down do not reformat numbers below 1
|
||||
* @param boolean $noTrailingZero removes trailing zeros right of the comma (default: true)
|
||||
*
|
||||
* @return string the formatted value and its unit
|
||||
*
|
||||
@ -1427,13 +1390,15 @@ function PMA_localizeNumber($value)
|
||||
*
|
||||
* @version 1.1.0 - 2005-10-27
|
||||
*/
|
||||
function PMA_formatNumber($value, $length = 3, $comma = 0, $only_down = false)
|
||||
function PMA_formatNumber($value, $digits_left = 3, $digits_right = 0, $only_down = false, $noTrailingZero = true)
|
||||
{
|
||||
if($value==0) return '0';
|
||||
|
||||
$originalValue = $value;
|
||||
//number_format is not multibyte safe, str_replace is safe
|
||||
if ($length === 0) {
|
||||
$value = number_format($value, $comma);
|
||||
if($originalValue!=0 && floatval($value) == 0) $value = ' <'.(1/PMA_pow(10,$comma));
|
||||
if ($digits_left === 0) {
|
||||
$value = number_format($value, $digits_right);
|
||||
if($originalValue!=0 && floatval($value) == 0) $value = ' <'.(1/PMA_pow(10,$digits_right));
|
||||
|
||||
return PMA_localizeNumber($value);
|
||||
}
|
||||
@ -1459,11 +1424,6 @@ function PMA_formatNumber($value, $length = 3, $comma = 0, $only_down = false)
|
||||
8 => 'Y'
|
||||
);
|
||||
|
||||
// we need at least 3 digits to be displayed
|
||||
if (3 > $length + $comma) {
|
||||
$length = 3 - $comma;
|
||||
}
|
||||
|
||||
// check for negative value to retain sign
|
||||
if ($value < 0) {
|
||||
$sign = '-';
|
||||
@ -1472,33 +1432,29 @@ function PMA_formatNumber($value, $length = 3, $comma = 0, $only_down = false)
|
||||
$sign = '';
|
||||
}
|
||||
|
||||
$dh = PMA_pow(10, $comma);
|
||||
$li = PMA_pow(10, $length);
|
||||
$unit = $units[0];
|
||||
|
||||
if ($value >= 1) {
|
||||
for ($d = 8; $d >= 0; $d--) {
|
||||
if (isset($units[$d]) && $value >= $li * PMA_pow(1000, $d-1)) {
|
||||
$value = round($value / (PMA_pow(1000, $d) / $dh)) /$dh;
|
||||
$unit = $units[$d];
|
||||
break 1;
|
||||
} // end if
|
||||
} // end for
|
||||
} elseif (!$only_down && (float) $value !== 0.0) {
|
||||
for ($d = -8; $d <= 8; $d++) {
|
||||
// force using pow() because of the negative exponent
|
||||
if (isset($units[$d]) && $value <= $li * PMA_pow(1000, $d-1, 'pow')) {
|
||||
$value = round($value / (PMA_pow(1000, $d, 'pow') / $dh)) /$dh;
|
||||
$unit = $units[$d];
|
||||
break 1;
|
||||
} // end if
|
||||
} // end for
|
||||
} // end if ($value >= 1) elseif (!$only_down && (float) $value !== 0.0)
|
||||
|
||||
//number_format is not multibyte safe, str_replace is safe
|
||||
$value = PMA_localizeNumber(number_format($value, $comma));
|
||||
$dh = PMA_pow(10, $digits_right);
|
||||
|
||||
if($originalValue!=0 && floatval($value) == 0) return ' <'.(1/PMA_pow(10,$comma)).' '.$unit;
|
||||
// This gives us the right SI prefix already, but $digits_left parameter not incorporated
|
||||
$d = floor(log10($value) / 3);
|
||||
// Lowering the SI prefix by 1 gives us an additional 3 zeros
|
||||
// So if we have 3,6,9,12.. free digits ($digits_left - $cur_digits) to use, then lower the SI prefix
|
||||
$cur_digits = floor(log10($value / PMA_pow(1000, $d, 'pow'))+1);
|
||||
if($digits_left > $cur_digits) {
|
||||
$d-= floor(($digits_left - $cur_digits)/3);
|
||||
}
|
||||
|
||||
if($d<0 && $only_down) $d=0;
|
||||
|
||||
$value = round($value / (PMA_pow(1000, $d, 'pow') / $dh)) /$dh;
|
||||
$unit = $units[$d];
|
||||
|
||||
// If we dont want any zeros after the comma just add the thousand seperator
|
||||
if($noTrailingZero)
|
||||
$value = PMA_localizeNumber(preg_replace("/(?<=\d)(?=(\d{3})+(?!\d))/",",",$value));
|
||||
else
|
||||
$value = PMA_localizeNumber(number_format($value, $digits_right)); //number_format is not multibyte safe, str_replace is safe
|
||||
|
||||
if($originalValue!=0 && floatval($value) == 0) return ' <'.(1/PMA_pow(10,$digits_right)).' '.$unit;
|
||||
|
||||
return $sign . $value . ' ' . $unit;
|
||||
} // end of the 'PMA_formatNumber' function
|
||||
|
||||
@ -2433,8 +2433,12 @@ function PMA_displayResultsOperations($the_disp_mode, $analyzed_sql) {
|
||||
* first table of this database, so that tbl_export.php and
|
||||
* the script it calls do not fail
|
||||
*/
|
||||
if (empty($_url_params['table'])) {
|
||||
if (empty($_url_params['table']) && !empty($_url_params['db'])) {
|
||||
$_url_params['table'] = PMA_DBI_fetch_value("SHOW TABLES");
|
||||
/* No result (probably no database selected) */
|
||||
if ($_url_params['table'] === FALSE) {
|
||||
unset($_url_params['table']);
|
||||
}
|
||||
}
|
||||
|
||||
echo PMA_linkOrButton(
|
||||
|
||||
@ -29,7 +29,7 @@ if (! empty($submit_mult)
|
||||
} else {
|
||||
$selected = $selected_tbl;
|
||||
switch ($submit_mult) {
|
||||
case 'add_prefix_tbl':
|
||||
case 'add_prefix_tbl':
|
||||
case 'replace_prefix_tbl':
|
||||
case 'copy_tbl_change_prefix':
|
||||
case 'drop_db':
|
||||
@ -259,7 +259,7 @@ if (!empty($submit_mult) && !empty($what)) {
|
||||
</table>
|
||||
</fieldset>
|
||||
<fieldset class="tblFooters">
|
||||
<button type="submit" name="mult_btn" value="<?php echo __('Yes'); ?>" id="buttonYes"><? echo __('Submit'); ?></button>
|
||||
<button type="submit" name="mult_btn" value="<?php echo __('Yes'); ?>" id="buttonYes"><?php echo __('Submit'); ?></button>
|
||||
</fieldset>
|
||||
<?php
|
||||
}
|
||||
@ -273,7 +273,7 @@ if (!empty($submit_mult) && !empty($what)) {
|
||||
</table>
|
||||
</fieldset>
|
||||
<fieldset class="tblFooters">
|
||||
<button type="submit" name="mult_btn" value="<?php echo __('Yes'); ?>" id="buttonYes"><? echo __('Submit'); ?></button>
|
||||
<button type="submit" name="mult_btn" value="<?php echo __('Yes'); ?>" id="buttonYes"><?php echo __('Submit'); ?></button>
|
||||
</fieldset>
|
||||
<?php
|
||||
}
|
||||
@ -421,7 +421,7 @@ elseif ($mult_btn == __('Yes')) {
|
||||
. PMA_backquote($selected[$i])
|
||||
. (($i == $selected_cnt-1) ? ');' : '');
|
||||
break;
|
||||
|
||||
|
||||
case 'add_prefix_tbl':
|
||||
$newtablename = $add_prefix . $selected[$i];
|
||||
$a_query = 'ALTER TABLE ' . PMA_backquote($selected[$i]) . ' RENAME ' . PMA_backquote($newtablename) ; // ADD PREFIX TO TABLE NAME
|
||||
|
||||
@ -50,9 +50,9 @@ if (!$GLOBALS['is_ajax_request']) {
|
||||
$tabs['status']['link'] = 'server_status.php';
|
||||
$tabs['status']['text'] = __('Status');
|
||||
|
||||
$tabs['process']['icon'] = 's_process.png';
|
||||
/*$tabs['process']['icon'] = 's_process.png';
|
||||
$tabs['process']['link'] = 'server_processlist.php';
|
||||
$tabs['process']['text'] = __('Processes');
|
||||
$tabs['process']['text'] = __('Processes');*/
|
||||
|
||||
if ($is_superuser) {
|
||||
$tabs['rights']['icon'] = 's_rights.png';
|
||||
|
||||
1452
po/be@latin.po
1452
po/be@latin.po
File diff suppressed because it is too large
Load Diff
1537
po/en_GB.po
1537
po/en_GB.po
File diff suppressed because it is too large
Load Diff
1307
po/phpmyadmin.pot
1307
po/phpmyadmin.pot
File diff suppressed because it is too large
Load Diff
1479
po/pt_BR.po
1479
po/pt_BR.po
File diff suppressed because it is too large
Load Diff
1444
po/sr@latin.po
1444
po/sr@latin.po
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user