1 /* vim: set expandtab sw=4 ts=4 sts=4: */
3 ** @fileoverview JavaScript functions used on tbl_select.php
6 ** @requires js/functions.js
13 function displayHelp() {
14 var msgbox
= PMA_ajaxShowMessage(PMA_messages
['strDisplayHelp'],10000);
15 msgbox
.click(function() {
16 PMA_ajaxRemoveMessage(msgbox
);
21 ** Extend the array object for max function
24 Array
.max = function (array
) {
25 return Math
.max
.apply( Math
, array
);
29 ** Extend the array object for min function
32 Array
.min = function (array
) {
33 return Math
.min
.apply( Math
, array
);
37 ** Checks if a string contains only numeric value
38 ** @param n: String (to be checked)
40 function isNumeric(n
) {
41 return !isNaN(parseFloat(n
)) && isFinite(n
);
45 ** Checks if an object is empty
46 ** @param n: Object (to be checked)
48 function isEmpty(obj
) {
57 ** Converts a timestamp into the format of its field type
58 ** @param val Integer Timestamp
59 ** @param type String Field type(datetime/timestamp/time/date)
61 function getDate(val
,type
) {
62 if (type
.toString().search(/datetime/i) != -1 || type
.toString().search(/timestamp/i) != -1) {
63 return Highcharts
.dateFormat('%Y-%m-%e %H:%M:%S', val
)
65 else if (type
.toString().search(/time/i) != -1) {
66 return Highcharts
.dateFormat('%H:%M:%S', val
+ 19800000)
68 else if (type
.toString().search(/date/i) != -1) {
69 return Highcharts
.dateFormat('%Y-%m-%e', val
)
74 ** Converts a date/time into timestamp
75 ** @param val String Date
76 ** @param type Sring Field type(datetime/timestamp/time/date)
78 function getTimeStamp(val
,type
) {
79 if (type
.toString().search(/datetime/i) != -1 || type
.toString().search(/timestamp/i) != -1) {
80 return getDateFromFormat(val
,'yyyy-MM-dd HH:mm:ss', val
)
82 else if (type
.toString().search(/time/i) != -1) {
83 return getDateFromFormat('1970-01-01 ' + val
,'yyyy-MM-dd HH:mm:ss')
85 else if (type
.toString().search(/date/i) != -1) {
86 return getDateFromFormat(val
,'yyyy-MM-dd')
91 ** Classifies the field type into numeric,timeseries or text
92 ** @param field: field type (as in database structure)
94 function getType(field
) {
95 if (field
.toString().search(/int/i) != -1 || field
.toString().search(/decimal/i) != -1 || field
.toString().search(/year/i) != -1)
97 else if (field
.toString().search(/time/i) != -1 || field
.toString().search(/date/i) != -1)
103 ** Converts a categorical array into numeric array
104 ** @param array categorical values array
106 function getCord(arr
) {
107 var newCord
= new Array();
108 var original
= $.extend(true,[],arr
);
109 var arr
= jQuery
.unique(arr
).sort();
110 $.each(original
, function(index
,value
) {
111 newCord
.push(jQuery
.inArray(value
,arr
));
113 return [newCord
,arr
,original
];
117 ** Scrolls the view to the display section
119 function scrollToChart() {
120 var x
= $('#dataDisplay').offset().top
- 100; // 100 provides buffer in viewport
121 $('html,body').animate({scrollTop
: x
}, 500);
124 $(document
).ready(function() {
127 ** Set a parameter for all Ajax queries made on this page. Don't let the
128 ** web server serve cached pages
134 var cursorMode
= ($("input[name='mode']:checked").val() == 'edit') ? 'crosshair' : 'pointer';
135 var currentChart
= null;
136 var currentData
= null;
137 var xLabel
= $('#tableid_0').val();
138 var yLabel
= $('#tableid_1').val();
139 var xType
= $('#types_0').val();
140 var yType
= $('#types_1').val();
141 var dataLabel
= $('#dataLabel').val();
144 var data
= jQuery
.parseJSON($('#querydata').html());
147 ** Input form submit on field change
149 $('#tableid_0').change(function() {
150 $('#zoom_search_form').submit();
153 $('#tableid_1').change(function() {
154 $('#zoom_search_form').submit();
157 $('#tableid_2').change(function() {
158 $('#zoom_search_form').submit();
161 $('#tableid_3').change(function() {
162 $('#zoom_search_form').submit();
166 * Input form validation
168 $('#inputFormSubmitId').click(function() {
169 if ($('#tableid_0').get(0).selectedIndex
== 0 || $('#tableid_1').get(0).selectedIndex
== 0)
170 PMA_ajaxShowMessage(PMA_messages
['strInputNull']);
171 else if (xLabel
== yLabel
)
172 PMA_ajaxShowMessage(PMA_messages
['strSameInputs']);
176 ** Prepare a div containing a link, otherwise it's incorrectly displayed
177 ** after a couple of clicks
179 $('<div id="togglesearchformdiv"><a id="togglesearchformlink"></a></div>')
180 .insertAfter('#zoom_search_form')
181 // don't show it until we have results on-screen
184 $('#togglesearchformlink')
185 .html(PMA_messages
['strShowSearchCriteria'])
186 .bind('click', function() {
188 $('#zoom_search_form').slideToggle();
189 if ($link
.text() == PMA_messages
['strHideSearchCriteria']) {
190 $link
.text(PMA_messages
['strShowSearchCriteria']);
192 $link
.text(PMA_messages
['strHideSearchCriteria']);
194 // avoid default click action
199 ** Set dialog properties for the data display form
201 $("#dataDisplay").dialog({
203 title
: 'Data point content',
204 modal
: false, //false otherwise other dialogues like timepicker may not function properly
205 height
: $('#dataDisplay').height() + 80,
206 width
: $('#dataDisplay').width() + 80
210 * Handle submit of zoom_display_form
213 $("#submitForm").click(function(event
) {
215 //Prevent default submission of form
216 event
.preventDefault();
218 //Find changed values by comparing form values with selectedRow Object
219 var newValues
= new Array();//Stores the values changed from original
223 for (key
in selectedRow
) {
224 if (key
!= 'where_clause'){
225 var oldVal
= selectedRow
[key
];
226 var newVal
= ($('#fields_null_id_' + it
).attr('checked')) ? null : $('#fieldID_' + it
).val();
227 if (oldVal
!= newVal
){
228 selectedRow
[key
] = newVal
;
229 newValues
[key
] = newVal
;
232 data
[currentData
][xLabel
] = newVal
;
234 else if (key
== yLabel
) {
236 data
[currentData
][yLabel
] = newVal
;
243 //Update the chart series and replot
244 if (xChange
|| yChange
) {
245 var newSeries
= new Array();
246 newSeries
[0] = new Object();
247 newSeries
[0].marker
= {
250 //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
252 xCord
[currentData
] = selectedRow
[xLabel
];
253 if (xType
== 'numeric') {
254 currentChart
.series
[0].data
[currentData
].update({ x
: selectedRow
[xLabel
] });
255 currentChart
.xAxis
[0].setExtremes(Array
.min(xCord
) - 6,Array
.max(xCord
) + 6);
257 else if (xType
== 'time') {
258 currentChart
.series
[0].data
[currentData
].update({ x
: getTimeStamp(selectedRow
[xLabel
],$('#types_0').val())});
261 var tempX
= getCord(xCord
);
262 var tempY
= getCord(yCord
);
264 newSeries
[0].data
= new Array();
268 $.each(data
,function(key
,value
) {
270 newSeries
[0].data
.push({ name
: value
[dataLabel
], x
: tempX
[0][i
], y
: value
[yLabel
], marker
: {fillColor
: colorCodes
[i
% 8]} , id
: i
} );
272 newSeries
[0].data
.push({ name
: value
[dataLabel
], x
: tempX
[0][i
], y
: tempY
[0][i
], marker
: {fillColor
: colorCodes
[i
% 8]} , id
: i
} );
275 currentSettings
.xAxis
.labels
= { formatter : function() {
276 if (tempX
[1][this.value
] && tempX
[1][this.value
].length
> 10)
277 return tempX
[1][this.value
].substring(0,10)
279 return tempX
[1][this.value
];
282 currentSettings
.series
= newSeries
;
283 currentChart
= PMA_createChart(currentSettings
);
289 yCord
[currentData
] = selectedRow
[yLabel
];
290 if (yType
== 'numeric') {
291 currentChart
.series
[0].data
[currentData
].update({ y
: selectedRow
[yLabel
] });
292 currentChart
.yAxis
[0].setExtremes(Array
.min(yCord
) - 6,Array
.max(yCord
) + 6);
294 else if (yType
=='time') {
295 currentChart
.series
[0].data
[currentData
].update({ y
: getTimeStamp(selectedRow
[yLabel
],$('#types_1').val())});
298 var tempX
= getCord(xCord
);
299 var tempY
= getCord(yCord
);
301 newSeries
[0].data
= new Array();
305 $.each(data
,function(key
,value
) {
306 if (xType
!= 'text' )
307 newSeries
[0].data
.push({ name
: value
[dataLabel
], x
: value
[xLabel
], y
: tempY
[0][i
], marker
: {fillColor
: colorCodes
[i
% 8]} , id
: i
} );
309 newSeries
[0].data
.push({ name
: value
[dataLabel
], x
: tempX
[0][i
], y
: tempY
[0][i
], marker
: {fillColor
: colorCodes
[i
% 8]} , id
: i
} );
312 currentSettings
.yAxis
.labels
= { formatter : function() {
313 if (tempY
[1][this.value
] && tempY
[1][this.value
].length
> 10)
314 return tempY
[1][this.value
].substring(0,10)
316 return tempY
[1][this.value
];
319 currentSettings
.series
= newSeries
;
320 currentChart
= PMA_createChart(currentSettings
);
323 currentChart
.series
[0].data
[currentData
].select();
327 //Generate SQL query for update
328 if (!isEmpty(newValues
)) {
329 var sql_query
= 'UPDATE `' + window
.parent
.table
+ '` SET ';
330 for (key
in newValues
) {
331 if (key
!= 'where_clause') {
332 sql_query
+= '`' + key
+ '`=' ;
333 var value
= newValues
[key
];
334 if (!isNumeric(value
) && value
!= null)
335 sql_query
+= '\'' + value
+ '\' ,';
337 sql_query
+= value
+ ' ,';
340 sql_query
= sql_query
.substring(0, sql_query
.length
- 1);
341 sql_query
+= ' WHERE ' + PMA_urldecode(data
[currentData
]['where_clause']);
343 //Post SQL query to sql.php
345 'token' : window
.parent
.token
,
346 'db' : window
.parent
.db
,
347 'ajax_request' : true,
348 'sql_query' : sql_query
,
349 'inline_edit' : false
351 if (data
.success
== true) {
352 $('#sqlqueryresults').html(data
.sql_query
);
353 $("#sqlqueryresults").trigger('appendAnchor');
356 PMA_ajaxShowMessage(data
.error
);
358 }//End database update
359 $("#dataDisplay").dialog("close");
360 });//End submit handler
363 * Generate plot using Highcharts
367 $('#zoom_search_form')
370 $('#togglesearchformlink')
371 .text(PMA_messages
['strShowSearchCriteria'])
372 $('#togglesearchformdiv').show();
374 var columnNames
= new Array();
375 var colorCodes
= ['#FF0000','#00FFFF','#0000FF','#0000A0','#FF0080','#800080','#FFFF00','#00FF00','#FF00FF'];
376 var series
= new Array();
377 var xCord
= new Array();
378 var yCord
= new Array();
379 var xCat
= new Array();
380 var yCat
= new Array();
384 // Set the basic plot settings
385 var currentSettings
= {
387 renderTo
: 'querychart',
390 width
:$('#resizer').width() -3,
391 height
:$('#resizer').height()-20
396 exporting
: { enabled
: false },
397 label
: { text
: $('#dataLabel').val() },
400 allowPointSelect
: true,
412 // Make AJAX request to tbl_zoom_select.php for getting the complete row info
414 'ajax_request' : true,
415 'get_data_row' : true,
416 'db' : window
.parent
.db
,
417 'table' : window
.parent
.table
,
418 'where_clause' : data
[id
]['where_clause'],
419 'token' : window
.parent
.token
421 $.post('tbl_zoom_select.php', post_params
, function(data
) {
422 // Row is contained in data.row_info, now fill the displayResultForm with row values
423 for ( key
in data
.row_info
) {
424 if (data
.row_info
[key
] == null)
425 $('#fields_null_id_' + fid
).attr('checked', true);
427 $('#fieldID_' + fid
).val(data
.row_info
[key
]);
430 selectedRow
= new Object();
431 selectedRow
= data
.row_info
;
434 $("#dataDisplay").dialog("open");
441 formatter: function() {
442 return this.point
.name
;
445 title
: { text
: 'Query Results' },
447 title
: { text
: $('#tableid_0').val() }
451 title
: { text
: $('#tableid_1').val() }
455 $('#resizer').resizable({
457 currentChart
.setSize(
459 this.offsetHeight
-20,
465 // Classify types as either numeric,time,text
466 xType
= getType(xType
);
467 yType
= getType(yType
);
469 //Set the axis type based on the field
470 currentSettings
.xAxis
.type
= (xType
== 'time') ? 'datetime' : 'linear';
471 currentSettings
.yAxis
.type
= (yType
== 'time') ? 'datetime' : 'linear';
473 // Formulate series data for plot
474 series
[0] = new Object();
475 series
[0].data
= new Array();
479 if (xType
!= 'text' && yType
!= 'text') {
480 $.each(data
,function(key
,value
) {
481 var xVal
= (xType
== 'numeric') ? value
[xLabel
] : getTimeStamp(value
[xLabel
],$('#types_0').val());
482 var yVal
= (yType
== 'numeric') ? value
[yLabel
] : getTimeStamp(value
[yLabel
],$('#types_1').val());
483 series
[0].data
.push({ name
: value
[dataLabel
], x
: xVal
, y
: yVal
, marker
: {fillColor
: colorCodes
[it
% 8]} , id
: it
} );
484 xCord
.push(value
[xLabel
]);
485 yCord
.push(value
[yLabel
]);
488 if (xType
== 'numeric') {
489 currentSettings
.xAxis
.max
= Array
.max(xCord
) + 6
490 currentSettings
.xAxis
.min
= Array
.min(xCord
) - 6
493 currentSettings
.xAxis
.labels
= { formatter : function() {
494 return getDate(this.value
, $('#types_0').val());
497 if (yType
== 'numeric') {
498 currentSettings
.yAxis
.max
= Array
.max(yCord
) + 6
499 currentSettings
.yAxis
.min
= Array
.min(yCord
) - 6
502 currentSettings
.yAxis
.labels
= { formatter : function() {
503 return getDate(this.value
, $('#types_1').val());
509 else if (xType
=='text' && yType
!='text') {
510 $.each(data
,function(key
,value
) {
511 xCord
.push(value
[xLabel
]);
512 yCord
.push(value
[yLabel
]);
515 tempX
= getCord(xCord
);
516 $.each(data
,function(key
,value
) {
517 var yVal
= (yType
== 'numeric') ? value
[yLabel
] : getTimeStamp(value
[yLabel
],$('#types_1').val());
518 series
[0].data
.push({ name
: value
[dataLabel
], x
: tempX
[0][it
], y
: yVal
, marker
: {fillColor
: colorCodes
[it
% 8]} , id
: it
} );
522 currentSettings
.xAxis
.labels
= { formatter : function() {
523 if (tempX
[1][this.value
] && tempX
[1][this.value
].length
> 10)
524 return tempX
[1][this.value
].substring(0,10)
526 return tempX
[1][this.value
];
529 if (yType
== 'numeric') {
530 currentSettings
.yAxis
.max
= Array
.max(yCord
) + 6
531 currentSettings
.yAxis
.min
= Array
.min(yCord
) - 6
534 currentSettings
.yAxis
.labels
= { formatter : function() {
535 return getDate(this.value
, $('#types_1').val());
541 else if (xType
!='text' && yType
=='text') {
542 $.each(data
,function(key
,value
) {
543 xCord
.push(value
[xLabel
]);
544 yCord
.push(value
[yLabel
]);
546 tempY
= getCord(yCord
);
547 $.each(data
,function(key
,value
) {
548 var xVal
= (xType
== 'numeric') ? value
[xLabel
] : getTimeStamp(value
[xLabel
],$('#types_0').val());
549 series
[0].data
.push({ name
: value
[dataLabel
], y
: tempY
[0][it
], x
: xVal
, marker
: {fillColor
: colorCodes
[it
% 8]} , id
: it
} );
552 if (xType
== 'numeric') {
553 currentSettings
.xAxis
.max
= Array
.max(xCord
) + 6
554 currentSettings
.xAxis
.min
= Array
.min(xCord
) - 6
557 currentSettings
.xAxis
.labels
= { formatter : function() {
558 return getDate(this.value
, $('#types_0').val());
561 currentSettings
.yAxis
.labels
= { formatter : function() {
562 if (tempY
[1][this.value
] && tempY
[1][this.value
].length
> 10)
563 return tempY
[1][this.value
].substring(0,10)
565 return tempY
[1][this.value
];
571 else if (xType
=='text' && yType
=='text') {
572 $.each(data
,function(key
,value
) {
573 xCord
.push(value
[xLabel
]);
574 yCord
.push(value
[yLabel
]);
576 tempX
= getCord(xCord
);
577 tempY
= getCord(yCord
);
578 $.each(data
,function(key
,value
) {
579 series
[0].data
.push({ name
: value
[dataLabel
], x
: tempX
[0][it
], y
: tempY
[0][it
], marker
: {fillColor
: colorCodes
[it
% 8]} , id
: it
} );
582 currentSettings
.xAxis
.labels
= { formatter : function() {
583 if (tempX
[1][this.value
] && tempX
[1][this.value
].length
> 10) {
584 return tempX
[1][this.value
].substring(0,10)
586 return tempX
[1][this.value
];
589 currentSettings
.yAxis
.labels
= { formatter : function() {
590 if (tempY
[1][this.value
] && tempY
[1][this.value
].length
> 10) {
591 return tempY
[1][this.value
].substring(0,10);
593 return tempY
[1][this.value
];
601 currentSettings
.series
= series
;
602 currentChart
= PMA_createChart(currentSettings
);