import { AJAX } from './ajax';
import CommonParams from './variables/common_params';
import { PMA_Messages as PMA_messages } from './variables/export_variables';
import { PMA_prepareForAjaxRequest } from './functions/AjaxRequest';
import { PMA_ajaxShowMessage, PMA_ajaxRemoveMessage } from './utils/show_ajax_messages';
import PMA_MicroHistory from './classes/MicroHistory';
import { PMA_commonActions } from './classes/CommonActions';
// Sql based imports
import { PMA_getSQLEditor, bindCodeMirrorToInlineEditor } from './functions/Sql/SqlEditor';
import { sqlQueryOptions, updateQueryParameters, PMA_highlightSQL } from './utils/sql';
import { PMA_handleSimulateQueryButton, insertQuery, checkSqlQuery } from './functions/Sql/SqlQuery';
import { escapeHtml } from './utils/Sanitise';
import { getForeignKeyCheckboxLoader, loadForeignKeyCheckbox } from './functions/Sql/ForeignKey';
import { PMA_previewSQL } from './functions/Sql/PreviewSql';
// Create Table based imports
import { checkTableEditForm, PMA_checkReservedWordColumns } from './functions/Table/CreateTable';
import { PMA_adjustTotals } from './functions/Database/Structure';
import { PMA_verifyColumnsProperties, PMA_hideShowConnection } from './functions/Table/TableColumns';
import { addDateTimePicker } from './utils/DateTime';
/**
* Here we register a function that will remove the onsubmit event from all
* forms that will be handled by the generic page loader. We then save this
* event handler in the "jQuery data", so that we can fire it up later in
* AJAX.requestHandler().
*
* See bug #3583316
*/
export function onload () {
// Registering the onload event for functions.js
// ensures that it will be fired for all pages
$('form').not('.ajax').not('.disableAjax').each(function () {
if ($(this).attr('onsubmit')) {
$(this).data('onsubmit', this.onsubmit).attr('onsubmit', '');
}
});
var $page_content = $('#page_content');
/**
* Workaround for passing submit button name,value on ajax form submit
* by appending hidden element with submit button name and value.
*/
$page_content.on('click', 'form input[type=submit]', function () {
var buttonName = $(this).attr('name');
if (typeof buttonName === 'undefined') {
return;
}
$(this).closest('form').append($('<input/>', {
'type' : 'hidden',
'name' : buttonName,
'value': $(this).val()
}));
});
/**
* Attach event listener to events when user modify visible
* Input,Textarea and select fields to make changes in forms
*/
$page_content.on(
'keyup change',
'form.lock-page textarea, ' +
'form.lock-page input[type="text"], ' +
'form.lock-page input[type="number"], ' +
'form.lock-page select',
{ value:1 },
AJAX.lockPageHandler
);
$page_content.on(
'change',
'form.lock-page input[type="checkbox"], ' +
'form.lock-page input[type="radio"]',
{ value:2 },
AJAX.lockPageHandler
);
/**
* Reset lock when lock-page form reset event is fired
* Note: reset does not bubble in all browser so attach to
* form directly.
*/
$('form.lock-page').on('reset', function (event) {
AJAX.resetLock();
});
}
/**
* Unbind all event handlers before tearing down a page
*/
export function teardown1 () {
$(document).off('click', 'a.themeselect');
$(document).off('change', '.autosubmit');
$('a.take_theme').off('click');
}
export function onload1 () {
/**
* Theme selector.
*/
$(document).on('click', 'a.themeselect', function (e) {
window.open(
e.target,
'themes',
'left=10,top=20,width=510,height=350,scrollbars=yes,status=yes,resizable=yes'
);
return false;
});
/**
* Automatic form submission on change.
*/
$(document).on('change', '.autosubmit', function (e) {
$(this).closest('form').submit();
});
/**
* Theme changer.
*/
$('a.take_theme').on('click', function (e) {
var what = this.name;
if (window.opener && window.opener.document.forms.setTheme.elements.set_theme) {
window.opener.document.forms.setTheme.elements.set_theme.value = what;
window.opener.document.forms.setTheme.submit();
window.close();
return false;
}
return true;
});
}
/* *************************************** CODEMIRROR EDITOR START *************************************** */
/**
* Attach CodeMirror2 editor to SQL edit area.
*/
export function onloadSqlEditor () {
var $elm = $('#sqlquery');
if ($elm.length > 0) {
if (CommonParams.get('CodemirrorEnable') === true) {
sqlQueryOptions.codemirror_editor = PMA_getSQLEditor($elm);
sqlQueryOptions.codemirror_editor.focus();
sqlQueryOptions.codemirror_editor.on('blur', updateQueryParameters);
} else {
// without codemirror
$elm.focus().on('blur', updateQueryParameters);
}
}
PMA_highlightSQL($('body'));
}
export function teardownSqlEditor () {
if (sqlQueryOptions.codemirror_editor) {
$('#sqlquery').text(sqlQueryOptions.codemirror_editor.getValue());
sqlQueryOptions.codemirror_editor.toTextArea();
sqlQueryOptions.codemirror_editor = false;
}
}
/**
* Unbind all event handlers before tearing down a page
*/
export function teardownSqlInlineEditor () {
$(document).off('click', 'a.inline_edit_sql');
$(document).off('click', 'input#sql_query_edit_save');
$(document).off('click', 'input#sql_query_edit_discard');
$('input.sqlbutton').off('click');
if (sqlQueryOptions.codemirror_editor) {
sqlQueryOptions.codemirror_editor.off('blur');
} else {
$(document).off('blur', '#sqlquery');
}
$(document).off('change', '#parameterized');
$(document).off('click', 'input.sqlbutton');
$('#sqlquery').off('keydown');
$('#sql_query_edit').off('keydown');
if (sqlQueryOptions.codemirror_inline_editor) {
// Copy the sql query to the text area to preserve it.
$('#sql_query_edit').text(sqlQueryOptions.codemirror_inline_editor.getValue());
$(sqlQueryOptions.codemirror_inline_editor.getWrapperElement()).off('keydown');
sqlQueryOptions.codemirror_inline_editor.toTextArea();
sqlQueryOptions.codemirror_inline_editor = false;
}
if (sqlQueryOptions.codemirror_editor) {
$(sqlQueryOptions.codemirror_editor.getWrapperElement()).off('keydown');
}
}
/**
* Jquery Coding for inline editing SQL_QUERY
*/
export function onloadSqlInlineEditor () {
// If we are coming back to the page by clicking forward button
// of the browser, bind the code mirror to inline query editor.
bindCodeMirrorToInlineEditor();
$(document).on('click', 'a.inline_edit_sql', function () {
if ($('#sql_query_edit').length) {
// An inline query editor is already open,
// we don't want another copy of it
return false;
}
var $form = $(this).prev('form');
var sql_query = $form.find('input[name=\'sql_query\']').val().trim();
var $inner_sql = $(this).parent().prev().find('code.sql');
var old_text = $inner_sql.html();
var new_content = '<textarea name="sql_query_edit" id="sql_query_edit">' + escapeHtml(sql_query) + '</textarea>\n';
new_content += getForeignKeyCheckboxLoader();
new_content += '<input type="submit" id="sql_query_edit_save" class="button btnSave" value="' + PMA_messages.strGo + '"/>\n';
new_content += '<input type="button" id="sql_query_edit_discard" class="button btnDiscard" value="' + PMA_messages.strCancel + '"/>\n';
var $editor_area = $('div#inline_editor');
if ($editor_area.length === 0) {
$editor_area = $('<div id="inline_editor_outer"></div>');
$editor_area.insertBefore($inner_sql);
}
$editor_area.html(new_content);
loadForeignKeyCheckbox();
$inner_sql.hide();
bindCodeMirrorToInlineEditor();
return false;
});
$(document).on('click', 'input#sql_query_edit_save', function (e) {
// hide already existing success message
var sql_query;
if (sqlQueryOptions.codemirror_inline_editor) {
sqlQueryOptions.codemirror_inline_editor.save();
sql_query = sqlQueryOptions.codemirror_inline_editor.getValue();
} else {
sql_query = $(this).parent().find('#sql_query_edit').val();
}
var fk_check = $(this).parent().find('#fk_checks').is(':checked');
var $form = $('a.inline_edit_sql').prev('form');
var $fake_form = $('<form>', { action: 'import.php', method: 'post' })
.append($form.find('input[name=server], input[name=db], input[name=table], input[name=token]').clone())
.append($('<input/>', { type: 'hidden', name: 'show_query', value: 1 }))
.append($('<input/>', { type: 'hidden', name: 'is_js_confirmed', value: 0 }))
.append($('<input/>', { type: 'hidden', name: 'sql_query', value: sql_query }))
.append($('<input/>', { type: 'hidden', name: 'fk_checks', value: fk_check ? 1 : 0 }));
if (! checkSqlQuery($fake_form[0])) {
return false;
}
$('.success').hide();
$fake_form.appendTo($('body')).submit();
});
$(document).on('click', 'input#sql_query_edit_discard', function () {
var $divEditor = $('div#inline_editor_outer');
$divEditor.siblings('code.sql').show();
$divEditor.remove();
});
$(document).on('click', 'input.sqlbutton', function (evt) {
insertQuery(evt.target.id);
PMA_handleSimulateQueryButton();
return false;
});
$(document).on('change', '#parameterized', updateQueryParameters);
var $inputUsername = $('#input_username');
if ($inputUsername) {
if ($inputUsername.val() === '') {
$inputUsername.trigger('focus');
} else {
$('#input_password').trigger('focus');
}
}
}
/* *************************************** CODEMIRROR EDITOR ENDS *************************************** */
/**
* Unbind all event handlers before tearing down a page
*/
export function teardownCtrlEnterFormSubmit () {
$(document).off('keydown', 'form input, form textarea, form select');
}
export function onloadCtrlEnterFormSubmit () {
/**
* Handle 'Ctrl/Alt + Enter' form submits
*/
$('form input, form textarea, form select').on('keydown', function (e) {
if ((e.ctrlKey && e.which === 13) || (e.altKey && e.which === 13)) {
var $form = $(this).closest('form');
if (! $form.find('input[type="submit"]') ||
! $form.find('input[type="submit"]').trigger('click')
) {
$form.submit();
}
}
});
}
/* *************************************** CREATE TABLE STARTS *************************************** */
/**
* Unbind all event handlers before tearing down a page
*/
export function teardownCreateTable () {
$(document).off('submit', '#create_table_form_minimal.ajax');
$(document).off('submit', 'form.create_table_form.ajax');
$(document).off('click', 'form.create_table_form.ajax input[name=submit_num_fields]');
$(document).off('keyup', 'form.create_table_form.ajax input');
$(document).off('change', 'input[name=partition_count],input[name=subpartition_count],select[name=partition_by]');
}
/**
* jQuery coding for 'Create Table'. Used on db_operations.php,
* db_structure.php and db_tracking.php (i.e., wherever
* PhpMyAdmin\Display\CreateTable is used)
*
* Attach Ajax Event handlers for Create Table
*/
export function onloadCreateTable () {
/**
* Attach event handler for submission of create table form (save)
*/
$(document).on('submit', 'form.create_table_form.ajax', function (event) {
event.preventDefault();
/**
* @var the_form object referring to the create table form
*/
var $form = $(this);
/*
* First validate the form; if there is a problem, avoid submitting it
*
* 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 (checkTableEditForm($form[0], $form.find('input[name=orig_num_fields]').val())) {
PMA_prepareForAjaxRequest($form);
if (PMA_checkReservedWordColumns($form)) {
PMA_ajaxShowMessage(PMA_messages.strProcessingRequest);
// User wants to submit the form
$.post($form.attr('action'), $form.serialize() + CommonParams.get('arg_separator') + 'do_save_data=1', function (data) {
if (typeof data !== 'undefined' && data.success === true) {
$('#properties_message')
.removeClass('error')
.html('');
PMA_ajaxShowMessage(data.message);
// Only if the create table dialog (distinct panel) exists
var $createTableDialog = $('#create_table_dialog');
if ($createTableDialog.length > 0) {
$createTableDialog.dialog('close').remove();
}
$('#tableslistcontainer').before(data.formatted_sql);
/**
* @var tables_table Object referring to the <tbody> element that holds the list of tables
*/
var tables_table = $('#tablesForm').find('tbody').not('#tbl_summary_row');
// this is the first table created in this db
if (tables_table.length === 0) {
PMA_commonActions.refreshMain(
CommonParams.get('opendb_url')
);
} else {
/**
* @var curr_last_row Object referring to the last <tr> element in {@link tables_table}
*/
var curr_last_row = $(tables_table).find('tr:last');
/**
* @var curr_last_row_index_string String containing the index of {@link curr_last_row}
*/
var curr_last_row_index_string = $(curr_last_row).find('input:checkbox').attr('id').match(/\d+/)[0];
/**
* @var curr_last_row_index Index of {@link curr_last_row}
*/
var curr_last_row_index = parseFloat(curr_last_row_index_string);
/**
* @var new_last_row_index Index of the new row to be appended to {@link tables_table}
*/
var new_last_row_index = curr_last_row_index + 1;
/**
* @var new_last_row_id String containing the id of the row to be appended to {@link tables_table}
*/
var new_last_row_id = 'checkbox_tbl_' + new_last_row_index;
data.new_table_string = data.new_table_string.replace(/checkbox_tbl_/, new_last_row_id);
// append to table
$(data.new_table_string)
.appendTo(tables_table);
// Sort the table
$(tables_table).PMA_sort_table('th');
// Adjust summary row
PMA_adjustTotals();
}
// Refresh navigation as a new table has been added
PMA_reloadNavigation();
// Redirect to table structure page on creation of new table
var argsep = CommonParams.get('arg_separator');
var params_12 = 'ajax_request=true' + argsep + 'ajax_page_request=true';
if (! (history && history.pushState)) {
params_12 += PMA_MicroHistory.menus.getRequestParam();
}
var tblStruct_url = 'tbl_structure.php?server=' + data._params.server +
argsep + 'db=' + data._params.db + argsep + 'token=' + data._params.token +
argsep + 'goto=db_structure.php' + argsep + 'table=' + data._params.table + '';
$.get(tblStruct_url, params_12, AJAX.responseHandler);
} else {
PMA_ajaxShowMessage(
'<div class="error">' + data.error + '</div>',
false
);
}
}); // end $.post()
}
} // end if (checkTableEditForm() )
}); // end create table form (save)
/**
* Submits the intermediate changes in the table creation form
* to refresh the UI accordingly
*/
function submitChangesInCreateTableForm (actionParam) {
/**
* @var the_form object referring to the create table form
*/
var $form = $('form.create_table_form.ajax');
var $msgbox = PMA_ajaxShowMessage(PMA_messages.strProcessingRequest);
PMA_prepareForAjaxRequest($form);
// User wants to add more fields to the table
$.post($form.attr('action'), $form.serialize() + '&' + actionParam, function (data) {
if (typeof data !== 'undefined' && data.success) {
var $pageContent = $('#page_content');
$pageContent.html(data.message);
PMA_highlightSQL($pageContent);
PMA_verifyColumnsProperties();
PMA_hideShowConnection($('.create_table_form select[name=tbl_storage_engine]'));
PMA_ajaxRemoveMessage($msgbox);
} else {
PMA_ajaxShowMessage(data.error);
}
}); // end $.post()
}
/**
* Attach event handler for create table form (add fields)
*/
$(document).on('click', 'form.create_table_form.ajax input[name=submit_num_fields]', function (event) {
event.preventDefault();
submitChangesInCreateTableForm('submit_num_fields=1');
}); // end create table form (add fields)
$(document).on('keydown', 'form.create_table_form.ajax input[name=added_fields]', function (event) {
if (event.keyCode === 13) {
event.preventDefault();
event.stopImmediatePropagation();
$(this)
.closest('form')
.find('input[name=submit_num_fields]')
.trigger('click');
}
});
/**
* Attach event handler to manage changes in number of partitions and subpartitions
*/
$(document).on('change', 'input[name=partition_count],input[name=subpartition_count],select[name=partition_by]', function (event) {
var $this = $(this);
var $form = $this.parents('form');
if ($form.is('.create_table_form.ajax')) {
submitChangesInCreateTableForm('submit_partition_change=1');
} else {
$form.submit();
}
});
$(document).on('change', 'input[value=AUTO_INCREMENT]', function () {
if (this.checked) {
var col = /\d/.exec($(this).attr('name'));
col = col[0];
var $selectFieldKey = $('select[name="field_key[' + col + ']"]');
if ($selectFieldKey.val() === 'none_' + col) {
$selectFieldKey.val('primary_' + col).trigger('change');
}
}
});
$('body')
.off('click', 'input.preview_sql')
.on('click', 'input.preview_sql', function () {
var $form = $(this).closest('form');
PMA_previewSQL($form);
});
}
/* *************************************** CREATE TABLE STARTS *************************************** */
/* ************************************** HANDLE CHECKALL CLICK ************************************** */
/**
* True if last click is to check a row.
*/
var last_click_checked = false;
/**
* Zero-based index of last clicked row.
* Used to handle the shift + click event in the code above.
*/
var last_clicked_row = -1;
/**
* Zero-based index of last shift clicked row.
*/
var last_shift_clicked_row = -1;
/**
* Unbind all event handlers before tearing down a page
*/
export function teadownFunctions () {
$(document).off('click', 'input:checkbox.checkall');
}
export function onloadFunctions () {
/**
* Row marking in horizontal mode (use "on" so that it works also for
* next pages reached via AJAX); a tr may have the class noclick to remove
* this behavior.
*/
$(document).on('click', 'input:checkbox.checkall', function (e) {
var $this = $(this);
var $tr = $this.closest('tr');
var $table = $this.closest('table');
if (!e.shiftKey || last_clicked_row === -1) {
// usual click
var $checkbox = $tr.find(':checkbox.checkall');
var checked = $this.prop('checked');
$checkbox.prop('checked', checked).trigger('change');
if (checked) {
$tr.addClass('marked');
} else {
$tr.removeClass('marked');
}
last_click_checked = checked;
// remember the last clicked row
last_clicked_row = last_click_checked ? $table.find('tr:not(.noclick)').index($tr) : -1;
last_shift_clicked_row = -1;
} else {
// handle the shift click
PMA_clearSelection();
var start;
var end;
// clear last shift click result
if (last_shift_clicked_row >= 0) {
if (last_shift_clicked_row >= last_clicked_row) {
start = last_clicked_row;
end = last_shift_clicked_row;
} else {
start = last_shift_clicked_row;
end = last_clicked_row;
}
$tr.parent().find('tr:not(.noclick)')
.slice(start, end + 1)
.removeClass('marked')
.find(':checkbox')
.prop('checked', false)
.trigger('change');
}
// handle new shift click
var curr_row = $table.find('tr:not(.noclick)').index($tr);
if (curr_row >= last_clicked_row) {
start = last_clicked_row;
end = curr_row;
} else {
start = curr_row;
end = last_clicked_row;
}
$tr.parent().find('tr:not(.noclick)')
.slice(start, end)
.addClass('marked')
.find(':checkbox')
.prop('checked', true)
.trigger('change');
// remember the last shift clicked row
last_shift_clicked_row = curr_row;
}
});
addDateTimePicker();
/**
* Add attribute to text boxes for iOS devices (based on bugID: 3508912)
*/
if (navigator.userAgent.match(/(iphone|ipod|ipad)/i)) {
$('input[type=text]').attr('autocapitalize', 'off').attr('autocorrect', 'off');
}
}
/* ************************************** HANDLE CHECKALL CLICK ************************************** */