diff --git a/Documentation.html b/Documentation.html
index d7c76e16a4..d590a6bb00 100644
--- a/Documentation.html
+++ b/Documentation.html
@@ -4410,13 +4410,43 @@ chmod o+rwx tmp
+ 6.31 How do I create a relation in designer?
To select relation, click :
The display column is shown in pink. To set/unset a column as the display column, click the "Choose column to display" icon, then click on the appropriate column name.
+
+
+ The Zoom search feature is an alternative to table search feature. It allows you to explore
+ a table by representing its data in a scatter plot. You can locate this feature by selecting
+ a table and clicking the 'Search' tab. One of the sub-tabs in the 'Table Search' page is
+ 'Zoom Search'.
+
+ Consider the table REL_persons in
+ FAQ 6.6 for an example. To use zoom search, two columns need to be selected,
+ for example, id and town_code. The id values will be represented on one axis and town_code
+ values on the other axis. Each row will be represented as a point in a scatter plot based
+ on its id and town_code. You can include two additional search criteria apart from the two
+ fields to display.
+
+ You can choose which field should be displayed as label for each point. If a display
+ column has been set for the table (see FAQ 6.7), it is taken as the label unless you specify otherwise.
+ You can also select the maximum number of rows you want to be displayed in the plot by
+ specifing it in the 'Max rows to plot' field. Once you have decided over your criteria,
+ click 'Go' to display the plot.
+
+ After the plot is generated, you can use the mousewheel to zoom in and out of the plot.
+ In addition, panning feature is enabled to navigate through the plot. You can zoom-in to
+ a certail level of detail and use panning to locate your area of interest. Clicking on a
+ point opens a dialogue box, displaying field values of the data row represented by the point.
+ You can edit the values if required and click on submit to issue an update query. Basic
+ instructions on how to use can be viewed by clicking the 'How to use?' link located just above
+ the plot.
+
phpMyAdmin project
diff --git a/js/messages.php b/js/messages.php
index 7bb7bd3fa1..8a606dc6eb 100644
--- a/js/messages.php
+++ b/js/messages.php
@@ -265,7 +265,9 @@ $js_messages['strDisplayHelp'] = '- '
. '
- '
. __('Hovering over a point will show its label.')
. '
- '
- . __('Drag and select an area in the plot to zoom into it.')
+ . __('Use mousewheel to zoom in or out of the plot.')
+ . '
- '
+ . __('Click and drag the mouse to navigate the plot.')
. '
- '
. __('Click reset zoom link to come back to original state.')
. '
- '
diff --git a/js/querywindow.js b/js/querywindow.js
index ba9fe6e18f..55c895a061 100644
--- a/js/querywindow.js
+++ b/js/querywindow.js
@@ -7,36 +7,35 @@ function PMA_queryAutoCommit()
function PMA_querywindowCommit(tab)
{
- document.getElementById('hiddenqueryform').querydisplay_tab.value = tab;
- document.getElementById('hiddenqueryform').submit();
+ $('#hiddenqueryform').find("input[name='querydisplay_tab']").attr("value" ,tab);
+ $('#hiddenqueryform').submit();
return false;
}
function PMA_querywindowSetFocus()
{
- document.getElementById('sqlquery').focus();
+ $('#sqlquery').focus();
}
function PMA_querywindowResize()
{
// for Gecko
- if (typeof(self.sizeToContent) == 'function') {
- self.sizeToContent();
+ if (typeof($(this)[0].sizeToContent) == 'function') {
+ $(this)[0].sizeToContent();
//self.scrollbars.visible = false;
// give some more space ... to prevent 'fli(pp/ck)ing'
- self.resizeBy(10, 50);
+ $(this)[0].resizeBy(10, 50);
return;
}
// for IE, Opera
- if (document.getElementById && typeof(document.getElementById('querywindowcontainer')) != 'undefined') {
-
+ if ($('#querywindowcontainer') != 'undefined') {
// get content size
- var newWidth = document.getElementById('querywindowcontainer').offsetWidth;
- var newHeight = document.getElementById('querywindowcontainer').offsetHeight;
+ var newWidth = $("#querywindowcontainer")[0].offsetWidth;
+ var newHeight = $("#querywindowcontainer")[0].offsetHeight;
// set size to contentsize
// plus some offset for scrollbars, borders, statusbar, menus ...
- self.resizeTo(newWidth + 45, newHeight + 75);
+ $(this)[0].resizeTo(newWidth + 45, newHeight + 75);
}
}
diff --git a/js/tbl_zoom_plot.js b/js/tbl_zoom_plot.js
index 796b543ba2..e773175d7a 100644
--- a/js/tbl_zoom_plot.js
+++ b/js/tbl_zoom_plot.js
@@ -35,7 +35,7 @@ Array.min = function (array) {
/**
** Checks if a string contains only numeric value
- ** @param n: String (to be checked)
+ ** @param n: String (to be checked)
**/
function isNumeric(n) {
return !isNaN(parseFloat(n)) && isFinite(n);
@@ -43,7 +43,7 @@ function isNumeric(n) {
/**
** Checks if an object is empty
- ** @param n: Object (to be checked)
+ ** @param n: Object (to be checked)
**/
function isEmpty(obj) {
var name;
@@ -59,15 +59,15 @@ function isEmpty(obj) {
** @param type String Field type(datetime/timestamp/time/date)
**/
function getDate(val,type) {
- if (type.toString().search(/datetime/i) != -1 || type.toString().search(/timestamp/i) != -1) {
- return Highcharts.dateFormat('%Y-%m-%e %H:%M:%S', val)
- }
- else if (type.toString().search(/time/i) != -1) {
- return Highcharts.dateFormat('%H:%M:%S', val + 19800000)
- }
+ if(type.toString().search(/datetime/i) != -1 || type.toString().search(/timestamp/i) != -1) {
+ return Highcharts.dateFormat('%Y-%m-%e %H:%M:%S', val)
+ }
+ else if(type.toString().search(/time/i) != -1) {
+ return Highcharts.dateFormat('%H:%M:%S', val)
+ }
else if (type.toString().search(/date/i) != -1) {
return Highcharts.dateFormat('%Y-%m-%e', val)
- }
+ }
}
/**
@@ -76,30 +76,30 @@ function getDate(val,type) {
** @param type Sring Field type(datetime/timestamp/time/date)
**/
function getTimeStamp(val,type) {
- if (type.toString().search(/datetime/i) != -1 || type.toString().search(/timestamp/i) != -1) {
- return getDateFromFormat(val,'yyyy-MM-dd HH:mm:ss', val)
- }
- else if (type.toString().search(/time/i) != -1) {
- return getDateFromFormat('1970-01-01 ' + val,'yyyy-MM-dd HH:mm:ss')
- }
+ if(type.toString().search(/datetime/i) != -1 || type.toString().search(/timestamp/i) != -1) {
+ return getDateFromFormat(val,'yyyy-MM-dd HH:mm:ss', val)
+ }
+ else if(type.toString().search(/time/i) != -1) {
+ return getDateFromFormat('1970-01-01 ' + val,'yyyy-MM-dd HH:mm:ss')
+ }
else if (type.toString().search(/date/i) != -1) {
- return getDateFromFormat(val,'yyyy-MM-dd')
- }
+ return getDateFromFormat(val,'yyyy-MM-dd')
+ }
}
/**
** Classifies the field type into numeric,timeseries or text
** @param field: field type (as in database structure)
- **/
+ **/
function getType(field) {
- if (field.toString().search(/int/i) != -1 || field.toString().search(/decimal/i) != -1 || field.toString().search(/year/i) != -1)
- return 'numeric';
- else if (field.toString().search(/time/i) != -1 || field.toString().search(/date/i) != -1)
- return 'time';
- else
- return 'text';
+ if(field.toString().search(/int/i) != -1 || field.toString().search(/decimal/i) != -1 || field.toString().search(/year/i) != -1)
+ return 'numeric';
+ else if(field.toString().search(/time/i) != -1 || field.toString().search(/date/i) != -1)
+ return 'time';
+ else
+ return 'text';
}
-/**
+/**
** Converts a categorical array into numeric array
** @param array categorical values array
**/
@@ -121,6 +121,51 @@ function scrollToChart() {
$('html,body').animate({scrollTop: x}, 500);
}
+/**
+ ** Handlers for panning feature
+ **/
+function includePan(currentChart) {
+ var mouseDown;
+ var lastX;
+ var lastY;
+ var chartWidth = $('#resizer').width() - 3;
+ var chartHeight = $('#resizer').height() - 20;
+ $('#querychart').mousedown(function() {
+ mouseDown = 1;
+ });
+
+ $('#querychart').mouseup(function() {
+ mouseDown = 0;
+ });
+ $('#querychart').mousemove(function(e) {
+ if (mouseDown == 1) {
+ if (e.pageX > lastX) {
+ var xExtremes = currentChart.xAxis[0].getExtremes();
+ var diff = (e.pageX - lastX) * (xExtremes.max - xExtremes.min) / chartWidth;
+ currentChart.xAxis[0].setExtremes(xExtremes.min - diff, xExtremes.max - diff);
+ }
+ else if (e.pageX < lastX) {
+ var xExtremes = currentChart.xAxis[0].getExtremes();
+ var diff = (lastX - e.pageX) * (xExtremes.max - xExtremes.min) / chartWidth;
+ currentChart.xAxis[0].setExtremes(xExtremes.min + diff, xExtremes.max + diff);
+ }
+
+ if (e.pageY > lastY) {
+ var yExtremes = currentChart.yAxis[0].getExtremes();
+ var ydiff = 1.0 * (e.pageY - lastY) * (yExtremes.max - yExtremes.min) / chartHeight;
+ currentChart.yAxis[0].setExtremes(yExtremes.min + ydiff, yExtremes.max + ydiff);
+ }
+ else if (e.pageY < lastY) {
+ var yExtremes = currentChart.yAxis[0].getExtremes();
+ var ydiff = 1.0 * (lastY - e.pageY) * (yExtremes.max - yExtremes.min) / chartHeight;
+ currentChart.yAxis[0].setExtremes(yExtremes.min - ydiff, yExtremes.max - ydiff);
+ }
+ }
+ lastX = e.pageX;
+ lastY = e.pageY;
+ });
+}
+
$(document).ready(function() {
/**
@@ -131,7 +176,7 @@ $(document).ready(function() {
cache: 'false'
});
- var cursorMode = ($("input[name='mode']:checked").val() == 'edit') ? 'crosshair' : 'pointer';
+ var cursorMode = ($("input[name='mode']:checked").val() == 'edit') ? 'crosshair' : 'pointer';
var currentChart = null;
var currentData = null;
var xLabel = $('#tableid_0').val();
@@ -139,8 +184,12 @@ $(document).ready(function() {
var xType = $('#types_0').val();
var yType = $('#types_1').val();
var dataLabel = $('#dataLabel').val();
+ var lastX;
+ var lastY;
+ var zoomRatio = 1;
- // Get query result
+
+ // Get query result
var data = jQuery.parseJSON($('#querydata').html());
/**
@@ -164,16 +213,16 @@ $(document).ready(function() {
/**
* Input form validation
- **/
+ **/
$('#inputFormSubmitId').click(function() {
- if ($('#tableid_0').get(0).selectedIndex == 0 || $('#tableid_1').get(0).selectedIndex == 0)
- PMA_ajaxShowMessage(PMA_messages['strInputNull']);
- else if (xLabel == yLabel)
+ if ($('#tableid_0').get(0).selectedIndex == 0 || $('#tableid_1').get(0).selectedIndex == 0)
+ PMA_ajaxShowMessage(PMA_messages['strInputNull']);
+ else if (xLabel == yLabel)
PMA_ajaxShowMessage(PMA_messages['strSameInputs']);
});
/**
- ** Prepare a div containing a link, otherwise it's incorrectly displayed
+ ** Prepare a div containing a link, otherwise it's incorrectly displayed
** after a couple of clicks
**/
$('')
@@ -191,177 +240,177 @@ $(document).ready(function() {
} else {
$link.text(PMA_messages['strHideSearchCriteria']);
}
- // avoid default click action
- return false;
- });
-
- /**
+ // avoid default click action
+ return false;
+ });
+
+ /**
** Set dialog properties for the data display form
**/
$("#dataDisplay").dialog({
autoOpen: false,
- title: 'Data point content',
+ title: 'Data point content',
modal: false, //false otherwise other dialogues like timepicker may not function properly
height: $('#dataDisplay').height() + 80,
width: $('#dataDisplay').width() + 80
});
/*
- * Handle submit of zoom_display_form
+ * Handle submit of zoom_display_form
*/
-
+
$("#submitForm").click(function(event) {
-
+
//Prevent default submission of form
event.preventDefault();
-
- //Find changed values by comparing form values with selectedRow Object
- var newValues = new Array();//Stores the values changed from original
+
+ //Find changed values by comparing form values with selectedRow Object
+ var newValues = new Array();//Stores the values changed from original
var it = 4;
var xChange = false;
var yChange = false;
- for (key in selectedRow) {
- if (key != 'where_clause'){
- var oldVal = selectedRow[key];
- var newVal = ($('#fields_null_id_' + it).attr('checked')) ? null : $('#fieldID_' + it).val();
- if (oldVal != newVal){
- selectedRow[key] = newVal;
- newValues[key] = newVal;
- if (key == xLabel) {
- xChange = true;
- data[currentData][xLabel] = newVal;
- }
- else if (key == yLabel) {
- yChange = true;
- data[currentData][yLabel] = newVal;
- }
- }
- }
- it++
- }//End data update
-
- //Update the chart series and replot
+ for (key in selectedRow) {
+ if (key != 'where_clause'){
+ var oldVal = selectedRow[key];
+ var newVal = ($('#fields_null_id_' + it).attr('checked')) ? null : $('#fieldID_' + it).val();
+ if (oldVal != newVal){
+ selectedRow[key] = newVal;
+ newValues[key] = newVal;
+ if(key == xLabel) {
+ xChange = true;
+ data[currentData][xLabel] = newVal;
+ }
+ else if(key == yLabel) {
+ yChange = true;
+ data[currentData][yLabel] = newVal;
+ }
+ }
+ }
+ it++
+ }//End data update
+
+ //Update the chart series and replot
if (xChange || yChange) {
- var newSeries = new Array();
- newSeries[0] = new Object();
+ var newSeries = new Array();
+ newSeries[0] = new Object();
newSeries[0].marker = {
symbol: 'circle'
};
- //Logic similar to plot generation, replot only if xAxis changes or yAxis changes. Code includes a lot of checks so as to replot only when necessary
- if (xChange) {
- xCord[currentData] = selectedRow[xLabel];
- if (xType == 'numeric') {
- currentChart.series[0].data[currentData].update({ x : selectedRow[xLabel] });
- currentChart.xAxis[0].setExtremes(Array.min(xCord) - 6,Array.max(xCord) + 6);
+ //Logic similar to plot generation, replot only if xAxis changes or yAxis changes. Code includes a lot of checks so as to replot only when necessary
+ if(xChange) {
+ xCord[currentData] = selectedRow[xLabel];
+ if(xType == 'numeric') {
+ currentChart.series[0].data[currentData].update({ x : selectedRow[xLabel] });
+ currentChart.xAxis[0].setExtremes(Array.min(xCord) - 6,Array.max(xCord) + 6);
}
- else if (xType == 'time') {
- currentChart.series[0].data[currentData].update({ x : getTimeStamp(selectedRow[xLabel],$('#types_0').val())});
- }
- else {
- var tempX = getCord(xCord);
- var tempY = getCord(yCord);
- var i = 0;
- newSeries[0].data = new Array();
- xCord = tempX[2];
- yCord = tempY[2];
+ else if(xType == 'time') {
+ currentChart.series[0].data[currentData].update({ x : getTimeStamp(selectedRow[xLabel],$('#types_0').val())});
+ }
+ else {
+ var tempX = getCord(xCord);
+ var tempY = getCord(yCord);
+ var i = 0;
+ newSeries[0].data = new Array();
+ xCord = tempX[2];
+ yCord = tempY[2];
- $.each(data,function(key,value) {
- if (yType != 'text')
- newSeries[0].data.push({ name: value[dataLabel], x: tempX[0][i], y: value[yLabel], marker: {fillColor: colorCodes[i % 8]} , id: i } );
- else
+ $.each(data,function(key,value) {
+ if(yType != 'text')
+ newSeries[0].data.push({ name: value[dataLabel], x: tempX[0][i], y: value[yLabel], marker: {fillColor: colorCodes[i % 8]} , id: i } );
+ else
newSeries[0].data.push({ name: value[dataLabel], x: tempX[0][i], y: tempY[0][i], marker: {fillColor: colorCodes[i % 8]} , id: i } );
- i++;
+ i++;
});
- currentSettings.xAxis.labels = { formatter : function() {
- if (tempX[1][this.value] && tempX[1][this.value].length > 10)
- return tempX[1][this.value].substring(0,10)
- else
- return tempX[1][this.value];
+ currentSettings.xAxis.labels = { formatter : function() {
+ if(tempX[1][this.value] && tempX[1][this.value].length > 10)
+ return tempX[1][this.value].substring(0,10)
+ else
+ return tempX[1][this.value];
}
}
- currentSettings.series = newSeries;
+ currentSettings.series = newSeries;
currentChart = PMA_createChart(currentSettings);
- }
+ }
- }
- if (yChange) {
+ }
+ if(yChange) {
- yCord[currentData] = selectedRow[yLabel];
- if (yType == 'numeric') {
- currentChart.series[0].data[currentData].update({ y : selectedRow[yLabel] });
- currentChart.yAxis[0].setExtremes(Array.min(yCord) - 6,Array.max(yCord) + 6);
+ yCord[currentData] = selectedRow[yLabel];
+ if(yType == 'numeric') {
+ currentChart.series[0].data[currentData].update({ y : selectedRow[yLabel] });
+ currentChart.yAxis[0].setExtremes(Array.min(yCord) - 6,Array.max(yCord) + 6);
}
- else if (yType =='time') {
- currentChart.series[0].data[currentData].update({ y : getTimeStamp(selectedRow[yLabel],$('#types_1').val())});
- }
- else {
- var tempX = getCord(xCord);
- var tempY = getCord(yCord);
- var i = 0;
- newSeries[0].data = new Array();
- xCord = tempX[2];
- yCord = tempY[2];
+ else if(yType =='time') {
+ currentChart.series[0].data[currentData].update({ y : getTimeStamp(selectedRow[yLabel],$('#types_1').val())});
+ }
+ else {
+ var tempX = getCord(xCord);
+ var tempY = getCord(yCord);
+ var i = 0;
+ newSeries[0].data = new Array();
+ xCord = tempX[2];
+ yCord = tempY[2];
- $.each(data,function(key,value) {
- if (xType != 'text' )
+ $.each(data,function(key,value) {
+ if(xType != 'text' )
newSeries[0].data.push({ name: value[dataLabel], x: value[xLabel], y: tempY[0][i], marker: {fillColor: colorCodes[i % 8]} , id: i } );
- else
+ else
newSeries[0].data.push({ name: value[dataLabel], x: tempX[0][i], y: tempY[0][i], marker: {fillColor: colorCodes[i % 8]} , id: i } );
- i++;
+ i++;
});
- currentSettings.yAxis.labels = { formatter : function() {
- if (tempY[1][this.value] && tempY[1][this.value].length > 10)
- return tempY[1][this.value].substring(0,10)
- else
- return tempY[1][this.value];
+ currentSettings.yAxis.labels = { formatter : function() {
+ if(tempY[1][this.value] && tempY[1][this.value].length > 10)
+ return tempY[1][this.value].substring(0,10)
+ else
+ return tempY[1][this.value];
}
}
- currentSettings.series = newSeries;
- currentChart = PMA_createChart(currentSettings);
- }
- }
- currentChart.series[0].data[currentData].select();
+ currentSettings.series = newSeries;
+ currentChart = PMA_createChart(currentSettings);
+ }
+ }
+ currentChart.series[0].data[currentData].select();
}
- //End plot update
+ //End plot update
- //Generate SQL query for update
- if (!isEmpty(newValues)) {
+ //Generate SQL query for update
+ if (!isEmpty(newValues)) {
var sql_query = 'UPDATE `' + window.parent.table + '` SET ';
- for (key in newValues) {
- if (key != 'where_clause') {
- sql_query += '`' + key + '`=' ;
- var value = newValues[key];
- if (!isNumeric(value) && value != null)
- sql_query += '\'' + value + '\' ,';
- else
- sql_query += value + ' ,';
- }
- }
- sql_query = sql_query.substring(0, sql_query.length - 1);
- sql_query += ' WHERE ' + PMA_urldecode(data[currentData]['where_clause']);
-
- //Post SQL query to sql.php
- $.post('sql.php', {
+ for (key in newValues) {
+ if(key != 'where_clause') {
+ sql_query += '`' + key + '`=' ;
+ var value = newValues[key];
+ if(!isNumeric(value) && value != null)
+ sql_query += '\'' + value + '\' ,';
+ else
+ sql_query += value + ' ,';
+ }
+ }
+ sql_query = sql_query.substring(0, sql_query.length - 1);
+ sql_query += ' WHERE ' + PMA_urldecode(data[currentData]['where_clause']);
+
+ //Post SQL query to sql.php
+ $.post('sql.php', {
'token' : window.parent.token,
'db' : window.parent.db,
'ajax_request' : true,
'sql_query' : sql_query,
- 'inline_edit' : false
- }, function(data) {
- if (data.success == true) {
- $('#sqlqueryresults').html(data.sql_query);
- $("#sqlqueryresults").trigger('appendAnchor');
- }
- else
- PMA_ajaxShowMessage(data.error);
- })//End $.post
- }//End database update
- $("#dataDisplay").dialog("close");
- });//End submit handler
+ 'inline_edit' : false
+ }, function(data) {
+ if(data.success == true) {
+ $('#sqlqueryresults').html(data.sql_query);
+ $("#sqlqueryresults").trigger('appendAnchor');
+ }
+ else
+ PMA_ajaxShowMessage(data.error);
+ })//End $.post
+ }//End database update
+ $("#dataDisplay").dialog("close");
+ });//End submit handler
/*
* Generate plot using Highcharts
- */
+ */
if (data != null) {
$('#zoom_search_form')
@@ -369,87 +418,101 @@ $(document).ready(function() {
.hide();
$('#togglesearchformlink')
.text(PMA_messages['strShowSearchCriteria'])
- $('#togglesearchformdiv').show();
+ $('#togglesearchformdiv').show();
var selectedRow;
- var columnNames = new Array();
- var colorCodes = ['#FF0000','#00FFFF','#0000FF','#0000A0','#FF0080','#800080','#FFFF00','#00FF00','#FF00FF'];
- var series = new Array();
- var xCord = new Array();
- var yCord = new Array();
- var xCat = new Array();
- var yCat = new Array();
- var tempX, tempY;
- var it = 0;
+ var colorCodes = ['#FF0000','#00FFFF','#0000FF','#0000A0','#FF0080','#800080','#FFFF00','#00FF00','#FF00FF'];
+ var series = new Array();
+ var xCord = new Array();
+ var yCord = new Array();
+ var tempX, tempY;
+ var it = 0;
+ var xMax; // xAxis extreme max
+ var xMin; // xAxis extreme min
+ var yMax; // yAxis extreme max
+ var yMin; // yAxis extreme min
// Set the basic plot settings
var currentSettings = {
chart: {
- renderTo: 'querychart',
- type: 'scatter',
- zoomType: 'xy',
- width:$('#resizer').width() -3,
- height:$('#resizer').height()-20
+ renderTo: 'querychart',
+ type: 'scatter',
+ //zoomType: 'xy',
+ width:$('#resizer').width() -3,
+ height:$('#resizer').height()-20
+ },
+ credits: {
+ enabled: false
},
- credits: {
- enabled: false
- },
- exporting: { enabled: false },
+ exporting: { enabled: false },
label: { text: $('#dataLabel').val() },
- plotOptions: {
- series: {
- allowPointSelect: true,
+ plotOptions: {
+ series: {
+ allowPointSelect: true,
cursor: 'pointer',
- showInLegend: false,
+ showInLegend: false,
dataLabels: {
- enabled: false
+ enabled: false,
},
- point: {
+ point: {
events: {
click: function() {
- var id = this.id;
- var fid = 4;
- currentData = id;
- // Make AJAX request to tbl_zoom_select.php for getting the complete row info
- var post_params = {
+ var id = this.id;
+ var fid = 4;
+ currentData = id;
+ // Make AJAX request to tbl_zoom_select.php for getting the complete row info
+ var post_params = {
'ajax_request' : true,
'get_data_row' : true,
'db' : window.parent.db,
'table' : window.parent.table,
'where_clause' : data[id]['where_clause'],
- 'token' : window.parent.token
+ 'token' : window.parent.token,
}
$.post('tbl_zoom_select.php', post_params, function(data) {
- // Row is contained in data.row_info, now fill the displayResultForm with row values
- for ( key in data.row_info) {
- if (data.row_info[key] == null)
- $('#fields_null_id_' + fid).attr('checked', true);
- else
- $('#fieldID_' + fid).val(data.row_info[key]);
- fid++;
- }
- selectedRow = new Object();
- selectedRow = data.row_info;
+ // Row is contained in data.row_info, now fill the displayResultForm with row values
+ for ( key in data.row_info) {
+ if (data.row_info[key] == null)
+ $('#fields_null_id_' + fid).attr('checked', true);
+ else
+ $('#fieldID_' + fid).val(data.row_info[key]);
+ fid++;
+ }
+ selectedRow = new Object();
+ selectedRow = data.row_info;
});
- $("#dataDisplay").dialog("open");
- }
+ $("#dataDisplay").dialog("open");
+ },
}
+ }
+ }
+ },
+ tooltip: {
+ formatter: function() {
+ return this.point.name;
+ }
+ },
+ title: { text: 'Query Results' },
+ xAxis: {
+ title: { text: $('#tableid_0').val() },
+ events: {
+ setExtremes: function(e){
+ this.resetZoom.show();
}
}
- },
- tooltip: {
- formatter: function() {
- return this.point.name;
- }
- },
- title: { text: 'Query Results' },
- xAxis: {
- title: { text: $('#tableid_0').val() }
+
},
yAxis: {
- min: null,
- title: { text: $('#tableid_1').val() }
- }
+ min: null,
+ title: { text: $('#tableid_1').val() },
+ endOnTick: false,
+ startOnTick: false,
+ events: {
+ setExtremes: function(e){
+ this.resetZoom.show();
+ }
+ }
+ },
}
$('#resizer').resizable({
@@ -461,145 +524,185 @@ $(document).ready(function() {
);
}
});
+
+ // Classify types as either numeric,time,text
+ xType = getType(xType);
+ yType = getType(yType);
- // Classify types as either numeric,time,text
- xType = getType(xType);
- yType = getType(yType);
-
- //Set the axis type based on the field
- currentSettings.xAxis.type = (xType == 'time') ? 'datetime' : 'linear';
- currentSettings.yAxis.type = (yType == 'time') ? 'datetime' : 'linear';
+ //Set the axis type based on the field
+ currentSettings.xAxis.type = (xType == 'time') ? 'datetime' : 'linear';
+ currentSettings.yAxis.type = (yType == 'time') ? 'datetime' : 'linear';
// Formulate series data for plot
series[0] = new Object();
series[0].data = new Array();
- series[0].marker = {
+ series[0].marker = {
symbol: 'circle'
};
- if (xType != 'text' && yType != 'text') {
- $.each(data,function(key,value) {
- var xVal = (xType == 'numeric') ? value[xLabel] : getTimeStamp(value[xLabel],$('#types_0').val());
- var yVal = (yType == 'numeric') ? value[yLabel] : getTimeStamp(value[yLabel],$('#types_1').val());
+ if (xType != 'text' && yType != 'text') {
+ $.each(data,function(key,value) {
+ var xVal = (xType == 'numeric') ? value[xLabel] : getTimeStamp(value[xLabel],$('#types_0').val());
+ var yVal = (yType == 'numeric') ? value[yLabel] : getTimeStamp(value[yLabel],$('#types_1').val());
series[0].data.push({ name: value[dataLabel], x: xVal, y: yVal, marker: {fillColor: colorCodes[it % 8]} , id: it } );
- xCord.push(value[xLabel]);
- yCord.push(value[yLabel]);
- it++;
+ xCord.push(value[xLabel]);
+ yCord.push(value[yLabel]);
+ it++;
});
- if (xType == 'numeric') {
- currentSettings.xAxis.max = Array.max(xCord) + 6
- currentSettings.xAxis.min = Array.min(xCord) - 6
+ if(xType == 'numeric') {
+ currentSettings.xAxis.max = Array.max(xCord) + 6
+ currentSettings.xAxis.min = Array.min(xCord) - 6
+ }
+ else {
+ currentSettings.xAxis.labels = { formatter : function() {
+ return getDate(this.value, $('#types_0').val());
+ }}
}
- else {
- currentSettings.xAxis.labels = { formatter : function() {
- return getDate(this.value, $('#types_0').val());
- }}
- }
- if (yType == 'numeric') {
- currentSettings.yAxis.max = Array.max(yCord) + 6
- currentSettings.yAxis.min = Array.min(yCord) - 6
- }
- else {
- currentSettings.yAxis.labels = { formatter : function() {
- return getDate(this.value, $('#types_1').val());
- }}
+ if(yType == 'numeric') {
+ currentSettings.yAxis.max = Array.max(yCord) + 6
+ currentSettings.yAxis.min = Array.min(yCord) - 6
+ }
+ else {
+ currentSettings.yAxis.labels = { formatter : function() {
+ return getDate(this.value, $('#types_1').val());
+ }}
}
}
-
- else if (xType =='text' && yType !='text') {
- $.each(data,function(key,value) {
- xCord.push(value[xLabel]);
- yCord.push(value[yLabel]);
- });
-
- tempX = getCord(xCord);
- $.each(data,function(key,value) {
- var yVal = (yType == 'numeric') ? value[yLabel] : getTimeStamp(value[yLabel],$('#types_1').val());
+
+ else if (xType =='text' && yType !='text') {
+ $.each(data,function(key,value) {
+ xCord.push(value[xLabel]);
+ yCord.push(value[yLabel]);
+ });
+
+ tempX = getCord(xCord);
+ $.each(data,function(key,value) {
+ var yVal = (yType == 'numeric') ? value[yLabel] : getTimeStamp(value[yLabel],$('#types_1').val());
series[0].data.push({ name: value[dataLabel], x: tempX[0][it], y: yVal, marker: {fillColor: colorCodes[it % 8]} , id: it } );
- it++;
+ it++;
});
-
- currentSettings.xAxis.labels = { formatter : function() {
- if (tempX[1][this.value] && tempX[1][this.value].length > 10)
- return tempX[1][this.value].substring(0,10)
- else
- return tempX[1][this.value];
- }
+
+ currentSettings.xAxis.labels = { formatter : function() {
+ if(tempX[1][this.value] && tempX[1][this.value].length > 10)
+ return tempX[1][this.value].substring(0,10)
+ else
+ return tempX[1][this.value];
+ }
}
- if (yType == 'numeric') {
- currentSettings.yAxis.max = Array.max(yCord) + 6
- currentSettings.yAxis.min = Array.min(yCord) - 6
+ if(yType == 'numeric') {
+ currentSettings.yAxis.max = Array.max(yCord) + 6
+ currentSettings.yAxis.min = Array.min(yCord) - 6
+ }
+ else {
+ currentSettings.yAxis.labels = { formatter : function() {
+ return getDate(this.value, $('#types_1').val());
+ }}
}
- else {
- currentSettings.yAxis.labels = { formatter : function() {
- return getDate(this.value, $('#types_1').val());
- }}
- }
- xCord = tempX[2];
- }
-
- else if (xType !='text' && yType =='text') {
- $.each(data,function(key,value) {
- xCord.push(value[xLabel]);
- yCord.push(value[yLabel]);
- });
- tempY = getCord(yCord);
- $.each(data,function(key,value) {
- var xVal = (xType == 'numeric') ? value[xLabel] : getTimeStamp(value[xLabel],$('#types_0').val());
+ xCord = tempX[2];
+ }
+
+ else if (xType !='text' && yType =='text') {
+ $.each(data,function(key,value) {
+ xCord.push(value[xLabel]);
+ yCord.push(value[yLabel]);
+ });
+ tempY = getCord(yCord);
+ $.each(data,function(key,value) {
+ var xVal = (xType == 'numeric') ? value[xLabel] : getTimeStamp(value[xLabel],$('#types_0').val());
series[0].data.push({ name: value[dataLabel], y: tempY[0][it], x: xVal, marker: {fillColor: colorCodes[it % 8]} , id: it } );
- it++;
+ it++;
});
- if (xType == 'numeric') {
- currentSettings.xAxis.max = Array.max(xCord) + 6
- currentSettings.xAxis.min = Array.min(xCord) - 6
+ if(xType == 'numeric') {
+ currentSettings.xAxis.max = Array.max(xCord) + 6
+ currentSettings.xAxis.min = Array.min(xCord) - 6
+ }
+ else {
+ currentSettings.xAxis.labels = { formatter : function() {
+ return getDate(this.value, $('#types_0').val());
+ }}
}
- else {
- currentSettings.xAxis.labels = { formatter : function() {
- return getDate(this.value, $('#types_0').val());
- }}
+ currentSettings.yAxis.labels = { formatter : function() {
+ if(tempY[1][this.value] && tempY[1][this.value].length > 10)
+ return tempY[1][this.value].substring(0,10)
+ else
+ return tempY[1][this.value];
+ }
}
- currentSettings.yAxis.labels = { formatter : function() {
- if (tempY[1][this.value] && tempY[1][this.value].length > 10)
- return tempY[1][this.value].substring(0,10)
- else
- return tempY[1][this.value];
- }
- }
- yCord = tempY[2];
- }
-
- else if (xType =='text' && yType =='text') {
- $.each(data,function(key,value) {
- xCord.push(value[xLabel]);
- yCord.push(value[yLabel]);
- });
- tempX = getCord(xCord);
- tempY = getCord(yCord);
- $.each(data,function(key,value) {
+ yCord = tempY[2];
+ }
+
+ else if (xType =='text' && yType =='text') {
+ $.each(data,function(key,value) {
+ xCord.push(value[xLabel]);
+ yCord.push(value[yLabel]);
+ });
+ tempX = getCord(xCord);
+ tempY = getCord(yCord);
+ $.each(data,function(key,value) {
series[0].data.push({ name: value[dataLabel], x: tempX[0][it], y: tempY[0][it], marker: {fillColor: colorCodes[it % 8]} , id: it } );
- it++;
+ it++;
});
- currentSettings.xAxis.labels = { formatter : function() {
- if (tempX[1][this.value] && tempX[1][this.value].length > 10) {
- return tempX[1][this.value].substring(0,10)
- } else {
- return tempX[1][this.value];
- }
- }};
- currentSettings.yAxis.labels = { formatter : function() {
- if (tempY[1][this.value] && tempY[1][this.value].length > 10) {
- return tempY[1][this.value].substring(0,10);
- } else {
- return tempY[1][this.value];
- }
- }};
- xCord = tempX[2];
- yCord = tempY[2];
+ currentSettings.xAxis.labels = { formatter : function() {
+ if(tempX[1][this.value] && tempX[1][this.value].length > 10)
+ return tempX[1][this.value].substring(0,10)
+ else
+ return tempX[1][this.value];
+ }
+ }
+ currentSettings.yAxis.labels = { formatter : function() {
+ if(tempY[1][this.value] && tempY[1][this.value].length > 10)
+ return tempY[1][this.value].substring(0,10)
+ else
+ return tempY[1][this.value];
+ }
+ }
+ xCord = tempX[2];
+ yCord = tempY[2];
- }
+ }
- currentSettings.series = series;
+ currentSettings.series = series;
currentChart = PMA_createChart(currentSettings);
- scrollToChart();
+ xMin = currentChart.xAxis[0].getExtremes().min;
+ xMax = currentChart.xAxis[0].getExtremes().max;
+ yMin = currentChart.yAxis[0].getExtremes().min;
+ yMax = currentChart.yAxis[0].getExtremes().max;
+ includePan(currentChart); //Enable panning feature
+ var setZoom = function() {
+ var newxm = xMin + (xMax - xMin) * (1 - zoomRatio) / 2;
+ var newxM = xMax - (xMax - xMin) * (1 - zoomRatio) / 2;
+ var newym = yMin + (yMax - yMin) * (1 - zoomRatio) / 2;
+ var newyM = yMax - (yMax - yMin) * (1 - zoomRatio) / 2;
+ currentChart.xAxis[0].setExtremes(newxm,newxM);
+ currentChart.yAxis[0].setExtremes(newym,newyM);
+ };
+ //Enable zoom feature
+ $("#querychart").mousewheel(function(objEvent, intDelta) {
+ if (intDelta > 0) {
+ if (zoomRatio > 0.1) {
+ zoomRatio = zoomRatio - 0.1;
+ setZoom();
+ }
+ }
+ else if (intDelta < 0) {
+ zoomRatio = zoomRatio + 0.1;
+ setZoom();
+ }
+ });
+ //Add reset zoom feature
+ currentChart.yAxis[0].resetZoom = currentChart.xAxis[0].resetZoom = $('Reset zoom')
+ .appendTo(currentChart.container)
+ .css({
+ position: 'absolute',
+ top: 10,
+ right: 20,
+ display: 'none'
+ })
+ .click(function(){
+ currentChart.xAxis[0].setExtremes(null, null)
+ currentChart.yAxis[0].setExtremes(null, null)
+ this.style.display = 'none'
+ });
+ scrollToChart();
}
});
diff --git a/libraries/advisory_rules.txt b/libraries/advisory_rules.txt
index c3445e09fe..7745157436 100644
--- a/libraries/advisory_rules.txt
+++ b/libraries/advisory_rules.txt
@@ -214,7 +214,6 @@ rule 'Rate of reading first index entry'
This usually indicates frequent full index scans. Full index scans are faster than table scans but require lots of CPU cycles in big tables, if those tables that have or had high volumes of UPDATEs and DELETEs, running 'OPTIMIZE TABLE' might reduce the amount of and/or speed up full index scans. Other than that full index scans can only be reduced by rewriting queries.
Index scans average: %s, this value should be less than 1 per hour | PMA_bytime(value,2)
-# This rule may be applicable to MyISAM-only workloads, but completely wrong for InnoDB - http://www.mysqlperformanceblog.com/2010/06/15/what-does-handler_read_rnd-mean/
rule 'Rate of reading fixed position'
Handler_read_rnd / Uptime
value * 60 * 60 > 1
diff --git a/tbl_zoom_select.php b/tbl_zoom_select.php
index 3942e0003e..518121d95a 100644
--- a/tbl_zoom_select.php
+++ b/tbl_zoom_select.php
@@ -21,6 +21,7 @@ $GLOBALS['js_include'][] = 'sql.js';
$GLOBALS['js_include'][] = 'functions.js';
$GLOBALS['js_include'][] = 'tbl_zoom_plot.js';
$GLOBALS['js_include'][] = 'date.js';
+$GLOBALS['js_include'][] = 'jquery/jquery.mousewheel.js';
$GLOBALS['js_include'][] = 'highcharts/highcharts.js';
/* Files required for chart exporting */
$GLOBALS['js_include'][] = 'highcharts/exporting.js';