1 /* vim: set expandtab sw=4 ts=4 sts=4: */
3 * @fileoverview JavaScript functions used on tbl_select.php
6 * @requires js/functions.js
10 * Ajax event handlers for this page
12 * Actions ajaxified here:
17 * Checks if given data-type is numeric or date.
19 * @param string data_type Column data-type
23 function PMA_checkIfDataTypeNumericOrDate (data_type) {
24 // To test for numeric data-types.
25 var numeric_re = new RegExp(
26 'TINYINT|SMALLINT|MEDIUMINT|INT|BIGINT|DECIMAL|FLOAT|DOUBLE|REAL',
30 // To test for date data-types.
31 var date_re = new RegExp(
32 'DATETIME|DATE|TIMESTAMP|TIME|YEAR',
36 // Return matched data-type
37 if (numeric_re.test(data_type)) {
38 return numeric_re.exec(data_type)[0];
41 if (date_re.test(data_type)) {
42 return date_re.exec(data_type)[0];
49 * Unbind all event handlers before tearing down a page
51 AJAX.registerTeardown('tbl_select.js', function () {
52 $('#togglesearchformlink').off('click');
53 $(document).off('submit', '#tbl_search_form.ajax');
54 $('select.geom_func').off('change');
55 $(document).off('click', 'span.open_search_gis_editor');
56 $('body').off('change', 'select[name*="criteriaColumnOperators"]'); // Fix for bug #13778, changed 'click' to 'change'
59 AJAX.registerOnload('tbl_select.js', function () {
61 * Prepare a div containing a link, otherwise it's incorrectly displayed
62 * after a couple of clicks
64 $('<div id="togglesearchformdiv"><a id="togglesearchformlink"></a></div>')
65 .insertAfter('#tbl_search_form')
66 // don't show it until we have results on-screen
69 $('#togglesearchformlink')
70 .html(PMA_messages.strShowSearchCriteria)
71 .on('click', function () {
73 $('#tbl_search_form').slideToggle();
74 if ($link.text() === PMA_messages.strHideSearchCriteria) {
75 $link.text(PMA_messages.strShowSearchCriteria);
77 $link.text(PMA_messages.strHideSearchCriteria);
79 // avoid default click action
83 var tableRows = $('#fieldset_table_qbe select');
84 $.each(tableRows, function (index, item) {
85 $(item).on('change', function () {
86 changeValueFieldType(this, index);
91 * Ajax event handler for Table search
93 $(document).on('submit', '#tbl_search_form.ajax', function (event) {
94 var unaryFunctions = [
101 var geomUnaryFunctions = [
108 // jQuery object to reuse
109 var $search_form = $(this);
110 event.preventDefault();
112 // empty previous search results while we are waiting for new results
113 $('#sqlqueryresultsouter').empty();
114 var $msgbox = PMA_ajaxShowMessage(PMA_messages.strSearching, false);
116 PMA_prepareForAjaxRequest($search_form);
119 $search_form.find(':input').each(function () {
120 var $input = $(this);
121 if ($input.attr('type') === 'checkbox' || $input.attr('type') === 'radio') {
122 if ($input.is(':checked')) {
123 values[this.name] = $input.val();
126 values[this.name] = $input.val();
129 var columnCount = $('select[name="columnsToDisplay[]"] option').length;
130 // Submit values only for the columns that have unary column operator or a search criteria
131 for (var a = 0; a < columnCount; a++) {
132 if ($.inArray(values['criteriaColumnOperators[' + a + ']'], unaryFunctions) >= 0) {
136 if (values['geom_func[' + a + ']'] &&
137 $.isArray(values['geom_func[' + a + ']'], geomUnaryFunctions) >= 0) {
141 if (values['criteriaValues[' + a + ']'] === '' || values['criteriaValues[' + a + ']'] === null) {
142 delete values['criteriaValues[' + a + ']'];
143 delete values['criteriaColumnOperators[' + a + ']'];
144 delete values['criteriaColumnNames[' + a + ']'];
145 delete values['criteriaColumnTypes[' + a + ']'];
146 delete values['criteriaColumnCollations[' + a + ']'];
149 // If all columns are selected, use a single parameter to indicate that
150 if (values['columnsToDisplay[]'] !== null) {
151 if (values['columnsToDisplay[]'].length === columnCount) {
152 delete values['columnsToDisplay[]'];
153 values.displayAllColumns = true;
156 values.displayAllColumns = true;
159 $.post($search_form.attr('action'), values, function (data) {
160 PMA_ajaxRemoveMessage($msgbox);
161 if (typeof data !== 'undefined' && data.success === true) {
162 if (typeof data.sql_query !== 'undefined') { // zero rows
163 $('#sqlqueryresultsouter').html(data.sql_query);
164 } else { // results found
165 $('#sqlqueryresultsouter').html(data.message);
166 $('.sqlqueryresults').trigger('makegrid').trigger('stickycolumns');
168 $('#tbl_search_form')
169 // workaround for bug #3168569 - Issue on toggling the "Hide search criteria" in chrome.
172 $('#togglesearchformlink')
173 // always start with the Show message
174 .text(PMA_messages.strShowSearchCriteria);
175 $('#togglesearchformdiv')
176 // now it's time to show the div containing the link
178 // needed for the display options slider in the results
180 $('html, body').animate({ scrollTop: 0 }, 'fast');
182 $('#sqlqueryresultsouter').html(data.error);
184 PMA_highlightSQL($('#sqlqueryresultsouter'));
188 // Following section is related to the 'function based search' for geometry data types.
189 // Initialy hide all the open_gis_editor spans
190 $('span.open_search_gis_editor').hide();
192 $('select.geom_func').bind('change', function () {
193 var $geomFuncSelector = $(this);
195 var binaryFunctions = [
229 var outputGeomFunctions = binaryFunctions.concat(tempArray);
231 // If the chosen function takes two geometry objects as parameters
232 var $operator = $geomFuncSelector.parents('tr').find('td:nth-child(5)').find('select');
233 if ($.inArray($geomFuncSelector.val(), binaryFunctions) >= 0) {
234 $operator.prop('readonly', true);
236 $operator.prop('readonly', false);
239 // if the chosen function's output is a geometry, enable GIS editor
240 var $editorSpan = $geomFuncSelector.parents('tr').find('span.open_search_gis_editor');
241 if ($.inArray($geomFuncSelector.val(), outputGeomFunctions) >= 0) {
248 $(document).on('click', 'span.open_search_gis_editor', function (event) {
249 event.preventDefault();
253 var value = $span.parent('td').children('input[type=\'text\']').val();
255 var field = 'Parameter';
257 var geom_func = $span.parents('tr').find('.geom_func').val();
259 if (geom_func === 'Envelope') {
261 } else if (geom_func === 'ExteriorRing') {
266 // Names of input field and null checkbox
267 var input_name = $span.parent('td').children('input[type=\'text\']').attr('name');
271 if (!gisEditorLoaded) {
272 loadJSAndGISEditor(value, field, type, input_name);
274 loadGISEditor(value, field, type, input_name);
279 * Ajax event handler for Range-Search.
281 $('body').on('change', 'select[name*="criteriaColumnOperators"]', function () { // Fix for bug #13778, changed 'click' to 'change'
282 $source_select = $(this);
283 // Get the column name.
284 var column_name = $(this)
289 // Get the data-type of column excluding size.
290 var data_type = $(this)
292 .find('td[data-type]')
294 data_type = PMA_checkIfDataTypeNumericOrDate(data_type);
297 var operator = $(this).val();
299 if ((operator === 'BETWEEN' || operator === 'NOT BETWEEN')
302 var $msgbox = PMA_ajaxShowMessage();
304 url: 'tbl_select.php',
307 server: PMA_commonParams.get('server'),
309 db: $('input[name="db"]').val(),
310 table: $('input[name="table"]').val(),
314 success: function (response) {
315 PMA_ajaxRemoveMessage($msgbox);
316 if (response.success) {
317 // Get the column min value.
318 var min = response.column_data.min
319 ? '(' + PMA_messages.strColumnMin +
320 ' ' + response.column_data.min + ')'
322 // Get the column max value.
323 var max = response.column_data.max
324 ? '(' + PMA_messages.strColumnMax +
325 ' ' + response.column_data.max + ')'
327 var button_options = {};
328 button_options[PMA_messages.strGo] = function () {
329 var min_value = $('#min_value').val();
330 var max_value = $('#max_value').val();
331 var final_value = '';
332 if (min_value.length && max_value.length) {
333 final_value = min_value + ', ' +
336 var $target_field = $source_select.closest('tr')
337 .find('[name*="criteriaValues"]');
339 // If target field is a select list.
340 if ($target_field.is('select')) {
341 $target_field.val(final_value);
342 var $options = $target_field.find('option');
343 var $closest_min = null;
344 var $closest_max = null;
345 // Find closest min and max value.
346 $options.each(function () {
348 $closest_min === null
349 || Math.abs($(this).val() - min_value) < Math.abs($closest_min.val() - min_value)
351 $closest_min = $(this);
355 $closest_max === null
356 || Math.abs($(this).val() - max_value) < Math.abs($closest_max.val() - max_value)
358 $closest_max = $(this);
362 $closest_min.attr('selected', 'selected');
363 $closest_max.attr('selected', 'selected');
365 $target_field.val(final_value);
367 $(this).dialog('close');
369 button_options[PMA_messages.strCancel] = function () {
370 $(this).dialog('close');
373 // Display dialog box.
376 '<legend>' + operator + '</legend>' +
377 '<label for="min_value">' + PMA_messages.strMinValue +
379 '<input type="text" id="min_value" />' + '<br>' +
380 '<span class="small_font">' + min + '</span>' + '<br>' +
381 '<label for="max_value">' + PMA_messages.strMaxValue +
383 '<input type="text" id="max_value" />' + '<br>' +
384 '<span class="small_font">' + max + '</span>' +
390 buttons: button_options,
391 title: PMA_messages.strRangeSearch,
393 // Add datepicker wherever required.
394 PMA_addDatepicker($('#min_value'), data_type);
395 PMA_addDatepicker($('#max_value'), data_type);
402 PMA_ajaxShowMessage(response.error);
405 error: function (response) {
406 PMA_ajaxShowMessage(PMA_messages.strErrorProcessingRequest);
411 var windowwidth = $(window).width();
412 $('.jsresponsive').css('max-width', (windowwidth - 69) + 'px');