The branch, master has been updated via 9147f30dc6b00dc63c998f1d2d3972d1a47e6c57 (commit) via 8f7312956d76eefd1fbf9567a3bb18634e8db560 (commit) via 1b7e2f6c7be6c7a96d780a7e9870d498f84e7339 (commit) via ae5ef42beff0475de4a841ff18953e4f66880c40 (commit) via 67dc02f23db70391220dc0336f2110645a34a9d2 (commit) via 557734c57f45e24abae08a031dde25dab73f1a05 (commit) via 201331275bff7e3e67e3d5f3fb2bc706e302ad27 (commit) via e3cb99d540a305caaa58f91d71a5f87d96f28e50 (commit) via 57af6f950289ce2283ebe0d4d56b68119b75322b (commit) via 33ad955596696415c0cfe0422a067f64f95d1d15 (commit) via 241caff7818f69531400eecd1ea63849009bffa9 (commit) via e4b676e3567f2992d9b77f623d328af2fa90cef8 (commit) via 7880782588e1609dac657a3c2b2f5a3630929859 (commit) via 00c420c74b4663fddf0b5fc47ac50fdd15dd23c6 (commit) via df0848fa9c94a100d153cb4500d723566e8c25c0 (commit) via e83f3acd26fbfb51366cae9b184e69e5376ae10d (commit) via 32969f3d4211a96575e2fd7e609cc21ddc63bbaf (commit) via 9388cd35b643ea65473ffa95cdf21213bcc4785f (commit) via cb63a92b44a3ab1ee38ec66d63d33432a6273f94 (commit) via d9486e259721b812cb0cd56ca057e55359250cc9 (commit) via e09759bef84ae8113f2e468117be66fb43d4b932 (commit) via 18a6f0b0701457dd6a33d6517915c89729d1c11c (commit) via 6cc3ff46f853960bdc90eb00fd595591e6a26f2e (commit) via 95ea722d73fc635b4b27c6731aeedfd430628ce8 (commit) via bedd413217a87770852671c4a2b211ca067df5e0 (commit) via 830f2fdaa72a05497448b5b83b6fb961bf2bd7d2 (commit) via 7c66a8bed58fffd66becd643c845027e57e43862 (commit) via b6cb93b017ddd35ab7c2083591228a9874eab60d (commit) via 1ce7ea6fb0180722ffadd056b565f63eaf215d4f (commit) via 36ec09e6ccec0f46ebc1c92b8c8bc5a396b9a136 (commit) via c01e39a716c5ba33d00ff45f1791d3094fe1c777 (commit) via 04e82bb1e908e233f1eb619324b84b18312282d7 (commit) via 811996e92a9365afc4c2ff8549ae887336ace5ad (commit) via cdf70921a4976d6fbd79793ba7fa2b5c873bbe2b (commit) via d5d9b38af093708d443a01f9172cc97867343796 (commit) via d90a58d06150f27f008d63c9fee8b92e56afaeea (commit) via 362a57f7e1663de26149f27abc4ef49144e8f744 (commit) via ea171beebec90c31107b5972d58761100f9cd122 (commit) via c520c098ad1b4728c751d334dc356bead56a4937 (commit) via 12c1471c9b7683f150db76082506d4d90f034787 (commit) via 57dc8ce4a595498a7de06ee34c7aa5129da7f934 (commit) via 41715e512a7eca3bdc83524fb1c1bf8c3f88fa51 (commit) via 28b142b5c314204ddf8590eb194eca2efd4061e5 (commit) via 03a1a84b7886d7a8170d8520ad9b8948f1403d7a (commit) via 602a64a1d2bf596d51de87618d11eba67c8bf1b4 (commit) via 78f93fdd3c64dfe84d1f8459c4c16a39fbf61d60 (commit) via 2a4c47c0a244366f3bc623a375ce8280c8dfddcd (commit) via 543df4c802d7f21dc0443b207390c4353cfacf4f (commit) via eaea0030641c6be215915684bcd40930ae2d61c8 (commit) via fb8a4956a8fb948f3e2a9e6c2ef3debf5797f2ca (commit) via 1653fd340c080d2caefb4c6bf1bd21a98443baa9 (commit) via 9498f5d4cd59799f6c7753354180952936cd4680 (commit) via 64425ccb66a518fe7c38bfd1c5f09d2e35afce3e (commit) via f64dffd44ab787598eedf500bf8718a3e8d448cf (commit) via f939564bfdfafe0960840b8482fd0a35e249c491 (commit) via 763fa66d7281930d57f618c1fba6712394d0a05c (commit) via 18694f2d7c81110c35aaa56942cbad5e3d7a4904 (commit) via a4fda9e8f9910a7dc7bec484b722a940e5eec8c0 (commit) via af1f872d81ed31e457094a4294fb3bedda826b85 (commit) via 70167fed52368079d1cbffd445514480f29d9ff3 (commit) via c7cef3b0ba0de9af03bcd9d733290e69882d5a29 (commit) via e794690417b8ff32824862909a08fd2b9165e391 (commit) via 91d372f9bcca4b92e6e63d7354fcf2a81b6b8f18 (commit) via b225436331c6a770914fdd180327690697d3c478 (commit) via 459b57ca578ee4bfcfa6839136dbedbbdabb33a2 (commit) via 7396fa3aa9544c480b11edc1b3b2d687b1bca5e8 (commit) via ae44636606a9c7b98d9f5d4998486579a4610a83 (commit) via aac58fd425e4ee4064fa5dbbe666304c5e2b6f2c (commit) via 699ca1d3904b0324a8d1fe0359ac40a725e6e92f (commit) from b319651b70b95c1c70d084ab8519109dae9e5450 (commit)
- Log ----------------------------------------------------------------- commit 9147f30dc6b00dc63c998f1d2d3972d1a47e6c57 Author: Marc Delisle marc@infomarc.info Date: Fri Aug 12 14:44:55 2011 -0400
Zoom-search in table Search
commit 8f7312956d76eefd1fbf9567a3bb18634e8db560 Merge: b319651 1b7e2f6 Author: Marc Delisle marc@infomarc.info Date: Fri Aug 12 14:40:56 2011 -0400
Merge commit '1b7e2f6c7be6c7a96d780a7e9870d498f84e7339'
commit 1b7e2f6c7be6c7a96d780a7e9870d498f84e7339 Author: Ammar Yasir ammaryasir.88@gmail.com Date: Fri Aug 12 23:30:21 2011 +0530
Added: Missing rgbcolor.js file
commit ae5ef42beff0475de4a841ff18953e4f66880c40 Author: Ammar Yasir ammaryasir.88@gmail.com Date: Fri Aug 12 23:15:38 2011 +0530
Fixed: Timestamp for time associated fields needed extra 19800000 (+5:30) value
commit 67dc02f23db70391220dc0336f2110645a34a9d2 Author: Ammar Yasir ammaryasir.88@gmail.com Date: Fri Aug 12 20:06:27 2011 +0530
Fixed: false timestamp error
commit 557734c57f45e24abae08a031dde25dab73f1a05 Author: Ammar Yasir ammaryasir.88@gmail.com Date: Fri Aug 12 20:03:03 2011 +0530
bug fix
commit 201331275bff7e3e67e3d5f3fb2bc706e302ad27 Author: Ammar Yasir ammaryasir.88@gmail.com Date: Fri Aug 12 18:38:53 2011 +0530
Fixed: yAxis min value determined on plot generation and not 0 by default
commit e3cb99d540a305caaa58f91d71a5f87d96f28e50 Author: Ammar Yasir ammaryasir.88@gmail.com Date: Fri Aug 12 01:39:22 2011 +0530
Added better support for datetime fields
commit 57af6f950289ce2283ebe0d4d56b68119b75322b Merge: 33ad955 d585bba Author: Ammar Yasir ammaryasir.88@gmail.com Date: Fri Aug 12 00:10:17 2011 +0530
Merge remote branch 'phpmyadmin/master'
Conflicts: js/tbl_select.js
commit 33ad955596696415c0cfe0422a067f64f95d1d15 Merge: 241caff a5394bd Author: Ammar Yasir ammaryasir.88@gmail.com Date: Sun Aug 7 10:55:41 2011 +0530
Merge remote branch 'phpmyadmin/master'
commit 241caff7818f69531400eecd1ea63849009bffa9 Author: Ammar Yasir ammaryasir.88@gmail.com Date: Wed Aug 3 09:17:16 2011 +0530
Used AJAX to get data row on point select, hence reducing the amount of data to be sent from server initially for plot.
commit e4b676e3567f2992d9b77f623d328af2fa90cef8 Merge: 7880782 54fbcaa Author: Ammar Yasir ammaryasir.88@gmail.com Date: Wed Aug 3 09:15:29 2011 +0530
Merge remote branch 'phpmyadmin/master'
commit 7880782588e1609dac657a3c2b2f5a3630929859 Author: Ammar Yasir ammaryasir.88@gmail.com Date: Mon Aug 1 10:01:42 2011 +0530
Added 'Max rows to plot' as input criteria
commit 00c420c74b4663fddf0b5fc47ac50fdd15dd23c6 Author: Ammar Yasir ammaryasir.88@gmail.com Date: Sun Jul 31 12:50:24 2011 +0530
Edit feature with support for string plot. Also made some optimizations to avoid unnecesarry replot
commit df0848fa9c94a100d153cb4500d723566e8c25c0 Author: Ammar Yasir ammaryasir.88@gmail.com Date: Sun Jul 31 12:41:09 2011 +0530
String plotting: truncated axis labels with length greater than 10.
commit e83f3acd26fbfb51366cae9b184e69e5376ae10d Author: Ammar Yasir ammaryasir.88@gmail.com Date: Sun Jul 31 12:35:07 2011 +0530
Added to 'How to use' message content, strings are converted into integers for plotting purpose.
commit 32969f3d4211a96575e2fd7e609cc21ddc63bbaf Merge: 9388cd3 e3b91b7 Author: Ammar Yasir ammaryasir.88@gmail.com Date: Sun Jul 31 07:14:01 2011 +0530
Merge remote branch 'phpmyadmin/master'
commit 9388cd35b643ea65473ffa95cdf21213bcc4785f Author: Ammar Yasir ammaryasir.88@gmail.com Date: Mon Jul 25 19:50:02 2011 +0530
Re:Validations for input form submit (missed addidng messages.php file)
commit cb63a92b44a3ab1ee38ec66d63d33432a6273f94 Merge: d9486e2 c63172f Author: Ammar Yasir ammaryasir.88@gmail.com Date: Mon Jul 25 19:46:55 2011 +0530
Merge remote branch 'phpmyadmin/master'
commit d9486e259721b812cb0cd56ca057e55359250cc9 Author: Ammar Yasir ammaryasir.88@gmail.com Date: Mon Jul 25 19:45:00 2011 +0530
Validations for input form submit
commit e09759bef84ae8113f2e468117be66fb43d4b932 Author: Ammar Yasir ammaryasir.88@gmail.com Date: Mon Jul 25 04:50:47 2011 +0530
Added support for ploting strings(char,varchar,enums)
commit 18a6f0b0701457dd6a33d6517915c89729d1c11c Merge: 6cc3ff4 73ee863 Author: Ammar Yasir ammaryasir.88@gmail.com Date: Mon Jul 25 04:49:22 2011 +0530
Merge remote branch 'phpmyadmin/master'
commit 6cc3ff46f853960bdc90eb00fd595591e6a26f2e Author: Ammar Yasir ammaryasir.88@gmail.com Date: Fri Jul 22 17:53:13 2011 +0530
Data point content is now displayed as a dialog box which opens on clicking a point and closes on finishing an edit
commit 95ea722d73fc635b4b27c6731aeedfd430628ce8 Author: Ammar Yasir ammaryasir.88@gmail.com Date: Fri Jul 22 17:51:53 2011 +0530
Fixed redirection issue on tbl_zoom_select.php page
commit bedd413217a87770852671c4a2b211ca067df5e0 Author: Ammar Yasir ammaryasir.88@gmail.com Date: Fri Jul 22 17:50:09 2011 +0530
Resolved merge conflict
commit 830f2fdaa72a05497448b5b83b6fb961bf2bd7d2 Author: Ammar Yasir ammaryasir.88@gmail.com Date: Fri Jul 22 16:58:52 2011 +0530
Merge remote tracking branch 'phpmyadmin'
commit 7c66a8bed58fffd66becd643c845027e57e43862 Merge: b6cb93b 8489f41 Author: Ammar Yasir ammaryasir.88@gmail.com Date: Fri Jul 22 16:50:30 2011 +0530
Merge remote branch 'phpmyadmin/master'
Conflicts: js/highcharts/highcharts.js
commit b6cb93b017ddd35ab7c2083591228a9874eab60d Author: Ammar Yasir ammaryasir.88@gmail.com Date: Fri Jul 15 20:04:15 2011 +0530
Default datalabel bugfix (defaulted to display field everytime)
commit 1ce7ea6fb0180722ffadd056b565f63eaf215d4f Author: Ammar Yasir ammaryasir.88@gmail.com Date: Fri Jul 15 19:39:42 2011 +0530
Display field is set as the defualt selected item in the datalabel select element
commit 36ec09e6ccec0f46ebc1c92b8c8bc5a396b9a136 Author: Ammar Yasir ammaryasir.88@gmail.com Date: Fri Jul 15 02:18:29 2011 +0530
Changed 'How to use?' lnk message onClick event function from this.remove() to PMA_ajaxRemoveMessage()
commit c01e39a716c5ba33d00ff45f1791d3094fe1c777 Author: Ammar Yasir ammaryasir.88@gmail.com Date: Fri Jul 15 00:43:41 2011 +0530
xAxis type changed to linear (earliear it defaulted to timeseries)
commit 04e82bb1e908e233f1eb619324b84b18312282d7 Author: Ammar Yasir ammaryasir.88@gmail.com Date: Fri Jul 15 00:38:51 2011 +0530
Default data label now taken from table display field
commit 811996e92a9365afc4c2ff8549ae887336ace5ad Merge: cdf7092 117dd68 Author: Ammar Yasir ammaryasir.88@gmail.com Date: Fri Jul 15 00:38:31 2011 +0530
Merge remote branch 'phpmyadmin/master'
commit cdf70921a4976d6fbd79793ba7fa2b5c873bbe2b Author: Ammar Yasir ammaryasir.88@gmail.com Date: Tue Jul 12 06:51:20 2011 +0530
Fixed misfunction of edit mode
commit d5d9b38af093708d443a01f9172cc97867343796 Merge: d90a58d 4bb11fd Author: Ammar Yasir ammaryasir.88@gmail.com Date: Tue Jul 12 06:50:46 2011 +0530
Merge remote branch 'phpmyadmin/master'
commit d90a58d06150f27f008d63c9fee8b92e56afaeea Author: Ammar Yasir ammaryasir.88@gmail.com Date: Sun Jul 10 08:37:15 2011 +0530
Some indentation errors fixed from previous commit
commit 362a57f7e1663de26149f27abc4ef49144e8f744 Author: Ammar Yasir ammaryasir.88@gmail.com Date: Sun Jul 10 08:14:00 2011 +0530
Functionality for edit data points added (primitive)
commit ea171beebec90c31107b5972d58761100f9cd122 Merge: c520c09 1962e36 Author: Ammar Yasir ammaryasir.88@gmail.com Date: Sun Jul 10 08:13:46 2011 +0530
Merge remote branch 'phpmyadmin/master'
commit c520c098ad1b4728c751d334dc356bead56a4937 Author: Ammar Yasir ammaryasir.88@gmail.com Date: Fri Jul 8 02:34:49 2011 +0530
On submit of an edit, the data point remains selected in the plot.
commit 12c1471c9b7683f150db76082506d4d90f034787 Author: Ammar Yasir ammaryasir.88@gmail.com Date: Fri Jul 8 02:26:56 2011 +0530
Changed text for 'How to use?' link 9$js_messages['strDisplayHelp'])
commit 57dc8ce4a595498a7de06ee34c7aa5129da7f934 Merge: 41715e5 5140c38 Author: Ammar Yasir ammaryasir.88@gmail.com Date: Thu Jul 7 21:00:10 2011 +0530
Merge remote branch 'phpmyadmin/master'
Conflicts: libraries/config.default.php tbl_select.php
commit 41715e512a7eca3bdc83524fb1c1bf8c3f88fa51 Author: Ammar Yasir ammaryasir.88@gmail.com Date: Thu Jul 7 20:53:32 2011 +0530
Removed mode feature, appended a missing configuration directive and changed help link duration to 10sec
commit 28b142b5c314204ddf8590eb194eca2efd4061e5 Author: Ammar Yasir ammaryasir.88@gmail.com Date: Tue Jul 5 05:22:38 2011 +0530
Made some changes -> Browse Mode makes the dialog fields disabled -> New name for max row to plot directive -> Show/Hide search criteria -> Link for displaying Help
commit 03a1a84b7886d7a8170d8520ad9b8948f1403d7a Author: Ammar Yasir ammaryasir.88@gmail.com Date: Tue Jul 5 05:21:16 2011 +0530
Test
commit 602a64a1d2bf596d51de87618d11eba67c8bf1b4 Author: Ammar Yasir ammaryasir.88@gmail.com Date: Mon Jul 4 21:59:17 2011 +0530
Added the Show/Hide search criteria feature
commit 78f93fdd3c64dfe84d1f8459c4c16a39fbf61d60 Merge: 2a4c47c 064d399 Author: Ammar Yasir ammaryasir.88@gmail.com Date: Mon Jul 4 21:58:47 2011 +0530
Merge remote branch 'phpmyadmin/master'
commit 2a4c47c0a244366f3bc623a375ce8280c8dfddcd Merge: 543df4c 2279fd9 Author: Ammar Yasir ammaryasir.88@gmail.com Date: Fri Jul 1 15:34:39 2011 +0530
Merge remote branch 'phpmyadmin/master'
Conflicts: tbl_select.php
commit 543df4c802d7f21dc0443b207390c4353cfacf4f Author: Ammar Yasir ammaryasir.88@gmail.com Date: Fri Jul 1 15:31:56 2011 +0530
Added interface for browsing/editing points
commit eaea0030641c6be215915684bcd40930ae2d61c8 Author: Ammar Yasir ammaryasir.88@gmail.com Date: Tue Jun 21 05:04:00 2011 +0530
Added some features -> Limit on max number of rows retreived(500) -> An instruction link regarding how to use -> Resize plot by dragging it by the bottom right corner -> Two additional search criteria
commit fb8a4956a8fb948f3e2a9e6c2ef3debf5797f2ca Merge: 1653fd3 d9304ef Author: Ammar Yasir ammaryasir.88@gmail.com Date: Tue Jun 21 04:35:24 2011 +0530
Merge remote branch 'phpmyadmin/master'
commit 1653fd340c080d2caefb4c6bf1bd21a98443baa9 Author: Ammar Yasir ammaryasir.88@gmail.com Date: Fri Jun 17 01:31:31 2011 +0530
Plot functionality using Hihcharts
commit 9498f5d4cd59799f6c7753354180952936cd4680 Merge: 64425cc 4338b70 Author: Ammar Yasir ammaryasir.88@gmail.com Date: Fri Jun 17 01:06:38 2011 +0530
Merge remote branch 'phpmyadmin/master'
commit 64425ccb66a518fe7c38bfd1c5f09d2e35afce3e Author: Ammar Yasir ammaryasir.88@gmail.com Date: Fri Jun 10 06:58:23 2011 +0530
Fixed some issues and added support for plotting strings
commit f64dffd44ab787598eedf500bf8718a3e8d448cf Merge: f939564 cd5cddb Author: Ammar Yasir ammaryasir.88@gmail.com Date: Fri Jun 10 06:56:52 2011 +0530
Merge remote branch 'phpmyadmin/master'
commit f939564bfdfafe0960840b8482fd0a35e249c491 Author: Ammar Yasir ammaryasir.88@gmail.com Date: Thu Jun 9 03:03:22 2011 +0530
Created the SVG based scatter-plot functionality -> Created classes corresponding to the plot and data objects, currently only data points -> Plots only for numeric fields
commit 763fa66d7281930d57f618c1fba6712394d0a05c Merge: 18694f2 90099b7 Author: Ammar Yasir ammaryasir.88@gmail.com Date: Thu Jun 9 02:54:33 2011 +0530
Merge remote branch 'phpmyadmin/master'
commit 18694f2d7c81110c35aaa56942cbad5e3d7a4904 Author: Ammar Yasir ammaryasir.88@gmail.com Date: Mon Jun 6 04:18:47 2011 +0530
Added generate plot feature using SVG ( only for numeric fields )
commit a4fda9e8f9910a7dc7bec484b722a940e5eec8c0 Merge: af1f872 8b47a1d Author: Ammar Yasir ammaryasir.88@gmail.com Date: Mon Jun 6 04:16:55 2011 +0530
Merge remote branch 'phpmyadmin/master'
commit af1f872d81ed31e457094a4294fb3bedda826b85 Merge: 70167fe 75091e5 Author: Ammar Yasir ammaryasir.88@gmail.com Date: Sat Jun 4 13:55:18 2011 +0530
Merge remote branch 'phpmyadmin/master'
commit 70167fed52368079d1cbffd445514480f29d9ff3 Author: Ammar Yasir ammaryasir.88@gmail.com Date: Wed Jun 1 01:22:31 2011 +0530
Made suggested change to tbl_select.php and tbl_zoom_select.php
commit c7cef3b0ba0de9af03bcd9d733290e69882d5a29 Author: Ammar Yasir ammaryasir.88@gmail.com Date: Tue May 31 19:02:50 2011 +0530
Refactored the tbl_select.php and tbl_zoom_select.php code in libraries/tbl_select.lib.php Parts refactored are: -> Setting titles -> getting fields list -> setting sub-tabs -> setting table header of QBE display -> displaying foreign data -> search criteria input elements
commit e794690417b8ff32824862909a08fd2b9165e391 Merge: 91d372f a47ac24 Author: Ammar Yasir ammaryasir.88@gmail.com Date: Tue May 31 18:59:28 2011 +0530
Merge remote branch 'phpmyadmin/master'
commit 91d372f9bcca4b92e6e63d7354fcf2a81b6b8f18 Author: Ammar Yasir ammaryasir.88@gmail.com Date: Sun May 29 12:16:13 2011 +0530
Added a library file for the table-search and zoom-search code Contains two functions: -> Get Field list and details -> Get where clause of query generation process
commit b225436331c6a770914fdd180327690697d3c478 Merge: 459b57c ae0af9e Author: Ammar Yasir ammaryasir.88@gmail.com Date: Sun May 29 12:14:04 2011 +0530
Merge remote branch 'phpmyadmin/master'
commit 459b57ca578ee4bfcfa6839136dbedbbdabb33a2 Merge: 7396fa3 434d233 Author: Ammar Yasir ammaryasir.88@gmail.com Date: Fri May 27 17:46:30 2011 +0530
Merge remote branch 'phpmyadmin/master'
commit 7396fa3aa9544c480b11edc1b3b2d687b1bca5e8 Author: Ammar Yasir ammaryasir.88@gmail.com Date: Thu May 26 12:22:16 2011 +0530
Designed the zoom-search form(tbl_zoom_select.php) -> User selecte exactly two columns. -> Generates two queries, one for each column criteria.
commit ae44636606a9c7b98d9f5d4998486579a4610a83 Author: Ammar Yasir ammaryasir.88@gmail.com Date: Mon May 23 21:26:07 2011 +0530
Made some changes on the tbl_select.php page to add a link for Zoom Search. Please dont mind the coding, I just coded very quickly to get back comments. If the flow of the interface is ok I'll code it properly.
commit aac58fd425e4ee4064fa5dbbe666304c5e2b6f2c Author: root root@localhost.localdomain Date: Wed May 18 22:40:33 2011 +0530
testing for push
commit 699ca1d3904b0324a8d1fe0359ac40a725e6e92f Author: root root@localhost.localdomain Date: Wed May 18 22:30:26 2011 +0530
Just testing upload
-----------------------------------------------------------------------
Summary of changes: ChangeLog | 1 + config.sample.inc.php | 2 +- db_structure.php | 1 + js/canvg/canvg.js | 304 +++----------- js/canvg/rgbcolor.js | 288 +++++++++++++ js/date.js | 335 +++++++++++++++ js/messages.php | 6 + js/tbl_select.js | 2 +- js/tbl_zoom_plot.js | 605 +++++++++++++++++++++++++++ libraries/common.inc.php | 1 + libraries/config.default.php | 425 +++++++++++++++++-- libraries/svg_plot/pma_scatter_plot.php | 267 ++++++++++++ libraries/svg_plot/pma_svg_data_element.php | 50 +++ libraries/svg_plot/pma_svg_data_point.php | 86 ++++ libraries/tbl_select.lib.php | 390 +++++++++++++++++ tbl_select.php | 280 +++---------- tbl_zoom_select.php | 447 ++++++++++++++++++++ 17 files changed, 2976 insertions(+), 514 deletions(-) create mode 100644 js/canvg/rgbcolor.js create mode 100644 js/date.js create mode 100644 js/tbl_zoom_plot.js create mode 100644 libraries/svg_plot/pma_scatter_plot.php create mode 100644 libraries/svg_plot/pma_svg_data_element.php create mode 100644 libraries/svg_plot/pma_svg_data_point.php create mode 100644 libraries/tbl_select.lib.php create mode 100644 tbl_zoom_select.php
diff --git a/ChangeLog b/ChangeLog index 633d481..e6c1bc4 100644 --- a/ChangeLog +++ b/ChangeLog @@ -43,6 +43,7 @@ phpMyAdmin - ChangeLog + AJAX for table Operations copy table - bug #3380946 [export] no uid Query result export (Suhosin limit) + Grid editing in browse mode (replaces row inline edit) ++ Zoom-search in table Search
3.4.5.0 (not yet released) - bug #3375325 [interface] Page list in navigation frame looks odd diff --git a/config.sample.inc.php b/config.sample.inc.php index edffd03..778785e 100644 --- a/config.sample.inc.php +++ b/config.sample.inc.php @@ -14,7 +14,7 @@ * This is needed for cookie based authentication to encrypt password in * cookie */ -$cfg['blowfish_secret'] = ''; /* YOU MUST FILL IN THIS FOR COOKIE AUTH! */ +$cfg['blowfish_secret'] = 'a8b7c6d'; /* YOU MUST FILL IN THIS FOR COOKIE AUTH! */
/* * Servers configuration diff --git a/db_structure.php b/db_structure.php index d76bcca..9c2e045 100644 --- a/db_structure.php +++ b/db_structure.php @@ -57,6 +57,7 @@ require_once './libraries/db_structure.lib.php'; $titles = PMA_buildActionTitles();
// 1. No tables + if ($num_tables == 0) { echo '<p>' . __('No tables found in database') . '</p>' . "\n";
diff --git a/js/canvg/canvg.js b/js/canvg/canvg.js index 19a47a7..dbc5a9d 100644 --- a/js/canvg/canvg.js +++ b/js/canvg/canvg.js @@ -12,6 +12,7 @@ if(!window.console) { window.console.dir = function(str) {}; }
+// <3 IE if(!Array.indexOf){ Array.prototype.indexOf = function(obj){ for(var i=0; i<this.length; i++){ @@ -27,7 +28,7 @@ if(!Array.indexOf){ // canvg(target, s) // empty parameters: replace all 'svg' elements on page with 'canvas' elements // target: canvas element or the id of a canvas element - // s: svg string, url to svg file, or xml document + // s: svg string or url to svg file // opts: optional hash of options // ignoreMouse: true => ignore mouse events // ignoreAnimation: true => ignore animations @@ -74,11 +75,7 @@ if(!Array.indexOf){ svg.opts = opts; var ctx = target.getContext('2d'); - if (typeof(s.documentElement) != 'undefined') { - // load from xml doc - svg.loadXmlDoc(ctx, s); - } - else if (s.substr(0,1) == '<') { + if (s.substr(0,1) == '<') { // load from xml string svg.loadXml(ctx, s); } @@ -92,7 +89,6 @@ if(!Array.indexOf){ var svg = { }; svg.FRAMERATE = 30; - svg.MAX_VIRTUAL_PIXELS = 30000; // globals svg.init = function(ctx) { @@ -103,7 +99,6 @@ if(!Array.indexOf){ svg.ctx = ctx; svg.ViewPort = new (function () { this.viewPorts = []; - this.Clear = function() { this.viewPorts = []; } this.SetCurrent = function(width, height) { this.viewPorts.push({ width: width, height: height }); } this.RemoveCurrent = function() { this.viewPorts.pop(); } this.Current = function() { return this.viewPorts[this.viewPorts.length - 1]; } @@ -556,7 +551,7 @@ if(!Array.indexOf){ } } - var data = svg.trim(svg.compressSpaces(v)).split(/\s(?=[a-z])/); + var data = v.split(/\s(?=[a-z])/); for (var i=0; i<data.length; i++) { var type = data[i].split('(')[0]; var s = data[i].split('(')[1].replace(')',''); @@ -621,7 +616,7 @@ if(!Array.indexOf){ return a; } - // get or create style, crawls up node tree + // get or create style this.style = function(name, createIfNotExists) { var s = this.styles[name]; if (s != null) return s; @@ -630,14 +625,6 @@ if(!Array.indexOf){ if (a != null && a.hasValue()) { return a; } - - var p = this.parent; - if (p != null) { - var ps = p.style(name); - if (ps != null && ps.hasValue()) { - return ps; - } - } s = new svg.Property(name, ''); if (createIfNotExists == true) this.styles[name] = s; @@ -648,9 +635,6 @@ if(!Array.indexOf){ this.render = function(ctx) { // don't render display=none if (this.attribute('display').value == 'none') return; - - // don't render visibility=hidden - if (this.attribute('visibility').value == 'hidden') return; ctx.save(); this.setContext(ctx); @@ -697,7 +681,7 @@ if(!Array.indexOf){ } // add tag styles - var styles = svg.Styles[node.nodeName]; + var styles = svg.Styles[this.type]; if (styles != null) { for (var name in styles) { this.styles[name] = styles[name]; @@ -714,12 +698,6 @@ if(!Array.indexOf){ this.styles[name] = styles[name]; } } - styles = svg.Styles[node.nodeName+'.'+classes[j]]; - if (styles != null) { - for (var name in styles) { - this.styles[name] = styles[name]; - } - } } } @@ -878,7 +856,7 @@ if(!Array.indexOf){ var width = svg.ViewPort.width(); var height = svg.ViewPort.height(); - if (typeof(this.root) == 'undefined' && this.attribute('width').hasValue() && this.attribute('height').hasValue()) { + if (this.attribute('width').hasValue() && this.attribute('height').hasValue()) { width = this.attribute('width').Length.toPixels('x'); height = this.attribute('height').Length.toPixels('y'); @@ -1208,6 +1186,9 @@ if(!Array.indexOf){ pp.reset();
var bb = new svg.BoundingBox(); + + if(this.attribute('visibility').value=='hidden') return; + if (ctx != null) ctx.beginPath(); while (!pp.isEnd()) { pp.nextCommand(); @@ -1488,37 +1469,6 @@ if(!Array.indexOf){ for (var i=0; i<stopsContainer.stops.length; i++) { g.addColorStop(stopsContainer.stops[i].offset, stopsContainer.stops[i].color); } - - if (this.attribute('gradientTransform').hasValue()) { - // render as transformed pattern on temporary canvas - var rootView = svg.ViewPort.viewPorts[0]; - - var rect = new svg.Element.rect(); - rect.attributes['x'] = new svg.Property('x', -svg.MAX_VIRTUAL_PIXELS/3.0); - rect.attributes['y'] = new svg.Property('y', -svg.MAX_VIRTUAL_PIXELS/3.0); - rect.attributes['width'] = new svg.Property('width', svg.MAX_VIRTUAL_PIXELS); - rect.attributes['height'] = new svg.Property('height', svg.MAX_VIRTUAL_PIXELS); - - var group = new svg.Element.g(); - group.attributes['transform'] = new svg.Property('transform', this.attribute('gradientTransform').value); - group.children = [ rect ]; - - var tempSvg = new svg.Element.svg(); - tempSvg.attributes['x'] = new svg.Property('x', 0); - tempSvg.attributes['y'] = new svg.Property('y', 0); - tempSvg.attributes['width'] = new svg.Property('width', rootView.width); - tempSvg.attributes['height'] = new svg.Property('height', rootView.height); - tempSvg.children = [ group ]; - - var c = document.createElement('canvas'); - c.width = rootView.width; - c.height = rootView.height; - var tempCtx = c.getContext('2d'); - tempCtx.fillStyle = g; - tempSvg.render(tempCtx); - return tempCtx.createPattern(c, 'no-repeat'); - } - return g; } } @@ -1544,8 +1494,16 @@ if(!Array.indexOf){ var y2 = (this.gradientUnits == 'objectBoundingBox' ? bb.y() + bb.height() * this.attribute('y2').numValue() : this.attribute('y2').Length.toPixels('y')); - - return ctx.createLinearGradient(x1, y1, x2, y2); + + var p1 = new svg.Point(x1, y1); + var p2 = new svg.Point(x2, y2); + if (this.attribute('gradientTransform').hasValue()) { + var transform = new svg.Transform(this.attribute('gradientTransform').value); + transform.applyToPoint(p1); + transform.applyToPoint(p2); + } + + return ctx.createLinearGradient(p1.x, p1.y, p2.x, p2.y); } } svg.Element.linearGradient.prototype = new svg.Element.GradientBase; @@ -1582,7 +1540,22 @@ if(!Array.indexOf){ ? (bb.width() + bb.height()) / 2.0 * this.attribute('r').numValue() : this.attribute('r').Length.toPixels()); - return ctx.createRadialGradient(fx, fy, 0, cx, cy, r); + var c = new svg.Point(cx, cy); + var f = new svg.Point(fx, fy); + if (this.attribute('gradientTransform').hasValue()) { + var transform = new svg.Transform(this.attribute('gradientTransform').value); + transform.applyToPoint(c); + transform.applyToPoint(f); + + for (var i=0; i<transform.transforms.length; i++) { + // average the scaling part of the transform, apply to radius + var scale1 = transform.transforms[i].m[0]; + var scale2 = transform.transforms[i].m[3]; + r = r * ((scale1 + scale2) / 2.0); + } + } + + return ctx.createRadialGradient(f.x, f.y, 0, c.x, c.y, r); } } svg.Element.radialGradient.prototype = new svg.Element.GradientBase; @@ -1720,73 +1693,6 @@ if(!Array.indexOf){ } svg.Element.animateTransform.prototype = new svg.Element.animate; - // font element - svg.Element.font = function(node) { - this.base = svg.Element.ElementBase; - this.base(node); - - this.horizAdvX = this.attribute('horiz-adv-x').numValue(); - - this.isRTL = false; - this.isArabic = false; - this.fontFace = null; - this.missingGlyph = null; - this.glyphs = []; - for (var i=0; i<this.children.length; i++) { - var child = this.children[i]; - if (child.type == 'font-face') { - this.fontFace = child; - if (child.style('font-family').hasValue()) { - svg.Definitions[child.style('font-family').value] = this; - } - } - else if (child.type == 'missing-glyph') this.missingGlyph = child; - else if (child.type == 'glyph') { - if (child.arabicForm != '') { - this.isRTL = true; - this.isArabic = true; - if (typeof(this.glyphs[child.unicode]) == 'undefined') this.glyphs[child.unicode] = []; - this.glyphs[child.unicode][child.arabicForm] = child; - } - else { - this.glyphs[child.unicode] = child; - } - } - } - } - svg.Element.font.prototype = new svg.Element.ElementBase; - - // font-face element - svg.Element.fontface = function(node) { - this.base = svg.Element.ElementBase; - this.base(node); - - this.ascent = this.attribute('ascent').value; - this.descent = this.attribute('descent').value; - this.unitsPerEm = this.attribute('units-per-em').numValue(); - } - svg.Element.fontface.prototype = new svg.Element.ElementBase; - - // missing-glyph element - svg.Element.missingglyph = function(node) { - this.base = svg.Element.path; - this.base(node); - - this.horizAdvX = 0; - } - svg.Element.missingglyph.prototype = new svg.Element.path; - - // glyph element - svg.Element.glyph = function(node) { - this.base = svg.Element.path; - this.base(node); - - this.horizAdvX = this.attribute('horiz-adv-x').numValue(); - this.unicode = this.attribute('unicode').value; - this.arabicForm = this.attribute('arabic-form').value; - } - svg.Element.glyph.prototype = new svg.Element.path; - // text element svg.Element.text = function(node) { this.base = svg.Element.RenderedElementBase; @@ -1809,16 +1715,19 @@ if(!Array.indexOf){ this.baseSetContext = this.setContext; this.setContext = function(ctx) { this.baseSetContext(ctx); - if (this.style('text-anchor').hasValue()) { - var textAnchor = this.style('text-anchor').value; + if (this.attribute('text-anchor').hasValue()) { + var textAnchor = this.attribute('text-anchor').value; ctx.textAlign = textAnchor == 'middle' ? 'center' : textAnchor; } if (this.attribute('alignment-baseline').hasValue()) ctx.textBaseline = this.attribute('alignment-baseline').value; } this.renderChildren = function(ctx) { + if(this.attribute('visibility').value=='hidden') return; + var x = this.attribute('x').Length.toPixels('x'); var y = this.attribute('y').Length.toPixels('y'); + for (var i=0; i<this.children.length; i++) { var child = this.children[i]; @@ -1850,63 +1759,8 @@ if(!Array.indexOf){ this.base = svg.Element.RenderedElementBase; this.base(node); - this.getGlyph = function(font, text, i) { - var c = text[i]; - var glyph = null; - if (font.isArabic) { - var arabicForm = 'isolated'; - if ((i==0 || text[i-1]==' ') && i<text.length-2 && text[i+1]!=' ') arabicForm = 'terminal'; - if (i>0 && text[i-1]!=' ' && i<text.length-2 && text[i+1]!=' ') arabicForm = 'medial'; - if (i>0 && text[i-1]!=' ' && (i == text.length-1 || text[i+1]==' ')) arabicForm = 'initial'; - if (typeof(font.glyphs[c]) != 'undefined') { - glyph = font.glyphs[c][arabicForm]; - if (glyph == null && font.glyphs[c].type == 'glyph') glyph = font.glyphs[c]; - } - } - else { - glyph = font.glyphs[c]; - } - if (glyph == null) glyph = font.missingGlyph; - return glyph; - } - this.renderChildren = function(ctx) { - var customFont = this.parent.style('font-family').Definition.getDefinition(); - if (customFont != null) { - var fontSize = this.parent.style('font-size').numValueOrDefault(svg.Font.Parse(svg.ctx.font).fontSize); - var fontStyle = this.parent.style('font-style').valueOrDefault(svg.Font.Parse(svg.ctx.font).fontStyle); - var text = this.getText(); - if (customFont.isRTL) text = text.split("").reverse().join(""); - - if (this.parent.style('text-anchor').value == 'middle') { - this.x = this.x - this.measureText(ctx) / 2.0; - } - - var dx = svg.ToNumberArray(this.parent.attribute('dx').value); - for (var i=0; i<text.length; i++) { - var glyph = this.getGlyph(customFont, text, i); - var scale = fontSize / customFont.fontFace.unitsPerEm; - ctx.translate(this.x, this.y); - ctx.scale(scale, -scale); - var lw = ctx.lineWidth; - ctx.lineWidth = ctx.lineWidth * customFont.fontFace.unitsPerEm / fontSize; - if (fontStyle == 'italic') ctx.transform(1, 0, .4, 1, 0, 0); - glyph.render(ctx); - if (fontStyle == 'italic') ctx.transform(1, 0, -.4, 1, 0, 0); - ctx.lineWidth = lw; - ctx.scale(1/scale, -1/scale); - ctx.translate(-this.x, -this.y); - - this.x += fontSize * (glyph.horizAdvX || customFont.horizAdvX) / customFont.fontFace.unitsPerEm; - if (typeof(dx[i]) != 'undefined' && !isNaN(dx[i])) { - this.x += dx[i]; - } - } - return; - } - - if (ctx.strokeStyle != '') ctx.strokeText(svg.compressSpaces(this.getText()), this.x, this.y); - if (ctx.fillStyle != '') ctx.fillText(svg.compressSpaces(this.getText()), this.x, this.y); + ctx.fillText(svg.compressSpaces(this.getText()), this.x, this.y); } this.getText = function() { @@ -1914,23 +1768,6 @@ if(!Array.indexOf){ } this.measureText = function(ctx) { - var customFont = this.parent.style('font-family').Definition.getDefinition(); - if (customFont != null) { - var fontSize = this.parent.style('font-size').numValueOrDefault(svg.Font.Parse(svg.ctx.font).fontSize); - var measure = 0; - var text = this.getText(); - if (customFont.isRTL) text = text.split("").reverse().join(""); - var dx = svg.ToNumberArray(this.parent.attribute('dx').value); - for (var i=0; i<text.length; i++) { - var glyph = this.getGlyph(customFont, text, i); - measure += (glyph.horizAdvX || customFont.horizAdvX) * fontSize / customFont.fontFace.unitsPerEm; - if (typeof(dx[i]) != 'undefined' && !isNaN(dx[i])) { - measure += dx[i]; - } - } - return measure; - } - var textToMeasure = svg.compressSpaces(this.getText()); if (!ctx.measureText) return textToMeasure.length * 10; return ctx.measureText(textToMeasure).width; @@ -1943,9 +1780,8 @@ if(!Array.indexOf){ this.base = svg.Element.TextElementBase; this.base(node); - this.text = node.nodeType == 3 ? node.nodeValue : // text - node.childNodes.length > 0 ? node.childNodes[0].nodeValue : // element - node.text; + // TEXT ELEMENT + this.text = node.nodeType == 3 ? node.nodeValue : node.childNodes[0].nodeValue; this.getText = function() { return this.text; } @@ -2095,9 +1931,8 @@ if(!Array.indexOf){ this.base = svg.Element.ElementBase; this.base(node); - // text, or spaces then CDATA - var css = node.childNodes[0].nodeValue + (node.childNodes.length > 1 ? node.childNodes[1].nodeValue : ''); - css = css.replace(/(/*([^*]|[\r\n]|(*+([^*/]|[\r\n])))**+/)|(^[\s]*//.*)/gm, ''); // remove comments + var css = node.childNodes[0].nodeValue; + css = css.replace(/(/*([^*]|[\r\n]|(*+([^*/]|[\r\n])))**+/)|(//.*)/gm, ''); // remove comments css = svg.compressSpaces(css); // replace whitespace var cssDefs = css.split('}'); for (var i=0; i<cssDefs.length; i++) { @@ -2110,31 +1945,14 @@ if(!Array.indexOf){ if (cssClass != '') { var props = {}; for (var k=0; k<cssProps.length; k++) { - var prop = cssProps[k].indexOf(':'); - var name = cssProps[k].substr(0, prop); - var value = cssProps[k].substr(prop + 1, cssProps[k].length - prop); + var prop = cssProps[k].split(':'); + var name = prop[0]; + var value = prop[1]; if (name != null && value != null) { - props[svg.trim(name)] = new svg.Property(svg.trim(name), svg.trim(value)); + props[svg.trim(prop[0])] = new svg.Property(svg.trim(prop[0]), svg.trim(prop[1])); } } svg.Styles[cssClass] = props; - if (cssClass == '@font-face') { - var fontFamily = props['font-family'].value.replace(/"/g,''); - var srcs = props['src'].value.split(','); - for (var s=0; s<srcs.length; s++) { - if (srcs[s].indexOf('format("svg")') > 0) { - var urlStart = srcs[s].indexOf('url'); - var urlEnd = srcs[s].indexOf(')', urlStart); - var url = srcs[s].substr(urlStart + 5, urlEnd - urlStart - 6); - var doc = svg.parseXml(svg.ajax(url)); - var fonts = doc.getElementsByTagName('font'); - for (var f=0; f<fonts.length; f++) { - var font = svg.CreateElement(fonts[f]); - svg.Definitions[fontFamily] = font; - } - } - } - } } } } @@ -2186,10 +2004,6 @@ if(!Array.indexOf){ } } } - - this.render = function(ctx) { - // NO RENDER - } } svg.Element.clipPath.prototype = new svg.Element.ElementBase;
@@ -2210,8 +2024,7 @@ if(!Array.indexOf){ // element factory svg.CreateElement = function(node) { - var className = node.nodeName.replace(/^[^:]+:/,''); // remove namespace - className = className.replace(/-/g,''); // remove dashes + var className = node.nodeName.replace(/^[^:]+:/,''); var e = null; if (typeof(svg.Element[className]) != 'undefined') { e = new svg.Element[className](node); @@ -2231,10 +2044,6 @@ if(!Array.indexOf){ // load from xml svg.loadXml = function(ctx, xml) { - svg.loadXmlDoc(ctx, svg.parseXml(xml)); - } - - svg.loadXmlDoc = function(ctx, dom) { svg.init(ctx); var mapXY = function(p) { @@ -2261,24 +2070,19 @@ if(!Array.indexOf){ }; } + var dom = svg.parseXml(xml); var e = svg.CreateElement(dom.documentElement); - e.root = true; // render loop var isFirstRender = true; var draw = function() { - svg.ViewPort.Clear(); - if (ctx.canvas.parentNode) svg.ViewPort.SetCurrent(ctx.canvas.parentNode.clientWidth, ctx.canvas.parentNode.clientHeight); - if (svg.opts == null || svg.opts['ignoreDimensions'] != true) { // set canvas size if (e.style('width').hasValue()) { - ctx.canvas.width = e.style('width').Length.toPixels('x'); - ctx.canvas.style.width = ctx.canvas.width + 'px'; + ctx.canvas.width = e.style('width').Length.toPixels(ctx.canvas.parentNode.clientWidth); } if (e.style('height').hasValue()) { - ctx.canvas.height = e.style('height').Length.toPixels('y'); - ctx.canvas.style.height = ctx.canvas.height + 'px'; + ctx.canvas.height = e.style('height').Length.toPixels(ctx.canvas.parentNode.clientHeight); } } svg.ViewPort.SetCurrent(ctx.canvas.clientWidth, ctx.canvas.clientHeight); diff --git a/js/canvg/rgbcolor.js b/js/canvg/rgbcolor.js new file mode 100644 index 0000000..0338a16 --- /dev/null +++ b/js/canvg/rgbcolor.js @@ -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; + + } + +} + diff --git a/js/date.js b/js/date.js new file mode 100644 index 0000000..9a92340 --- /dev/null +++ b/js/date.js @@ -0,0 +1,335 @@ +// =================================================================== +// Author: Matt Kruse matt@mattkruse.com +// WWW: http://www.mattkruse.com/ +// +// NOTICE: You may use this code for any purpose, commercial or +// private, without any further permission from the author. You may +// remove this notice from your final code if you wish, however it is +// appreciated by the author if at least my web site address is kept. +// +// You may *NOT* re-distribute this code in any way except through its +// use. That means, you can include it in your product, or your web +// site, or any other form where the code is actually being used. You +// may not put the plain javascript up on your site for download or +// include it in your javascript libraries for download. +// If you wish to share this code with others, please just point them +// to the URL instead. +// Please DO NOT link directly to my .js files from your site. Copy +// the files to your server and use them there. Thank you. +// =================================================================== + +// HISTORY +// ------------------------------------------------------------------ +// May 17, 2003: Fixed bug in parseDate() for dates <1970 +// March 11, 2003: Added parseDate() function +// March 11, 2003: Added "NNN" formatting option. Doesn't match up +// perfectly with SimpleDateFormat formats, but +// backwards-compatability was required. + +// ------------------------------------------------------------------ +// These functions use the same 'format' strings as the +// java.text.SimpleDateFormat class, with minor exceptions. +// The format string consists of the following abbreviations: +// +// Field | Full Form | Short Form +// -------------+--------------------+----------------------- +// Year | yyyy (4 digits) | yy (2 digits), y (2 or 4 digits) +// Month | MMM (name or abbr.)| MM (2 digits), M (1 or 2 digits) +// | NNN (abbr.) | +// Day of Month | dd (2 digits) | d (1 or 2 digits) +// Day of Week | EE (name) | E (abbr) +// Hour (1-12) | hh (2 digits) | h (1 or 2 digits) +// Hour (0-23) | HH (2 digits) | H (1 or 2 digits) +// Hour (0-11) | KK (2 digits) | K (1 or 2 digits) +// Hour (1-24) | kk (2 digits) | k (1 or 2 digits) +// Minute | mm (2 digits) | m (1 or 2 digits) +// Second | ss (2 digits) | s (1 or 2 digits) +// AM/PM | a | +// +// NOTE THE DIFFERENCE BETWEEN MM and mm! Month=MM, not mm! +// Examples: +// "MMM d, y" matches: January 01, 2000 +// Dec 1, 1900 +// Nov 20, 00 +// "M/d/yy" matches: 01/20/00 +// 9/2/00 +// "MMM dd, yyyy hh:mm:ssa" matches: "January 01, 2000 12:30:45AM" +// ------------------------------------------------------------------ + +var MONTH_NAMES=new Array('January','February','March','April','May','June','July','August','September','October','November','December','Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'); +var DAY_NAMES=new Array('Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday','Sun','Mon','Tue','Wed','Thu','Fri','Sat'); +function LZ(x) {return(x<0||x>9?"":"0")+x} + +// ------------------------------------------------------------------ +// isDate ( date_string, format_string ) +// Returns true if date string matches format of format string and +// is a valid date. Else returns false. +// It is recommended that you trim whitespace around the value before +// passing it to this function, as whitespace is NOT ignored! +// ------------------------------------------------------------------ +function isDate(val,format) { + var date=getDateFromFormat(val,format); + if (date==0) { return false; } + return true; + } + +// ------------------------------------------------------------------- +// compareDates(date1,date1format,date2,date2format) +// Compare two date strings to see which is greater. +// Returns: +// 1 if date1 is greater than date2 +// 0 if date2 is greater than date1 of if they are the same +// -1 if either of the dates is in an invalid format +// ------------------------------------------------------------------- +function compareDates(date1,dateformat1,date2,dateformat2) { + var d1=getDateFromFormat(date1,dateformat1); + var d2=getDateFromFormat(date2,dateformat2); + if (d1==0 || d2==0) { + return -1; + } + else if (d1 > d2) { + return 1; + } + return 0; + } + +// ------------------------------------------------------------------ +// formatDate (date_object, format) +// Returns a date in the output format specified. +// The format string uses the same abbreviations as in getDateFromFormat() +// ------------------------------------------------------------------ +function formatDate(date,format) { + format=format+""; + var result=""; + var i_format=0; + var c=""; + var token=""; + var y=date.getYear()+""; + var M=date.getMonth()+1; + var d=date.getDate(); + var E=date.getDay(); + var H=date.getHours(); + var m=date.getMinutes(); + var s=date.getSeconds(); + var yyyy,yy,MMM,MM,dd,hh,h,mm,ss,ampm,HH,H,KK,K,kk,k; + // Convert real date parts into formatted versions + var value=new Object(); + if (y.length < 4) {y=""+(y-0+1900);} + value["y"]=""+y; + value["yyyy"]=y; + value["yy"]=y.substring(2,4); + value["M"]=M; + value["MM"]=LZ(M); + value["MMM"]=MONTH_NAMES[M-1]; + value["NNN"]=MONTH_NAMES[M+11]; + value["d"]=d; + value["dd"]=LZ(d); + value["E"]=DAY_NAMES[E+7]; + value["EE"]=DAY_NAMES[E]; + value["H"]=H; + value["HH"]=LZ(H); + if (H==0){value["h"]=12;} + else if (H>12){value["h"]=H-12;} + else {value["h"]=H;} + value["hh"]=LZ(value["h"]); + if (H>11){value["K"]=H-12;} else {value["K"]=H;} + value["k"]=H+1; + value["KK"]=LZ(value["K"]); + value["kk"]=LZ(value["k"]); + if (H > 11) { value["a"]="PM"; } + else { value["a"]="AM"; } + value["m"]=m; + value["mm"]=LZ(m); + value["s"]=s; + value["ss"]=LZ(s); + while (i_format < format.length) { + c=format.charAt(i_format); + token=""; + while ((format.charAt(i_format)==c) && (i_format < format.length)) { + token += format.charAt(i_format++); + } + if (value[token] != null) { result=result + value[token]; } + else { result=result + token; } + } + return result; + } + +// ------------------------------------------------------------------ +// Utility functions for parsing in getDateFromFormat() +// ------------------------------------------------------------------ +function _isInteger(val) { + var digits="1234567890"; + for (var i=0; i < val.length; i++) { + if (digits.indexOf(val.charAt(i))==-1) { return false; } + } + return true; + } +function _getInt(str,i,minlength,maxlength) { + for (var x=maxlength; x>=minlength; x--) { + var token=str.substring(i,i+x); + if (token.length < minlength) { return null; } + if (_isInteger(token)) { return token; } + } + return null; + } + +// ------------------------------------------------------------------ +// getDateFromFormat( date_string , format_string ) +// +// This function takes a date string and a format string. It matches +// If the date string matches the format string, it returns the +// getTime() of the date. If it does not match, it returns 0. +// ------------------------------------------------------------------ +function getDateFromFormat(val,format) { + val=val+""; + format=format+""; + var i_val=0; + var i_format=0; + var c=""; + var token=""; + var token2=""; + var x,y; + var now=new Date(); + var year=now.getYear(); + var month=now.getMonth()+1; + var date=1; + var hh=now.getHours(); + var mm=now.getMinutes(); + var ss=now.getSeconds(); + var ampm=""; + + while (i_format < format.length) { + // Get next token from format string + c=format.charAt(i_format); + token=""; + while ((format.charAt(i_format)==c) && (i_format < format.length)) { + token += format.charAt(i_format++); + } + // Extract contents of value based on format token + if (token=="yyyy" || token=="yy" || token=="y") { + if (token=="yyyy") { x=4;y=4; } + if (token=="yy") { x=2;y=2; } + if (token=="y") { x=2;y=4; } + year=_getInt(val,i_val,x,y); + if (year==null) { return 0; } + i_val += year.length; + if (year.length==2) { + if (year > 70) { year=1900+(year-0); } + else { year=2000+(year-0); } + } + } + else if (token=="MMM"||token=="NNN"){ + month=0; + for (var i=0; i<MONTH_NAMES.length; i++) { + var month_name=MONTH_NAMES[i]; + if (val.substring(i_val,i_val+month_name.length).toLowerCase()==month_name.toLowerCase()) { + if (token=="MMM"||(token=="NNN"&&i>11)) { + month=i+1; + if (month>12) { month -= 12; } + i_val += month_name.length; + break; + } + } + } + if ((month < 1)||(month>12)){return 0;} + } + else if (token=="EE"||token=="E"){ + for (var i=0; i<DAY_NAMES.length; i++) { + var day_name=DAY_NAMES[i]; + if (val.substring(i_val,i_val+day_name.length).toLowerCase()==day_name.toLowerCase()) { + i_val += day_name.length; + break; + } + } + } + else if (token=="MM"||token=="M") { + month=_getInt(val,i_val,token.length,2); + if(month==null||(month<1)||(month>12)){return 0;} + i_val+=month.length;} + else if (token=="dd"||token=="d") { + date=_getInt(val,i_val,token.length,2); + if(date==null||(date<1)||(date>31)){return 0;} + i_val+=date.length;} + else if (token=="hh"||token=="h") { + hh=_getInt(val,i_val,token.length,2); + if(hh==null||(hh<1)||(hh>12)){return 0;} + i_val+=hh.length;} + else if (token=="HH"||token=="H") { + hh=_getInt(val,i_val,token.length,2); + if(hh==null||(hh<0)||(hh>23)){return 0;} + i_val+=hh.length;} + else if (token=="KK"||token=="K") { + hh=_getInt(val,i_val,token.length,2); + if(hh==null||(hh<0)||(hh>11)){return 0;} + i_val+=hh.length;} + else if (token=="kk"||token=="k") { + hh=_getInt(val,i_val,token.length,2); + if(hh==null||(hh<1)||(hh>24)){return 0;} + i_val+=hh.length;hh--;} + else if (token=="mm"||token=="m") { + mm=_getInt(val,i_val,token.length,2); + if(mm==null||(mm<0)||(mm>59)){return 0;} + i_val+=mm.length;} + else if (token=="ss"||token=="s") { + ss=_getInt(val,i_val,token.length,2); + if(ss==null||(ss<0)||(ss>59)){return 0;} + i_val+=ss.length;} + else if (token=="a") { + if (val.substring(i_val,i_val+2).toLowerCase()=="am") {ampm="AM";} + else if (val.substring(i_val,i_val+2).toLowerCase()=="pm") {ampm="PM";} + else {return 0;} + i_val+=2;} + else { + if (val.substring(i_val,i_val+token.length)!=token) {return 0;} + else {i_val+=token.length;} + } + } + // If there are any trailing characters left in the value, it doesn't match + if (i_val != val.length) { return 0; } + // Is date valid for month? + if (month==2) { + // Check for leap year + if ( ( (year%4==0)&&(year%100 != 0) ) || (year%400==0) ) { // leap year + if (date > 29){ return 0; } + } + else { if (date > 28) { return 0; } } + } + if ((month==4)||(month==6)||(month==9)||(month==11)) { + if (date > 30) { return 0; } + } + // Correct hours value + if (hh<12 && ampm=="PM") { hh=hh-0+12; } + else if (hh>11 && ampm=="AM") { hh-=12; } + var newdate=new Date(year,month-1,date,hh,mm,ss); + return newdate.getTime(); + } + +// ------------------------------------------------------------------ +// parseDate( date_string [, prefer_euro_format] ) +// +// This function takes a date string and tries to match it to a +// number of possible date formats to get the value. It will try to +// match against the following international formats, in this order: +// y-M-d MMM d, y MMM d,y y-MMM-d d-MMM-y MMM d +// M/d/y M-d-y M.d.y MMM-d M/d M-d +// d/M/y d-M-y d.M.y d-MMM d/M d-M +// A second argument may be passed to instruct the method to search +// for formats like d/M/y (european format) before M/d/y (American). +// Returns a Date object or null if no patterns match. +// ------------------------------------------------------------------ +function parseDate(val) { + var preferEuro=(arguments.length==2)?arguments[1]:false; + generalFormats=new Array('y-M-d','MMM d, y','MMM d,y','y-MMM-d','d-MMM-y','MMM d'); + monthFirst=new Array('M/d/y','M-d-y','M.d.y','MMM-d','M/d','M-d'); + dateFirst =new Array('d/M/y','d-M-y','d.M.y','d-MMM','d/M','d-M'); + var checkList=new Array('generalFormats',preferEuro?'dateFirst':'monthFirst',preferEuro?'monthFirst':'dateFirst'); + var d=null; + for (var i=0; i<checkList.length; i++) { + var l=window[checkList[i]]; + for (var j=0; j<l.length; j++) { + d=getDateFromFormat(val,l[j]); + if (d!=0) { return new Date(d); } + } + } + return null; + } diff --git a/js/messages.php b/js/messages.php index 63fb182..b942a18 100644 --- a/js/messages.php +++ b/js/messages.php @@ -258,6 +258,12 @@ $js_messages['strSave'] = __('Save'); $js_messages['strHideSearchCriteria'] = __('Hide search criteria'); $js_messages['strShowSearchCriteria'] = __('Show search criteria');
+/* For tbl_zoom_plot.js */ +$js_messages['strZoomSearch'] = __('Zoom Search'); +$js_messages['strDisplayHelp'] = __('* Each point represents a data row.<br>* Hovering over a point will show its label.<br>* Drag and select an area in the plot to zoom into it.<br>* Click reset zoom link to come back to original state.<br>* Click a data point to view and possibly edit the data row.<br>* The plot can be resized by dragging it along the bottom right corner.<br>* Strings are converted into integer for plotting'); +$js_messages['strInputNull'] = __('<b>Select two columns</b>'); +$js_messages['strSameInputs'] = __('<b>Select two different columns</b>'); + /* For tbl_change.js */ $js_messages['strIgnore'] = __('Ignore');
diff --git a/js/tbl_select.js b/js/tbl_select.js index 3bc1137..af2242a 100644 --- a/js/tbl_select.js +++ b/js/tbl_select.js @@ -66,7 +66,7 @@ $(document).ready(function() { if (typeof response == 'string') { // found results $("#sqlqueryresults").html(response); - $("#sqlqueryresults").trigger('makegrid'); + $("#sqlqueryresults").trigger('appendAnchor'); $('#tbl_search_form') // work around for bug #3168569 - Issue on toggling the "Hide search criteria" in chrome. .slideToggle() diff --git a/js/tbl_zoom_plot.js b/js/tbl_zoom_plot.js new file mode 100644 index 0000000..b9c0d75 --- /dev/null +++ b/js/tbl_zoom_plot.js @@ -0,0 +1,605 @@ +/* vim: set expandtab sw=4 ts=4 sts=4: */ +/** + ** @fileoverview JavaScript functions used on tbl_select.php + ** + ** @requires jQuery + ** @requires js/functions.js + **/ + + +/** + ** Display Help/Info + **/ +function displayHelp() { + var msgbox = PMA_ajaxShowMessage(PMA_messages['strDisplayHelp'],10000); + msgbox.click(function() { + PMA_ajaxRemoveMessage(msgbox); + }); +} + +/** + ** Extend the array object for max function + ** @param array + **/ +Array.max = function (array) { + return Math.max.apply( Math, array ); +} + +/** + ** Extend the array object for min function + ** @param array + **/ +Array.min = function (array) { + return Math.min.apply( Math, array ); +} + +/** + ** Checks if a string contains only numeric value + ** @param n: String (to be checked) + **/ +function isNumeric(n) { + return !isNaN(parseFloat(n)) && isFinite(n); +} + +/** + ** Checks if an object is empty + ** @param n: Object (to be checked) + **/ +function isEmpty(obj) { + var name; + for (name in obj) { + return false; + } + return true; +} + +/** + ** Converts a timestamp into the format of its field type + ** @param val Integer Timestamp + ** @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) + } + else if (type.toString().search(/date/i) != -1) { + return Highcharts.dateFormat('%Y-%m-%e', val) + } +} + +/** + ** Converts a date/time into timestamp + ** @param val String Date + ** @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') + } + else if (type.toString().search(/date/i) != -1) { + 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'; +} +/** + ** Converts a categorical array into numeric array + ** @param array categorical values array + **/ +function getCord(arr) { + var newCord = new Array(); + var original = $.extend(true,[],arr); + var arr = jQuery.unique(arr).sort(); + $.each(original, function(index,value) { + newCord.push(jQuery.inArray(value,arr)); + }); + return [newCord,arr,original]; +} + +/** + ** Scrolls the view to the display section + **/ +function scrollToChart() { + var x = $('#dataDisplay').offset().top - 100; // 100 provides buffer in viewport + $('html,body').animate({scrollTop: x}, 500); +} + +$(document).ready(function() { + + /** + ** Set a parameter for all Ajax queries made on this page. Don't let the + ** web server serve cached pages + **/ + $.ajaxSetup({ + cache: 'false' + }); + + var cursorMode = ($("input[name='mode']:checked").val() == 'edit') ? 'crosshair' : 'pointer'; + var currentChart = null; + var currentData = null; + var xLabel = $('#tableid_0').val(); + var yLabel = $('#tableid_1').val(); + var xType = $('#types_0').val(); + var yType = $('#types_1').val(); + var dataLabel = $('#dataLabel').val(); + + // Get query result + var data = jQuery.parseJSON($('#querydata').html()); + + /** + ** Input form submit on field change + **/ + $('#tableid_0').change(function() { + $('#zoom_search_form').submit(); + }) + + $('#tableid_1').change(function() { + $('#zoom_search_form').submit(); + }) + + $('#tableid_2').change(function() { + $('#zoom_search_form').submit(); + }) + + $('#tableid_3').change(function() { + $('#zoom_search_form').submit(); + }) + + /** + * 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) + PMA_ajaxShowMessage(PMA_messages['strSameInputs']); + }); + + /** + ** Prepare a div containing a link, otherwise it's incorrectly displayed + ** after a couple of clicks + **/ + $('<div id="togglesearchformdiv"><a id="togglesearchformlink"></a></div>') + .insertAfter('#zoom_search_form') + // don't show it until we have results on-screen + .hide(); + + $('#togglesearchformlink') + .html(PMA_messages['strShowSearchCriteria']) + .bind('click', function() { + var $link = $(this); + $('#zoom_search_form').slideToggle(); + if ($link.text() == PMA_messages['strHideSearchCriteria']) { + $link.text(PMA_messages['strShowSearchCriteria']); + } else { + $link.text(PMA_messages['strHideSearchCriteria']); + } + // avoid default click action + return false; + }); + + /** + ** Set dialog properties for the data display form + **/ + $("#dataDisplay").dialog({ + autoOpen: false, + 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 + */ + + $("#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 + 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 + if (xChange || yChange) { + 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); + } + 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 + newSeries[0].data.push({ name: value[dataLabel], x: tempX[0][i], y: tempY[0][i], marker: {fillColor: colorCodes[i % 8]} , id: 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.series = newSeries; + currentChart = PMA_createChart(currentSettings); + } + + } + 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); + } + 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' ) + newSeries[0].data.push({ name: value[dataLabel], x: value[xLabel], y: tempY[0][i], 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++; + }); + 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(); + } + //End plot update + + //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', { + '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 + + /* + * Generate plot using Highcharts + */ + + if (data != null) { + $('#zoom_search_form') + .slideToggle() + .hide(); + $('#togglesearchformlink') + .text(PMA_messages['strShowSearchCriteria']) + $('#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; + + // Set the basic plot settings + var currentSettings = { + chart: { + renderTo: 'querychart', + type: 'scatter', + zoomType: 'xy', + width:$('#resizer').width() -3, + height:$('#resizer').height()-20 + }, + credits: { + enabled: false + }, + exporting: { enabled: false }, + label: { text: $('#dataLabel').val() }, + plotOptions: { + series: { + allowPointSelect: true, + cursor: 'pointer', + showInLegend: false, + dataLabels: { + enabled: false, + }, + 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 = { + '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, + } + $.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; + }); + + $("#dataDisplay").dialog("open"); + }, + } + } + } + }, + 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() }, + }, + } + + $('#resizer').resizable({ + resize: function() { + currentChart.setSize( + this.offsetWidth -3, + this.offsetHeight -20, + false + ); + } + }); + + // 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'; + + // Formulate series data for plot + series[0] = new Object(); + series[0].data = new Array(); + 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()); + 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++; + }); + 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()); + }} + } + 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()); + series[0].data.push({ name: value[dataLabel], x: tempX[0][it], y: yVal, marker: {fillColor: colorCodes[it % 8]} , id: 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]; + } + } + 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()); + }} + } + 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++; + }); + 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()); + }} + } + 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) { + series[0].data.push({ name: value[dataLabel], x: tempX[0][it], y: tempY[0][it], marker: {fillColor: colorCodes[it % 8]} , id: 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.series = series; + currentChart = PMA_createChart(currentSettings); + scrollToChart(); + } +}); diff --git a/libraries/common.inc.php b/libraries/common.inc.php index c806923..d40cd7b 100644 --- a/libraries/common.inc.php +++ b/libraries/common.inc.php @@ -413,6 +413,7 @@ $goto_whitelist = array( 'tbl_replace.php', 'tbl_row_action.php', 'tbl_select.php', + 'tbl_zoom_select.php', //'themes.php', 'transformation_overview.php', 'transformation_wrapper.php', diff --git a/libraries/config.default.php b/libraries/config.default.php index efb0cbb..d8367e5 100644 --- a/libraries/config.default.php +++ b/libraries/config.default.php @@ -1137,7 +1137,6 @@ $cfg['DefaultTabDatabase'] = 'db_structure.php'; */ $cfg['DefaultTabTable'] = 'sql.php';
- /******************************************************************************* * Export defaults */ @@ -1845,7 +1844,6 @@ $cfg['Export']['xml_export_contents'] = true; */ $cfg['Export']['yaml_structure_or_data'] = 'data';
- /******************************************************************************* * Import defaults */ @@ -2443,7 +2441,6 @@ $cfg['UserprefsDisallow'] = array(); */ $cfg['UserprefsDeveloperTab'] = false;
- /******************************************************************************* * Window title settings */ @@ -2554,9 +2551,7 @@ $cfg['DefaultQueryDatabase'] = ''; /******************************************************************************* * SQL Query box settings * These are the links display in all of the SQL Query boxes - */ - -/** + * * @global array $cfg['SQLQuery'] */ $cfg['SQLQuery'] = array(); @@ -2628,7 +2623,7 @@ $cfg['SaveDir'] = ''; $cfg['TempDir'] = '';
-/******************************************************************************* +/** * Misc. settings */
@@ -2673,12 +2668,7 @@ $cfg['LinkLengthLimit'] = 1000; */ $cfg['DisableMultiTableMaintenance'] = false;
- /******************************************************************************* - * SQL Parser - */ - -/** * SQL Parser Settings * * @global array $cfg['SQP'] @@ -2708,10 +2698,6 @@ $cfg['SQP']['fmtIndUnit'] = 'em';
/******************************************************************************* - * SQL Validator - */ - -/** * If you wish to use the SQL Validator service, you should be aware of the * following: * All SQL statements are stored anonymously for statistical purposes. @@ -2746,10 +2732,6 @@ $cfg['SQLValidator']['password'] = '';
/******************************************************************************* * Developers ONLY! - */ - -/** - * Debugging settings * * @global array $cfg['DBG'] */ @@ -2768,50 +2750,328 @@ $cfg['DBG']['sql'] = false; */
/** - * Column types - * - * Fill in this array to overwrite data from data_*.inc.php files + * Column types; + * VARCHAR, TINYINT, TEXT and DATE are listed first, based on estimated popularity * * @global array $cfg['ColumnTypes'] */ -$cfg['ColumnTypes'] = array(); +$cfg['ColumnTypes'] = array( + // most used + 'INT', + 'VARCHAR', + 'TEXT', + 'DATE', + + // numeric + 'NUMERIC' => array( + 'TINYINT', + 'SMALLINT', + 'MEDIUMINT', + 'INT', + 'BIGINT', + '-', + 'DECIMAL', + 'FLOAT', + 'DOUBLE', + 'REAL', + '-', + 'BIT', + 'BOOLEAN', + 'SERIAL', + ), + + + // Date/Time + 'DATE and TIME' => array( + 'DATE', + 'DATETIME', + 'TIMESTAMP', + 'TIME', + 'YEAR', + ), + + // Text + 'STRING' => array( + 'CHAR', + 'VARCHAR', + '-', + 'TINYTEXT', + 'TEXT', + 'MEDIUMTEXT', + 'LONGTEXT', + '-', + 'BINARY', + 'VARBINARY', + '-', + 'TINYBLOB', + 'MEDIUMBLOB', + 'BLOB', + 'LONGBLOB', + '-', + 'ENUM', + 'SET', + ), + + 'SPATIAL' => array( + 'GEOMETRY', + 'POINT', + 'LINESTRING', + 'POLYGON', + 'MULTIPOINT', + 'MULTILINESTRING', + 'MULTIPOLYGON', + 'GEOMETRYCOLLECTION', + ), +);
/** * Attributes * - * Fill in this array to overwrite data from data_*.inc.php files - * * @global array $cfg['AttributeTypes'] */ -$cfg['AttributeTypes'] = array(); +$cfg['AttributeTypes'] = array( + '', + 'BINARY', + 'UNSIGNED', + 'UNSIGNED ZEROFILL', + 'on update CURRENT_TIMESTAMP', +); +
if ($cfg['ShowFunctionFields']) { /** * Available functions * - * Fill in this array to overwrite data from data_*.inc.php files - * * @global array $cfg['Functions'] */ - $cfg['Functions'] = array(); + $cfg['Functions'] = array( + 'ABS', + 'ACOS', + 'ASCII', + 'ASIN', + 'ATAN', + 'BIN', + 'BIT_COUNT', + 'BIT_LENGTH', + 'CEILING', + 'CHAR', + 'CHAR_LENGTH', + 'COMPRESS', + 'COS', + 'COT', + 'CRC32', + 'CURDATE', + 'CURRENT_USER', + 'CURTIME', + 'DATE', + 'DAYNAME', + 'DEGREES', + 'DES_DECRYPT', + 'DES_ENCRYPT', + 'ENCRYPT', + 'EXP', + 'FLOOR', + 'FROM_DAYS', + 'FROM_UNIXTIME', + 'HEX', + 'INET_ATON', + 'INET_NTOA', + 'LENGTH', + 'LN', + 'LOG', + 'LOG10', + 'LOG2', + 'LOWER', + 'MD5', + 'NOW', + 'OCT', + 'OLD_PASSWORD', + 'ORD', + 'PASSWORD', + 'RADIANS', + 'RAND', + 'REVERSE', + 'ROUND', + 'SEC_TO_TIME', + 'SHA1', + 'SOUNDEX', + 'SPACE', + 'SQRT', + 'STDDEV_POP', + 'STDDEV_SAMP', + 'TAN', + 'TIMESTAMP', + 'TIME_TO_SEC', + 'UNCOMPRESS', + 'UNHEX', + 'UNIX_TIMESTAMP', + 'UPPER', + 'USER', + 'UTC_DATE', + 'UTC_TIME', + 'UTC_TIMESTAMP', + 'UUID', + 'VAR_POP', + 'VAR_SAMP', + 'YEAR', + );
/** * Which column types will be mapped to which Group? * - * Fill in this array to overwrite data from data_*.inc.php files - * * @global array $cfg['RestrictColumnTypes'] */ - $cfg['RestrictColumnTypes'] = array(); + $cfg['RestrictColumnTypes'] = array( + 'TINYINT' => 'FUNC_NUMBER', + 'SMALLINT' => 'FUNC_NUMBER', + 'MEDIUMINT' => 'FUNC_NUMBER', + 'INT' => 'FUNC_NUMBER', + 'BIGINT' => 'FUNC_NUMBER', + 'DECIMAL' => 'FUNC_NUMBER', + 'FLOAT' => 'FUNC_NUMBER', + 'DOUBLE' => 'FUNC_NUMBER', + 'REAL' => 'FUNC_NUMBER', + 'BIT' => 'FUNC_NUMBER', + 'BOOLEAN' => 'FUNC_NUMBER', + 'SERIAL' => 'FUNC_NUMBER', + + 'DATE' => 'FUNC_DATE', + 'DATETIME' => 'FUNC_DATE', + 'TIMESTAMP' => 'FUNC_DATE', + 'TIME' => 'FUNC_DATE', + 'YEAR' => 'FUNC_DATE', + + 'CHAR' => 'FUNC_CHAR', + 'VARCHAR' => 'FUNC_CHAR', + 'TINYTEXT' => 'FUNC_CHAR', + 'TEXT' => 'FUNC_CHAR', + 'MEDIUMTEXT' => 'FUNC_CHAR', + 'LONGTEXT' => 'FUNC_CHAR', + 'BINARY' => 'FUNC_CHAR', + 'VARBINARY' => 'FUNC_CHAR', + 'TINYBLOB' => 'FUNC_CHAR', + 'MEDIUMBLOB' => 'FUNC_CHAR', + 'BLOB' => 'FUNC_CHAR', + 'LONGBLOB' => 'FUNC_CHAR', + 'ENUM' => '', + 'SET' => '', + + 'GEOMETRY' => 'FUNC_SPATIAL', + 'POINT' => 'FUNC_SPATIAL', + 'LINESTRING' => 'FUNC_SPATIAL', + 'POLYGON' => 'FUNC_SPATIAL', + 'MULTIPOINT' => 'FUNC_SPATIAL', + 'MULTILINESTRING' => 'FUNC_SPATIAL', + 'MULTIPOLYGON' => 'FUNC_SPATIAL', + 'GEOMETRYCOLLECTION' => 'FUNC_SPATIAL', + + );
/** * Map above defined groups to any function * - * Fill in this array to overwrite data from data_*.inc.php files - * * @global array $cfg['RestrictFunctions'] */ - $cfg['RestrictFunctions'] = array(); + $cfg['RestrictFunctions'] = array( + 'FUNC_CHAR' => array( + 'BIN', + 'CHAR', + 'CURRENT_USER', + 'COMPRESS', + 'DAYNAME', + 'DES_DECRYPT', + 'DES_ENCRYPT', + 'ENCRYPT', + 'HEX', + 'INET_NTOA', + 'LOWER', + 'MD5', + 'OLD_PASSWORD', + 'PASSWORD', + 'REVERSE', + 'SHA1', + 'SOUNDEX', + 'SPACE', + 'UNCOMPRESS', + 'UNHEX', + 'UPPER', + 'USER', + 'UUID', + ), + + 'FUNC_DATE' => array( + 'CURDATE', + 'CURTIME', + 'DATE', + 'FROM_DAYS', + 'FROM_UNIXTIME', + 'NOW', + 'SEC_TO_TIME', + 'TIMESTAMP', + 'UTC_DATE', + 'UTC_TIME', + 'UTC_TIMESTAMP', + 'YEAR', + ), + + 'FUNC_NUMBER' => array( + 'ABS', + 'ACOS', + 'ASCII', + 'ASIN', + 'ATAN', + 'BIT_LENGTH', + 'BIT_COUNT', + 'CEILING', + 'CHAR_LENGTH', + 'COS', + 'COT', + 'CRC32', + 'DEGREES', + 'EXP', + 'FLOOR', + 'INET_ATON', + 'LENGTH', + 'LN', + 'LOG', + 'LOG2', + 'LOG10', + 'OCT', + 'ORD', + 'RADIANS', + 'RAND', + 'ROUND', + 'SQRT', + 'STDDEV_POP', + 'STDDEV_SAMP', + 'TAN', + 'TIME_TO_SEC', + 'UNIX_TIMESTAMP', + 'VAR_POP', + 'VAR_SAMP', + ), + + 'FUNC_SPATIAL' => array( + 'GeomFromText', + 'GeomFromWKB', + + 'GeomCollFromText', + 'LineFromText', + 'MLineFromText', + 'PointFromText', + 'MPointFromText', + 'PolyFromText', + 'MPolyFromText', + + 'GeomCollFromWKB', + 'LineFromWKB', + 'MLineFromWKB', + 'PointFromWKB', + 'MPointFromWKB', + 'PolyFromWKB', + 'MPolyFromWKB', + ), + );
/** * Default functions for above defined groups @@ -2825,6 +3085,97 @@ if ($cfg['ShowFunctionFields']) { 'first_timestamp' => 'NOW', 'pk_char36' => 'UUID', ); -} + + +} // end if + +/** + * Search operators + * + * @global array $cfg['NumOperators'] + */ +$cfg['NumOperators'] = array( + '=', + '>', + '>=', + '<', + '<=', + '!=', + 'LIKE', + 'NOT LIKE', + 'IN (...)', + 'NOT IN (...)', + 'BETWEEN', + 'NOT BETWEEN', +); + +/** + * Search operators + * + * @global array $cfg['TextOperators'] + */ +$cfg['TextOperators'] = array( + 'LIKE', + 'LIKE %...%', + 'NOT LIKE', + '=', + '!=', + 'REGEXP', + 'REGEXP ^...$', + 'NOT REGEXP', + "= ''", + "!= ''", + 'IN (...)', + 'NOT IN (...)', + 'BETWEEN', + 'NOT BETWEEN', +); + +/** + * Search operators + * + * @global array $cfg['EnumOperators'] + */ +$cfg['EnumOperators'] = array( + '=', + '!=', +); + +/** + * Search operators + * + * @global array $cfg['SetOperators'] + */ +$cfg['SetOperators'] = array( + 'IN', + 'NOT IN', +); + +/** + * Search operators + * + * @global array $cfg['NullOperators'] + */ +$cfg['NullOperators'] = array( + 'IS NULL', + 'IS NOT NULL', +); + +/** + * Search operators + * + * @global array $cfg['UnaryOperators'] + */ +$cfg['UnaryOperators'] = array( + 'IS NULL' => 1, + 'IS NOT NULL' => 1, + "= ''" => 1, + "!= ''" => 1 +); + +/** + * Max rows retreived for zoom search + */ +$cfg['maxRowPlotLimit'] = 500;
?> diff --git a/libraries/svg_plot/pma_scatter_plot.php b/libraries/svg_plot/pma_scatter_plot.php new file mode 100644 index 0000000..10c0aea --- /dev/null +++ b/libraries/svg_plot/pma_scatter_plot.php @@ -0,0 +1,267 @@ +<?php +/** + * Generates the SVG needed for the plot + * + * @package phpMyAdmin + */ + +require_once 'pma_svg_data_point.php'; + +class PMA_Scatter_Plot +{ + /** + * @var array Raw data for the plot + */ + private $_data; + + /** + * @var array Data points of the plot + */ + private $_dataPoints; + + /** + * @var array Set of default settigs values are here. + */ + private $_settings = array( + + // Array of colors to be used for plot. + 'colors' => array( + '#BCE02E', + '#E0642E', + '#E0D62E', + '#2E97E0', + '#B02EE0', + '#E02E75', + '#5CE02E', + '#E0B02E', + '#000000', + '#0022E0', + '#726CB1', + '#481A36', + '#BAC658', + '#127224', + '#825119', + '#238C74', + '#4C489B', + '#87C9BF', + ), + // Plot background color. + 'bgColor' => '#84AD83', + + // The width of the plot. + 'width' => 520, + + // The height of the plot. + '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' => '', + + // Data point label. If empty, label will be taken from the data. + 'dataLabel' => '', + + ); + + /** + * @var array Options that the user has specified. + */ + private $_userSpecifiedSettings = null; + + /** + * Returns the settings array + * + * @return the settings array. + */ + public function getSettings() + { + return $this->_settings; + } + + /** + * Returns the data array + * + * @return the data array. + */ + public function getData() + { + return $this->_data; + } + + /** + * Constructor. Stores user specified options. + * + * @param array $data Data for the visualization + * @param array $options Users specified options + */ + public function __construct($data, $options) + { + $this->_userSpecifiedSettings = $options; + $this->_data = $data; + } + + /** + * All the variable initialization, options handling 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() + { + $this->_dataPoints = array(); + if (! is_null($this->_userSpecifiedSettings)) { + foreach (array_keys($this->_userSpecifiedSettings) as $key){ + $this->_settings[$key] = $this->_userSpecifiedSettings[$key]; + } + } + if ($this->_settings['dataLabel'] == '') { + $labels = array_keys($this->_data[0]); + $this->_settings['dataLabel'] = $labels[0]; + } + } + + /** + * Generate the visualization in SVG format. + * + * @return the generated image resource + */ + private function _svg() + { + $this->init(); + + $output = '<?xml version="1.0" encoding="UTF-8" standalone="no"?>' . "\n"; + $output .= '<svg version="1.1" xmlns:svg="http://www.w3.org/2000/svg"' + . ' xmlns="http://www.w3.org/2000/svg" width="' . $this->_settings['width'] . '"' + . ' height="' . $this->_settings['height'] . '">'; + $output .= '<g id="groupPanel">'; + $output .= '<defs> + <path id="myTextPath1" + d="M10,190 L10,50"/> + <path id="myTextPath2" + d="M250,10 L370,10"/> + </defs>'; + $output .= '<text x="6" y="190" style="font-family: Arial; font-size : 54; stroke:none; fill:#000000;" > + <textPath xlink:href="#myTextPath1" >'; + $output .= $this->_settings['yLabel']; + $output .= '</textPath> + </text>'; + + $output .= '<text x="250" y="10" style="font-family: Arial; font-size : 54; stroke:none; fill:#000000;" > + <textPath xlink:href="#myTextPath2" >'; + $output .= $this->_settings['xLabel']; + $output .= '</textPath> + </text>'; + + + $scale_data = $this->_scaleDataSet($this->_data, $this->_settings['xLabel'], $this->_settings['yLabel']); + $output .= $this->_prepareDataSet($this->_data, 0, $scale_data, $this->_settings['dataLabel']); + + $output .= '</g>'; + $output .= '</svg>'; + + return $output; + } + + /** + * Get the visualization as a SVG. + * + * @return the visualization as a SVG + */ + public function asSVG() + { + $output = $this->_svg(); + return $output; + } + + /** + * Calculates the scale, horizontal and vertical offset that should be used. + * + * @param array $data Row data + * + * @return an array containing the scale, x and y offsets + */ + private function _scaleDataSet($data,$xField,$yField) + { + + // Currently assuming only numeric fields are selected + $coordinates = array(); + foreach ($data as $row) { + $coordinates[0][] = $row[$xField]; + $coordinates[1][] = $row[$yField]; + } + for ($i = 0 ; $i < 2 ; $i++) { + + $maxC = ($i == 0) ? 500 : 320; + + if( !is_numeric($coordinates[$i][0])) { + $uniqueC = array_unique($coordinates[$i]); + $countC = count(array_unique($coordinates[$i])); + $map = $tmp = array(); + foreach ($uniqueC as $uc) { + $tmp[] = $uc; + } + for ($j = 0 ; $j < $countC ; $j++) { + $map[$tmp[$j]] = 20 + $j * $maxC / $countC; + } + for($j = 0 ; $j < count($coordinates[$i]) ; $j++) { + $coordinates[$i][$j] = $map[$coordinates[$i][$j]]; + } + + } + elseif (is_numeric($coordinates[$i][0])) { + + $maxC = max($coordinates[$i]); + for($j = 0 ; $j < count($coordinates[$i]) ; $j++) { + + if ($i == 0) + $coordinates[$i][$j] = 20 + 500 * $coordinates[$i][$j] / $maxC; + else + $coordinates[$i][$j] = 20 + 320 * (1 - $coordinates[$i][$j] / $maxC); + } + } + } + return $coordinates; + } + + /** + * Prepares and return the dataset as needed by the visualization. + * + * @param array $data Raw data + * @param int $color_number Start index to the color array + * @param array $scale_data Data related to scaling + * @param string $label Label for the data points + * @param image $results Image object in the case of png + * + * @return the formatted array of data. + */ + private function _prepareDataSet($data, $color_number, $scale_data, $label) + { + $result = ''; + // loop through the rows + for($i = 0 ; $i < count($data) ; $i++) { + + $index = $color_number % sizeof($this->_settings['colors']); + + $data_element = new PMA_SVG_Data_Point($scale_data[0][$i],$scale_data[1][$i],$data[$i][$label],$data[$i]); + + $options = array('color' => $this->_settings['colors'][$index], 'id' => $i); + $this->_dataPoints[] = $data_element; + + $result .= $data_element->prepareRowAsSVG($options); + $color_number++; + } + + + return $result; + } +} +?> + diff --git a/libraries/svg_plot/pma_svg_data_element.php b/libraries/svg_plot/pma_svg_data_element.php new file mode 100644 index 0000000..97f7734 --- /dev/null +++ b/libraries/svg_plot/pma_svg_data_element.php @@ -0,0 +1,50 @@ +<?php +/** + * Base class for the plot data type classes. + * + * @package phpMyAdmin + */ +abstract class PMA_SVG_Data_Element{ + + protected $label = ''; + + protected $dataRow = array(); + + /** + * Store user specified label and dataRow + * @param string $label users specified label + * @param array $dataRow A data row from the query result + */ + function __construct($label,$dataRow) + { + $this->label = $label; + $this->dataRow = $dataRow; + } + + /** + * Handles the generation of each Data Row/Element as a SVG element + * @return the code related to a row in the GIS dataset + */ + public abstract function prepareRowAsSVG($options); + + public function getLabel() + { + return $this->label; + } + + public function setLabel($label) + { + $this->label = $label; + } + + public function getDataRow() + { + return $this->dataRow; + } + + public function setDataRow($dataRow) + { + $this->dataRow = $dataRow; + } +} +?> diff --git a/libraries/svg_plot/pma_svg_data_point.php b/libraries/svg_plot/pma_svg_data_point.php new file mode 100644 index 0000000..7d01b2b --- /dev/null +++ b/libraries/svg_plot/pma_svg_data_point.php @@ -0,0 +1,86 @@ +<?php +/** + * Handles the visualization of Data Point objects. + * + * @package phpMyAdmin + */ + +require_once 'pma_svg_data_element.php'; + +class PMA_SVG_Data_Point extends PMA_SVG_Data_Element +{ + /* + * X-Coordinate of the point + */ + private $cx; + + /* + * Y-Coordinate of the point + */ + private $cy; + + /* + * A private constructor; prevents direct creation of object. + */ + public function __construct($cx, $cy, $label, $dataRow) + { + parent::__construct($label,$dataRow); + $this->cx = $cx; + $this->cy = $cy; + + } + + public function prepareRowAsSVG($options) + { + return $this->prepareSvg($options); + } + + /** + * Prepares and returns the code related to a row in the query result as SVG. + * + * @param array $options Array containing options related to properties of the point + * + * @return the code related to a row in the query result. + */ + + protected function prepareSvg($options) + { + $point_options = array( + 'name' => $this->label . '_' .$options['id'], + 'id' => $this->label . 'id' . '_' . $options['id'], + 'class' => 'point', + 'fill' => 'white', + 'stroke' => $options['color'], + 'stroke-width'=> 2, + ); + + $row = '<circle cx="' . $this->cx . '" cy="' . $this->cy . '" r=".1"'; + foreach ($point_options as $option => $val) { + $row .= ' ' . $option . '="' . trim($val) . '"'; + } + $row .= '/>'; + + return $row; + } + + public function getCx() + { + return $this->cx; + } + + public function setCx($cx) + { + $this->cx = $cx; + } + + public function getCy() + { + return $this->cy; + } + + public function setCy($cy) + { + $this->cy = $cy; + } +} +?> diff --git a/libraries/tbl_select.lib.php b/libraries/tbl_select.lib.php new file mode 100644 index 0000000..6384f60 --- /dev/null +++ b/libraries/tbl_select.lib.php @@ -0,0 +1,390 @@ +<?php +/* vim: set expandtab sw=4 ts=4 sts=4: */ +/** + * Functions for the table-search page and zoom-search page + * + * Funtion PMA_tbl_getFields : Returns the fields of a table + * Funtion PMA_tbl_search_getWhereClause : Returns the where clause for query generation + * + * @package phpMyAdmin + */ + +require_once 'url_generating.lib.php'; + + /** + * PMA_tbl_setTitle() sets the title for foreign keys display link + * + * @param $propertiesIconic Type of icon property + * @param $themeImage Icon Image + * @return string $str Value of the Title + * + */ + +function PMA_tbl_setTitle($propertiesIconic,$pmaThemeImage){ + if ($propertiesIconic == true) { + $str = '<img class="icon" width="16" height="16" src="' . $pmaThemeImage + .'b_browse.png" alt="' . __('Browse foreign values') . '" title="' + . __('Browse foreign values') . '" />'; + + if ($propertiesIconic === 'both') { + $str .= __('Browse foreign values'); + return $str; + } + } else { + return __('Browse foreign values'); + } +} + + /** + * PMA_tbl_getFields() gets all the fields of a table along with their types,collations and whether null or not. + * + * @uses PMA_DBI_query() + * @uses PMA_backquote() + * @uses PMA_DBI_num_rows() + * @uses PMA_DBI_fetch_assoc() + * @uses PMA_DBI_free_result() + * @uses preg_replace() + * @uses str_replace() + * @uses strncasecmp() + * @uses empty() + * + * @param $db Selected database + * @param $table Selected table + * + * @return array($fields_list,$fields_type,$fields_collation,$fields_null) Array containing the field list, field types, collations and null constatint + * + */ + +function PMA_tbl_getFields($table,$db) { + + // Gets the list and number of fields + + $result = PMA_DBI_query('SHOW FULL FIELDS FROM ' . PMA_backquote($table) . ' FROM ' . PMA_backquote($db) . ';', null, PMA_DBI_QUERY_STORE); + $fields_cnt = PMA_DBI_num_rows($result); + $fields_list = $fields_null = $fields_type = $fields_collation = array(); + while ($row = PMA_DBI_fetch_assoc($result)) { + $fields_list[] = $row['Field']; + $type = $row['Type']; + // reformat mysql query output + if (strncasecmp($type, 'set', 3) == 0 + || strncasecmp($type, 'enum', 4) == 0) { + $type = str_replace(',', ', ', $type); + } else { + + // strip the "BINARY" attribute, except if we find "BINARY(" because + // this would be a BINARY or VARBINARY field type + if (!preg_match('@BINARY[\(]@i', $type)) { + $type = preg_replace('@BINARY@i', '', $type); + } + $type = preg_replace('@ZEROFILL@i', '', $type); + $type = preg_replace('@UNSIGNED@i', '', $type); + + $type = strtolower($type); + } + if (empty($type)) { + $type = ' '; + } + $fields_null[] = $row['Null']; + $fields_type[] = $type; + $fields_collation[] = !empty($row['Collation']) && $row['Collation'] != 'NULL' + ? $row['Collation'] + : ''; + } // end while + PMA_DBI_free_result($result); + unset($result, $type); + + return array($fields_list,$fields_type,$fields_collation,$fields_null); + +} + +/* PMA_tbl_setTableHeader() sets the table header for displaying a table in query-by-example format + * + * @return HTML content, the tags and content for table header + * + */ + +function PMA_tbl_setTableHeader(){ + +return '<thead> + <tr><th>' . __('Column') . '</th> + <th>' . __('Type') . '</th> + <th>' . __('Collation') . '</th> + <th>' . __('Operator') . '</th> + <th>' . __('Value') . '</th> + </tr> + </thead>'; + + +} + +/* PMA_tbl_getSubTabs() returns an array with necessary configrations to create sub-tabs(Table Search and Zoom Search) in the table_select page + * + * @return array $subtabs Array containing configuration (icon,text,link,id,args) of sub-tabs for Table Search and Zoom search + * + */ + +function PMA_tbl_getSubTabs(){ + + $subtabs = array(); + + $subtabs['search']['icon'] = 'b_search.png'; + $subtabs['search']['text'] = __('Table Search'); + $subtabs['search']['link'] = 'tbl_select.php'; + $subtabs['search']['id'] = 'tbl_search_id'; + $subtabs['search']['args']['pos'] = 0; + + $subtabs['zoom']['icon'] = 'b_props.png'; + $subtabs['zoom']['link'] = 'tbl_zoom_select.php'; + $subtabs['zoom']['text'] = __('Zoom Search'); + $subtabs['zoom']['id'] = 'zoom_search_id'; + + return $subtabs; + +} + + +/* PMA_tbl_getForeignFields_Values() creates the HTML content for: 1) Browsing foreign data for a field. 2) Creating elements for search criteria input on fields. + * + * @uses PMA_foreignDropdown + * @uses PMA_generate_common_url + * @uses isset() + * @uses is_array() + * @uses in_array() + * @uses urlencode() + * @uses str_replace() + * @uses stbstr() + * + * @param $foreigners Array of foreign keys + * @param $foreignData Foreign keys data + * @param $field Column name + * @param $tbl_fields_type Column type + * @param $i Column index + * @param $db Selected database + * @param $table Selected table + * @param $titles Selected title + * @param $foreignMaxLimit Max limit of displaying foreign elements + * @param $fields Array of search criteria inputs + * + * @return string $str HTML content for viewing foreing data and elements for search criteria input. + * + */ + +function PMA_getForeignFields_Values($foreigners, $foreignData, $field, $tbl_fields_type, $i, $db, $table,$titles,$foreignMaxLimit, $fields){ + + $str = ''; + + if ($foreigners && isset($foreigners[$field]) && is_array($foreignData['disp_row'])) { + // f o r e i g n k e y s + $str .= ' <select name="fields[' . $i . ']" id="fieldID_' . $i .'">' . "\n"; + // go back to first row + // here, the 4th parameter is empty because there is no current + // value of data for the dropdown (the search page initial values + // are displayed empty) + $str .= PMA_foreignDropdown($foreignData['disp_row'], + $foreignData['foreign_field'], + $foreignData['foreign_display'], + '', $foreignMaxLimit); + $str .= ' </select>' . "\n"; + } + elseif ($foreignData['foreign_link'] == true) { + if(isset($fields[$i]) && is_string($fields[$i])){ + $str .= '<input type="text" id="fieldID_' . $i .'"name="fields[' . $i . '] " value="' . $fields[$i] . '"'; + 'id="field_' . md5($field) . '[' . $i .']" + class="textfield"/>' ; + } + else{ + $str .= '<input type="text" id="fieldID_' . $i .'"name="fields[' . $i . '] "'; + 'id="field_' . md5($field) . '[' . $i .']" + class="textfield" />' ; + } + ?> + <?php $str .= '<script type="text/javascript">'; + // <![CDATA[ + $str .= <<<EOT +<a target="_blank" onclick="window.open(this.href, 'foreigners', 'width=640,height=240,scrollbars=yes'); return false" href="browse_foreigners.php? +EOT; + $str .= '' . PMA_generate_common_url($db, $table) . '&field=' . urlencode($field) . '&fieldkey=' . $i . '">' . str_replace("'", "\'", $titles['Browse']) . '</a>'; + // ]] + $str .= '</script>'; + } + elseif (strncasecmp($tbl_fields_type[$i], 'enum', 4) == 0) { + // e n u m s + $enum_value=explode(', ', str_replace("'", '', substr($tbl_fields_type[$i], 5, -1))); + $cnt_enum_value = count($enum_value); + $str .= '<select name="fields[' . ($i) . '][]" id="fieldID_' . $i .'"' + .' multiple="multiple" size="' . min(3, $cnt_enum_value) . '">' . "\n"; + for ($j = 0; $j < $cnt_enum_value; $j++) { + if(isset($fields[$i]) && is_array($fields[$i]) && in_array($enum_value[$j],$fields[$i])){ + $str .= ' <option value="' . $enum_value[$j] . '" Selected>' + . $enum_value[$j] . '</option>'; + } + else{ + $str .= ' <option value="' . $enum_value[$j] . '">' + . $enum_value[$j] . '</option>'; + } + } // end for + $str .= ' </select>' . "\n"; + } + else { + // o t h e r c a s e s + $the_class = 'textfield'; + $type = $tbl_fields_type[$i]; + if ($type == 'date') { + $the_class .= ' datefield'; + } elseif ($type == 'datetime' || substr($type, 0, 9) == 'timestamp') { + $the_class .= ' datetimefield'; + } + if(isset($fields[$i]) && is_string($fields[$i])){ + $str .= ' <input type="text" name="fields[' . $i . ']" ' + .' size="40" class="' . $the_class . '" id="fieldID_' . $i .'" value = "' . $fields[$i] . '"/>' . "\n"; + } + else{ + $str .= ' <input type="text" name="fields[' . $i . ']"' + .' size="40" class="' . $the_class . '" id="fieldID_' . $i .'" />' . "\n"; + } + }; + return $str; + +} + + +/* PMA_tbl_search_getWhereClause() Return the where clause for query generation based on the inputs provided. + * + * @uses PMA_backquote + * @uses PMA_sqlAddslashes + * @uses preg_match + * @uses isset() + * @uses in_array() + * @uses str_replace() + * @uses strpos() + * @uses explode() + * @uses trim() + * + * @param $fields Search criteria input + * @param $names Name of the field(column) on which search criteria is submitted + * @param $types Type of the field + * @param $collations Field collation + * @param $func_type Search fucntion/operator + * @param $unaryFlag Whether operator unary or not + * + * @return string $str HTML content for viewing foreing data and elements for search criteria input. + * + */ + +function PMA_tbl_search_getWhereClause($fields, $names, $types, $collations, $func_type, $unaryFlag){ + + + $w = ''; + if($unaryFlag){ + $fields = ''; + $w = PMA_backquote($names) . ' ' . $func_type; + + } elseif (strncasecmp($types, 'enum', 4) == 0) { + if (!empty($fields)) { + if (! is_array($fields)) { + $fields = explode(',', $fields); + } + $enum_selected_count = count($fields); + if ($func_type == '=' && $enum_selected_count > 1) { + $func_type = 'IN'; + $parens_open = '('; + $parens_close = ')'; + + } elseif ($func_type == '!=' && $enum_selected_count > 1) { + $func_type = 'NOT IN'; + $parens_open = '('; + $parens_close = ')'; + + } else { + $parens_open = ''; + $parens_close = ''; + } + $enum_where = '\'' . PMA_sqlAddslashes($fields[0]) . '\''; + for ($e = 1; $e < $enum_selected_count; $e++) { + $enum_where .= ', \'' . PMA_sqlAddslashes($fields[$e]) . '\''; + } + + $w = PMA_backquote($names) . ' ' . $func_type . ' ' . $parens_open . $enum_where . $parens_close; + } + + } elseif ($fields != '') { + // For these types we quote the value. Even if it's another type (like INT), + // for a LIKE we always quote the value. MySQL converts strings to numbers + // and numbers to strings as necessary during the comparison + if (preg_match('@char|binary|blob|text|set|date|time|year@i', $types) || strpos(' ' . $func_type, 'LIKE')) { + $quot = '\''; + } else { + $quot = ''; + } + + // LIKE %...% + if ($func_type == 'LIKE %...%') { + $func_type = 'LIKE'; + $fields = '%' . $fields . '%'; + } + if ($func_type == 'REGEXP ^...$') { + $func_type = 'REGEXP'; + $fields = '^' . $fields . '$'; + } + + if ($func_type == 'IN (...)' || $func_type == 'NOT IN (...)' || $func_type == 'BETWEEN' || $func_type == 'NOT BETWEEN') { + $func_type = str_replace(' (...)', '', $func_type); + + // quote values one by one + $values = explode(',', $fields); + foreach ($values as &$value) + $value = $quot . PMA_sqlAddslashes(trim($value)) . $quot; + + if ($func_type == 'BETWEEN' || $func_type == 'NOT BETWEEN') + $w = PMA_backquote($names) . ' ' . $func_type . ' ' . (isset($values[0]) ? $values[0] : '') . ' AND ' . (isset($values[1]) ? $values[1] : ''); + else + $w = PMA_backquote($names) . ' ' . $func_type . ' (' . implode(',', $values) . ')'; + } + else { + $w = PMA_backquote($names) . ' ' . $func_type . ' ' . $quot . PMA_sqlAddslashes($fields) . $quot;; + } + + } // end if + + return $w; +} + +/** + * Formats a SVG plot for the query results. + * + * @param array $data Data for the status chart + * @param array &$settings Settings used to generate the chart + * + * @return string HTML and JS code for the SVG plot + */ +function PMA_SVG_scatter_plot($data, &$settings) +{ + require_once './libraries/svg_plot/pma_scatter_plot.php'; + + if (empty($data)) { + // empty data + return ''; + } else { + $scatter_plot = new PMA_Scatter_Plot($data, $settings); + + if ($settings != null) { + foreach ($scatter_plot->getSettings() as $setting => $val) { + if (! isset($settings[$setting])) { + $settings[$setting] = $val; + } + } + } + return $scatter_plot->asSVG(); + } + +} + + + + + + + + + +?> diff --git a/tbl_select.php b/tbl_select.php index c6b0a35..e9b1eae 100644 --- a/tbl_select.php +++ b/tbl_select.php @@ -15,6 +15,7 @@ */ require_once './libraries/common.inc.php'; require_once './libraries/mysql_charsets.lib.php'; +require_once './libraries/tbl_select.lib.php';
$GLOBALS['js_include'][] = 'makegrid.js'; $GLOBALS['js_include'][] = 'sql.js'; @@ -22,18 +23,8 @@ $GLOBALS['js_include'][] = 'tbl_select.js'; $GLOBALS['js_include'][] = 'tbl_change.js'; $GLOBALS['js_include'][] = 'jquery/jquery-ui-1.8.custom.js'; $GLOBALS['js_include'][] = 'jquery/timepicker.js'; -if ($GLOBALS['cfg']['PropertiesIconic'] == true) { - $titles['Browse'] = - '<img class="icon" width="16" height="16" src="' . $pmaThemeImage - .'b_browse.png" alt="' . __('Browse foreign values') . '" title="' - . __('Browse foreign values') . '" />'; - - if ($GLOBALS['cfg']['PropertiesIconic'] === 'both') { - $titles['Browse'] .= __('Browse foreign values'); - } -} else { - $titles['Browse'] = __('Browse foreign values'); -} + +$titles['Browse'] = PMA_tbl_setTitle($GLOBALS['cfg']['PropertiesIconic'], $pmaThemeImage);
/** * Not selection yet required -> displays the selection form @@ -61,45 +52,26 @@ if (! isset($param) || $param[0] == '') { $err_url = $goto . '?' . PMA_generate_common_url($db, $table);
// Gets the list and number of fields - $result = PMA_DBI_query('SHOW FULL FIELDS FROM ' . PMA_backquote($table) . ' FROM ' . PMA_backquote($db) . ';', null, PMA_DBI_QUERY_STORE); - $fields_cnt = PMA_DBI_num_rows($result); - $fields_list = $fields_null = $fields_type = $fields_collation = array(); - while ($row = PMA_DBI_fetch_assoc($result)) { - $fields_list[] = $row['Field']; - $type = $row['Type']; - // reformat mysql query output - if (strncasecmp($type, 'set', 3) == 0 - || strncasecmp($type, 'enum', 4) == 0) { - $type = str_replace(',', ', ', $type); - } else {
- // strip the "BINARY" attribute, except if we find "BINARY(" because - // this would be a BINARY or VARBINARY field type - if (!preg_match('@BINARY[(]@i', $type)) { - $type = preg_replace('@BINARY@i', '', $type); - } - $type = preg_replace('@ZEROFILL@i', '', $type); - $type = preg_replace('@UNSIGNED@i', '', $type); - - $type = strtolower($type); - } - if (empty($type)) { - $type = ' '; - } - $fields_null[] = $row['Null']; - $fields_type[] = $type; - $fields_collation[] = !empty($row['Collation']) && $row['Collation'] != 'NULL' - ? $row['Collation'] - : ''; - } // end while - PMA_DBI_free_result($result); - unset($result, $type); + list($fields_list, $fields_type, $fields_collation, $fields_null) = PMA_tbl_getFields($table,$db); + $fields_cnt = count($fields_list);
// retrieve keys into foreign fields, if any // check also foreigners even if relwork is FALSE (to get // foreign keys from innodb) $foreigners = PMA_getForeigners($db, $table); ?> + +<fieldset id="fieldset_subtab"> +<?php +$url_params = array(); +$url_params['db'] = $db; +$url_params['table'] = $table; + +echo PMA_generate_html_tabs(PMA_tbl_getSubTabs(), $url_params); + +?> + <form method="post" action="tbl_select.php" name="insertForm" id="tbl_search_form" <?php echo ($GLOBALS['cfg']['AjaxEnable'] ? ' class="ajax"' : ''); ?>> <?php echo PMA_generate_common_hidden_inputs($db, $table); ?> <input type="hidden" name="goto" value="<?php echo $goto; ?>" /> @@ -110,14 +82,7 @@ if (! isset($param) || $param[0] == '') { <fieldset id="fieldset_table_qbe"> <legend><?php echo __('Do a "query by example" (wildcard: "%")') ?></legend> <table class="data"> - <thead> - <tr><th><?php echo __('Column'); ?></th> - <th><?php echo __('Type'); ?></th> - <th><?php echo __('Collation'); ?></th> - <th><?php echo __('Operator'); ?></th> - <th><?php echo __('Value'); ?></th> - </tr> - </thead> + <?php echo PMA_tbl_setTableHeader(); ?> <tbody> <?php $odd_row = true; @@ -130,57 +95,31 @@ if (! isset($param) || $param[0] == '') { <td><?php echo $fields_collation[$i]; ?></td> <td><select name="func[]"> <?php - // determine valid operators if (strncasecmp($fields_type[$i], 'enum', 4) == 0) { - // enum operators - $operators = array( - '=', - '!=', - ); + foreach ($GLOBALS['cfg']['EnumOperators'] as $fc) { + echo "\n" . ' ' + . '<option value="' . htmlspecialchars($fc) . '">' + . htmlspecialchars($fc) . '</option>'; + } } elseif (preg_match('@char|blob|text|set@i', $fields_type[$i])) { - // text operators - $operators = array( - 'LIKE', - 'LIKE %...%', - 'NOT LIKE', - '=', - '!=', - 'REGEXP', - 'REGEXP ^...$', - 'NOT REGEXP', - "= ''", - "!= ''", - 'IN (...)', - 'NOT IN (...)', - 'BETWEEN', - 'NOT BETWEEN', - ); + foreach ($GLOBALS['cfg']['TextOperators'] as $fc) { + echo "\n" . ' ' + . '<option value="' . htmlspecialchars($fc) . '">' + . htmlspecialchars($fc) . '</option>'; + } } else { - // numeric operators - $operators = array( - '=', - '>', - '>=', - '<', - '<=', - '!=', - 'LIKE', - 'NOT LIKE', - 'IN (...)', - 'NOT IN (...)', - 'BETWEEN', - 'NOT BETWEEN', - ); + foreach ($GLOBALS['cfg']['NumOperators'] as $fc) { + echo "\n" . ' ' + . '<option value="' . htmlspecialchars($fc) . '">' + . htmlspecialchars($fc) . '</option>'; + } } // end if... else... - - // if field can be NULL, add IS NULL and IS NOT NULL if ($fields_null[$i]) { - $operators[] = 'IS NULL'; - $operators[] = 'IS NOT NULL'; - } - foreach ($operators as $op) { - echo "\n" . ' ' - . '<option value="' . htmlspecialchars($op) . '">' . htmlspecialchars($op) . '</option>'; + foreach ($GLOBALS['cfg']['NullOperators'] as $fc) { + echo "\n" . ' ' + . '<option value="' . htmlspecialchars($fc) . '">' + . htmlspecialchars($fc) . '</option>'; + } } ?>
@@ -192,54 +131,9 @@ if (! isset($param) || $param[0] == '') {
$foreignData = PMA_getForeignData($foreigners, $field, false, '', '');
- if ($foreigners && isset($foreigners[$field]) && is_array($foreignData['disp_row'])) { - // f o r e i g n k e y s - echo ' <select name="fields[' . $i . ']">' . "\n"; - // go back to first row - - // here, the 4th parameter is empty because there is no current - // value of data for the dropdown (the search page initial values - // are displayed empty) - echo PMA_foreignDropdown($foreignData['disp_row'], - $foreignData['foreign_field'], - $foreignData['foreign_display'], - '', $GLOBALS['cfg']['ForeignKeyMaxLimit']); - echo ' </select>' . "\n"; - } elseif ($foreignData['foreign_link'] == true) { - ?> - <input type="text" name="fields[<?php echo $i; ?>]" - id="field_<?php echo md5($field); ?>[<?php echo $i; ?>]" - class="textfield" /> - <script type="text/javascript"> - // <![CDATA[ - document.writeln('<a target="_blank" onclick="window.open(this.href, \'foreigners\', \'width=640,height=240,scrollbars=yes\'); return false" href="browse_foreigners.php?<?php echo PMA_generate_common_url($db, $table); ?>&field=<?php echo urlencode($field); ?>&fieldkey=<?php echo $i; ?>"><?php echo str_replace("'", "\'", $titles['Browse']); ?></a>'); - // ]]> - </script> - <?php - } elseif (strncasecmp($fields_type[$i], 'enum', 4) == 0) { - // e n u m s - $enum_value=explode(', ', str_replace("'", '', substr($fields_type[$i], 5, -1))); - $cnt_enum_value = count($enum_value); - echo ' <select name="fields[' . $i . '][]"' - .' multiple="multiple" size="' . min(3, $cnt_enum_value) . '">' . "\n"; - for ($j = 0; $j < $cnt_enum_value; $j++) { - echo ' <option value="' . $enum_value[$j] . '">' - . $enum_value[$j] . '</option>'; - } // end for - echo ' </select>' . "\n"; - } else { - // o t h e r c a s e s - $the_class = 'textfield'; - $type = $fields_type[$i]; - if ($type == 'date') { - $the_class .= ' datefield'; - } elseif ($type == 'datetime' || substr($type, 0, 9) == 'timestamp') { - $the_class .= ' datetimefield'; - } - echo ' <input type="text" name="fields[' . $i . ']"' - .' size="40" class="' . $the_class . '" id="field_' . $i . '" />' . "\n"; - }; - ?> + echo PMA_getForeignFields_Values($foreigners, $foreignData, $field, $fields_type, $i, $db, $table, $titles,$GLOBALS['cfg']['ForeignKeyMaxLimit'], '' ); + + ?> <input type="hidden" name="names[<?php echo $i; ?>]" value="<?php echo htmlspecialchars($fields_list[$i]); ?>" /> <input type="hidden" name="types[<?php echo $i; ?>]" @@ -321,13 +215,20 @@ if (! isset($param) || $param[0] == '') { <div id="sqlqueryresults"></div> <?php require './libraries/footer.inc.php'; +?> + +</fieldset> + +<?php }
+ /** * Selection criteria have been submitted -> do the work */ else { + echo "ZZ"; // Builds the query
$sql_query = 'SELECT ' . (isset($distinct) ? 'DISTINCT ' : ''); @@ -354,88 +255,18 @@ else { $sql_query .= ' WHERE ' . $where; } else { $w = $charsets = array(); - $unary_operators = array( - 'IS NULL' => 1, - 'IS NOT NULL' => 1, - "= ''" => 1, - "!= ''" => 1 - ); $cnt_func = count($func); reset($func); while (list($i, $func_type) = each($func)) { - list($charsets[$i]) = explode('_', $collations[$i]); - if (isset($unary_operators[$func_type])) { - $fields[$i] = ''; - $w[] = PMA_backquote($names[$i]) . ' ' . $func_type; - - } elseif (strncasecmp($types[$i], 'enum', 4) == 0) { - if (!empty($fields[$i])) { - if (! is_array($fields[$i])) { - $fields[$i] = explode(',', $fields[$i]); - } - $enum_selected_count = count($fields[$i]); - if ($func_type == '=' && $enum_selected_count > 1) { - $func_type = $func[$i] = 'IN'; - $parens_open = '('; - $parens_close = ')'; - - } elseif ($func_type == '!=' && $enum_selected_count > 1) { - $func_type = $func[$i] = 'NOT IN'; - $parens_open = '('; - $parens_close = ')'; - - } else { - $parens_open = ''; - $parens_close = ''; - } - $enum_where = ''' . PMA_sqlAddSlashes($fields[$i][0]) . '''; - for ($e = 1; $e < $enum_selected_count; $e++) { - $enum_where .= ', '' . PMA_sqlAddSlashes($fields[$i][$e]) . '''; - } - - $w[] = PMA_backquote($names[$i]) . ' ' . $func_type . ' ' . $parens_open . $enum_where . $parens_close; - } - - } elseif ($fields[$i] != '') { - // For these types we quote the value. Even if it's another type (like INT), - // for a LIKE we always quote the value. MySQL converts strings to numbers - // and numbers to strings as necessary during the comparison - if (preg_match('@char|binary|blob|text|set|date|time|year@i', $types[$i]) || strpos(' ' . $func_type, 'LIKE')) { - $quot = '''; - } else { - $quot = ''; - } - - // LIKE %...% - if ($func_type == 'LIKE %...%') { - $func_type = 'LIKE'; - $fields[$i] = '%' . $fields[$i] . '%'; - } - if ($func_type == 'REGEXP ^...$') { - $func_type = 'REGEXP'; - $fields[$i] = '^' . $fields[$i] . '$'; - } - - if ($func_type == 'IN (...)' || $func_type == 'NOT IN (...)' || $func_type == 'BETWEEN' || $func_type == 'NOT BETWEEN') { - $func_type = str_replace(' (...)', '', $func_type); - - // quote values one by one - $values = explode(',', $fields[$i]); - foreach ($values as &$value) - $value = $quot . PMA_sqlAddSlashes(trim($value)) . $quot; - - if ($func_type == 'BETWEEN' || $func_type == 'NOT BETWEEN') - $w[] = PMA_backquote($names[$i]) . ' ' . $func_type . ' ' . (isset($values[0]) ? $values[0] : '') . ' AND ' . (isset($values[1]) ? $values[1] : ''); - else - $w[] = PMA_backquote($names[$i]) . ' ' . $func_type . ' (' . implode(',', $values) . ')'; - } - else { - $w[] = PMA_backquote($names[$i]) . ' ' . $func_type . ' ' . $quot . PMA_sqlAddSlashes($fields[$i]) . $quot;; - } - - } // end if + + list($charsets[$i]) = explode('_', $collations[$i]); + $unaryFlag = (isset($GLOBALS['cfg']['UnaryOperators'][$func_type]) && $GLOBALS['cfg']['UnaryOperators'][$func_type] == 1) ? true : false; + $whereClause = PMA_tbl_search_getWhereClause($fields[$i],$names[$i], $types[$i], $collations[$i], $func_type, $unaryFlag); + if($whereClause) + $w[] = $whereClause; + } // end for - + //print_r($w); if ($w) { $sql_query .= ' WHERE ' . implode(' AND ', $w); } @@ -444,7 +275,6 @@ else { if ($orderField != '--nil--') { $sql_query .= ' ORDER BY ' . PMA_backquote($orderField) . ' ' . $order; } // end if - require './sql.php'; }
diff --git a/tbl_zoom_select.php b/tbl_zoom_select.php new file mode 100644 index 0000000..cdb784d --- /dev/null +++ b/tbl_zoom_select.php @@ -0,0 +1,447 @@ +<?php +/* vim: set expandtab sw=4 ts=4 sts=4: */ +/** + * Handles table zoom search tab + * + * display table zoom search form, create SQL queries from form data + * + */ + +/** + * Gets some core libraries + */ +require_once './libraries/common.inc.php'; +require_once './libraries/mysql_charsets.lib.php'; +require_once './libraries/tbl_select.lib.php'; +require_once './libraries/relation.lib.php'; +require_once './libraries/tbl_info.inc.php'; + +$GLOBALS['js_include'][] = 'makegrid.js'; +$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'][] = 'highcharts/highcharts.js'; +/* Files required for chart exporting */ +$GLOBALS['js_include'][] = 'highcharts/exporting.js'; +$GLOBALS['js_include'][] = 'canvg/canvg.js'; +$GLOBALS['js_include'][] = 'canvg/rgbcolor.js'; +$GLOBALS['js_include'][] = 'jquery/jquery-ui-1.8.custom.js'; +$GLOBALS['js_include'][] = 'jquery/timepicker.js'; + + +/** + * Handle AJAX request for data row on point select + * @var post_params Object containing parameters for the POST request + */ + +if (isset($_REQUEST['get_data_row']) && $_REQUEST['get_data_row'] == true) { + + $extra_data = array(); + $row_info_query = 'SELECT * FROM `' . $_REQUEST['db'] . '`.`' . $_REQUEST['table'] . '` WHERE ' . $_REQUEST['where_clause']; + $result = PMA_DBI_query( $row_info_query . ";" , null, PMA_DBI_QUERY_STORE); + $fields_meta = PMA_DBI_get_fields_meta($result); + while ($row = PMA_DBI_fetch_assoc($result)) + $extra_data['row_info'] = $row; + + PMA_ajaxResponse(NULL, true, $extra_data); +} + +$titles['Browse'] = PMA_tbl_setTitle($GLOBALS['cfg']['PropertiesIconic'], $pmaThemeImage); +/** + * Not selection yet required -> displays the selection form + */ + + // Gets some core libraries + require_once './libraries/tbl_common.php'; + //$err_url = 'tbl_select.php' . $err_url; + $url_query .= '&goto=tbl_select.php&back=tbl_select.php'; + + /** + * Gets tables informations + */ + require_once './libraries/tbl_info.inc.php'; + + /** + * Displays top menu links + */ + require_once './libraries/tbl_links.inc.php'; + + if (! isset($goto)) { + $goto = $GLOBALS['cfg']['DefaultTabTable']; + } + // Defines the url to return to in case of error in the next sql statement + $err_url = $goto . '?' . PMA_generate_common_url($db, $table); + + // Gets the list and number of fields + + list($fields_list, $fields_type, $fields_collation, $fields_null) = PMA_tbl_getFields($table,$db); + $fields_cnt = count($fields_list); + + // retrieve keys into foreign fields, if any + // check also foreigners even if relwork is FALSE (to get + // foreign keys from innodb) + $foreigners = PMA_getForeigners($db, $table); + $flag = 1; + $tbl_fields_type = $tbl_fields_collation = $tbl_fields_null = array(); + if(!isset($zoom_submit) && !isset($inputs)) + $dataLabel = PMA_getDisplayField($db,$table); + + ?> + + +<div id="sqlqueryresults"></div> +<fieldset id="fieldset_subtab"> +<?php +$url_params = array(); +$url_params['db'] = $db; +$url_params['table'] = $table; +echo PMA_generate_html_tabs(PMA_tbl_getSubTabs(), $url_params); + +/** + * Set the field name,type,collation and whether null on select of a coulmn + */ +if(isset($inputs) && ($inputs[0] != __('pma_null') || $inputs[1] != __('pma_null'))) +{ + $flag = 2; + for($i = 0 ; $i < 4 ; $i++) + { + if($inputs[$i] != __('pma_null')) + { + $key = array_search($inputs[$i],$fields_list); + $tbl_fields_type[$i] = $fields_type[$key]; + $tbl_fields_collation[$i] = $fields_collation[$key]; + $tbl_fields_null[$i] = $fields_null[$key]; + } + + } +} + + +?> + +<?php + +/* + * Form for input criteria + */ + +?> +<form method="post" action="tbl_zoom_select.php" name="zoomInputForm" id="zoom_search_form" <?php echo ($GLOBALS['cfg']['AjaxEnable'] ? ' class="ajax"' : ''); ?>> +<?php echo PMA_generate_common_hidden_inputs($db, $table); ?> +<input type="hidden" name="goto" value="<?php echo $goto; ?>" /> +<input type="hidden" name="back" value="tbl_zoom_select.php" /> +<input type="hidden" name="flag" id="id_flag" value=<?php echo $flag; ?> /> + + + + +<fieldset id="inputSection"> + +<legend><?php echo __('Do a "query by example" (wildcard: "%") for two different columns') ?></legend> +<table class="data"> +<?php echo PMA_tbl_setTableHeader();?> +<tbody> +<?php + $odd_row = true; + +for($i = 0 ; $i < 4 ; $i++){ + + if($i == 2){ + echo "<tr><td>"; + echo __("Additional search criteria"); + echo "</td><tr>"; + } + +?> + <tr class="noclick <?php echo $odd_row ? 'odd' : 'even'; $odd_row = ! $odd_row; ?>"> + <th><select name="inputs[]" id=<?php echo 'tableid_' . $i?> > + <option value= <?php echo __('pma_null')?>><?php echo __('None'); ?> </option> + <?php + for ($j = 0 ; $j < $fields_cnt ; $j++){ + if(isset($inputs[$i]) && $inputs[$i] == htmlspecialchars($fields_list[$j])){?> + <option value=<?php echo htmlspecialchars($fields_list[$j]);?> Selected> <?php echo htmlspecialchars($fields_list[$j]);?></option> + <?php + } + else{ ?> + <option value=<?php echo htmlspecialchars($fields_list[$j]);?> > <?php echo htmlspecialchars($fields_list[$j]);?></option> + <?php + } + } ?> + </select></th> + <td><?php if(isset($tbl_fields_type[$i]))echo $tbl_fields_type[$i]; ?></td> + <td><?php if(isset($tbl_fields_collation[$i]))echo $tbl_fields_collation[$i]; ?></td> + + <td> + <?php if(isset($inputs) && $inputs[$i] != __('pma_null')){ ?> + <select name="zoomFunc[]"> + <?php + + if (strncasecmp($tbl_fields_type[$i], 'enum', 4) == 0) { + foreach ($GLOBALS['cfg']['EnumOperators'] as $fc) { + if(isset($zoomFunc[$i]) && $zoomFunc[$i] == htmlspecialchars($fc)){ + echo "\n" . ' ' + . '<option value="' . htmlspecialchars($fc) . '" Selected>' + . htmlspecialchars($fc) . '</option>'; + } + else { + echo "\n" . ' ' + . '<option value="' . htmlspecialchars($fc) . '">' + . htmlspecialchars($fc) . '</option>'; + } + } + } elseif (preg_match('@char|blob|text|set@i', $tbl_fields_type[$i])) { + foreach ($GLOBALS['cfg']['TextOperators'] as $fc) { + if(isset($zoomFunc[$i]) && $zoomFunc[$i] == $fc){ + echo "\n" . ' ' + . '<option value="' . htmlspecialchars($fc) . '" Selected>' + . htmlspecialchars($fc) . '</option>'; + } + else { + echo "\n" . ' ' + . '<option value="' . htmlspecialchars($fc) . '">' + . htmlspecialchars($fc) . '</option>'; + } + } + } else { + foreach ($GLOBALS['cfg']['NumOperators'] as $fc) { + if(isset($zoomFunc[$i]) && $zoomFunc[$i] == $fc){ + echo "\n" . ' ' + . '<option value="' . htmlspecialchars($fc) . '" Selected>' + . htmlspecialchars($fc) . '</option>'; + } + else { + echo "\n" . ' ' + . '<option value="' . htmlspecialchars($fc) . '">' + . htmlspecialchars($fc) . '</option>'; + } + } + } // end if... else... + + if ($tbl_fields_null[$i]) { + foreach ($GLOBALS['cfg']['NullOperators'] as $fc) { + if(isset($zoomFunc[$i]) && $zoomFunc[$i] == $fc){ + echo "\n" . ' ' + . '<option value="' . htmlspecialchars($fc) . '" Selected>' + . htmlspecialchars($fc) . '</option>'; + } + else { + echo "\n" . ' ' + . '<option value="' . htmlspecialchars($fc) . '">' + . htmlspecialchars($fc) . '</option>'; + } + } + } + ?> + </select> + </td> + <td> + <?php + $field = $inputs[$i]; + + $foreignData = PMA_getForeignData($foreigners, $field, false, '', ''); + if (isset($fields)) + echo PMA_getForeignFields_Values($foreigners, $foreignData, $field, $tbl_fields_type, $i ,$db, $table, $titles, $GLOBALS['cfg']['ForeignKeyMaxLimit'], $fields); + else + echo PMA_getForeignFields_Values($foreigners, $foreignData, $field, $tbl_fields_type, $i ,$db, $table, $titles, $GLOBALS['cfg']['ForeignKeyMaxLimit'], ''); + + } + else{ ?> + + </td><td></td> + + <?php } ?> + + </td> + </tr> + + <input type="hidden" name="types[<?php echo $i; ?>]" id="types_<?php echo $i; ?>" + value="<?php if(isset($tbl_fields_type[$i]))echo $tbl_fields_type[$i]; ?>" /> + <input type="hidden" name="collations[<?php echo $i; ?>]" + value="<?php if(isset($tbl_fields_collation[$i]))echo $tbl_fields_collation[$i]; ?>" /> + + + +<?php + }//end for +?> + </table> + + <?php + /* + * Other inputs like data label and mode go after selection of column criteria + */ + + //Set default datalabel if not selected + if(isset($zoom_submit) && $inputs[0] != __('pma_null') && $inputs[1] != __('pma_null')) { + if ($dataLabel == '') + $dataLabel = PMA_getDisplayField($db,$table); + } + ?> + <table class="data"> + <tr><td><label for="label"><?php echo __("Data Label"); ?></label>        </td> + <td><select name="dataLabel" id='dataLabel' > + <option value = ''> <?php echo __('None'); ?> </option> + <?php + for ($j = 0 ; $j < $fields_cnt ; $j++){ + if(isset($dataLabel) && $dataLabel == htmlspecialchars($fields_list[$j])){?> + <option value=<?php echo htmlspecialchars($fields_list[$j]);?> Selected> <?php echo htmlspecialchars($fields_list[$j]);?></option> + <?php + } + else{ ?> + <option value=<?php echo htmlspecialchars($fields_list[$j]);?> > <?php echo htmlspecialchars($fields_list[$j]);?></option> + <?php + } + } ?> + </select> + </td></tr> + <tr><td><label for="label"><?php echo __("Maximum rows to plot"); ?></label></td> + <td> + <?php if(isset($maxPlotLimit)) { ?> + <input type="text" name="maxPlotLimit" value="<?php echo $maxPlotLimit; ?>" /></td></tr> + <?php + } + else { ?> + <input type="text" name="maxPlotLimit" value="<?php echo $GLOBALS['cfg']['maxRowPlotLimit']; ?>" /></td></tr> + <?php + } ?> + </table> + +</fieldset> +<fieldset class="tblFooters"> + <input type="hidden" name="max_number_of_fields" + value="<?php echo $fields_cnt; ?>" /> + <input type="submit" name="zoom_submit" id="inputFormSubmitId" value="<?php echo __('Go'); ?>" /> +</fieldset> +</form> + +<?php + +/* + * Handle the input criteria and gerate the query result + * Form for displaying query results + */ +if(isset($zoom_submit) && $inputs[0] != __('pma_null') && $inputs[1] != __('pma_null') && $inputs[0] != $inputs[1]) { + + /* + * Query generation part + */ + $w = $data = array(); + $sql_query = 'SELECT *'; + + //Add the table + + $sql_query .= ' FROM ' . PMA_backquote($table); + for($i = 0 ; $i < 4 ; $i++){ + if($inputs[$i] == __('pma_null')) + continue; + $tmp = array(); + // The where clause + $charsets = array(); + $cnt_func = count($zoomFunc[$i]); + $func_type = $zoomFunc[$i]; + list($charsets[$i]) = explode('_', $collations[$i]); + $unaryFlag = (isset($GLOBALS['cfg']['UnaryOperators'][$func_type]) && $GLOBALS['cfg']['UnaryOperators'][$func_type] == 1) ? true : false; + $whereClause = PMA_tbl_search_getWhereClause($fields[$i],$inputs[$i], $types[$i], $collations[$i], $func_type, $unaryFlag); + if($whereClause) + $w[] = $whereClause; + + } // end for + if ($w) { + $sql_query .= ' WHERE ' . implode(' AND ', $w); + } + $sql_query .= ' LIMIT ' . $maxPlotLimit; + + /* + * Query execution part + */ + $result = PMA_DBI_query( $sql_query . ";" , null, PMA_DBI_QUERY_STORE); + $fields_meta = PMA_DBI_get_fields_meta($result); + while ($row = PMA_DBI_fetch_assoc($result)) { + //Need a row with indexes as 0,1,2 for the PMA_getUniqueCondition hence using a temporary array + $tmpRow = array(); + foreach($row as $val) + $tmpRow[] = $val; + //Get unique conditon on each row (will be needed for row update) + $uniqueCondition = PMA_getUniqueCondition($result, $fields_cnt, $fields_meta, $tmpRow, true); + + //Append it to row array as where_clause + $row['where_clause'] = $uniqueCondition[0]; + if($dataLabel == $inputs[0] || $dataLabel == $inputs[1]) + $data[] = array($inputs[0] => $row[$inputs[0]], $inputs[1] => $row[$inputs[1]], 'where_clause' => $uniqueCondition[0]); + else + $data[] = array($inputs[0] => $row[$inputs[0]], $inputs[1] => $row[$inputs[1]], $dataLabel => $row[$dataLabel], 'where_clause' => $uniqueCondition[0]); + } + +?> + +<?php + /* + * Form for displaying point data and also the scatter plot + */ +?> + <form method="post" action="tbl_zoom_select.php" name="displayResultForm" id="zoom_display_form" <?php echo ($GLOBALS['cfg']['AjaxEnable'] ? ' class="ajax"' : ''); ?>> + <?php echo PMA_generate_common_hidden_inputs($db, $table); ?> + <input type="hidden" name="goto" value="<?php echo $goto; ?>" /> + <input type="hidden" name="back" value="tbl_zoom_select.php" /> + + <fieldset id="displaySection"> + <legend><?php echo __('Browse/Edit the points') ?></legend> + <center> + <?php + //JSON encode the data(query result) + if(isset($zoom_submit) && !empty($data)){ ?> + <div id='resizer' style="width:600px;height:400px"> + <?php if (isset($data)) ?><center> <a href="#" onClick="displayHelp();"><?php echo __('How to use'); ?></a> </center> + <div id="querydata" style="display:none"> + <?php if(isset($data)) echo json_encode($data); ?> + </div> + <div id="querychart" style="float:right"></div> + </div> + <?php + } ?> + </center> + <fieldset id='dataDisplay' style="display:none"> + <fieldset> + <table class="data"> + <thead> + <tr> + <th> <?php echo __('Column'); ?> </th> + <th> <?php echo __('Null'); ?> </th> + <th> <?php echo __('Value'); ?> </th> + </tr> + </thead> + <tbody> + <?php + $odd_row = true; + for ($i = 4; $i < $fields_cnt + 4 ; $i++) { + $tbl_fields_type[$i] = $fields_type[$i - 4]; + $fieldpopup = $fields_list[$i - 4]; + $foreignData = PMA_getForeignData($foreigners, $fieldpopup, false, '', ''); + ?> + <tr class="noclick <?php echo $odd_row ? 'odd' : 'even'; $odd_row = ! $odd_row; ?>"> + <th><?php echo htmlspecialchars($fields_list[$i - 4]); ?></th> + <th><?php echo '<input type="checkbox" class="checkbox_null" name="fields_null[ ' . $i . ' ]" id="fields_null_id_' . $i . '" />'; ?></th> + <th><?php echo PMA_getForeignFields_Values($foreigners, $foreignData, $fieldpopup, $tbl_fields_type, $i, $db, $table, $titles,$GLOBALS['cfg']['ForeignKeyMaxLimit'], '' ); ?> </th> + </tr> + <?php + } ?> + </tbody> + </table> + </fieldset> + <fieldset class="tblFooters"> + <input type="submit" id="submitForm" name="edit_point" value="<?php echo __('Submit'); ?>" /> + </fieldset> + </fieldset> + + </fieldset> + <input type="hidden" id="queryID" name="sql_query" /> + </form> + </fieldset> + <?php +} +?> + + <?php + require './libraries/footer.inc.php'; +?>
hooks/post-receive