Update website

This commit is contained in:
Guilhem Lavaux 2025-02-11 21:30:02 +01:00
parent 0a686aeb9a
commit c4ffa0f6ee
4360 changed files with 1727 additions and 718385 deletions

View file

@ -1,767 +0,0 @@
/**
* @fileoverview function used in table data manipulation pages
*
* @requires jQuery
* @requires jQueryUI
* @requires js/functions.js
*
*/
/* global extendingValidatorMessages */ // templates/javascript/variables.twig
/* global openGISEditor, gisEditorLoaded, loadJSAndGISEditor, loadGISEditor */ // js/gis_data_editor.js
/**
* Modify form controls when the "NULL" checkbox is checked
*
* @param {string} theType the MySQL field type
* @param {string} urlField the urlencoded field name - OBSOLETE
* @param {string} md5Field the md5 hashed field name
* @param {string} multiEdit the multi_edit row sequence number
*
* @return {boolean} always true
*/
function nullify(theType, urlField, md5Field, multiEdit) {
var rowForm = document.forms.insertForm;
if (typeof rowForm.elements['funcs' + multiEdit + '[' + md5Field + ']'] !== 'undefined') {
rowForm.elements['funcs' + multiEdit + '[' + md5Field + ']'].selectedIndex = -1;
}
// "ENUM" field with more than 20 characters
if (Number(theType) === 1) {
rowForm.elements['fields' + multiEdit + '[' + md5Field + ']'][1].selectedIndex = -1;
// Other "ENUM" field
} else if (Number(theType) === 2) {
var elts = rowForm.elements['fields' + multiEdit + '[' + md5Field + ']'];
// when there is just one option in ENUM:
if (elts.checked) {
elts.checked = false;
} else {
var eltsCnt = elts.length;
for (var i = 0; i < eltsCnt; i++) {
elts[i].checked = false;
} // end for
} // end if
// "SET" field
} else if (Number(theType) === 3) {
rowForm.elements['fields' + multiEdit + '[' + md5Field + '][]'].selectedIndex = -1;
// Foreign key field (drop-down)
} else if (Number(theType) === 4) {
rowForm.elements['fields' + multiEdit + '[' + md5Field + ']'].selectedIndex = -1;
// foreign key field (with browsing icon for foreign values)
} else if (Number(theType) === 6) {
rowForm.elements['fields' + multiEdit + '[' + md5Field + ']'].value = '';
// Other field types
} else /* if (theType === 5)*/{
rowForm.elements['fields' + multiEdit + '[' + md5Field + ']'].value = '';
} // end if... else if... else
return true;
} // end of the 'nullify()' function
/**
* javascript DateTime format validation.
* its used to prevent adding default (0000-00-00 00:00:00) to database when user enter wrong values
* Start of validation part
*/
// function checks the number of days in febuary
function daysInFebruary(year) {
return year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0) ? 29 : 28;
}
// function to convert single digit to double digit
function fractionReplace(number) {
var num = parseInt(number, 10);
return num >= 1 && num <= 9 ? '0' + num : '00';
}
/* function to check the validity of date
* The following patterns are accepted in this validation (accepted in mysql as well)
* 1) 2001-12-23
* 2) 2001-1-2
* 3) 02-12-23
* 4) And instead of using '-' the following punctuations can be used (+,.,*,^,@,/) All these are accepted by mysql as well. Therefore no issues
*/
function isDate(val, tmstmp) {
var value = val.replace(/[.|*|^|+|//|@]/g, '-');
var arrayVal = value.split('-');
for (var a = 0; a < arrayVal.length; a++) {
if (arrayVal[a].length === 1) {
arrayVal[a] = fractionReplace(arrayVal[a]);
}
}
value = arrayVal.join('-');
var pos = 2;
var dtexp = new RegExp(/^([0-9]{4})-(((01|03|05|07|08|10|12)-((0[0-9])|([1-2][0-9])|(3[0-1])))|((02|04|06|09|11)-((0[0-9])|([1-2][0-9])|30))|((00)-(00)))$/);
if (value.length === 8) {
pos = 0;
}
if (dtexp.test(value)) {
var month = parseInt(value.substring(pos + 3, pos + 5), 10);
var day = parseInt(value.substring(pos + 6, pos + 8), 10);
var year = parseInt(value.substring(0, pos + 2), 10);
if (month === 2 && day > daysInFebruary(year)) {
return false;
}
if (value.substring(0, pos + 2).length === 2) {
year = parseInt('20' + value.substring(0, pos + 2), 10);
}
if (tmstmp === true) {
if (year < 1978) {
return false;
}
if (year > 2038 || year > 2037 && day > 19 && month >= 1 || year > 2037 && month > 1) {
return false;
}
}
} else {
return false;
}
return true;
}
/* function to check the validity of time
* The following patterns are accepted in this validation (accepted in mysql as well)
* 1) 2:3:4
* 2) 2:23:43
* 3) 2:23:43.123456
*/
function isTime(val) {
var arrayVal = val.split(':');
for (var a = 0, l = arrayVal.length; a < l; a++) {
if (arrayVal[a].length === 1) {
arrayVal[a] = fractionReplace(arrayVal[a]);
}
}
var newVal = arrayVal.join(':');
var tmexp = new RegExp(/^(-)?(([0-7]?[0-9][0-9])|(8[0-2][0-9])|(83[0-8])):((0[0-9])|([1-5][0-9])):((0[0-9])|([1-5][0-9]))(\.[0-9]{1,6}){0,1}$/);
return tmexp.test(newVal);
}
/**
* To check whether insert section is ignored or not
* @param {string} multiEdit
* @return {boolean}
*/
function checkForCheckbox(multiEdit) {
if ($('#insert_ignore_' + multiEdit).length) {
return $('#insert_ignore_' + multiEdit).is(':unchecked');
}
return true;
}
// used in Search page mostly for INT fields
// eslint-disable-next-line no-unused-vars
function verifyAfterSearchFieldChange(index, searchFormId) {
var $thisInput = $('input[name=\'criteriaValues[' + index + ']\']');
// Add data-skip-validators attribute to skip validation in changeValueFieldType function
if ($('#fieldID_' + index).data('data-skip-validators')) {
$(searchFormId).validate().destroy();
return;
}
// validation for integer type
if ($thisInput.data('type') === 'INT' || $thisInput.data('type') === 'TINYINT') {
// Trim spaces if it's an integer
$thisInput.val($thisInput.val().trim());
var hasMultiple = $thisInput.prop('multiple');
if (hasMultiple) {
$(searchFormId).validate({
// update errors as we write
onkeyup: function (element) {
$(element).valid();
}
});
// validator method for IN(...), NOT IN(...)
// BETWEEN and NOT BETWEEN
jQuery.validator.addMethod('validationFunctionForMultipleInt', function (value) {
return value.match(/^(?:(?:\d\s*)|\s*)+(?:,\s*\d+)*$/i) !== null;
}, Messages.strEnterValidNumber);
validateMultipleIntField($thisInput, true);
} else {
$(searchFormId).validate({
// update errors as we write
onkeyup: function (element) {
$(element).valid();
}
});
validateIntField($thisInput, true);
}
// Update error on dropdown change
$thisInput.valid();
}
}
/**
* Validate the an input contains multiple int values
* @param {jQuery} jqueryInput the Jquery object
* @param {boolean} returnValueIfFine the value to return if the validator passes
* @return {void}
*/
function validateMultipleIntField(jqueryInput, returnValueIfFine) {
// removing previous rules
jqueryInput.rules('remove');
jqueryInput.rules('add', {
validationFunctionForMultipleInt: {
param: jqueryInput.value,
depends: function () {
return returnValueIfFine;
}
}
});
}
/**
* Validate the an input contains an int value
* @param {jQuery} jqueryInput the Jquery object
* @param {boolean} returnValueIfIsNumber the value to return if the validator passes
* @return {void}
*/
function validateIntField(jqueryInput, returnValueIfIsNumber) {
var mini = parseInt(jqueryInput.data('min'));
var maxi = parseInt(jqueryInput.data('max'));
// removing previous rules
jqueryInput.rules('remove');
jqueryInput.rules('add', {
number: {
param: true,
depends: function () {
return returnValueIfIsNumber;
}
},
min: {
param: mini,
depends: function () {
if (isNaN(jqueryInput.val())) {
return false;
} else {
return returnValueIfIsNumber;
}
}
},
max: {
param: maxi,
depends: function () {
if (isNaN(jqueryInput.val())) {
return false;
} else {
return returnValueIfIsNumber;
}
}
}
});
}
function verificationsAfterFieldChange(urlField, multiEdit, theType) {
var evt = window.event || arguments.callee.caller.arguments[0];
var target = evt.target || evt.srcElement;
var $thisInput = $(':input[name^=\'fields[multi_edit][' + multiEdit + '][' + urlField + ']\']');
// the function drop-down that corresponds to this input field
var $thisFunction = $('select[name=\'funcs[multi_edit][' + multiEdit + '][' + urlField + ']\']');
var functionSelected = false;
if (typeof $thisFunction.val() !== 'undefined' && $thisFunction.val() !== null && $thisFunction.val().length > 0) {
functionSelected = true;
}
// To generate the textbox that can take the salt
var newSaltBox = '<br><input type=text name=salt[multi_edit][' + multiEdit + '][' + urlField + ']' + ' id=salt_' + target.id + ' placeholder=\'' + Messages.strEncryptionKey + '\'>';
// If encrypting or decrypting functions that take salt as input is selected append the new textbox for salt
if (target.value === 'AES_ENCRYPT' || target.value === 'AES_DECRYPT' || target.value === 'DES_ENCRYPT' || target.value === 'DES_DECRYPT' || target.value === 'ENCRYPT') {
if (!$('#salt_' + target.id).length) {
$thisInput.after(newSaltBox);
}
} else {
// Remove the textbox for salt
$('#salt_' + target.id).prev('br').remove();
$('#salt_' + target.id).remove();
}
// Remove possible blocking rules if the user changed functions
$('#' + target.id).rules('remove', 'validationFunctionForMd5');
$('#' + target.id).rules('remove', 'validationFunctionForAesDesEncrypt');
if (target.value === 'MD5') {
$('#' + target.id).rules('add', {
validationFunctionForMd5: {
param: $thisInput,
depends: function () {
return checkForCheckbox(multiEdit);
}
}
});
}
if (target.value === 'DES_ENCRYPT' || target.value === 'AES_ENCRYPT') {
$('#' + target.id).rules('add', {
validationFunctionForAesDesEncrypt: {
param: $thisInput,
depends: function () {
return checkForCheckbox(multiEdit);
}
}
});
}
if (target.value === 'HEX' && theType.substring(0, 3) === 'int') {
// Add note when HEX function is selected on a int
var newHexInfo = '<br><p id="note' + target.id + '">' + Messages.HexConversionInfo + '</p>';
if (!$('#note' + target.id).length) {
$thisInput.after(newHexInfo);
}
} else {
$('#note' + target.id).prev('br').remove();
$('#note' + target.id).remove();
}
// Unchecks the corresponding "NULL" control
$('input[name=\'fields_null[multi_edit][' + multiEdit + '][' + urlField + ']\']').prop('checked', false);
// Unchecks the Ignore checkbox for the current row
$('input[name=\'insert_ignore_' + multiEdit + '\']').prop('checked', false);
var charExceptionHandling;
if (theType.substring(0, 4) === 'char') {
charExceptionHandling = theType.substring(5, 6);
} else if (theType.substring(0, 7) === 'varchar') {
charExceptionHandling = theType.substring(8, 9);
}
if (functionSelected) {
$thisInput.removeAttr('min');
$thisInput.removeAttr('max');
// @todo: put back attributes if corresponding function is deselected
}
if ($thisInput.data('rulesadded') === null && !functionSelected) {
// call validate before adding rules
$($thisInput[0].form).validate();
// validate for date time
if (theType === 'datetime' || theType === 'time' || theType === 'date' || theType === 'timestamp') {
$thisInput.rules('add', {
validationFunctionForDateTime: {
param: theType,
depends: function () {
return checkForCheckbox(multiEdit);
}
}
});
}
// validation for integer type
if ($thisInput.data('type') === 'INT') {
validateIntField($thisInput, checkForCheckbox(multiEdit));
// validation for CHAR types
} else if ($thisInput.data('type') === 'CHAR') {
var maxlen = $thisInput.data('maxlength');
if (typeof maxlen !== 'undefined') {
if (maxlen <= 4) {
maxlen = charExceptionHandling;
}
$thisInput.rules('add', {
maxlength: {
param: maxlen,
depends: function () {
return checkForCheckbox(multiEdit);
}
}
});
}
// validate binary & blob types
} else if ($thisInput.data('type') === 'HEX') {
$thisInput.rules('add', {
validationFunctionForHex: {
param: true,
depends: function () {
return checkForCheckbox(multiEdit);
}
}
});
}
$thisInput.data('rulesadded', true);
} else if ($thisInput.data('rulesadded') === true && functionSelected) {
// remove any rules added
$thisInput.rules('remove');
// remove any error messages
$thisInput.removeClass('error').removeAttr('aria-invalid').siblings('.error').remove();
$thisInput.data('rulesadded', null);
}
}
/* End of fields validation*/
/**
* Unbind all event handlers before tearing down a page
*/
AJAX.registerTeardown('table/change.js', function () {
$(document).off('click', 'span.open_gis_editor');
$(document).off('click', 'input[name^=\'insert_ignore_\']');
$(document).off('click', 'input[name=\'gis_data[save]\']');
$(document).off('click', 'input.checkbox_null');
$('select[name="submit_type"]').off('change');
$(document).off('change', '#insert_rows');
});
/**
* Ajax handlers for Change Table page
*
* Actions Ajaxified here:
* Submit Data to be inserted into the table.
* Restart insertion with 'N' rows.
*/
AJAX.registerOnload('table/change.js', function () {
if ($('#insertForm').length) {
// validate the comment form when it is submitted
$('#insertForm').validate();
jQuery.validator.addMethod('validationFunctionForHex', function (value) {
return value.match(/^[a-f0-9]*$/i) !== null;
});
jQuery.validator.addMethod('validationFunctionForMd5', function (value, element, options) {
return !(value.substring(0, 3) === 'MD5' && typeof options.data('maxlength') !== 'undefined' && options.data('maxlength') < 32);
});
jQuery.validator.addMethod('validationFunctionForAesDesEncrypt', function (value, element, options) {
var funType = value.substring(0, 3);
if (funType !== 'AES' && funType !== 'DES') {
return false;
}
var dataType = options.data('type');
if (dataType === 'HEX' || dataType === 'CHAR') {
return true;
}
return false;
});
jQuery.validator.addMethod('validationFunctionForDateTime', function (value, element, options) {
var dtValue = value;
var theType = options;
if (theType === 'date') {
return isDate(dtValue);
} else if (theType === 'time') {
return isTime(dtValue);
} else if (theType === 'datetime' || theType === 'timestamp') {
var tmstmp = false;
dtValue = dtValue.trim();
if (dtValue === 'CURRENT_TIMESTAMP' || dtValue === 'current_timestamp()') {
return true;
}
if (theType === 'timestamp') {
tmstmp = true;
}
if (dtValue === '0000-00-00 00:00:00') {
return true;
}
var dv = dtValue.indexOf(' ');
if (dv === -1) {
// Only the date component, which is valid
return isDate(dtValue, tmstmp);
}
return isDate(dtValue.substring(0, dv), tmstmp) && isTime(dtValue.substring(dv + 1));
}
});
}
/*
* message extending script must be run
* after initiation of functions
*/
extendingValidatorMessages();
$.datepicker.initialized = false;
$(document).on('click', 'span.open_gis_editor', function (event) {
event.preventDefault();
var $span = $(this);
// Current value
var value = $span.parent('td').children('input[type=\'text\']').val();
// Field name
var field = $span.parents('tr').children('td').first().find('input[type=\'hidden\']').val();
// Column type
var type = $span.parents('tr').find('span.column_type').text();
// Names of input field and null checkbox
var inputName = $span.parent('td').children('input[type=\'text\']').attr('name');
openGISEditor();
if (!gisEditorLoaded) {
loadJSAndGISEditor(value, field, type, inputName);
} else {
loadGISEditor(value, field, type, inputName);
}
});
/**
* Forced validation check of fields
*/
$(document).on('click', 'input[name^=\'insert_ignore_\']', function () {
$('#insertForm').valid();
});
/**
* Uncheck the null checkbox as geometry data is placed on the input field
*/
$(document).on('click', 'input[name=\'gis_data[save]\']', function () {
var inputName = $('form#gis_data_editor_form').find('input[name=\'input_name\']').val();
var currentRow = $('input[name=\'' + inputName + '\']').parents('tr');
var $nullCheckbox = currentRow.find('.checkbox_null');
$nullCheckbox.prop('checked', false);
var rowId = currentRow.find('.open_gis_editor').data('row-id');
// Unchecks the Ignore checkbox for the current row
$('input[name=\'insert_ignore_' + rowId + '\']').prop('checked', false);
});
/**
* Handles all current checkboxes for Null; this only takes care of the
* checkboxes on currently displayed rows as the rows generated by
* "Continue insertion" are handled in the "Continue insertion" code
*
*/
$(document).on('click', 'input.checkbox_null', function () {
nullify(
// use hidden fields populated by /table/change
$(this).siblings('.nullify_code').val(), $(this).closest('tr').find('input:hidden').first().val(), $(this).siblings('.hashed_field').val(), $(this).siblings('.multi_edit').val());
});
/**
* Reset the auto_increment column to 0 when selecting any of the
* insert options in submit_type-dropdown. Only perform the reset
* when we are in edit-mode, and not in insert-mode(no previous value
* available).
*/
$('select[name="submit_type"]').on('change', function () {
var thisElemSubmitTypeVal = $(this).val();
var $table = $('table.insertRowTable');
var autoIncrementColumn = $table.find('input[name^="auto_increment"]');
autoIncrementColumn.each(function () {
var $thisElemAIField = $(this);
var thisElemName = $thisElemAIField.attr('name');
var prevValueField = $table.find('input[name="' + thisElemName.replace('auto_increment', 'fields_prev') + '"]');
var valueField = $table.find('input[name="' + thisElemName.replace('auto_increment', 'fields') + '"]');
var previousValue = $(prevValueField).val();
if (previousValue !== undefined) {
if (thisElemSubmitTypeVal === 'insert' || thisElemSubmitTypeVal === 'insertignore' || thisElemSubmitTypeVal === 'showinsert') {
$(valueField).val(null);
} else {
$(valueField).val(previousValue);
}
}
});
});
/**
* Handle ENTER key when press on Continue insert with field
*/
$('#insert_rows').on('keypress', function (e) {
var key = e.which;
if (key === 13) {
addNewContinueInsertionFields(e);
}
});
/**
* Continue Insertion form
*/
$(document).on('change', '#insert_rows', addNewContinueInsertionFields);
});
function addNewContinueInsertionFields(event) {
event.preventDefault();
/**
* @var columnCount Number of number of columns table has.
*/
var columnCount = $('table.insertRowTable').first().find('tr').has('input[name*=\'fields_name\']').length;
/**
* @var curr_rows Number of current insert rows already on page
*/
var currRows = $('table.insertRowTable').length;
/**
* @var target_rows Number of rows the user wants
*/
var targetRows = $('#insert_rows').val();
// remove all datepickers
$('input.datefield, input.datetimefield').each(function () {
$(this).datepicker('destroy');
});
if (currRows < targetRows) {
var tempIncrementIndex = function () {
var $thisElement = $(this);
/**
* Extract the index from the name attribute for all input/select fields and increment it
* name is of format funcs[multi_edit][10][<long random string of alphanum chars>]
*/
/**
* @var this_name String containing name of the input/select elements
*/
var thisName = $thisElement.attr('name');
/** split {@link thisName} at [10], so we have the parts that can be concatenated later */
var nameParts = thisName.split(/\[\d+\]/);
/** extract the [10] from {@link nameParts} */
var oldRowIndexString = thisName.match(/\[\d+\]/)[0];
/** extract 10 - had to split into two steps to accomodate double digits */
var oldRowIndex = parseInt(oldRowIndexString.match(/\d+/)[0], 10);
/** calculate next index i.e. 11 */
newRowIndex = oldRowIndex + 1;
/** generate the new name i.e. funcs[multi_edit][11][foobarbaz] */
var newName = nameParts[0] + '[' + newRowIndex + ']' + nameParts[1];
var hashedField = nameParts[1].match(/\[(.+)\]/)[1];
$thisElement.attr('name', newName);
/** If element is select[name*='funcs'], update id */
if ($thisElement.is('select[name*=\'funcs\']')) {
var thisId = $thisElement.attr('id');
var idParts = thisId.split(/_/);
var oldIdIndex = idParts[1];
var prevSelectedValue = $('#field_' + oldIdIndex + '_1').val();
var newIdIndex = parseInt(oldIdIndex) + columnCount;
var newId = 'field_' + newIdIndex + '_1';
$thisElement.attr('id', newId);
$thisElement.find('option').filter(function () {
return $(this).text() === prevSelectedValue;
}).attr('selected', 'selected');
// If salt field is there then update its id.
var nextSaltInput = $thisElement.parent().next('td').next('td').find('input[name*=\'salt\']');
if (nextSaltInput.length !== 0) {
nextSaltInput.attr('id', 'salt_' + newId);
}
}
// handle input text fields and textareas
if ($thisElement.is('.textfield') || $thisElement.is('.char') || $thisElement.is('textarea')) {
// do not remove the 'value' attribute for ENUM columns
// special handling for radio fields after updating ids to unique - see below
if ($thisElement.closest('tr').find('span.column_type').html() !== 'enum') {
$thisElement.val($thisElement.closest('tr').find('span.default_value').html());
}
$thisElement.off('change')
// Remove onchange attribute that was placed
// by /table/change; it refers to the wrong row index
.attr('onchange', null)
// Keep these values to be used when the element
// will change
.data('hashed_field', hashedField).data('new_row_index', newRowIndex).on('change', function () {
var $changedElement = $(this);
verificationsAfterFieldChange($changedElement.data('hashed_field'), $changedElement.data('new_row_index'), $changedElement.closest('tr').find('span.column_type').html());
});
}
if ($thisElement.is('.checkbox_null')) {
$thisElement
// this event was bound earlier by jQuery but
// to the original row, not the cloned one, so unbind()
.off('click')
// Keep these values to be used when the element
// will be clicked
.data('hashed_field', hashedField).data('new_row_index', newRowIndex).on('click', function () {
var $changedElement = $(this);
nullify($changedElement.siblings('.nullify_code').val(), $thisElement.closest('tr').find('input:hidden').first().val(), $changedElement.data('hashed_field'), '[multi_edit][' + $changedElement.data('new_row_index') + ']');
});
}
};
var tempReplaceAnchor = function () {
var $anchor = $(this);
var newValue = 'rownumber=' + newRowIndex;
// needs improvement in case something else inside
// the href contains this pattern
var newHref = $anchor.attr('href').replace(/rownumber=\d+/, newValue);
$anchor.attr('href', newHref);
};
var restoreValue = function () {
if ($(this).closest('tr').find('span.column_type').html() === 'enum') {
if ($(this).val() === $checkedValue) {
$(this).prop('checked', true);
} else {
$(this).prop('checked', false);
}
}
};
while (currRows < targetRows) {
/**
* @var $last_row Object referring to the last row
*/
var $lastRow = $('#insertForm').find('.insertRowTable').last();
// need to access this at more than one level
// (also needs improvement because it should be calculated
// just once per cloned row, not once per column)
var newRowIndex = 0;
var $checkedValue = $lastRow.find('input:checked').val();
// Clone the insert tables
$lastRow.clone(true, true).insertBefore('#actions_panel').find('input[name*=multi_edit],select[name*=multi_edit],textarea[name*=multi_edit]').each(tempIncrementIndex).end().find('.foreign_values_anchor').each(tempReplaceAnchor);
var $oldRow = $lastRow.find('.textfield');
$oldRow.each(restoreValue);
// set the value of enum field of new row to default
var $newRow = $('#insertForm').find('.insertRowTable').last();
$newRow.find('.textfield').each(function () {
if ($(this).closest('tr').find('span.column_type').html() === 'enum') {
if ($(this).val() === $(this).closest('tr').find('span.default_value').html()) {
$(this).prop('checked', true);
} else {
$(this).prop('checked', false);
}
}
});
// Insert/Clone the ignore checkboxes
if (currRows === 1) {
$('<input id="insert_ignore_1" type="checkbox" name="insert_ignore_1" checked="checked">').insertBefore($('table.insertRowTable').last()).after('<label for="insert_ignore_1">' + Messages.strIgnore + '</label>');
} else {
/**
* @var $last_checkbox Object reference to the last checkbox in #insertForm
*/
var $lastCheckbox = $('#insertForm').children('input:checkbox').last();
/** name of {@link $lastCheckbox} */
var lastCheckboxName = $lastCheckbox.attr('name');
/** index of {@link $lastCheckbox} */
var lastCheckboxIndex = parseInt(lastCheckboxName.match(/\d+/), 10);
/** name of new {@link $lastCheckbox} */
var newName = lastCheckboxName.replace(/\d+/, lastCheckboxIndex + 1);
$('<br><div class="clearfloat"></div>').insertBefore($('table.insertRowTable').last());
$lastCheckbox.clone().attr({
'id': newName,
'name': newName
}).prop('checked', true).insertBefore($('table.insertRowTable').last());
$('label[for^=insert_ignore]').last().clone().attr('for', newName).insertBefore($('table.insertRowTable').last());
$('<br>').insertBefore($('table.insertRowTable').last());
}
currRows++;
}
// recompute tabindex for text fields and other controls at footer;
// IMO it's not really important to handle the tabindex for
// function and Null
var tabIndex = 0;
$('.textfield, .char, textarea').each(function () {
tabIndex++;
$(this).attr('tabindex', tabIndex);
// update the IDs of textfields to ensure that they are unique
$(this).attr('id', 'field_' + tabIndex + '_3');
});
$('.control_at_footer').each(function () {
tabIndex++;
$(this).attr('tabindex', tabIndex);
});
} else if (currRows > targetRows) {
/**
* Displays alert if data loss possible on decrease
* of rows.
*/
var checkLock = jQuery.isEmptyObject(AJAX.lockedTargets);
if (checkLock || confirm(Messages.strConfirmRowChange) === true) {
while (currRows > targetRows) {
$('input[id^=insert_ignore]').last().nextUntil('fieldset').addBack().remove();
currRows--;
}
} else {
document.getElementById('insert_rows').value = currRows;
}
}
// Add all the required datepickers back
Functions.addDateTimePicker();
}
// eslint-disable-next-line no-unused-vars
function changeValueFieldType(elem, searchIndex) {
var fieldsValue = $('input#fieldID_' + searchIndex);
if (0 === fieldsValue.size()) {
return;
}
var type = $(elem).val();
if ('LIKE' === type || 'LIKE %...%' === type || 'NOT LIKE' === type || 'NOT LIKE %...%' === type) {
$('#fieldID_' + searchIndex).data('data-skip-validators', true);
return;
} else {
$('#fieldID_' + searchIndex).data('data-skip-validators', false);
}
if ('IN (...)' === type || 'NOT IN (...)' === type || 'BETWEEN' === type || 'NOT BETWEEN' === type) {
$('#fieldID_' + searchIndex).prop('multiple', true);
} else {
$('#fieldID_' + searchIndex).prop('multiple', false);
}
}

View file

@ -1,403 +0,0 @@
/* global ColumnType, DataTable, JQPlotChartFactory */ // js/chart.js
/* global codeMirrorEditor */ // js/functions.js
var chartData = {};
var tempChartTitle;
var currentChart = null;
var currentSettings = null;
var dateTimeCols = [];
var numericCols = [];
function extractDate(dateString) {
var matches;
var match;
var dateTimeRegExp = /[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}/;
var dateRegExp = /[0-9]{4}-[0-9]{2}-[0-9]{2}/;
matches = dateTimeRegExp.exec(dateString);
if (matches !== null && matches.length > 0) {
match = matches[0];
return new Date(match.substr(0, 4), parseInt(match.substr(5, 2), 10) - 1, match.substr(8, 2), match.substr(11, 2), match.substr(14, 2), match.substr(17, 2));
} else {
matches = dateRegExp.exec(dateString);
if (matches !== null && matches.length > 0) {
match = matches[0];
return new Date(match.substr(0, 4), parseInt(match.substr(5, 2), 10) - 1, match.substr(8, 2));
}
}
return null;
}
function queryChart(data, columnNames, settings) {
if ($('#querychart').length === 0) {
return;
}
var plotSettings = {
title: {
text: settings.title,
escapeHtml: true
},
grid: {
drawBorder: false,
shadow: false,
background: 'rgba(0,0,0,0)'
},
legend: {
show: true,
placement: 'outsideGrid',
location: 'e',
rendererOptions: {
numberColumns: 2
}
},
axes: {
xaxis: {
label: Functions.escapeHtml(settings.xaxisLabel)
},
yaxis: {
label: settings.yaxisLabel
}
},
stackSeries: settings.stackSeries
};
// create the chart
var factory = new JQPlotChartFactory();
var chart = factory.createChart(settings.type, 'querychart');
// create the data table and add columns
var dataTable = new DataTable();
if (settings.type === 'timeline') {
dataTable.addColumn(ColumnType.DATE, columnNames[settings.mainAxis]);
} else if (settings.type === 'scatter') {
dataTable.addColumn(ColumnType.NUMBER, columnNames[settings.mainAxis]);
} else {
dataTable.addColumn(ColumnType.STRING, columnNames[settings.mainAxis]);
}
var i;
var values = [];
if (settings.seriesColumn === null) {
$.each(settings.selectedSeries, function (index, element) {
dataTable.addColumn(ColumnType.NUMBER, columnNames[element]);
});
// set data to the data table
var columnsToExtract = [settings.mainAxis];
$.each(settings.selectedSeries, function (index, element) {
columnsToExtract.push(element);
});
var newRow;
var row;
var col;
for (i = 0; i < data.length; i++) {
row = data[i];
newRow = [];
for (var j = 0; j < columnsToExtract.length; j++) {
col = columnNames[columnsToExtract[j]];
if (j === 0) {
if (settings.type === 'timeline') {
// first column is date type
newRow.push(extractDate(row[col]));
} else if (settings.type === 'scatter') {
newRow.push(parseFloat(row[col]));
} else {
// first column is string type
newRow.push(row[col]);
}
} else {
// subsequent columns are of type, number
newRow.push(parseFloat(row[col]));
}
}
values.push(newRow);
}
dataTable.setData(values);
} else {
var seriesNames = {};
var seriesNumber = 1;
var seriesColumnName = columnNames[settings.seriesColumn];
for (i = 0; i < data.length; i++) {
if (!seriesNames[data[i][seriesColumnName]]) {
seriesNames[data[i][seriesColumnName]] = seriesNumber;
seriesNumber++;
}
}
$.each(seriesNames, function (seriesName) {
dataTable.addColumn(ColumnType.NUMBER, seriesName);
});
var valueMap = {};
var xValue;
var value;
var mainAxisName = columnNames[settings.mainAxis];
var valueColumnName = columnNames[settings.valueColumn];
for (i = 0; i < data.length; i++) {
xValue = data[i][mainAxisName];
value = valueMap[xValue];
if (!value) {
value = [xValue];
valueMap[xValue] = value;
}
seriesNumber = seriesNames[data[i][seriesColumnName]];
value[seriesNumber] = parseFloat(data[i][valueColumnName]);
}
$.each(valueMap, function (index, value) {
values.push(value);
});
dataTable.setData(values);
}
// draw the chart and return the chart object
chart.draw(dataTable, plotSettings);
return chart;
}
function drawChart() {
currentSettings.width = $('#resizer').width() - 20;
currentSettings.height = $('#resizer').height() - 20;
// TODO: a better way using .redraw() ?
if (currentChart !== null) {
currentChart.destroy();
}
var columnNames = [];
$('#chartXAxisSelect option').each(function () {
columnNames.push(Functions.escapeHtml($(this).text()));
});
try {
currentChart = queryChart(chartData, columnNames, currentSettings);
if (currentChart !== null) {
$('#saveChart').attr('href', currentChart.toImageString());
}
} catch (err) {
Functions.ajaxShowMessage(err.message, false);
}
}
function getSelectedSeries() {
var val = $('#chartSeriesSelect').val() || [];
var ret = [];
$.each(val, function (i, v) {
ret.push(parseInt(v, 10));
});
return ret;
}
function onXAxisChange() {
var $xAxisSelect = $('#chartXAxisSelect');
currentSettings.mainAxis = parseInt($xAxisSelect.val(), 10);
if (dateTimeCols.indexOf(currentSettings.mainAxis) !== -1) {
document.getElementById('timelineChartType').classList.remove('d-none');
} else {
document.getElementById('timelineChartType').classList.add('d-none');
if (currentSettings.type === 'timeline') {
$('#lineChartTypeRadio').prop('checked', true);
currentSettings.type = 'line';
}
}
if (numericCols.indexOf(currentSettings.mainAxis) !== -1) {
document.getElementById('scatterChartType').classList.remove('d-none');
} else {
document.getElementById('scatterChartType').classList.add('d-none');
if (currentSettings.type === 'scatter') {
$('#lineChartTypeRadio').prop('checked', true);
currentSettings.type = 'line';
}
}
var xAxisTitle = $xAxisSelect.children('option:selected').text();
$('#xAxisLabelInput').val(xAxisTitle);
currentSettings.xaxisLabel = xAxisTitle;
}
function onDataSeriesChange() {
var $seriesSelect = $('#chartSeriesSelect');
currentSettings.selectedSeries = getSelectedSeries();
var yAxisTitle;
if (currentSettings.selectedSeries.length === 1) {
document.getElementById('pieChartType').classList.remove('d-none');
yAxisTitle = $seriesSelect.children('option:selected').text();
} else {
document.getElementById('pieChartType').classList.add('d-none');
if (currentSettings.type === 'pie') {
$('#lineChartTypeRadio').prop('checked', true);
currentSettings.type = 'line';
}
yAxisTitle = Messages.strYValues;
}
$('#yAxisLabelInput').val(yAxisTitle);
currentSettings.yaxisLabel = yAxisTitle;
}
/**
* Unbind all event handlers before tearing down a page
*/
AJAX.registerTeardown('table/chart.js', function () {
$('input[name="chartType"]').off('click');
$('#barStackedCheckbox').off('click');
$('#seriesColumnCheckbox').off('click');
$('#chartTitleInput').off('focus').off('keyup').off('blur');
$('#chartXAxisSelect').off('change');
$('#chartSeriesSelect').off('change');
$('#chartSeriesColumnSelect').off('change');
$('#chartValueColumnSelect').off('change');
$('#xAxisLabelInput').off('keyup');
$('#yAxisLabelInput').off('keyup');
$('#resizer').off('resizestop');
$('#tblchartform').off('submit');
});
AJAX.registerOnload('table/chart.js', function () {
// handle manual resize
$('#resizer').on('resizestop', function () {
// make room so that the handle will still appear
$('#querychart').height($('#resizer').height() * 0.96);
$('#querychart').width($('#resizer').width() * 0.96);
if (currentChart !== null) {
currentChart.redraw({
resetAxes: true
});
}
});
// handle chart type changes
$('input[name="chartType"]').on('click', function () {
var type = currentSettings.type = $(this).val();
if (type === 'bar' || type === 'column' || type === 'area') {
document.getElementById('barStacked').classList.remove('d-none');
} else {
$('#barStackedCheckbox').prop('checked', false);
$.extend(true, currentSettings, {
stackSeries: false
});
document.getElementById('barStacked').classList.add('d-none');
}
drawChart();
});
// handle chosing alternative data format
$('#seriesColumnCheckbox').on('click', function () {
var $seriesColumn = $('#chartSeriesColumnSelect');
var $valueColumn = $('#chartValueColumnSelect');
var $chartSeries = $('#chartSeriesSelect');
if ($(this).is(':checked')) {
$seriesColumn.prop('disabled', false);
$valueColumn.prop('disabled', false);
$chartSeries.prop('disabled', true);
currentSettings.seriesColumn = parseInt($seriesColumn.val(), 10);
currentSettings.valueColumn = parseInt($valueColumn.val(), 10);
} else {
$seriesColumn.prop('disabled', true);
$valueColumn.prop('disabled', true);
$chartSeries.prop('disabled', false);
currentSettings.seriesColumn = null;
currentSettings.valueColumn = null;
}
drawChart();
});
// handle stacking for bar, column and area charts
$('#barStackedCheckbox').on('click', function () {
if ($(this).is(':checked')) {
$.extend(true, currentSettings, {
stackSeries: true
});
} else {
$.extend(true, currentSettings, {
stackSeries: false
});
}
drawChart();
});
// handle changes in chart title
$('#chartTitleInput').on('focus', function () {
tempChartTitle = $(this).val();
}).on('keyup', function () {
currentSettings.title = $('#chartTitleInput').val();
drawChart();
}).on('blur', function () {
if ($(this).val() !== tempChartTitle) {
drawChart();
}
});
// handle changing the x-axis
$('#chartXAxisSelect').on('change', function () {
onXAxisChange();
drawChart();
});
// handle changing the selected data series
$('#chartSeriesSelect').on('change', function () {
onDataSeriesChange();
drawChart();
});
// handle changing the series column
$('#chartSeriesColumnSelect').on('change', function () {
currentSettings.seriesColumn = parseInt($(this).val(), 10);
drawChart();
});
// handle changing the value column
$('#chartValueColumnSelect').on('change', function () {
currentSettings.valueColumn = parseInt($(this).val(), 10);
drawChart();
});
// handle manual changes to the chart x-axis labels
$('#xAxisLabelInput').on('keyup', function () {
currentSettings.xaxisLabel = $(this).val();
drawChart();
});
// handle manual changes to the chart y-axis labels
$('#yAxisLabelInput').on('keyup', function () {
currentSettings.yaxisLabel = $(this).val();
drawChart();
});
// handler for ajax form submission
$('#tblchartform').on('submit', function () {
var $form = $(this);
if (codeMirrorEditor) {
$form[0].elements.sql_query.value = codeMirrorEditor.getValue();
}
if (!Functions.checkSqlQuery($form[0])) {
return false;
}
var $msgbox = Functions.ajaxShowMessage();
Functions.prepareForAjaxRequest($form);
$.post($form.attr('action'), $form.serialize(), function (data) {
if (typeof data !== 'undefined' && data.success === true && typeof data.chartData !== 'undefined') {
chartData = JSON.parse(data.chartData);
drawChart();
Functions.ajaxRemoveMessage($msgbox);
} else {
Functions.ajaxShowMessage(data.error, false);
}
}, 'json'); // end $.post()
return false;
});
// from jQuery UI
$('#resizer').resizable({
minHeight: 240,
minWidth: 300
}).width($('#div_view_options').width() - 50).trigger('resizestop');
currentSettings = {
type: 'line',
width: $('#resizer').width() - 20,
height: $('#resizer').height() - 20,
xaxisLabel: $('#xAxisLabelInput').val(),
yaxisLabel: $('#yAxisLabelInput').val(),
title: $('#chartTitleInput').val(),
stackSeries: false,
mainAxis: parseInt($('#chartXAxisSelect').val(), 10),
selectedSeries: getSelectedSeries(),
seriesColumn: null
};
var vals = $('input[name="dateTimeCols"]').val().split(' ');
$.each(vals, function (i, v) {
dateTimeCols.push(parseInt(v, 10));
});
vals = $('input[name="numericCols"]').val().split(' ');
$.each(vals, function (i, v) {
numericCols.push(parseInt(v, 10));
});
onXAxisChange();
onDataSeriesChange();
$('#tblchartform').trigger('submit');
});

View file

@ -1,40 +0,0 @@
/**
* Unbind all event handlers before tearing down a page
*/
AJAX.registerTeardown('table/find_replace.js', function () {
$('#find_replace_form').off('submit');
$('#toggle_find').off('click');
});
/**
* Bind events
*/
AJAX.registerOnload('table/find_replace.js', function () {
$('<div id="toggle_find_div"><a id="toggle_find"></a></div>').insertAfter('#find_replace_form').hide();
$('#toggle_find').html(Messages.strHideFindNReplaceCriteria).on('click', function () {
var $link = $(this);
$('#find_replace_form').slideToggle();
if ($link.text() === Messages.strHideFindNReplaceCriteria) {
$link.text(Messages.strShowFindNReplaceCriteria);
} else {
$link.text(Messages.strHideFindNReplaceCriteria);
}
return false;
});
$('#find_replace_form').on('submit', function (e) {
e.preventDefault();
var findReplaceForm = $('#find_replace_form');
Functions.prepareForAjaxRequest(findReplaceForm);
var $msgbox = Functions.ajaxShowMessage();
$.post(findReplaceForm.attr('action'), findReplaceForm.serialize(), function (data) {
Functions.ajaxRemoveMessage($msgbox);
if (data.success === true) {
$('#toggle_find_div').show();
$('#toggle_find').trigger('click');
$('#sqlqueryresultsouter').html(data.preview);
} else {
$('#sqlqueryresultsouter').html(data.error);
}
});
});
});

View file

@ -1,330 +0,0 @@
/**
* @fileoverview functions used for visualizing GIS data
*
* @requires jquery
*/
/* global drawOpenLayers PASSIVE_EVENT_LISTENERS */ // templates/table/gis_visualization/gis_visualization.twig
// Constants
var zoomFactor = 1.5;
var defaultX = 0;
var defaultY = 0;
var defaultScale = 1;
// Variables
var x = defaultX;
var y = defaultY;
var scale = defaultScale;
/** @type {SVGElement|undefined} */
var gisSvg;
/** @type {ol.Map|undefined} */
var map;
/**
* Zooms and pans the visualization.
*/
function zoomAndPan() {
var g = gisSvg.getElementById('groupPanel');
if (!g) {
return;
}
$('#groupPanel', gisSvg).attr('transform', 'translate(' + x + ', ' + y + ') scale(' + scale + ')');
$('circle.vector', gisSvg).attr('r', 3 / scale);
$('circle.vector', gisSvg).attr('stroke-width', 2 / scale);
$('polyline.vector', gisSvg).attr('stroke-width', 2 / scale);
$('path.vector', gisSvg).attr('stroke-width', 0.5 / scale);
}
/**
* Initially loads either SVG or OSM visualization based on the choice.
*/
function selectVisualization() {
if ($('#choice').prop('checked') !== true) {
$('#openlayersmap').hide();
} else {
$('#placeholder').hide();
}
}
/**
* Adds necessary styles to the div that contains the openStreetMap.
*/
function styleOSM() {
var $placeholder = $('#placeholder');
var cssObj = {
'border': '1px solid #aaa',
'width': $placeholder.width(),
'height': $placeholder.height(),
'float': 'right'
};
$('#openlayersmap').css(cssObj);
}
/**
* Store a reference to the gis svg element.
*/
function storeGisSvgRef() {
gisSvg = $('#placeholder').find('svg').get(0);
}
/**
* Adds controls for zooming and panning.
*/
function addZoomPanControllers() {
if (!gisSvg) {
return;
}
var themeImagePath = $('#themeImagePath').val();
$('#placeholder').append(
// pan arrows
'<img class="button" id="left_arrow" src="' + themeImagePath + 'west-mini.png">', '<img class="button" id="right_arrow" src="' + themeImagePath + 'east-mini.png">', '<img class="button" id="up_arrow" src="' + themeImagePath + 'north-mini.png">', '<img class="button" id="down_arrow" src="' + themeImagePath + 'south-mini.png">',
// zoom controls
'<img class="button" id="zoom_in" src="' + themeImagePath + 'zoom-plus-mini.png">', '<img class="button" id="zoom_world" src="' + themeImagePath + 'zoom-world-mini.png">', '<img class="button" id="zoom_out" src="' + themeImagePath + 'zoom-minus-mini.png">');
}
/**
* Resizes the GIS visualization to fit into the space available.
*/
function resizeGISVisualization() {
var $placeholder = $('#placeholder');
var oldWidth = $placeholder.width();
var visWidth = $('#div_view_options').width() - 48;
// Assign new value for width
$placeholder.width(visWidth);
$(gisSvg).attr('width', visWidth);
// Assign the offset created due to resizing to defaultX and center the svg.
defaultX = (visWidth - oldWidth) / 2;
x = defaultX;
y = defaultY;
scale = defaultScale;
}
/**
* Initialize the GIS visualization.
*/
function initGISVisualization() {
storeGisSvgRef();
// Loads either SVG or OSM visualization based on the choice
selectVisualization();
// Resizes the GIS visualization to fit into the space available
resizeGISVisualization();
if (typeof ol !== 'undefined') {
// Adds necessary styles to the div that contains the openStreetMap
styleOSM();
}
// Adds controllers for zooming and panning
addZoomPanControllers();
zoomAndPan();
}
function drawOpenLayerMap() {
$('#placeholder').hide();
$('#openlayersmap').show();
// Function doesn't work properly if #openlayersmap is hidden
if (typeof map !== 'object') {
// Draws openStreetMap with openLayers
map = drawOpenLayers();
}
}
function getRelativeCoords(e) {
var position = $('#placeholder').offset();
return {
x: e.pageX - position.left,
y: e.pageY - position.top
};
}
/**
* @param {WheelEvent} event
*/
function onGisMouseWheel(event) {
if (event.deltaY === 0) {
return;
}
event.preventDefault();
var relCoords = getRelativeCoords(event);
var factor = event.deltaY > 0 ? zoomFactor : 1 / zoomFactor;
// zoom
scale *= factor;
// zooming keeping the position under mouse pointer unmoved.
x = relCoords.x - (relCoords.x - x) * factor;
y = relCoords.y - (relCoords.y - y) * factor;
zoomAndPan();
}
/**
* Ajax handlers for GIS visualization page
*
* Actions Ajaxified here:
*
* Zooming in and zooming out on mouse wheel movement.
* Panning the visualization on dragging.
* Zooming in on double clicking.
* Zooming out on clicking the zoom out button.
* Panning on clicking the arrow buttons.
* Displaying tooltips for GIS objects.
*/
/**
* Unbind all event handlers before tearing down a page
*/
AJAX.registerTeardown('table/gis_visualization.js', function () {
$(document).off('click', '#choice');
$(document).off('dragstart', 'svg');
$(document).off('mouseup', 'svg');
$(document).off('drag', 'svg');
$(document).off('dblclick', '#placeholder');
$(document).off('click', '#zoom_in');
$(document).off('click', '#zoom_world');
$(document).off('click', '#zoom_out');
$(document).off('click', '#left_arrow');
$(document).off('click', '#right_arrow');
$(document).off('click', '#up_arrow');
$(document).off('click', '#down_arrow');
$('.vector').off('mousemove').off('mouseout');
$('#placeholder').get(0).removeEventListener('wheel', onGisMouseWheel, PASSIVE_EVENT_LISTENERS ? {
passive: false
} : undefined);
if (map) {
// Removes ol.Map's resize listener from window
map.setTarget(null);
map = undefined;
}
});
AJAX.registerOnload('table/gis_visualization.js', function () {
// If we are in GIS visualization, initialize it
if ($('#gis_div').length > 0) {
initGISVisualization();
}
if ($('#choice').prop('checked') === true) {
drawOpenLayerMap();
}
if (typeof ol === 'undefined') {
$('#choice, #labelChoice').hide();
}
$(document).on('click', '#choice', function () {
if ($(this).prop('checked') === false) {
$('#placeholder').show();
$('#openlayersmap').hide();
} else {
drawOpenLayerMap();
}
});
$('#placeholder').get(0).addEventListener('wheel', onGisMouseWheel, PASSIVE_EVENT_LISTENERS ? {
passive: false
} : undefined);
var dragX = 0;
var dragY = 0;
$('svg').draggable({
helper: function () {
return $('<div>'); // Give a fake element to be used for dragging display
}
});
$(document).on('dragstart', 'svg', function (event, dd) {
$('#placeholder').addClass('placeholderDrag');
dragX = Math.round(dd.offset.left);
dragY = Math.round(dd.offset.top);
});
$(document).on('mouseup', 'svg', function () {
$('#placeholder').removeClass('placeholderDrag');
});
$(document).on('drag', 'svg', function (event, dd) {
var newX = Math.round(dd.offset.left);
x += newX - dragX;
dragX = newX;
var newY = Math.round(dd.offset.top);
y += newY - dragY;
dragY = newY;
zoomAndPan();
});
$(document).on('dblclick', '#placeholder', function (event) {
if (event.target.classList.contains('button')) {
return;
}
scale *= zoomFactor;
// zooming in keeping the position under mouse pointer unmoved.
var relCoords = getRelativeCoords(event);
x = relCoords.x - (relCoords.x - x) * zoomFactor;
y = relCoords.y - (relCoords.y - y) * zoomFactor;
zoomAndPan();
});
$(document).on('click', '#zoom_in', function (e) {
e.preventDefault();
// zoom in
scale *= zoomFactor;
var width = $(gisSvg).attr('width');
var height = $(gisSvg).attr('height');
// zooming in keeping the center unmoved.
x = width / 2 - (width / 2 - x) * zoomFactor;
y = height / 2 - (height / 2 - y) * zoomFactor;
zoomAndPan();
});
$(document).on('click', '#zoom_world', function (e) {
e.preventDefault();
scale = 1;
x = defaultX;
y = defaultY;
zoomAndPan();
});
$(document).on('click', '#zoom_out', function (e) {
e.preventDefault();
// zoom out
scale /= zoomFactor;
var width = $(gisSvg).attr('width');
var height = $(gisSvg).attr('height');
// zooming out keeping the center unmoved.
x = width / 2 - (width / 2 - x) / zoomFactor;
y = height / 2 - (height / 2 - y) / zoomFactor;
zoomAndPan();
});
$(document).on('click', '#left_arrow', function (e) {
e.preventDefault();
x += 100;
zoomAndPan();
});
$(document).on('click', '#right_arrow', function (e) {
e.preventDefault();
x -= 100;
zoomAndPan();
});
$(document).on('click', '#up_arrow', function (e) {
e.preventDefault();
y += 100;
zoomAndPan();
});
$(document).on('click', '#down_arrow', function (e) {
e.preventDefault();
y -= 100;
zoomAndPan();
});
/**
* Detect the mousemove event and show tooltips.
*/
$('.vector').on('mousemove', function (event) {
var contents = Functions.escapeHtml($(this).attr('name')).trim();
$('#tooltip').remove();
if (contents !== '') {
$('<div id="tooltip">' + contents + '</div>').css({
position: 'absolute',
top: event.pageY + 10,
left: event.pageX + 10,
border: '1px solid #fdd',
padding: '2px',
'background-color': '#fee',
opacity: 0.90
}).appendTo('body').fadeIn(200);
}
});
/**
* Detect the mouseout event and hide tooltips.
*/
$('.vector').on('mouseout', function () {
$('#tooltip').remove();
});
});

View file

@ -1,308 +0,0 @@
/**
* Unbind all event handlers before tearing down a page
*/
AJAX.registerTeardown('table/operations.js', function () {
$(document).off('submit', '#copyTable.ajax');
$(document).off('submit', '#moveTableForm');
$(document).off('submit', '#tableOptionsForm');
$(document).off('submit', '#partitionsForm');
$(document).off('click', '#tbl_maintenance li a.maintain_action.ajax');
$(document).off('click', '#drop_tbl_anchor.ajax');
$(document).off('click', '#drop_view_anchor.ajax');
$(document).off('click', '#truncate_tbl_anchor.ajax');
$(document).off('click', '#delete_tbl_anchor.ajax');
});
/**
* Confirm and send POST request
*
* @param {JQuery} linkObject
* @param {'TRUNCATE'|'DELETE'} action
*
* @return {void}
*/
var confirmAndPost = function (linkObject, action) {
/**
* @var {String} question String containing the question to be asked for confirmation
*/
var question = '';
if (action === 'TRUNCATE') {
question += Messages.strTruncateTableStrongWarning + ' ';
} else if (action === 'DELETE') {
question += Messages.strDeleteTableStrongWarning + ' ';
}
question += Functions.sprintf(Messages.strDoYouReally, linkObject.data('query'));
question += Functions.getForeignKeyCheckboxLoader();
linkObject.confirm(question, linkObject.attr('href'), function (url) {
Functions.ajaxShowMessage(Messages.strProcessingRequest);
var params = Functions.getJsConfirmCommonParam(this, linkObject.getPostData());
$.post(url, params, function (data) {
if ($('.sqlqueryresults').length !== 0) {
$('.sqlqueryresults').remove();
}
if ($('.result_query').length !== 0) {
$('.result_query').remove();
}
if (typeof data !== 'undefined' && data.success === true) {
Functions.ajaxShowMessage(data.message);
$('<div class="sqlqueryresults ajax"></div>').prependTo('#page_content');
$('.sqlqueryresults').html(data.sql_query);
Functions.highlightSql($('#page_content'));
} else {
Functions.ajaxShowMessage(data.error, false);
}
});
}, Functions.loadForeignKeyCheckbox);
};
/**
* jQuery coding for 'Table operations'. Used on /table/operations
* Attach Ajax Event handlers for Table operations
*/
AJAX.registerOnload('table/operations.js', function () {
/**
* Ajax action for submitting the "Copy table"
*/
$(document).on('submit', '#copyTable.ajax', function (event) {
event.preventDefault();
var $form = $(this);
Functions.prepareForAjaxRequest($form);
var argsep = CommonParams.get('arg_separator');
$.post($form.attr('action'), $form.serialize() + argsep + 'submit_copy=Go', function (data) {
if (typeof data !== 'undefined' && data.success === true) {
if ($form.find('input[name=\'switch_to_new\']').prop('checked')) {
CommonParams.set('db', $form.find('select[name=\'target_db\'],input[name=\'target_db\']').val());
CommonParams.set('table', $form.find('input[name=\'new_name\']').val());
CommonActions.refreshMain(false, function () {
Functions.ajaxShowMessage(data.message);
});
} else {
Functions.ajaxShowMessage(data.message);
}
// Refresh navigation when the table is copied
Navigation.reload();
} else {
Functions.ajaxShowMessage(data.error, false);
}
}); // end $.post()
}); // end of copyTable ajax submit
/**
* Ajax action for submitting the "Move table"
*/
$(document).on('submit', '#moveTableForm', function (event) {
event.preventDefault();
var $form = $(this);
Functions.prepareForAjaxRequest($form);
var argsep = CommonParams.get('arg_separator');
$.post($form.attr('action'), $form.serialize() + argsep + 'submit_move=1', function (data) {
if (typeof data !== 'undefined' && data.success === true) {
CommonParams.set('db', data.params.db);
CommonParams.set('table', data.params.table);
CommonActions.refreshMain('index.php?route=/table/sql', function () {
Functions.ajaxShowMessage(data.message);
});
// Refresh navigation when the table is copied
Navigation.reload();
} else {
Functions.ajaxShowMessage(data.error, false);
}
});
});
/**
* Ajax action for submitting the "Table options"
*/
$(document).on('submit', '#tableOptionsForm', function (event) {
event.preventDefault();
event.stopPropagation();
var $form = $(this);
var $tblNameField = $form.find('input[name=new_name]');
var $tblCollationField = $form.find('select[name=tbl_collation]');
var collationOrigValue = $('select[name="tbl_collation"] option[selected]').val();
var $changeAllColumnCollationsCheckBox = $('#checkbox_change_all_collations');
var question = Messages.strChangeAllColumnCollationsWarning;
if ($tblNameField.val() !== $tblNameField[0].defaultValue) {
// reload page and navigation if the table has been renamed
Functions.prepareForAjaxRequest($form);
if ($tblCollationField.val() !== collationOrigValue && $changeAllColumnCollationsCheckBox.is(':checked')) {
$form.confirm(question, $form.attr('action'), function () {
submitOptionsForm();
});
} else {
submitOptionsForm();
}
} else {
if ($tblCollationField.val() !== collationOrigValue && $changeAllColumnCollationsCheckBox.is(':checked')) {
$form.confirm(question, $form.attr('action'), function () {
$form.removeClass('ajax').trigger('submit').addClass('ajax');
});
} else {
$form.removeClass('ajax').trigger('submit').addClass('ajax');
}
}
function submitOptionsForm() {
$.post($form.attr('action'), $form.serialize(), function (data) {
if (typeof data !== 'undefined' && data.success === true) {
CommonParams.set('table', data.params.table);
CommonActions.refreshMain(false, function () {
$('#page_content').html(data.message);
Functions.highlightSql($('#page_content'));
});
// Refresh navigation when the table is renamed
Navigation.reload();
} else {
Functions.ajaxShowMessage(data.error, false);
}
});
}
});
/**
* Ajax events for actions in the "Table maintenance"
*/
$(document).on('click', '#tbl_maintenance li a.maintain_action.ajax', function (event) {
event.preventDefault();
var $link = $(this);
if ($('.sqlqueryresults').length !== 0) {
$('.sqlqueryresults').remove();
}
if ($('.result_query').length !== 0) {
$('.result_query').remove();
}
// variables which stores the common attributes
var params = $.param({
'ajax_request': 1,
'server': CommonParams.get('server')
});
var postData = $link.getPostData();
if (postData) {
params += CommonParams.get('arg_separator') + postData;
}
$.post($link.attr('href'), params, function (data) {
function scrollToTop() {
$('html, body').animate({
scrollTop: 0
});
}
var $tempDiv;
if (typeof data !== 'undefined' && data.success === true && data.sql_query !== undefined) {
Functions.ajaxShowMessage(data.message);
$('<div class=\'sqlqueryresults ajax\'></div>').prependTo('#page_content');
$('.sqlqueryresults').html(data.sql_query);
Functions.highlightSql($('#page_content'));
scrollToTop();
} else if (typeof data !== 'undefined' && data.success === true) {
$tempDiv = $('<div id=\'temp_div\'></div>');
$tempDiv.html(data.message);
var $success = $tempDiv.find('.result_query .alert-success');
Functions.ajaxShowMessage($success);
$('<div class=\'sqlqueryresults ajax\'></div>').prependTo('#page_content');
$('.sqlqueryresults').html(data.message);
Functions.highlightSql($('#page_content'));
$('.sqlqueryresults').children('fieldset,br').remove();
scrollToTop();
} else {
$tempDiv = $('<div id=\'temp_div\'></div>');
$tempDiv.html(data.error);
var $error;
if ($tempDiv.find('.error code').length !== 0) {
$error = $tempDiv.find('.error code').addClass('error');
} else {
$error = $tempDiv;
}
Functions.ajaxShowMessage($error, false);
}
}); // end $.post()
}); // end of table maintenance ajax click
/**
* Ajax action for submitting the "Partition Maintenance"
* Also, asks for confirmation when DROP partition is submitted
*/
$(document).on('submit', '#partitionsForm', function (event) {
event.preventDefault();
var $form = $(this);
function submitPartitionMaintenance() {
var argsep = CommonParams.get('arg_separator');
var submitData = $form.serialize() + argsep + 'ajax_request=true' + argsep + 'ajax_page_request=true';
Functions.ajaxShowMessage(Messages.strProcessingRequest);
AJAX.source = $form;
$.post($form.attr('action'), submitData, AJAX.responseHandler);
}
if ($('#partitionOperationRadioDrop').is(':checked')) {
$form.confirm(Messages.strDropPartitionWarning, $form.attr('action'), function () {
submitPartitionMaintenance();
});
} else if ($('#partitionOperationRadioTruncate').is(':checked')) {
$form.confirm(Messages.strTruncatePartitionWarning, $form.attr('action'), function () {
submitPartitionMaintenance();
});
} else {
submitPartitionMaintenance();
}
});
$(document).on('click', '#drop_tbl_anchor.ajax', function (event) {
event.preventDefault();
var $link = $(this);
/**
* @var {String} question String containing the question to be asked for confirmation
*/
var question = Messages.strDropTableStrongWarning + ' ';
question += Functions.sprintf(Messages.strDoYouReally, $link[0].getAttribute('data-query'));
question += Functions.getForeignKeyCheckboxLoader();
$(this).confirm(question, $(this).attr('href'), function (url) {
var $msgbox = Functions.ajaxShowMessage(Messages.strProcessingRequest);
var params = Functions.getJsConfirmCommonParam(this, $link.getPostData());
$.post(url, params, function (data) {
if (typeof data !== 'undefined' && data.success === true) {
Functions.ajaxRemoveMessage($msgbox);
// Table deleted successfully, refresh both the frames
Navigation.reload();
CommonParams.set('table', '');
CommonActions.refreshMain(CommonParams.get('opendb_url'), function () {
Functions.ajaxShowMessage(data.message);
});
} else {
Functions.ajaxShowMessage(data.error, false);
}
});
}, Functions.loadForeignKeyCheckbox);
}); // end of Drop Table Ajax action
$(document).on('click', '#drop_view_anchor.ajax', function (event) {
event.preventDefault();
var $link = $(this);
/**
* @var {String} question String containing the question to be asked for confirmation
*/
var question = Messages.strDropTableStrongWarning + ' ';
question += Functions.sprintf(Messages.strDoYouReally, 'DROP VIEW `' + Functions.escapeHtml(CommonParams.get('table') + '`'));
$(this).confirm(question, $(this).attr('href'), function (url) {
var $msgbox = Functions.ajaxShowMessage(Messages.strProcessingRequest);
var params = Functions.getJsConfirmCommonParam(this, $link.getPostData());
$.post(url, params, function (data) {
if (typeof data !== 'undefined' && data.success === true) {
Functions.ajaxRemoveMessage($msgbox);
// Table deleted successfully, refresh both the frames
Navigation.reload();
CommonParams.set('table', '');
CommonActions.refreshMain(CommonParams.get('opendb_url'), function () {
Functions.ajaxShowMessage(data.message);
});
} else {
Functions.ajaxShowMessage(data.error, false);
}
});
});
}); // end of Drop View Ajax action
$(document).on('click', '#truncate_tbl_anchor.ajax', function (event) {
event.preventDefault();
confirmAndPost($(this), 'TRUNCATE');
});
$(document).on('click', '#delete_tbl_anchor.ajax', function (event) {
event.preventDefault();
confirmAndPost($(this), 'DELETE');
});
}); // end $(document).ready for 'Table operations'

View file

@ -1,208 +0,0 @@
/**
* for table relation
*/
var TableRelation = {};
TableRelation.showHideClauses = function ($thisDropdown) {
if ($thisDropdown.val() === '') {
$thisDropdown.parent().nextAll('span').hide();
} else {
if ($thisDropdown.is('select[name^="destination_foreign_column"]')) {
$thisDropdown.parent().nextAll('span').show();
}
}
};
/**
* Sets dropdown options to values
* @param $dropdown
* @param values
* @param selectedValue
* @return {void}
*/
TableRelation.setDropdownValues = function ($dropdown, values, selectedValue) {
$dropdown.empty();
var optionsAsString = '';
// add an empty string to the beginning for empty selection
values.unshift('');
$.each(values, function () {
optionsAsString += '<option value=\'' + Functions.escapeHtml(this) + '\'' + (selectedValue === Functions.escapeHtml(this) ? ' selected=\'selected\'' : '') + '>' + Functions.escapeHtml(this) + '</option>';
});
$dropdown.append($(optionsAsString));
};
/**
* Retrieves and populates dropdowns to the left based on the selected value
*
* @param $dropdown the dropdown whose value got changed
* @return {void}
*/
TableRelation.getDropdownValues = function ($dropdown) {
var foreignDb = null;
var foreignTable = null;
var $databaseDd;
var $tableDd;
var $columnDd;
var foreign = '';
// if the changed dropdown is for foreign key constraints
if ($dropdown.is('select[name^="destination_foreign"]')) {
$databaseDd = $dropdown.parent().parent().parent().find('select[name^="destination_foreign_db"]');
$tableDd = $dropdown.parent().parent().parent().find('select[name^="destination_foreign_table"]');
$columnDd = $dropdown.parent().parent().parent().find('select[name^="destination_foreign_column"]');
foreign = '_foreign';
} else {
// internal relations
$databaseDd = $dropdown.parent().find('select[name^="destination_db"]');
$tableDd = $dropdown.parent().find('select[name^="destination_table"]');
$columnDd = $dropdown.parent().find('select[name^="destination_column"]');
}
// if the changed dropdown is a database selector
if ($dropdown.is('select[name^="destination' + foreign + '_db"]')) {
foreignDb = $dropdown.val();
// if no database is selected empty table and column dropdowns
if (foreignDb === '') {
TableRelation.setDropdownValues($tableDd, []);
TableRelation.setDropdownValues($columnDd, []);
return;
}
} else {
// if a table selector
foreignDb = $databaseDd.val();
foreignTable = $dropdown.val();
// if no table is selected empty the column dropdown
if (foreignTable === '') {
TableRelation.setDropdownValues($columnDd, []);
return;
}
}
var $msgbox = Functions.ajaxShowMessage();
var $form = $dropdown.parents('form');
var $db = $form.find('input[name="db"]').val();
var $table = $form.find('input[name="table"]').val();
var argsep = CommonParams.get('arg_separator');
var params = 'getDropdownValues=true' + argsep + 'ajax_request=true' + argsep + 'db=' + encodeURIComponent($db) + argsep + 'table=' + encodeURIComponent($table) + argsep + 'foreign=' + (foreign !== '') + argsep + 'foreignDb=' + encodeURIComponent(foreignDb) + (foreignTable !== null ? argsep + 'foreignTable=' + encodeURIComponent(foreignTable) : '');
var $server = $form.find('input[name="server"]');
if ($server.length > 0) {
params += argsep + 'server=' + $form.find('input[name="server"]').val();
}
$.ajax({
type: 'POST',
url: 'index.php?route=/table/relation',
data: params,
dataType: 'json',
success: function (data) {
Functions.ajaxRemoveMessage($msgbox);
if (typeof data !== 'undefined' && data.success) {
// if the changed dropdown is a database selector
if (foreignTable === null) {
// set values for table and column dropdowns
TableRelation.setDropdownValues($tableDd, data.tables);
TableRelation.setDropdownValues($columnDd, []);
} else {
// if a table selector
// set values for the column dropdown
var primary = null;
if (typeof data.primary !== 'undefined' && 1 === data.primary.length) {
primary = data.primary[0];
}
TableRelation.setDropdownValues($columnDd.first(), data.columns, primary);
TableRelation.setDropdownValues($columnDd.slice(1), data.columns);
}
} else {
Functions.ajaxShowMessage(data.error, false);
}
}
});
};
/**
* Unbind all event handlers before tearing down a page
*/
AJAX.registerTeardown('table/relation.js', function () {
$('body').off('change', 'select[name^="destination_db"], ' + 'select[name^="destination_table"], ' + 'select[name^="destination_foreign_db"], ' + 'select[name^="destination_foreign_table"]');
$('body').off('click', 'a.add_foreign_key_field');
$('body').off('click', 'a.add_foreign_key');
$('a.drop_foreign_key_anchor.ajax').off('click');
});
AJAX.registerOnload('table/relation.js', function () {
/**
* Ajax event handler to fetch table/column dropdown values.
*/
$('body').on('change', 'select[name^="destination_db"], ' + 'select[name^="destination_table"], ' + 'select[name^="destination_foreign_db"], ' + 'select[name^="destination_foreign_table"]', function () {
TableRelation.getDropdownValues($(this));
});
/**
* Ajax event handler to add a column to a foreign key constraint.
*/
$('body').on('click', 'a.add_foreign_key_field', function (event) {
event.preventDefault();
event.stopPropagation();
// Add field.
$(this).prev('span').clone(true, true).insertBefore($(this)).find('select').val('');
// Add foreign field.
var $sourceElem = $('select[name^="destination_foreign_column[' + $(this).attr('data-index') + ']"]').last().parent();
$sourceElem.clone(true, true).insertAfter($sourceElem).find('select').val('');
});
/**
* Ajax event handler to add a foreign key constraint.
*/
$('body').on('click', 'a.add_foreign_key', function (event) {
event.preventDefault();
event.stopPropagation();
var $prevRow = $(this).closest('tr').prev('tr');
var $newRow = $prevRow.clone(true, true);
// Update serial number.
var currIndex = $newRow.find('a.add_foreign_key_field').attr('data-index');
var newIndex = parseInt(currIndex) + 1;
$newRow.find('a.add_foreign_key_field').attr('data-index', newIndex);
// Update form parameter names.
$newRow.find('select[name^="foreign_key_fields_name"]').not($newRow.find('select[name^="foreign_key_fields_name"]').first()).find('select[name^="destination_foreign_column"]').not($newRow.find('select[name^="foreign_key_fields_name"]').not($newRow.find('select[name^="foreign_key_fields_name"]').first()).find('select[name^="destination_foreign_column"]').first()).each(function () {
$(this).parent().remove();
});
$newRow.find('input, select').each(function () {
$(this).attr('name', $(this).attr('name').replace(/\d/, newIndex));
});
$newRow.find('input[type="text"]').each(function () {
$(this).val('');
});
// Finally add the row.
$newRow.insertAfter($prevRow);
});
/**
* Ajax Event handler for 'Drop Foreign key'
*/
$('a.drop_foreign_key_anchor.ajax').on('click', function (event) {
event.preventDefault();
var $anchor = $(this);
// Object containing reference to the current field's row
var $currRow = $anchor.parents('tr');
var dropQuery = Functions.escapeHtml($currRow.children('td').children('.drop_foreign_key_msg').val());
var question = Functions.sprintf(Messages.strDoYouReally, dropQuery);
$anchor.confirm(question, $anchor.attr('href'), function (url) {
var $msg = Functions.ajaxShowMessage(Messages.strDroppingForeignKey, false);
var params = Functions.getJsConfirmCommonParam(this, $anchor.getPostData());
$.post(url, params, function (data) {
if (data.success === true) {
Functions.ajaxRemoveMessage($msg);
CommonActions.refreshMain(false, function () {
// Do nothing
});
} else {
Functions.ajaxShowMessage(Messages.strErrorProcessingRequest + ' : ' + data.error, false);
}
}); // end $.post()
});
}); // end Drop Foreign key
var windowWidth = $(window).width();
$('.jsresponsive').css('max-width', windowWidth - 35 + 'px');
});

View file

@ -1,299 +0,0 @@
/**
* @fileoverview JavaScript functions used on /table/search
*
* @requires jQuery
* @requires js/functions.js
*/
/* global changeValueFieldType, verifyAfterSearchFieldChange */ // js/table/change.js
/* global openGISEditor, gisEditorLoaded, loadJSAndGISEditor, loadGISEditor */ // js/gis_data_editor.js
var TableSelect = {};
/**
* Checks if given data-type is numeric or date.
*
* @param {string} dataType Column data-type
*
* @return {boolean | string}
*/
TableSelect.checkIfDataTypeNumericOrDate = function (dataType) {
// To test for numeric data-types.
var numericRegExp = new RegExp('TINYINT|SMALLINT|MEDIUMINT|INT|BIGINT|DECIMAL|FLOAT|DOUBLE|REAL', 'i');
// To test for date data-types.
var dateRegExp = new RegExp('DATETIME|DATE|TIMESTAMP|TIME|YEAR', 'i');
// Return matched data-type
if (numericRegExp.test(dataType)) {
return numericRegExp.exec(dataType)[0];
}
if (dateRegExp.test(dataType)) {
return dateRegExp.exec(dataType)[0];
}
return false;
};
/**
* Unbind all event handlers before tearing down a page
*/
AJAX.registerTeardown('table/select.js', function () {
$('#togglesearchformlink').off('click');
$(document).off('submit', '#tbl_search_form.ajax');
$('select.geom_func').off('change');
$(document).off('click', 'span.open_search_gis_editor');
$('body').off('change', 'select[name*="criteriaColumnOperators"]'); // Fix for bug #13778, changed 'click' to 'change'
});
AJAX.registerOnload('table/select.js', function () {
/**
* 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('#tbl_search_form')
// don't show it until we have results on-screen
.hide();
$('#togglesearchformlink').html(Messages.strShowSearchCriteria).on('click', function () {
var $link = $(this);
$('#tbl_search_form').slideToggle();
if ($link.text() === Messages.strHideSearchCriteria) {
$link.text(Messages.strShowSearchCriteria);
} else {
$link.text(Messages.strHideSearchCriteria);
}
// avoid default click action
return false;
});
var tableRows = $('#fieldset_table_qbe select.column-operator');
$.each(tableRows, function (index, item) {
$(item).on('change', function () {
changeValueFieldType(this, index);
verifyAfterSearchFieldChange(index, '#tbl_search_form');
});
});
/**
* Ajax event handler for Table search
*/
$(document).on('submit', '#tbl_search_form.ajax', function (event) {
var unaryFunctions = ['IS NULL', 'IS NOT NULL', '= \'\'', '!= \'\''];
var geomUnaryFunctions = ['IsEmpty', 'IsSimple', 'IsRing', 'IsClosed'];
// jQuery object to reuse
var $searchForm = $(this);
event.preventDefault();
// empty previous search results while we are waiting for new results
$('#sqlqueryresultsouter').empty();
var $msgbox = Functions.ajaxShowMessage(Messages.strSearching, false);
Functions.prepareForAjaxRequest($searchForm);
var values = {};
$searchForm.find(':input').each(function () {
var $input = $(this);
if ($input.attr('type') === 'checkbox' || $input.attr('type') === 'radio') {
if ($input.is(':checked')) {
values[this.name] = $input.val();
}
} else {
values[this.name] = $input.val();
}
});
var columnCount = $('select[name="columnsToDisplay[]"] option').length;
// Submit values only for the columns that have unary column operator or a search criteria
for (var a = 0; a < columnCount; a++) {
if ($.inArray(values['criteriaColumnOperators[' + a + ']'], unaryFunctions) >= 0) {
continue;
}
if (values['geom_func[' + a + ']'] && $.inArray(values['geom_func[' + a + ']'], geomUnaryFunctions) >= 0) {
continue;
}
if (values['criteriaValues[' + a + ']'] === '' || values['criteriaValues[' + a + ']'] === null) {
delete values['criteriaValues[' + a + ']'];
delete values['criteriaColumnOperators[' + a + ']'];
delete values['criteriaColumnNames[' + a + ']'];
delete values['criteriaColumnTypes[' + a + ']'];
delete values['criteriaColumnCollations[' + a + ']'];
}
}
// If all columns are selected, use a single parameter to indicate that
if (values['columnsToDisplay[]'] !== null) {
if (values['columnsToDisplay[]'].length === columnCount) {
delete values['columnsToDisplay[]'];
values.displayAllColumns = true;
}
} else {
values.displayAllColumns = true;
}
$.post($searchForm.attr('action'), values, function (data) {
Functions.ajaxRemoveMessage($msgbox);
if (typeof data !== 'undefined' && data.success === true) {
if (typeof data.sql_query !== 'undefined') {
// zero rows
$('#sqlqueryresultsouter').html(data.sql_query);
} else {
// results found
$('#sqlqueryresultsouter').html(data.message);
$('.sqlqueryresults').trigger('makegrid');
}
$('#tbl_search_form')
// workaround for bug #3168569 - Issue on toggling the "Hide search criteria" in chrome.
.slideToggle().hide();
$('#togglesearchformlink')
// always start with the Show message
.text(Messages.strShowSearchCriteria);
$('#togglesearchformdiv')
// now it's time to show the div containing the link
.show();
$('html, body').animate({
scrollTop: 0
}, 'fast');
} else {
$('#sqlqueryresultsouter').html(data.error);
}
Functions.highlightSql($('#sqlqueryresultsouter'));
}); // end $.post()
});
// Following section is related to the 'function based search' for geometry data types.
// Initially hide all the open_gis_editor spans
$('span.open_search_gis_editor').hide();
$('select.geom_func').on('change', function () {
var $geomFuncSelector = $(this);
var binaryFunctions = ['Contains', 'Crosses', 'Disjoint', 'Equals', 'Intersects', 'Overlaps', 'Touches', 'Within', 'MBRContains', 'MBRDisjoint', 'MBREquals', 'MBRIntersects', 'MBROverlaps', 'MBRTouches', 'MBRWithin', 'ST_Contains', 'ST_Crosses', 'ST_Disjoint', 'ST_Equals', 'ST_Intersects', 'ST_Overlaps', 'ST_Touches', 'ST_Within'];
var tempArray = ['Envelope', 'EndPoint', 'StartPoint', 'ExteriorRing', 'Centroid', 'PointOnSurface'];
var outputGeomFunctions = binaryFunctions.concat(tempArray);
// If the chosen function takes two geometry objects as parameters
var $operator = $geomFuncSelector.parents('tr').find('td').eq(4).find('select');
if ($.inArray($geomFuncSelector.val(), binaryFunctions) >= 0) {
$operator.prop('readonly', true);
} else {
$operator.prop('readonly', false);
}
// if the chosen function's output is a geometry, enable GIS editor
var $editorSpan = $geomFuncSelector.parents('tr').find('span.open_search_gis_editor');
if ($.inArray($geomFuncSelector.val(), outputGeomFunctions) >= 0) {
$editorSpan.show();
} else {
$editorSpan.hide();
}
});
$(document).on('click', 'span.open_search_gis_editor', function (event) {
event.preventDefault();
var $span = $(this);
// Current value
var value = $span.parent('td').children('input[type=\'text\']').val();
// Field name
var field = 'Parameter';
// Column type
var geomFunc = $span.parents('tr').find('.geom_func').val();
var type;
if (geomFunc === 'Envelope') {
type = 'polygon';
} else if (geomFunc === 'ExteriorRing') {
type = 'linestring';
} else {
type = 'point';
}
// Names of input field and null checkbox
var inputName = $span.parent('td').children('input[type=\'text\']').attr('name');
// Token
openGISEditor();
if (!gisEditorLoaded) {
loadJSAndGISEditor(value, field, type, inputName);
} else {
loadGISEditor(value, field, type, inputName);
}
});
/**
* Ajax event handler for Range-Search.
*/
$('body').on('change', 'select[name*="criteriaColumnOperators"]', function () {
// Fix for bug #13778, changed 'click' to 'change'
var $sourceSelect = $(this);
// Get the column name.
var columnName = $(this).closest('tr').find('th').first().text();
// Get the data-type of column excluding size.
var dataType = $(this).closest('tr').find('td[data-type]').attr('data-type');
dataType = TableSelect.checkIfDataTypeNumericOrDate(dataType);
// Get the operator.
var operator = $(this).val();
if ((operator === 'BETWEEN' || operator === 'NOT BETWEEN') && dataType) {
var $msgbox = Functions.ajaxShowMessage();
$.ajax({
url: 'index.php?route=/table/search',
type: 'POST',
data: {
'server': CommonParams.get('server'),
'ajax_request': 1,
'db': $('input[name="db"]').val(),
'table': $('input[name="table"]').val(),
'column': columnName,
'range_search': 1
},
success: function (response) {
Functions.ajaxRemoveMessage($msgbox);
if (response.success) {
// Get the column min value.
var min = response.column_data.min ? '(' + Messages.strColumnMin + ' ' + response.column_data.min + ')' : '';
// Get the column max value.
var max = response.column_data.max ? '(' + Messages.strColumnMax + ' ' + response.column_data.max + ')' : '';
$('#rangeSearchModal').modal('show');
$('#rangeSearchLegend').first().html(operator);
$('#rangeSearchMin').first().text(min);
$('#rangeSearchMax').first().text(max);
// Reset input values on reuse
$('#min_value').first().val('');
$('#max_value').first().val('');
// Add datepicker wherever required.
Functions.addDatepicker($('#min_value'), dataType);
Functions.addDatepicker($('#max_value'), dataType);
$('#rangeSearchModalGo').on('click', function () {
var minValue = $('#min_value').val();
var maxValue = $('#max_value').val();
var finalValue = '';
if (minValue.length && maxValue.length) {
finalValue = minValue + ', ' + maxValue;
}
var $targetField = $sourceSelect.closest('tr').find('[name*="criteriaValues"]');
// If target field is a select list.
if ($targetField.is('select')) {
$targetField.val(finalValue);
var $options = $targetField.find('option');
var $closestMin = null;
var $closestMax = null;
// Find closest min and max value.
$options.each(function () {
if ($closestMin === null || Math.abs($(this).val() - minValue) < Math.abs($closestMin.val() - minValue)) {
$closestMin = $(this);
}
if ($closestMax === null || Math.abs($(this).val() - maxValue) < Math.abs($closestMax.val() - maxValue)) {
$closestMax = $(this);
}
});
$closestMin.attr('selected', 'selected');
$closestMax.attr('selected', 'selected');
} else {
$targetField.val(finalValue);
}
$('#rangeSearchModal').modal('hide');
});
} else {
Functions.ajaxShowMessage(response.error);
}
},
error: function () {
Functions.ajaxShowMessage(Messages.strErrorProcessingRequest);
}
});
}
});
var windowWidth = $(window).width();
$('.jsresponsive').css('max-width', windowWidth - 69 + 'px');
});

View file

@ -1,416 +0,0 @@
/**
* @fileoverview functions used on the table structure page
* @name Table Structure
*
* @requires jQuery
* @requires jQueryUI
* @required js/functions.js
*/
// eslint-disable-next-line no-unused-vars
/* global primaryIndexes:writable, indexes:writable, fulltextIndexes:writable, spatialIndexes:writable */ // js/functions.js
/* global sprintf */ // js/vendor/sprintf.js
/**
* AJAX scripts for /table/structure
*
* Actions ajaxified here:
* Drop Column
* Add Primary Key
* Drop Primary Key/Index
*
*/
/**
* Reload fields table
*/
function reloadFieldForm() {
$.post($('#fieldsForm').attr('action'), $('#fieldsForm').serialize() + CommonParams.get('arg_separator') + 'ajax_request=true', function (formData) {
var $tempDiv = $('<div id=\'temp_div\'><div>').append(formData.message);
$('#fieldsForm').replaceWith($tempDiv.find('#fieldsForm'));
$('#addColumns').replaceWith($tempDiv.find('#addColumns'));
$('#move_columns_dialog').find('ul').replaceWith($tempDiv.find('#move_columns_dialog ul'));
});
$('#page_content').show();
}
function checkFirst() {
if ($('select[name=after_field] option:selected').data('pos') === 'first') {
$('input[name=field_where]').val('first');
} else {
$('input[name=field_where]').val('after');
}
}
/**
* Unbind all event handlers before tearing down a page
*/
AJAX.registerTeardown('table/structure.js', function () {
$(document).off('click', 'a.drop_column_anchor.ajax');
$(document).off('click', 'a.add_key.ajax');
$(document).off('click', '#move_columns_anchor');
$(document).off('submit', '.append_fields_form.ajax');
$('body').off('click', '#fieldsForm button.mult_submit');
$(document).off('click', 'a[id^=partition_action].ajax');
$(document).off('click', '#remove_partitioning.ajax');
});
AJAX.registerOnload('table/structure.js', function () {
// Re-initialize variables.
primaryIndexes = [];
indexes = [];
fulltextIndexes = [];
spatialIndexes = [];
/**
*Ajax action for submitting the "Column Change" and "Add Column" form
*/
$('.append_fields_form.ajax').off();
$(document).on('submit', '.append_fields_form.ajax', function (event) {
event.preventDefault();
/**
* @var form object referring to the export form
*/
var $form = $(this);
var fieldCnt = $form.find('input[name=orig_num_fields]').val();
function submitForm() {
var $msg = Functions.ajaxShowMessage(Messages.strProcessingRequest);
$.post($form.attr('action'), $form.serialize() + CommonParams.get('arg_separator') + 'do_save_data=1', function (data) {
if ($('.sqlqueryresults').length !== 0) {
$('.sqlqueryresults').remove();
} else if ($('.error:not(.tab)').length !== 0) {
$('.error:not(.tab)').remove();
}
if (typeof data.success !== 'undefined' && data.success === true) {
$('#page_content').empty().append(data.message).show();
Functions.highlightSql($('#page_content'));
$('.result_query .alert-primary').remove();
if (typeof data.structure_refresh_route !== 'string') {
// Do not reload the form when the code below freshly filled it
reloadFieldForm();
}
$form.remove();
Functions.ajaxRemoveMessage($msg);
Navigation.reload();
if (typeof data.structure_refresh_route === 'string') {
// Fetch the table structure right after adding a new column
$.get(data.structure_refresh_route, function (data) {
if (typeof data.success !== 'undefined' && data.success === true) {
$('#page_content').append(data.message).show();
}
});
} else {
CommonActions.refreshMain('index.php?route=/table/structure');
}
} else {
Functions.ajaxShowMessage(data.error, false);
}
}); // end $.post()
}
function checkIfConfirmRequired($form) {
var i = 0;
var id;
var elm;
var val;
var nameOrig;
var elmOrig;
var valOrig;
var checkRequired = false;
for (i = 0; i < fieldCnt; i++) {
id = '#field_' + i + '_5';
elm = $(id);
val = elm.val();
nameOrig = 'input[name=field_collation_orig\\[' + i + '\\]]';
elmOrig = $form.find(nameOrig);
valOrig = elmOrig.val();
if (val && valOrig && val !== valOrig) {
checkRequired = true;
break;
}
}
return checkRequired;
}
/*
* First validate the form; if there is a problem, avoid submitting it
*
* Functions.checkTableEditForm() needs a pure element and not a jQuery object,
* this is why we pass $form[0] as a parameter (the jQuery object
* is actually an array of DOM elements)
*/
if (Functions.checkTableEditForm($form[0], fieldCnt)) {
// OK, form passed validation step
Functions.prepareForAjaxRequest($form);
if (Functions.checkReservedWordColumns($form)) {
// User wants to submit the form
// If Collation is changed, Warn and Confirm
if (checkIfConfirmRequired($form)) {
var question = sprintf(Messages.strChangeColumnCollation, 'https://wiki.phpmyadmin.net/pma/Garbled_data');
$form.confirm(question, $form.attr('action'), function () {
submitForm();
});
} else {
submitForm();
}
}
}
}); // end change table button "do_save_data"
/**
* Attach Event Handler for 'Drop Column'
*/
$(document).on('click', 'a.drop_column_anchor.ajax', function (event) {
event.preventDefault();
/**
* @var currTableName String containing the name of the current table
*/
var currTableName = $(this).closest('form').find('input[name=table]').val();
/**
* @var currRow Object reference to the currently selected row (i.e. field in the table)
*/
var $currRow = $(this).parents('tr');
/**
* @var currColumnName String containing name of the field referred to by {@link curr_row}
*/
var currColumnName = $currRow.children('th').children('label').text().trim();
currColumnName = Functions.escapeHtml(currColumnName);
/**
* @var $afterFieldItem Corresponding entry in the 'After' field.
*/
var $afterFieldItem = $('select[name=\'after_field\'] option[value=\'' + currColumnName + '\']');
/**
* @var question String containing the question to be asked for confirmation
*/
var question = Functions.sprintf(Messages.strDoYouReally, 'ALTER TABLE `' + currTableName + '` DROP `' + currColumnName + '`;');
var $thisAnchor = $(this);
$thisAnchor.confirm(question, $thisAnchor.attr('href'), function (url) {
var $msg = Functions.ajaxShowMessage(Messages.strDroppingColumn, false);
var params = Functions.getJsConfirmCommonParam(this, $thisAnchor.getPostData());
params += CommonParams.get('arg_separator') + 'ajax_page_request=1';
$.post(url, params, function (data) {
if (typeof data !== 'undefined' && data.success === true) {
Functions.ajaxRemoveMessage($msg);
if ($('.result_query').length) {
$('.result_query').remove();
}
if (data.sql_query) {
$('<div class="result_query"></div>').html(data.sql_query).prependTo('#structure_content');
Functions.highlightSql($('#page_content'));
}
// Adjust the row numbers
for (var $row = $currRow.next(); $row.length > 0; $row = $row.next()) {
var newVal = parseInt($row.find('td').eq(1).text(), 10) - 1;
$row.find('td').eq(1).text(newVal);
}
$afterFieldItem.remove();
$currRow.hide('medium').remove();
// Remove the dropped column from select menu for 'after field'
$('select[name=after_field]').find('[value="' + currColumnName + '"]').remove();
// by default select the (new) last option to add new column
// (in case last column is dropped)
$('select[name=after_field] option').last().attr('selected', 'selected');
// refresh table stats
if (data.tableStat) {
$('#tablestatistics').html(data.tableStat);
}
// refresh the list of indexes (comes from /sql)
$('.index_info').replaceWith(data.indexes_list);
Navigation.reload();
} else {
Functions.ajaxShowMessage(Messages.strErrorProcessingRequest + ' : ' + data.error, false);
}
}); // end $.post()
});
}); // end of Drop Column Anchor action
/**
* Ajax Event handler for adding keys
*/
$(document).on('click', 'a.add_key.ajax', function (event) {
event.preventDefault();
var $this = $(this);
var currTableName = $this.closest('form').find('input[name=table]').val();
var currColumnName = $this.parents('tr').children('th').children('label').text().trim();
var addClause = '';
if ($this.is('.add_primary_key_anchor')) {
addClause = 'ADD PRIMARY KEY';
} else if ($this.is('.add_index_anchor')) {
addClause = 'ADD INDEX';
} else if ($this.is('.add_unique_anchor')) {
addClause = 'ADD UNIQUE';
} else if ($this.is('.add_spatial_anchor')) {
addClause = 'ADD SPATIAL';
} else if ($this.is('.add_fulltext_anchor')) {
addClause = 'ADD FULLTEXT';
}
var question = Functions.sprintf(Messages.strDoYouReally, 'ALTER TABLE `' + Functions.escapeHtml(currTableName) + '` ' + addClause + '(`' + Functions.escapeHtml(currColumnName) + '`);');
var $thisAnchor = $(this);
$thisAnchor.confirm(question, $thisAnchor.attr('href'), function (url) {
Functions.ajaxShowMessage();
AJAX.source = $this;
var params = Functions.getJsConfirmCommonParam(this, $thisAnchor.getPostData());
params += CommonParams.get('arg_separator') + 'ajax_page_request=1';
$.post(url, params, AJAX.responseHandler);
});
}); // end Add key
/**
* Inline move columns
**/
$(document).on('click', '#move_columns_anchor', function (e) {
e.preventDefault();
var buttonOptionsError = {};
buttonOptionsError[Messages.strOK] = function () {
$(this).dialog('close').remove();
};
var columns = [];
$('#tablestructure').find('tbody tr').each(function () {
var colName = $(this).find('input:checkbox').eq(0).val();
var hiddenInput = $('<input>').prop({
name: 'move_columns[]',
type: 'hidden'
}).val(colName);
columns[columns.length] = $('<li></li>').addClass('placeholderDrag').text(colName).append(hiddenInput);
});
var colList = $('#move_columns_dialog').find('ul').find('li').remove().end();
for (var i in columns) {
colList.append(columns[i]);
}
colList.sortable({
axis: 'y',
containment: $('#move_columns_dialog').find('div'),
tolerance: 'pointer'
}).disableSelection();
var $form = $('#move_columns_dialog').find('form');
$form.data('serialized-unmoved', $form.serialize());
const designerModalPreviewModal = document.getElementById('designerModalPreviewModal');
designerModalPreviewModal.addEventListener('shown.bs.modal', () => {
const modalBody = designerModalPreviewModal.querySelector('.modal-body');
const $form = $('#move_column_form');
const formUrl = $form.attr('action');
const sep = CommonParams.get('arg_separator');
const formData = $form.serialize() + sep + 'preview_sql=1' + sep + 'ajax_request=1';
$.post({
url: formUrl,
data: formData,
success: response => {
if (!response.success) {
modalBody.innerHTML = '<div class="alert alert-danger" role="alert">' + Messages.strErrorProcessingRequest + '</div>';
return;
}
modalBody.innerHTML = response.sql_data;
Functions.highlightSql($('#designerModalPreviewModal'));
},
error: () => {
modalBody.innerHTML = '<div class="alert alert-danger" role="alert">' + Messages.strErrorProcessingRequest + '</div>';
}
});
});
designerModalPreviewModal.addEventListener('hidden.bs.modal', () => {
designerModalPreviewModal.querySelector('.modal-body').innerHTML = '<div class="spinner-border" role="status">' + '<span class="visually-hidden">' + Messages.strLoading + '</span></div>';
});
$('#moveColumnsModal').modal('show');
$('#designerModalGoButton').off('click'); // Unregister previous modals
$('#designerModalGoButton').on('click', function () {
event.preventDefault();
var $msgbox = Functions.ajaxShowMessage();
var $this = $('#moveColumnsModal');
var $form = $this.find('form');
var serialized = $form.serialize();
// check if any columns were moved at all
$('#moveColumnsModal').modal('hide');
if (serialized === $form.data('serialized-unmoved')) {
Functions.ajaxRemoveMessage($msgbox);
return;
}
$.post($form.prop('action'), serialized + CommonParams.get('arg_separator') + 'ajax_request=true', function (data) {
if (data.success === false) {
Functions.ajaxRemoveMessage($msgbox);
var errorModal = $('#moveColumnsErrorModal');
errorModal.modal('show');
errorModal.find('.modal-body').first().html(data.error);
} else {
// sort the fields table
var $fieldsTable = $('table#tablestructure tbody');
// remove all existing rows and remember them
var $rows = $fieldsTable.find('tr').remove();
// loop through the correct order
for (var i in data.columns) {
var theColumn = data.columns[i];
var $theRow = $rows.find('input:checkbox[value=\'' + theColumn + '\']').closest('tr');
// append the row for this column to the table
$fieldsTable.append($theRow);
}
var $firstrow = $fieldsTable.find('tr').eq(0);
// Adjust the row numbers and colors
for (var $row = $firstrow; $row.length > 0; $row = $row.next()) {
$row.find('td').eq(1).text($row.index() + 1).end().removeClass('odd even').addClass($row.index() % 2 === 0 ? 'odd' : 'even');
}
Functions.ajaxShowMessage(data.message);
}
});
});
});
/**
* Handles multi submits in table structure page such as change, browse, drop, primary etc.
*/
$('body').on('click', '#fieldsForm button.mult_submit', function (e) {
e.preventDefault();
var $form = $(this).parents('form');
var argsep = CommonParams.get('arg_separator');
var submitData = $form.serialize() + argsep + 'ajax_request=true' + argsep + 'ajax_page_request=true';
Functions.ajaxShowMessage();
AJAX.source = $form;
$.post(this.formAction, submitData, AJAX.responseHandler);
});
/**
* Handles clicks on Action links in partition table
*/
$(document).on('click', 'a[id^=partition_action].ajax', function (e) {
e.preventDefault();
var $link = $(this);
function submitPartitionAction(url) {
var params = 'ajax_request=true&ajax_page_request=true&' + $link.getPostData();
Functions.ajaxShowMessage();
AJAX.source = $link;
$.post(url, params, AJAX.responseHandler);
}
if ($link.is('#partition_action_DROP')) {
$link.confirm(Messages.strDropPartitionWarning, $link.attr('href'), function (url) {
submitPartitionAction(url);
});
} else if ($link.is('#partition_action_TRUNCATE')) {
$link.confirm(Messages.strTruncatePartitionWarning, $link.attr('href'), function (url) {
submitPartitionAction(url);
});
} else {
submitPartitionAction($link.attr('href'));
}
});
/**
* Handles remove partitioning
*/
$(document).on('click', '#remove_partitioning.ajax', function (e) {
e.preventDefault();
var $link = $(this);
var question = Messages.strRemovePartitioningWarning;
$link.confirm(question, $link.attr('href'), function (url) {
var params = Functions.getJsConfirmCommonParam({
'ajax_request': true,
'ajax_page_request': true
}, $link.getPostData());
Functions.ajaxShowMessage();
AJAX.source = $link;
$.post(url, params, AJAX.responseHandler);
});
});
$(document).on('change', 'select[name=after_field]', function () {
checkFirst();
});
});

View file

@ -1,123 +0,0 @@
/**
* Unbind all event handlers before tearing down the page
*/
AJAX.registerTeardown('table/tracking.js', function () {
$('body').off('click', '#versionsForm.ajax button[name="submit_mult"], #versionsForm.ajax input[name="submit_mult"]');
$('body').off('click', 'a.delete_version_anchor.ajax');
$('body').off('click', 'a.delete_entry_anchor.ajax');
});
/**
* Bind event handlers
*/
AJAX.registerOnload('table/tracking.js', function () {
$('#versions tr').first().find('th').append($('<div class="sorticon"></div>'));
$('#versions').tablesorter({
sortList: [[1, 0]],
headers: {
0: {
sorter: false
},
1: {
sorter: 'integer'
},
5: {
sorter: false
},
6: {
sorter: false
}
}
});
if ($('#ddl_versions tbody tr').length > 0) {
$('#ddl_versions tr').first().find('th').append($('<div class="sorticon"></div>'));
$('#ddl_versions').tablesorter({
sortList: [[0, 0]],
headers: {
0: {
sorter: 'integer'
},
3: {
sorter: false
},
4: {
sorter: false
}
}
});
}
if ($('#dml_versions tbody tr').length > 0) {
$('#dml_versions tr').first().find('th').append($('<div class="sorticon"></div>'));
$('#dml_versions').tablesorter({
sortList: [[0, 0]],
headers: {
0: {
sorter: 'integer'
},
3: {
sorter: false
},
4: {
sorter: false
}
}
});
}
/**
* Handles multi submit for tracking versions
*/
$('body').on('click', '#versionsForm.ajax button[name="submit_mult"], #versionsForm.ajax input[name="submit_mult"]', function (e) {
e.preventDefault();
var $button = $(this);
var $form = $button.parent('form');
var argsep = CommonParams.get('arg_separator');
var submitData = $form.serialize() + argsep + 'ajax_request=true' + argsep + 'ajax_page_request=true' + argsep + 'submit_mult=' + $button.val();
if ($button.val() === 'delete_version') {
var question = Messages.strDeleteTrackingVersionMultiple;
$button.confirm(question, $form.attr('action'), function (url) {
Functions.ajaxShowMessage();
AJAX.source = $form;
$.post(url, submitData, AJAX.responseHandler);
});
} else {
Functions.ajaxShowMessage();
AJAX.source = $form;
$.post($form.attr('action'), submitData, AJAX.responseHandler);
}
});
/**
* Ajax Event handler for 'Delete version'
*/
$('body').on('click', 'a.delete_version_anchor.ajax', function (e) {
e.preventDefault();
var $anchor = $(this);
var question = Messages.strDeleteTrackingVersion;
$anchor.confirm(question, $anchor.attr('href'), function (url) {
Functions.ajaxShowMessage();
AJAX.source = $anchor;
var argSep = CommonParams.get('arg_separator');
var params = Functions.getJsConfirmCommonParam(this, $anchor.getPostData());
params += argSep + 'ajax_page_request=1';
$.post(url, params, AJAX.responseHandler);
});
});
/**
* Ajax Event handler for 'Delete tracking report entry'
*/
$('body').on('click', 'a.delete_entry_anchor.ajax', function (e) {
e.preventDefault();
var $anchor = $(this);
var question = Messages.strDeletingTrackingEntry;
$anchor.confirm(question, $anchor.attr('href'), function (url) {
Functions.ajaxShowMessage();
AJAX.source = $anchor;
var argSep = CommonParams.get('arg_separator');
var params = Functions.getJsConfirmCommonParam(this, $anchor.getPostData());
params += argSep + 'ajax_page_request=1';
$.post(url, params, AJAX.responseHandler);
});
});
});

View file

@ -1,590 +0,0 @@
// TODO: change the axis
/**
* @fileoverview JavaScript functions used on /table/search
*
* @requires jQuery
* @requires js/functions.js
**/
/* global changeValueFieldType, verifyAfterSearchFieldChange */ // js/table/change.js
/**
* Display Help/Info
* @return {false}
**/
function displayHelp() {
var modal = $('#helpModal');
modal.modal('show');
modal.find('.modal-body').first().html(Messages.strDisplayHelp);
$('#helpModalLabel').first().html(Messages.strHelpTitle);
return false;
}
/**
* Extend the array object for max function
* @param {number[]} array
* @return {int}
**/
Array.max = function (array) {
return Math.max.apply(Math, array);
};
/**
* Extend the array object for min function
* @param {number[]} array
* @return {int}
**/
Array.min = function (array) {
return Math.min.apply(Math, array);
};
/**
* Checks if a string contains only numeric value
* @param {string} n (to be checked)
* @return {bool}
**/
function isNumeric(n) {
return !isNaN(parseFloat(n)) && isFinite(n);
}
/**
** Checks if an object is empty
* @param {object} obj (to be checked)
* @return {bool}
**/
function isEmpty(obj) {
var name;
for (name in obj) {
return false;
}
return true;
}
/**
* Converts a date/time into timestamp
* @param {string} val Date
* @param {string} type Field type(datetime/timestamp/time/date)
* @return {any} A value
**/
function getTimeStamp(val, type) {
if (type.toString().search(/datetime/i) !== -1 || type.toString().search(/timestamp/i) !== -1) {
return $.datepicker.parseDateTime('yy-mm-dd', 'HH:mm:ss', val);
} else if (type.toString().search(/time/i) !== -1) {
return $.datepicker.parseDateTime('yy-mm-dd', 'HH:mm:ss', '1970-01-01 ' + val);
} else if (type.toString().search(/date/i) !== -1) {
return $.datepicker.parseDate('yy-mm-dd', val);
}
}
/**
* Classifies the field type into numeric,timeseries or text
* @param {object} field field type (as in database structure)
* @return {'text'|'numeric'|'time'}
**/
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';
}
}
/**
* Unbind all event handlers before tearing down a page
*/
AJAX.registerTeardown('table/zoom_plot_jqplot.js', function () {
$('#tableid_0').off('change');
$('#tableid_1').off('change');
$('#tableid_2').off('change');
$('#tableid_3').off('change');
$('#inputFormSubmitId').off('click');
$('#togglesearchformlink').off('click');
$(document).off('keydown', '#dataDisplay :input');
$('button.button-reset').off('click');
$('div#resizer').off('resizestop');
$('div#querychart').off('jqplotDataClick');
});
AJAX.registerOnload('table/zoom_plot_jqplot.js', function () {
var currentChart = null;
var searchedDataKey = null;
var xLabel = $('#tableid_0').val();
var yLabel = $('#tableid_1').val();
// will be updated via Ajax
var xType = $('#types_0').val();
var yType = $('#types_1').val();
var dataLabel = $('#dataLabel').val();
// Get query result
var searchedData;
try {
searchedData = JSON.parse($('#querydata').html());
} catch (err) {
searchedData = null;
}
// adding event listener on select after AJAX request
var comparisonOperatorOnChange = function () {
var tableRows = $('#inputSection select.column-operator');
$.each(tableRows, function (index, item) {
$(item).on('change', function () {
changeValueFieldType(this, index);
verifyAfterSearchFieldChange(index, '#zoom_search_form');
});
});
};
/**
** Input form submit on field change
**/
// first column choice corresponds to the X axis
$('#tableid_0').on('change', function () {
// AJAX request for field type, collation, operators, and value field
$.post('index.php?route=/table/zoom-search', {
'ajax_request': true,
'change_tbl_info': true,
'server': CommonParams.get('server'),
'db': CommonParams.get('db'),
'table': CommonParams.get('table'),
'field': $('#tableid_0').val(),
'it': 0
}, function (data) {
$('#tableFieldsId').find('tr').eq(1).find('td').eq(0).html(data.field_type);
$('#tableFieldsId').find('tr').eq(1).find('td').eq(1).html(data.field_collation);
$('#tableFieldsId').find('tr').eq(1).find('td').eq(2).html(data.field_operators);
$('#tableFieldsId').find('tr').eq(1).find('td').eq(3).html(data.field_value);
xLabel = $('#tableid_0').val();
$('#types_0').val(data.field_type);
xType = data.field_type;
$('#collations_0').val(data.field_collations);
comparisonOperatorOnChange();
Functions.addDateTimePicker();
});
});
// second column choice corresponds to the Y axis
$('#tableid_1').on('change', function () {
// AJAX request for field type, collation, operators, and value field
$.post('index.php?route=/table/zoom-search', {
'ajax_request': true,
'change_tbl_info': true,
'server': CommonParams.get('server'),
'db': CommonParams.get('db'),
'table': CommonParams.get('table'),
'field': $('#tableid_1').val(),
'it': 1
}, function (data) {
$('#tableFieldsId').find('tr').eq(2).find('td').eq(0).html(data.field_type);
$('#tableFieldsId').find('tr').eq(2).find('td').eq(1).html(data.field_collation);
$('#tableFieldsId').find('tr').eq(2).find('td').eq(2).html(data.field_operators);
$('#tableFieldsId').find('tr').eq(2).find('td').eq(3).html(data.field_value);
yLabel = $('#tableid_1').val();
$('#types_1').val(data.field_type);
yType = data.field_type;
$('#collations_1').val(data.field_collations);
comparisonOperatorOnChange();
Functions.addDateTimePicker();
});
});
$('#tableid_2').on('change', function () {
// AJAX request for field type, collation, operators, and value field
$.post('index.php?route=/table/zoom-search', {
'ajax_request': true,
'change_tbl_info': true,
'server': CommonParams.get('server'),
'db': CommonParams.get('db'),
'table': CommonParams.get('table'),
'field': $('#tableid_2').val(),
'it': 2
}, function (data) {
$('#tableFieldsId').find('tr').eq(4).find('td').eq(0).html(data.field_type);
$('#tableFieldsId').find('tr').eq(4).find('td').eq(1).html(data.field_collation);
$('#tableFieldsId').find('tr').eq(4).find('td').eq(2).html(data.field_operators);
$('#tableFieldsId').find('tr').eq(4).find('td').eq(3).html(data.field_value);
$('#types_2').val(data.field_type);
$('#collations_2').val(data.field_collations);
comparisonOperatorOnChange();
Functions.addDateTimePicker();
});
});
$('#tableid_3').on('change', function () {
// AJAX request for field type, collation, operators, and value field
$.post('index.php?route=/table/zoom-search', {
'ajax_request': true,
'change_tbl_info': true,
'server': CommonParams.get('server'),
'db': CommonParams.get('db'),
'table': CommonParams.get('table'),
'field': $('#tableid_3').val(),
'it': 3
}, function (data) {
$('#tableFieldsId').find('tr').eq(5).find('td').eq(0).html(data.field_type);
$('#tableFieldsId').find('tr').eq(5).find('td').eq(1).html(data.field_collation);
$('#tableFieldsId').find('tr').eq(5).find('td').eq(2).html(data.field_operators);
$('#tableFieldsId').find('tr').eq(5).find('td').eq(3).html(data.field_value);
$('#types_3').val(data.field_type);
$('#collations_3').val(data.field_collations);
comparisonOperatorOnChange();
Functions.addDateTimePicker();
});
});
/**
* Input form validation
**/
$('#inputFormSubmitId').on('click', function () {
if ($('#tableid_0').get(0).selectedIndex === 0 || $('#tableid_1').get(0).selectedIndex === 0) {
Functions.ajaxShowMessage(Messages.strInputNull);
} else if (xLabel === yLabel) {
Functions.ajaxShowMessage(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(Messages.strShowSearchCriteria).on('click', function () {
var $link = $(this);
$('#zoom_search_form').slideToggle();
if ($link.text() === Messages.strHideSearchCriteria) {
$link.text(Messages.strShowSearchCriteria);
} else {
$link.text(Messages.strHideSearchCriteria);
}
// avoid default click action
return false;
});
/**
* Handle saving of a row in the editor
*/
var dataPointSave = function () {
// Find changed values by comparing form values with selectedRow Object
var newValues = {}; // Stores the values changed from original
var sqlTypes = {};
var it = 0;
var xChange = false;
var yChange = false;
var key;
var tempGetVal = function () {
return $(this).val();
};
for (key in selectedRow) {
var oldVal = selectedRow[key];
var newVal = $('#edit_fields_null_id_' + it).prop('checked') ? null : $('#edit_fieldID_' + it).val();
if (newVal instanceof Array) {
// when the column is of type SET
newVal = $('#edit_fieldID_' + it).map(tempGetVal).get().join(',');
}
if (oldVal !== newVal) {
selectedRow[key] = newVal;
newValues[key] = newVal;
if (key === xLabel) {
xChange = true;
searchedData[searchedDataKey][xLabel] = newVal;
} else if (key === yLabel) {
yChange = true;
searchedData[searchedDataKey][yLabel] = newVal;
}
}
var $input = $('#edit_fieldID_' + it);
if ($input.hasClass('bit')) {
sqlTypes[key] = 'bit';
} else {
sqlTypes[key] = null;
}
it++;
} // End data update
// Update the chart series and replot
if (xChange || yChange) {
// 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[searchedDataKey] = selectedRow[xLabel];
// [searchedDataKey][0] contains the x value
if (xType === 'numeric') {
series[0][searchedDataKey][0] = selectedRow[xLabel];
} else if (xType === 'time') {
series[0][searchedDataKey][0] = getTimeStamp(selectedRow[xLabel], $('#types_0').val());
} else {
series[0][searchedDataKey][0] = '';
// TODO: text values
}
currentChart.series[0].data = series[0];
// TODO: axis changing
currentChart.replot();
}
if (yChange) {
yCord[searchedDataKey] = selectedRow[yLabel];
// [searchedDataKey][1] contains the y value
if (yType === 'numeric') {
series[0][searchedDataKey][1] = selectedRow[yLabel];
} else if (yType === 'time') {
series[0][searchedDataKey][1] = getTimeStamp(selectedRow[yLabel], $('#types_1').val());
} else {
series[0][searchedDataKey][1] = '';
// TODO: text values
}
currentChart.series[0].data = series[0];
// TODO: axis changing
currentChart.replot();
}
} // End plot update
// Generate SQL query for update
if (!isEmpty(newValues)) {
var sqlQuery = 'UPDATE `' + CommonParams.get('table') + '` SET ';
for (key in newValues) {
sqlQuery += '`' + key + '`=';
var value = newValues[key];
// null
if (value === null) {
sqlQuery += 'NULL, ';
// empty
} else if (value.trim() === '') {
sqlQuery += '\'\', ';
// other
} else {
// type explicitly identified
if (sqlTypes[key] !== null) {
if (sqlTypes[key] === 'bit') {
sqlQuery += 'b\'' + value + '\', ';
}
// type not explicitly identified
} else {
if (!isNumeric(value)) {
sqlQuery += '\'' + value + '\', ';
} else {
sqlQuery += value + ', ';
}
}
}
}
// remove two extraneous characters ', '
sqlQuery = sqlQuery.substring(0, sqlQuery.length - 2);
sqlQuery += ' WHERE ' + Sql.urlDecode(searchedData[searchedDataKey].where_clause);
$.post('index.php?route=/sql', {
'server': CommonParams.get('server'),
'db': CommonParams.get('db'),
'ajax_request': true,
'sql_query': sqlQuery,
'inline_edit': false
}, function (data) {
if (typeof data !== 'undefined' && data.success === true) {
$('#sqlqueryresultsouter').html(data.sql_query);
Functions.highlightSql($('#sqlqueryresultsouter'));
} else {
Functions.ajaxShowMessage(data.error, false);
}
}); // End $.post
} // End database update
};
$('#dataPointSaveButton').on('click', function () {
dataPointSave();
});
$('#dataPointModalLabel').first().html(Messages.strDataPointContent);
/**
* Attach Ajax event handlers for input fields
* in the dialog. Used to submit the Ajax
* request when the ENTER key is pressed.
*/
$(document).on('keydown', '#dataDisplay :input', function (e) {
if (e.which === 13) {
// 13 is the ENTER key
e.preventDefault();
if (typeof dataPointSave === 'function') {
dataPointSave();
}
}
});
/*
* Generate plot using jqplot
*/
if (searchedData !== null) {
$('#zoom_search_form').slideToggle().hide();
$('#togglesearchformlink').text(Messages.strShowSearchCriteria);
$('#togglesearchformdiv').show();
var selectedRow;
var series = [];
var xCord = [];
var yCord = [];
var xVal;
var yVal;
var format;
var options = {
series: [
// for a scatter plot
{
showLine: false
}],
grid: {
drawBorder: false,
shadow: false,
background: 'rgba(0,0,0,0)'
},
axes: {
xaxis: {
label: $('#tableid_0').val(),
labelRenderer: $.jqplot.CanvasAxisLabelRenderer
},
yaxis: {
label: $('#tableid_1').val(),
labelRenderer: $.jqplot.CanvasAxisLabelRenderer
}
},
highlighter: {
show: true,
tooltipAxes: 'y',
yvalues: 2,
// hide the first y value
formatString: '<span class="hide">%s</span>%s'
},
cursor: {
show: true,
zoom: true,
showTooltip: false
}
};
// If data label is not set, do not show tooltips
if (dataLabel === '') {
options.highlighter.show = false;
}
// Classify types as either numeric,time,text
xType = getType(xType);
yType = getType(yType);
// could have multiple series but we'll have just one
series[0] = [];
if (xType === 'time') {
var originalXType = $('#types_0').val();
if (originalXType === 'date') {
format = '%Y-%m-%d';
}
// TODO: does not seem to work
// else if (originalXType === 'time') {
// format = '%H:%M';
// } else {
// format = '%Y-%m-%d %H:%M';
// }
$.extend(options.axes.xaxis, {
renderer: $.jqplot.DateAxisRenderer,
tickOptions: {
formatString: format
}
});
}
if (yType === 'time') {
var originalYType = $('#types_1').val();
if (originalYType === 'date') {
format = '%Y-%m-%d';
}
$.extend(options.axes.yaxis, {
renderer: $.jqplot.DateAxisRenderer,
tickOptions: {
formatString: format
}
});
}
$.each(searchedData, function (key, value) {
if (xType === 'numeric') {
xVal = parseFloat(value[xLabel]);
}
if (xType === 'time') {
xVal = getTimeStamp(value[xLabel], originalXType);
}
if (yType === 'numeric') {
yVal = parseFloat(value[yLabel]);
}
if (yType === 'time') {
yVal = getTimeStamp(value[yLabel], originalYType);
}
series[0].push([xVal, yVal,
// extra Y values
value[dataLabel],
// for highlighter
// (may set an undefined value)
value.where_clause,
// for click on point
key,
// key from searchedData
value.where_clause_sign]);
});
// under IE 8, the initial display is mangled; after a manual
// resizing, it's ok
// under IE 9, everything is fine
currentChart = $.jqplot('querychart', series, options);
currentChart.resetZoom();
$('button.button-reset').on('click', function (event) {
event.preventDefault();
currentChart.resetZoom();
});
$('div#resizer').resizable();
$('div#resizer').on('resizestop', function () {
// make room so that the handle will still appear
$('div#querychart').height($('div#resizer').height() * 0.96);
$('div#querychart').width($('div#resizer').width() * 0.96);
currentChart.replot({
resetAxes: true
});
});
$('div#querychart').on('jqplotDataClick', function (event, seriesIndex, pointIndex, data) {
searchedDataKey = data[4]; // key from searchedData (global)
var fieldId = 0;
var postParams = {
'ajax_request': true,
'get_data_row': true,
'server': CommonParams.get('server'),
'db': CommonParams.get('db'),
'table': CommonParams.get('table'),
'where_clause': data[3],
'where_clause_sign': data[5]
};
$.post('index.php?route=/table/zoom-search', postParams, function (data) {
// Row is contained in data.row_info,
// now fill the displayResultForm with row values
var key;
for (key in data.row_info) {
var $field = $('#edit_fieldID_' + fieldId);
var $fieldNull = $('#edit_fields_null_id_' + fieldId);
if (data.row_info[key] === null) {
$fieldNull.prop('checked', true);
$field.val('');
} else {
$fieldNull.prop('checked', false);
if ($field.attr('multiple')) {
// when the column is of type SET
$field.val(data.row_info[key].split(','));
} else {
$field.val(data.row_info[key]);
}
}
fieldId++;
}
selectedRow = data.row_info;
});
$('#dataPointModal').modal('show');
});
}
$('#help_dialog').on('click', function () {
displayHelp();
});
});