From 747bf54f99f144f84b544ce242b103d6ee73a43d Mon Sep 17 00:00:00 2001 From: Piyush Vijay Date: Fri, 7 Sep 2018 18:24:57 +0530 Subject: [PATCH 1/8] Add KeyHandler and CrossFramingProtection file in modular code. Signed-Off-By: Piyush Vijay --- js/src/consts/files.js | 16 +++- js/src/cross_framing_protection.js | 16 ++++ js/src/functions/KeyHandler.js | 126 +++++++++++++++++++++++++++++ js/src/key_handler.js | 28 +++++++ libraries/classes/Header.php | 4 +- 5 files changed, 186 insertions(+), 4 deletions(-) create mode 100644 js/src/cross_framing_protection.js create mode 100644 js/src/functions/KeyHandler.js create mode 100644 js/src/key_handler.js diff --git a/js/src/consts/files.js b/js/src/consts/files.js index 22072897f9..4b58350181 100644 --- a/js/src/consts/files.js +++ b/js/src/consts/files.js @@ -7,7 +7,17 @@ * @type {Object} files */ const PhpToJsFileMapping = { - global: ['error_report', 'config', 'navigation', 'page_settings', 'shortcuts_handler', 'functions', 'indexes'], + global: [ + 'error_report', + 'config', + 'navigation', + 'page_settings', + 'shortcuts_handler', + 'functions', + 'indexes', + 'key_handler', + 'cross_framing_protection' + ], server_privileges: ['server_privileges'], server_databases: ['server_databases'], server_status_advisor: ['server_status_advisor'], @@ -84,7 +94,9 @@ const JsFileList = [ 'tbl_tracking', 'tbl_change', 'tbl_select', - 'tbl_find_replace' + 'tbl_find_replace', + 'key_handler', + 'cross_framing_protection' ]; export { diff --git a/js/src/cross_framing_protection.js b/js/src/cross_framing_protection.js new file mode 100644 index 0000000000..173295d1b5 --- /dev/null +++ b/js/src/cross_framing_protection.js @@ -0,0 +1,16 @@ +/* vim: set expandtab sw=4 ts=4 sts=4: */ + +/** + * Conditionally included if framing is not allowed + */ + +if (self === top) { + var styleElement = document.getElementById('cfs-style'); + // check if styleElement has already been removed + // to avoid frequently reported js error + if (typeof(styleElement) !== 'undefined' && styleElement !== null) { + styleElement.parentNode.removeChild(styleElement); + } +} else { + top.location = self.location; +} diff --git a/js/src/functions/KeyHandler.js b/js/src/functions/KeyHandler.js new file mode 100644 index 0000000000..d62a396697 --- /dev/null +++ b/js/src/functions/KeyHandler.js @@ -0,0 +1,126 @@ +/* vim: set expandtab sw=4 ts=4 sts=4: */ + +// global var that holds: 0- if ctrl key is not pressed 1- if ctrl key is pressed +var ctrlKeyHistory = 0; + +/** + * Allows moving around inputs/select by Ctrl+arrows + * + * @param object event data + */ +export function onKeyDownArrowsHandler (e) { + e = e || window.event; + + var o = (e.srcElement || e.target); + if (!o) { + return; + } + if (o.tagName !== 'TEXTAREA' && o.tagName !== 'INPUT' && o.tagName !== 'SELECT') { + return; + } + if ((e.which !== 17) && (e.which !== 37) && (e.which !== 38) && (e.which !== 39) && (e.which !== 40)) { + return; + } + if (!o.id) { + return; + } + + if (e.type === 'keyup') { + if (e.which === 17) { + ctrlKeyHistory = 0; + } + return; + } else if (e.type === 'keydown') { + if (e.which === 17) { + ctrlKeyHistory = 1; + } + } + + if (ctrlKeyHistory !== 1) { + return; + } + + e.preventDefault(); + + var pos = o.id.split('_'); + if (pos[0] !== 'field' || typeof pos[2] === 'undefined') { + return; + } + + var x = pos[2]; + var y = pos[1]; + + switch (e.keyCode) { + case 38: + // up + y--; + break; + case 40: + // down + y++; + break; + case 37: + // left + x--; + break; + case 39: + // right + x++; + break; + default: + return; + } + + var isFirefox = navigator.userAgent.toLowerCase().indexOf('firefox/') > -1; + + var id = 'field_' + y + '_' + x; + + var nO = document.getElementById(id); + if (! nO) { + id = 'field_' + y + '_' + x + '_0'; + nO = document.getElementById(id); + } + + // skip non existent fields + if (! nO) { + return; + } + + // for firefox select tag + var lvalue = o.selectedIndex; + var nOvalue = nO.selectedIndex; + + nO.focus(); + + if (isFirefox) { + var ffcheck = 0; + var ffversion; + for (ffversion = 3 ; ffversion < 25 ; ffversion++) { + var isFirefoxV24 = navigator.userAgent.toLowerCase().indexOf('firefox/' + ffversion) > -1; + if (isFirefoxV24) { + ffcheck = 1; + break; + } + } + if (ffcheck === 1) { + if (e.which === 38 || e.which === 37) { + nOvalue++; + } else if (e.which === 40 || e.which === 39) { + nOvalue--; + } + nO.selectedIndex = nOvalue; + } else { + if (e.which === 38 || e.which === 37) { + lvalue++; + } else if (e.which === 40 || e.which === 39) { + lvalue--; + } + o.selectedIndex = lvalue; + } + } + + if (nO.tagName !== 'SELECT') { + nO.select(); + } + e.returnValue = false; +} diff --git a/js/src/key_handler.js b/js/src/key_handler.js new file mode 100644 index 0000000000..b5783b021f --- /dev/null +++ b/js/src/key_handler.js @@ -0,0 +1,28 @@ +/* vim: set expandtab sw=4 ts=4 sts=4: */ + +/** + * Module import + */ +import { onKeyDownArrowsHandler } from './functions/KeyHandler'; + +function teardownKeyhandler () { + $(document).off('keydown keyup', '#table_columns'); + $(document).off('keydown keyup', 'table.insertRowTable'); +} + +function onloadKeyhandler () { + $(document).on('keydown keyup', '#table_columns', function (event) { + onKeyDownArrowsHandler(event.originalEvent); + }); + $(document).on('keydown keyup', 'table.insertRowTable', function (event) { + onKeyDownArrowsHandler(event.originalEvent); + }); +} + +/** + * Module export + */ +export { + teardownKeyhandler, + onloadKeyhandler +}; diff --git a/libraries/classes/Header.php b/libraries/classes/Header.php index 20189e42c6..32ccba56f9 100644 --- a/libraries/classes/Header.php +++ b/libraries/classes/Header.php @@ -184,10 +184,10 @@ class Header $this->_scripts->addFile('messages.php', array('l' => $GLOBALS['lang'])); $this->_scripts->addFile('vendors~index_new.js'); $this->_scripts->addFile('index_new.js'); - $this->_scripts->addFile('keyhandler.js'); + $this->_scripts->addFile('key_handler'); // Cross-framing protection if ($GLOBALS['cfg']['AllowThirdPartyFraming'] === false) { - $this->_scripts->addFile('cross_framing_protection.js'); + $this->_scripts->addFile('cross_framing_protection'); } $this->_scripts->addFile('rte.js'); if ($GLOBALS['cfg']['SendErrorReports'] !== 'never') { From 66ddb3a6afaa5351a2df3265f79495beccb2a51d Mon Sep 17 00:00:00 2001 From: Piyush Vijay Date: Fri, 7 Sep 2018 18:56:52 +0530 Subject: [PATCH 2/8] Add Drag and Drop Import in modular code. Signed-Off-By: Piyush Vijay --- js/src/classes/DragDropImport.js | 363 +++++++++++++++++++++++++++++++ js/src/consts/files.js | 6 +- js/src/drag_drop_import.js | 59 +++++ libraries/classes/Header.php | 2 +- 4 files changed, 427 insertions(+), 3 deletions(-) create mode 100644 js/src/classes/DragDropImport.js create mode 100644 js/src/drag_drop_import.js diff --git a/js/src/classes/DragDropImport.js b/js/src/classes/DragDropImport.js new file mode 100644 index 0000000000..14d25f3e0d --- /dev/null +++ b/js/src/classes/DragDropImport.js @@ -0,0 +1,363 @@ +/* vim: set expandtab sw=4 ts=4 sts=4: */ + + +/** + * Module import + */ +import { PMA_Messages as PMA_messages } from '../variables/export_variables'; +import PMA_commonParams from '../variables/common_params'; +import { escapeHtml } from '../utils/Sanitise'; +import { AJAX } from '../ajax'; + +/** + * Class to handle PMA Drag and Drop Import + * feature + */ +var DragDropImport = { + /** + * @var int, count of total uploads in this view + */ + uploadCount: 0, + /** + * @var int, count of live uploads + */ + liveUploadCount: 0, + /** + * @var string array, allowed extensions + */ + allowedExtensions: ['sql', 'xml', 'ldi', 'mediawiki', 'shp'], + /** + * @var string array, allowed extensions for compressed files + */ + allowedCompressedExtensions: ['gz', 'bz2', 'zip'], + /** + * @var obj array to store message returned by import_status.php + */ + importStatus: [], + /** + * Checks if any dropped file has valid extension or not + * + * @param file filename + * + * @return string, extension for valid extension, '' otherwise + */ + _getExtension: function (file) { + var arr = file.split('.'); + var ext = arr[arr.length - 1]; + + // check if compressed + if (jQuery.inArray(ext.toLowerCase(), + DragDropImport.allowedCompressedExtensions) !== -1) { + ext = arr[arr.length - 2]; + } + + // Now check for extension + if (jQuery.inArray(ext.toLowerCase(), + DragDropImport.allowedExtensions) !== -1) { + return ext; + } + return ''; + }, + /** + * Shows upload progress for different sql uploads + * + * @param: hash (string), hash for specific file upload + * @param: percent (float), file upload percentage + * + * @return void + */ + _setProgress: function (hash, percent) { + $('.pma_sql_import_status div li[data-hash="' + hash + '"]') + .children('progress').val(percent); + }, + /** + * Function to upload the file asynchronously + * + * @param formData FormData object for a specific file + * @param hash hash of the current file upload + * + * @return void + */ + _sendFileToServer: function (formData, hash) { + var uploadURL = './import.php'; // Upload URL + var extraData = {}; + var jqXHR = $.ajax({ + xhr: function () { + var xhrobj = $.ajaxSettings.xhr(); + if (xhrobj.upload) { + xhrobj.upload.addEventListener('progress', function (event) { + var percent = 0; + var position = event.loaded || event.position; + var total = event.total; + if (event.lengthComputable) { + percent = Math.ceil(position / total * 100); + } + // Set progress + DragDropImport._setProgress(hash, percent); + }, false); + } + return xhrobj; + }, + url: uploadURL, + type: 'POST', + contentType:false, + processData: false, + cache: false, + data: formData, + success: function (data) { + DragDropImport._importFinished(hash, false, data.success); + if (!data.success) { + DragDropImport.importStatus[DragDropImport.importStatus.length] = { + hash: hash, + message: data.error + }; + } + } + }); + + // -- provide link to cancel the upload + $('.pma_sql_import_status div li[data-hash="' + hash + + '"] span.filesize').html('' + + PMA_messages.dropImportMessageCancel + ''); + + // -- add event listener to this link to abort upload operation + $('.pma_sql_import_status div li[data-hash="' + hash + + '"] span.filesize span.pma_drop_file_status') + .on('click', function () { + if ($(this).attr('task') === 'cancel') { + jqXHR.abort(); + $(this).html('' + PMA_messages.dropImportMessageAborted + ''); + DragDropImport._importFinished(hash, true, false); + } else if ($(this).children('span').html() === + PMA_messages.dropImportMessageFailed) { + // -- view information + var $this = $(this); + $.each(DragDropImport.importStatus, + function (key, value) { + if (value.hash === hash) { + $('.pma_drop_result:visible').remove(); + var filename = $this.parent('span').attr('data-filename'); + $('body').append('

' + + PMA_messages.dropImportImportResultHeader + ' - ' + + filename + 'x

' + value.message + '
'); + $('.pma_drop_result').draggable(); // to make this dialog draggable + } + }); + } + }); + }, + /** + * Triggered when an object is dragged into the PMA UI + * + * @param event obj + * + * @return void + */ + _dragenter : function (event) { + // We don't want to prevent users from using + // browser's default drag-drop feature on some page(s) + if ($('.noDragDrop').length !== 0) { + return; + } + + event.stopPropagation(); + event.preventDefault(); + if (!DragDropImport._hasFiles(event)) { + return; + } + if (PMA_commonParams.get('db') === '') { + $('.pma_drop_handler').html(PMA_messages.dropImportSelectDB); + } else { + $('.pma_drop_handler').html(PMA_messages.dropImportDropFiles); + } + $('.pma_drop_handler').fadeIn(); + }, + /** + * Check if dragged element contains Files + * + * @param event the event object + * + * @return bool + */ + _hasFiles: function (event) { + return !(typeof event.originalEvent.dataTransfer.types === 'undefined' || + $.inArray('Files', event.originalEvent.dataTransfer.types) < 0 || + $.inArray( + 'application/x-moz-nativeimage', + event.originalEvent.dataTransfer.types + ) >= 0); + }, + /** + * Triggered when dragged file is being dragged over PMA UI + * + * @param event obj + * + * @return void + */ + _dragover: function (event) { + // We don't want to prevent users from using + // browser's default drag-drop feature on some page(s) + if ($('.noDragDrop').length !== 0) { + return; + } + + event.stopPropagation(); + event.preventDefault(); + if (!DragDropImport._hasFiles(event)) { + return; + } + $('.pma_drop_handler').fadeIn(); + }, + /** + * Triggered when dragged objects are left + * + * @param event obj + * + * @return void + */ + _dragleave: function (event) { + // We don't want to prevent users from using + // browser's default drag-drop feature on some page(s) + if ($('.noDragDrop').length !== 0) { + return; + } + event.stopPropagation(); + event.preventDefault(); + var $pma_drop_handler = $('.pma_drop_handler'); + $pma_drop_handler.clearQueue().stop(); + $pma_drop_handler.fadeOut(); + $pma_drop_handler.html(PMA_messages.dropImportDropFiles); + }, + /** + * Called when upload has finished + * + * @param string, unique hash for a certain upload + * @param bool, true if upload was aborted + * @param bool, status of sql upload, as sent by server + * + * @return void + */ + _importFinished: function (hash, aborted, status) { + $('.pma_sql_import_status div li[data-hash="' + hash + '"]') + .children('progress').hide(); + var icon = 'icon ic_s_success'; + // -- provide link to view upload status + if (!aborted) { + if (status) { + $('.pma_sql_import_status div li[data-hash="' + hash + + '"] span.filesize span.pma_drop_file_status') + .html('' + PMA_messages.dropImportMessageSuccess + ''); + } else { + $('.pma_sql_import_status div li[data-hash="' + hash + + '"] span.filesize span.pma_drop_file_status') + .html('' + PMA_messages.dropImportMessageFailed + + ''); + icon = 'icon ic_s_error'; + } + } else { + icon = 'icon ic_s_notice'; + } + $('.pma_sql_import_status div li[data-hash="' + hash + + '"] span.filesize span.pma_drop_file_status') + .attr('task', 'info'); + + // Set icon + $('.pma_sql_import_status div li[data-hash="' + hash + '"]') + .prepend(' '); + + // Decrease liveUploadCount by one + $('.pma_import_count').html(--DragDropImport.liveUploadCount); + if (!DragDropImport.liveUploadCount) { + $('.pma_sql_import_status h2 .close').fadeIn(); + } + }, + /** + * Triggered when dragged objects are dropped to UI + * From this function, the AJAX Upload operation is initiated + * + * @param event object + * + * @return void + */ + _drop: function (event) { + // We don't want to prevent users from using + // browser's default drag-drop feature on some page(s) + if ($('.noDragDrop').length !== 0) { + return; + } + + var dbname = PMA_commonParams.get('db'); + var server = PMA_commonParams.get('server'); + + // if no database is selected -- no + if (dbname !== '') { + var files = event.originalEvent.dataTransfer.files; + if (!files || files.length === 0) { + // No files actually transferred + $('.pma_drop_handler').fadeOut(); + event.stopPropagation(); + event.preventDefault(); + return; + } + $('.pma_sql_import_status').slideDown(); + for (var i = 0; i < files.length; i++) { + var ext = (DragDropImport._getExtension(files[i].name)); + var hash = AJAX.hash(++DragDropImport.uploadCount); + + var $pma_sql_import_status_div = $('.pma_sql_import_status div'); + $pma_sql_import_status_div.append('
  • ' + + ((ext !== '') ? '' : ' ') + + escapeHtml(files[i].name) + '' + (files[i].size / 1024).toFixed(2) + + ' kb
  • '); + + // scroll the UI to bottom + $pma_sql_import_status_div.scrollTop( + $pma_sql_import_status_div.scrollTop() + 50 + ); // 50 hardcoded for now + + if (ext !== '') { + // Increment liveUploadCount by one + $('.pma_import_count').html(++DragDropImport.liveUploadCount); + $('.pma_sql_import_status h2 .close').fadeOut(); + + $('.pma_sql_import_status div li[data-hash="' + hash + '"]') + .append('
    '); + + // uploading + var fd = new FormData(); + fd.append('import_file', files[i]); + fd.append('noplugin', Math.random().toString(36).substring(2, 12)); + fd.append('db', dbname); + fd.append('server', server); + fd.append('token', PMA_commonParams.get('token')); + fd.append('import_type', 'database'); + // todo: method to find the value below + fd.append('MAX_FILE_SIZE', '4194304'); + // todo: method to find the value below + fd.append('charset_of_file','utf-8'); + // todo: method to find the value below + fd.append('allow_interrupt', 'yes'); + fd.append('skip_queries', '0'); + fd.append('format',ext); + fd.append('sql_compatibility','NONE'); + fd.append('sql_no_auto_value_on_zero','something'); + fd.append('ajax_request','true'); + fd.append('hash', hash); + + // init uploading + DragDropImport._sendFileToServer(fd, hash); + } else if (!DragDropImport.liveUploadCount) { + $('.pma_sql_import_status h2 .close').fadeIn(); + } + } + } + $('.pma_drop_handler').fadeOut(); + event.stopPropagation(); + event.preventDefault(); + } +}; + +export default DragDropImport; diff --git a/js/src/consts/files.js b/js/src/consts/files.js index 4b58350181..4b559c2f6a 100644 --- a/js/src/consts/files.js +++ b/js/src/consts/files.js @@ -16,7 +16,8 @@ const PhpToJsFileMapping = { 'functions', 'indexes', 'key_handler', - 'cross_framing_protection' + 'cross_framing_protection', + 'drag_drop_import' ], server_privileges: ['server_privileges'], server_databases: ['server_databases'], @@ -96,7 +97,8 @@ const JsFileList = [ 'tbl_select', 'tbl_find_replace', 'key_handler', - 'cross_framing_protection' + 'cross_framing_protection', + 'drag_drop_import' ]; export { diff --git a/js/src/drag_drop_import.js b/js/src/drag_drop_import.js new file mode 100644 index 0000000000..472ffa48d8 --- /dev/null +++ b/js/src/drag_drop_import.js @@ -0,0 +1,59 @@ +/* vim: set expandtab sw=4 ts=4 sts=4: */ + +/** + * Module import + */ +import DragDropImport from './classes/DragDropImport'; + +/* This script handles PMA Drag Drop Import, loaded only when configuration is enabled.*/ + +export function teardownDragDropImport () { + $(document).off('dragenter'); + $(document).off('dragover'); + $(document).off('dragleave', '.pma_drop_handler'); + $(document).off('drop', 'body'); + $(document).off('click', '.pma_sql_import_status h2 .minimize'); + $(document).off('click', '.pma_sql_import_status h2 .close'); + $(document).off('click', '.pma_drop_result h2 .close'); +} + +export function onloadDragDropImport () { + /** + * Called when some user drags, dragover, leave + * a file to the PMA UI + * @param object Event data + * @return void + */ + $(document).on('dragenter', DragDropImport._dragenter); + $(document).on('dragover', DragDropImport._dragover); + $(document).on('dragleave', '.pma_drop_handler', DragDropImport._dragleave); + + // when file is dropped to PMA UI + $(document).on('drop', 'body', DragDropImport._drop); + + // minimizing-maximising the sql ajax upload status + $(document).on('click', '.pma_sql_import_status h2 .minimize', function () { + if ($(this).attr('toggle') === 'off') { + $('.pma_sql_import_status div').css('height','270px'); + $(this).attr('toggle','on'); + $(this).html('-'); // to minimize + } else { + $('.pma_sql_import_status div').css('height','0px'); + $(this).attr('toggle','off'); + $(this).html('+'); // to maximise + } + }); + + // closing sql ajax upload status + $(document).on('click', '.pma_sql_import_status h2 .close', function () { + $('.pma_sql_import_status').fadeOut(function () { + $('.pma_sql_import_status div').html(''); + DragDropImport.importStatus = []; // clear the message array + }); + }); + + // Closing the import result box + $(document).on('click', '.pma_drop_result h2 .close', function () { + $(this).parent('h2').parent('div').remove(); + }); +} diff --git a/libraries/classes/Header.php b/libraries/classes/Header.php index 32ccba56f9..c771be2bbc 100644 --- a/libraries/classes/Header.php +++ b/libraries/classes/Header.php @@ -213,7 +213,7 @@ class Header $this->_scripts->addFile('common.js'); if($GLOBALS['cfg']['enable_drag_drop_import'] === true) { - $this->_scripts->addFile('drag_drop_import.js'); + $this->_scripts->addFile('drag_drop_import'); } $this->_scripts->addFile('page_settings'); if (! $GLOBALS['PMA_Config']->get('DisableShortcutKeys')) { From b7371e418d05ac6efb2e835f5b1a312acaf80ba7 Mon Sep 17 00:00:00 2001 From: Piyush Vijay Date: Fri, 7 Sep 2018 19:59:12 +0530 Subject: [PATCH 3/8] Add Table Normalization in modular code. Signed-Off-By: Piyush Vijay --- js/src/consts/files.js | 6 +- js/src/functions/Table/Normalization.js | 463 ++++++++++++++++++++++++ js/src/navigation.js | 1 + js/src/normalization.js | 299 +++++++++++++++ js/src/utils/NormalizationEnum.js | 13 + normalization.php | 2 +- 6 files changed, 781 insertions(+), 3 deletions(-) create mode 100644 js/src/functions/Table/Normalization.js create mode 100644 js/src/normalization.js create mode 100644 js/src/utils/NormalizationEnum.js diff --git a/js/src/consts/files.js b/js/src/consts/files.js index 4b559c2f6a..d2606443bd 100644 --- a/js/src/consts/files.js +++ b/js/src/consts/files.js @@ -56,7 +56,8 @@ const PhpToJsFileMapping = { tbl_zoom_select: ['sql', 'tbl_change'], tbl_find_replace: ['tbl_find_replace'], tbl_import: ['import'], - tbl_export: ['export'] + tbl_export: ['export'], + normalization: ['normalization'] }; const JsFileList = [ @@ -98,7 +99,8 @@ const JsFileList = [ 'tbl_find_replace', 'key_handler', 'cross_framing_protection', - 'drag_drop_import' + 'drag_drop_import', + 'normalization' ]; export { diff --git a/js/src/functions/Table/Normalization.js b/js/src/functions/Table/Normalization.js new file mode 100644 index 0000000000..4bbdefc11b --- /dev/null +++ b/js/src/functions/Table/Normalization.js @@ -0,0 +1,463 @@ +/* vim: set expandtab sw=4 ts=4 sts=4: */ + +/** + * Module Import + */ +import { PMA_Messages as PMA_messages } from '../../variables/export_variables'; +import PMA_commonParams from '../../variables/common_params'; +import { PMA_sprintf } from '../../utils/sprintf'; +import { escapeHtml, escapeJsString } from '../../utils/Sanitise'; +import { PMA_ajaxShowMessage } from '../../utils/show_ajax_messages'; +import NormalizationEnum from '../../utils/NormalizationEnum'; + +export function appendHtmlColumnsList () { + $.get( + 'normalization.php', + { + 'ajax_request': true, + 'db': PMA_commonParams.get('db'), + 'table': PMA_commonParams.get('table'), + 'getColumns': true + }, + function (data) { + if (data.success === true) { + $('select[name=makeAtomic]').html(data.message); + } + } + ); +} + +function goTo3NFStep1 (newTables) { + if (Object.keys(newTables).length === 1) { + newTables = [PMA_commonParams.get('table')]; + } + $.post( + 'normalization.php', + { + 'ajax_request': true, + 'db': PMA_commonParams.get('db'), + 'tables': newTables, + 'step': '3.1' + }, function (data) { + $('#page_content').find('h3').html(PMA_messages.str3NFNormalization); + $('#mainContent').find('legend').html(data.legendText); + $('#mainContent').find('h4').html(data.headText); + $('#mainContent').find('p').html(data.subText); + $('#mainContent').find('#extra').html(data.extra); + $('#extra').find('form').each(function () { + var form_id = $(this).attr('id'); + var colname = $(this).data('colname'); + $('#' + form_id + ' input[value=\'' + colname + '\']').next().remove(); + $('#' + form_id + ' input[value=\'' + colname + '\']').remove(); + }); + $('#mainContent').find('#newCols').html(''); + $('.tblFooters').html(''); + + if (data.subText !== '') { + $('') + .attr({ type: 'button', value: PMA_messages.strDone }) + .on('click', function () { + processDependencies('', true); + }) + .appendTo('.tblFooters'); + } + } + ); +} + +function goTo2NFStep1 () { + $.post( + 'normalization.php', + { + 'ajax_request': true, + 'db': PMA_commonParams.get('db'), + 'table': PMA_commonParams.get('table'), + 'step': '2.1' + }, function (data) { + $('#page_content h3').html(PMA_messages.str2NFNormalization); + $('#mainContent legend').html(data.legendText); + $('#mainContent h4').html(data.headText); + $('#mainContent p').html(data.subText); + $('#mainContent #extra').html(data.extra); + $('#mainContent #newCols').html(''); + if (data.subText !== '') { + var doneButton = $('') + .attr({ type: 'submit', value: PMA_messages.strDone, }) + .on('click', function () { + processDependencies(data.primary_key); + }) + .appendTo('.tblFooters'); + } else { + if (NormalizationEnum.normalizeto === '3nf') { + $('#mainContent #newCols').html(PMA_messages.strToNextStep); + setTimeout(function () { + goTo3NFStep1([PMA_commonParams.get('table')]); + }, 3000); + } + } + }); +} + +function goToFinish1NF () { + if (NormalizationEnum.normalizeto !== '1nf') { + goTo2NFStep1(); + return true; + } + $('#mainContent legend').html(PMA_messages.strEndStep); + $('#mainContent h4').html( + '

    ' + PMA_sprintf(PMA_messages.strFinishMsg, escapeHtml(PMA_commonParams.get('table'))) + '

    ' + ); + $('#mainContent p').html(''); + $('#mainContent #extra').html(''); + $('#mainContent #newCols').html(''); + $('.tblFooters').html(''); +} + +function goToStep4 () { + $.post( + 'normalization.php', + { + 'ajax_request': true, + 'db': PMA_commonParams.get('db'), + 'table': PMA_commonParams.get('table'), + 'step4': true + }, function (data) { + $('#mainContent legend').html(data.legendText); + $('#mainContent h4').html(data.headText); + $('#mainContent p').html(data.subText); + $('#mainContent #extra').html(data.extra); + $('#mainContent #newCols').html(''); + $('.tblFooters').html(''); + for (var pk in NormalizationEnum.primary_key) { + $('#extra input[value=\'' + escapeJsString(NormalizationEnum.primary_key[pk]) + '\']').attr('disabled','disabled'); + } + } + ); +} + +export function goToStep3 () { + $.post( + 'normalization.php', + { + 'ajax_request': true, + 'db': PMA_commonParams.get('db'), + 'table': PMA_commonParams.get('table'), + 'step3': true + }, function (data) { + $('#mainContent legend').html(data.legendText); + $('#mainContent h4').html(data.headText); + $('#mainContent p').html(data.subText); + $('#mainContent #extra').html(data.extra); + $('#mainContent #newCols').html(''); + $('.tblFooters').html(''); + NormalizationEnum.primary_key = JSON.parse(data.primary_key); + for (var pk in NormalizationEnum.primary_key) { + $('#extra input[value=\'' + escapeJsString(NormalizationEnum.primary_key[pk]) + '\']').attr('disabled','disabled'); + } + } + ); +} + +export function goToStep2 (extra) { + $.post( + 'normalization.php', + { + 'ajax_request': true, + 'db': PMA_commonParams.get('db'), + 'table': PMA_commonParams.get('table'), + 'step2': true + }, function (data) { + $('#mainContent legend').html(data.legendText); + $('#mainContent h4').html(data.headText); + $('#mainContent p').html(data.subText); + $('#mainContent #extra,#mainContent #newCols').html(''); + $('.tblFooters').html(''); + if (data.hasPrimaryKey === '1') { + if (extra === 'goToStep3') { + $('#mainContent h4').html(PMA_messages.strPrimaryKeyAdded); + $('#mainContent p').html(PMA_messages.strToNextStep); + } + if (extra === 'goToFinish1NF') { + goToFinish1NF(); + } else { + setTimeout(function () { + goToStep3(); + }, 3000); + } + } else { + // form to select columns to make primary + $('#mainContent #extra').html(data.extra); + } + } + ); +} + +function goTo2NFFinish (pd) { + var tables = {}; + for (var dependson in pd) { + tables[dependson] = $('#extra input[name="' + dependson + '"]').val(); + } + var datastring = { + 'ajax_request': true, + 'db': PMA_commonParams.get('db'), + 'table': PMA_commonParams.get('table'), + 'pd': JSON.stringify(pd), + 'newTablesName':JSON.stringify(tables), + 'createNewTables2NF':1 + }; + $.ajax({ + type: 'POST', + url: 'normalization.php', + data: datastring, + async:false, + success: function (data) { + if (data.success === true) { + if (data.queryError === false) { + if (NormalizationEnum.normalizeto === '3nf') { + $('#pma_navigation_reload').trigger('click'); + goTo3NFStep1(tables); + return true; + } + $('#mainContent legend').html(data.legendText); + $('#mainContent h4').html(data.headText); + $('#mainContent p').html(''); + $('#mainContent #extra').html(''); + $('.tblFooters').html(''); + } else { + PMA_ajaxShowMessage(data.extra, false); + } + $('#pma_navigation_reload').trigger('click'); + } else { + PMA_ajaxShowMessage(data.error, false); + } + } + }); +} + +function goTo3NFFinish (newTables) { + for (var table in newTables) { + for (var newtbl in newTables[table]) { + var updatedname = $('#extra input[name="' + newtbl + '"]').val(); + newTables[table][updatedname] = newTables[table][newtbl]; + if (updatedname !== newtbl) { + delete newTables[table][newtbl]; + } + } + } + var datastring = { + 'ajax_request': true, + 'db': PMA_commonParams.get('db'), + 'newTables':JSON.stringify(newTables), + 'createNewTables3NF':1 + }; + $.ajax({ + type: 'POST', + url: 'normalization.php', + data: datastring, + async:false, + success: function (data) { + if (data.success === true) { + if (data.queryError === false) { + $('#mainContent legend').html(data.legendText); + $('#mainContent h4').html(data.headText); + $('#mainContent p').html(''); + $('#mainContent #extra').html(''); + $('.tblFooters').html(''); + } else { + PMA_ajaxShowMessage(data.extra, false); + } + $('#pma_navigation_reload').trigger('click'); + } else { + PMA_ajaxShowMessage(data.error, false); + } + } + }); +} + +function goTo2NFStep2 (pd, primary_key) { + $('#newCols').html(''); + $('#mainContent legend').html(PMA_messages.strStep + ' 2.2 ' + PMA_messages.strConfirmPd); + $('#mainContent h4').html(PMA_messages.strSelectedPd); + $('#mainContent p').html(PMA_messages.strPdHintNote); + var extra = '
    '; + var pdFound = false; + for (var dependson in pd) { + if (dependson !== primary_key) { + pdFound = true; + extra += '

    ' + escapeHtml(dependson) + ' -> ' + escapeHtml(pd[dependson].toString()) + '

    '; + } + } + if (!pdFound) { + extra += '

    ' + PMA_messages.strNoPdSelected + '

    '; + extra += '
    '; + } else { + extra += ''; + var datastring = { + 'ajax_request': true, + 'db': PMA_commonParams.get('db'), + 'table': PMA_commonParams.get('table'), + 'pd': JSON.stringify(pd), + 'getNewTables2NF':1 + }; + $.ajax({ + type: 'POST', + url: 'normalization.php', + data: datastring, + async:false, + success: function (data) { + if (data.success === true) { + extra += data.message; + } else { + PMA_ajaxShowMessage(data.error, false); + } + } + }); + } + $('#mainContent #extra').html(extra); + $('.tblFooters').html(''); + $('#goTo2NFFinish').on('click', function () { + goTo2NFFinish(pd); + }); +} + +function goTo3NFStep2 (pd, tablesTds) { + $('#newCols').html(''); + $('#mainContent legend').html(PMA_messages.strStep + ' 3.2 ' + PMA_messages.strConfirmTd); + $('#mainContent h4').html(PMA_messages.strSelectedTd); + $('#mainContent p').html(PMA_messages.strPdHintNote); + var extra = '
    '; + var pdFound = false; + for (var table in tablesTds) { + for (var i in tablesTds[table]) { + var dependson = tablesTds[table][i]; + if (dependson !== '' && dependson !== table) { + pdFound = true; + extra += '

    ' + escapeHtml(dependson) + ' -> ' + escapeHtml(pd[dependson].toString()) + '

    '; + } + } + } + if (!pdFound) { + extra += '

    ' + PMA_messages.strNoTdSelected + '

    '; + extra += '
    '; + } else { + extra += ''; + var datastring = { + 'ajax_request': true, + 'db': PMA_commonParams.get('db'), + 'tables': JSON.stringify(tablesTds), + 'pd': JSON.stringify(pd), + 'getNewTables3NF':1 + }; + $.ajax({ + type: 'POST', + url: 'normalization.php', + data: datastring, + async:false, + success: function (data) { + NormalizationEnum.data_parsed = data; + if (data.success === true) { + extra += NormalizationEnum.data_parsed.html; + } else { + PMA_ajaxShowMessage(data.error, false); + } + } + }); + } + $('#mainContent #extra').html(extra); + $('.tblFooters').html(''); + $('#goTo3NFFinish').on('click', function () { + if (!pdFound) { + goTo3NFFinish([]); + } else { + goTo3NFFinish(NormalizationEnum.data_parsed.newTables); + } + }); +} + +function processDependencies (primary_key, isTransitive) { + var pd = {}; + var tablesTds = {}; + var dependsOn; + pd[primary_key] = []; + $('#extra form').each(function () { + var tblname; + if (isTransitive === true) { + tblname = $(this).data('tablename'); + primary_key = tblname; + if (!(tblname in tablesTds)) { + tablesTds[tblname] = []; + } + tablesTds[tblname].push(primary_key); + } + var form_id = $(this).attr('id'); + $('#' + form_id + ' input[type=checkbox]:not(:checked)').prop('checked', false); + dependsOn = ''; + $('#' + form_id + ' input[type=checkbox]:checked').each(function () { + dependsOn += $(this).val() + ', '; + $(this).attr('checked','checked'); + }); + if (dependsOn === '') { + dependsOn = primary_key; + } else { + dependsOn = dependsOn.slice(0, -2); + } + if (! (dependsOn in pd)) { + pd[dependsOn] = []; + } + pd[dependsOn].push($(this).data('colname')); + if (isTransitive === true) { + if (!(tblname in tablesTds)) { + tablesTds[tblname] = []; + } + if ($.inArray(dependsOn, tablesTds[tblname]) === -1) { + tablesTds[tblname].push(dependsOn); + } + } + }); + NormalizationEnum.backup = $('#mainContent').html(); + if (isTransitive === true) { + goTo3NFStep2(pd, tablesTds); + } else { + goTo2NFStep2(pd, primary_key); + } + return false; +} + +export function moveRepeatingGroup (repeatingCols) { + var newTable = $('input[name=repeatGroupTable]').val(); + var newColumn = $('input[name=repeatGroupColumn]').val(); + if (!newTable) { + $('input[name=repeatGroupTable]').focus(); + return false; + } + if (!newColumn) { + $('input[name=repeatGroupColumn]').focus(); + return false; + } + var datastring = { + 'ajax_request': true, + 'db': PMA_commonParams.get('db'), + 'table': PMA_commonParams.get('table'), + 'repeatingColumns': repeatingCols, + 'newTable': newTable, + 'newColumn': newColumn, + 'primary_columns': NormalizationEnum.primary_key.toString() + }; + $.ajax({ + type: 'POST', + url: 'normalization.php', + data: datastring, + async:false, + success: function (data) { + if (data.success === true) { + if (data.queryError === false) { + goToStep3(); + } + PMA_ajaxShowMessage(data.message, false); + $('#pma_navigation_reload').trigger('click'); + } else { + PMA_ajaxShowMessage(data.error, false); + } + } + }); +} diff --git a/js/src/navigation.js b/js/src/navigation.js index af942dc215..c09292075b 100644 --- a/js/src/navigation.js +++ b/js/src/navigation.js @@ -4,6 +4,7 @@ import { PMA_Messages as PMA_messages } from './variables/export_variables'; import CommonParams from './variables/common_params'; import { PMA_ajaxShowMessage, PMA_ajaxRemoveMessage, PMA_tooltip } from './utils/show_ajax_messages'; import { isStorageSupported } from './functions/config'; +import { indexEditorDialog } from './functions/Indexes'; /** * function used in or for navigation panel diff --git a/js/src/normalization.js b/js/src/normalization.js new file mode 100644 index 0000000000..ace44b883b --- /dev/null +++ b/js/src/normalization.js @@ -0,0 +1,299 @@ +/* vim: set expandtab sw=4 ts=4 sts=4: */ + +/** + * Module import + */ +import { PMA_Messages as PMA_messages } from './variables/export_variables'; +import PMA_commonParams from './variables/common_params'; +import { PMA_ajaxShowMessage } from './utils/show_ajax_messages'; +import { PMA_sprintf } from './utils/sprintf'; +import { escapeHtml } from './utils/Sanitise'; +import { + goToStep2, + goToStep3, + moveRepeatingGroup, + appendHtmlColumnsList +} from './functions/Table/Normalization'; +import NormalizationEnum from './utils/NormalizationEnum'; +import { indexEditorDialog } from './functions/Indexes'; +/** + * @fileoverview events handling from normalization page + * @name normalization + * + * @requires jQuery + */ + +/** + * AJAX scripts for normalization.php + * + */ + +export function teardownNormalization () { + $('#extra').off('click', '#selectNonAtomicCol'); + $('#splitGo').off('click'); + $('.tblFooters').off('click', '#saveSplit'); + $('#extra').off('click', '#addNewPrimary'); + $('.tblFooters').off('click', '#saveNewPrimary'); + $('#extra').off('click', '#removeRedundant'); + $('#mainContent p').off('click', '#createPrimaryKey'); + $('#mainContent').off('click', '#backEditPd'); + $('#mainContent').off('click', '#showPossiblePd'); + $('#mainContent').off('click', '.pickPd'); +} + +export function onloadNormalization () { + var selectedCol; + NormalizationEnum.normalizeto = $('#mainContent').data('normalizeto'); + $('#extra').on('click', '#selectNonAtomicCol', function () { + if ($(this).val() === 'no_such_col') { + goToStep2(); + } else { + selectedCol = $(this).val(); + } + }); + + $('#splitGo').on('click', function () { + if (!selectedCol || selectedCol === '') { + return false; + } + var numField = $('#numField').val(); + $.get( + 'normalization.php', + { + 'ajax_request': true, + 'db': PMA_commonParams.get('db'), + 'table': PMA_commonParams.get('table'), + 'splitColumn': true, + 'numFields': numField + }, + function (data) { + if (data.success === true) { + $('#newCols').html(data.message); + $('.default_value').hide(); + $('.enum_notice').hide(); + + $('') + .attr({ type: 'submit', id: 'saveSplit', value: PMA_messages.strSave }) + .appendTo('.tblFooters'); + + var cancelSplitButton = $('') + .attr({ type: 'submit', id: 'cancelSplit', value: PMA_messages.strCancel }) + .on('click', function () { + $('#newCols').html(''); + $(this).parent().html(''); + }) + .appendTo('.tblFooters'); + } + } + ); + return false; + }); + $('.tblFooters').on('click','#saveSplit', function () { + central_column_list = []; + if ($('#newCols #field_0_1').val() === '') { + $('#newCols #field_0_1').focus(); + return false; + } + var argsep = PMA_commonParams.get('arg_separator'); + var datastring = $('#newCols :input').serialize(); + datastring += argsep + 'ajax_request=1' + argsep + 'do_save_data=1' + argsep + 'field_where=last'; + $.post('tbl_addfield.php', datastring, function (data) { + if (data.success) { + $.post( + 'sql.php', + { + 'ajax_request': true, + 'db': PMA_commonParams.get('db'), + 'table': PMA_commonParams.get('table'), + 'dropped_column': selectedCol, + 'purge' : 1, + 'sql_query': 'ALTER TABLE `' + PMA_commonParams.get('table') + '` DROP `' + selectedCol + '`;', + 'is_js_confirmed': 1 + }, + function (data) { + if (data.success === true) { + appendHtmlColumnsList(); + $('#newCols').html(''); + $('.tblFooters').html(''); + } else { + PMA_ajaxShowMessage(data.error, false); + } + selectedCol = ''; + } + ); + } else { + PMA_ajaxShowMessage(data.error, false); + } + }); + }); + + $('#extra').on('click', '#addNewPrimary', function () { + $.get( + 'normalization.php', + { + 'ajax_request': true, + 'db': PMA_commonParams.get('db'), + 'table': PMA_commonParams.get('table'), + 'addNewPrimary': true + }, + function (data) { + if (data.success === true) { + $('#newCols').html(data.message); + $('.default_value').hide(); + $('.enum_notice').hide(); + + $('') + .attr({ type: 'submit', id: 'saveNewPrimary', value: PMA_messages.strSave }) + .appendTo('.tblFooters'); + $('') + .attr({ type: 'submit', id: 'cancelSplit', value: PMA_messages.strCancel }) + .on('click', function () { + $('#newCols').html(''); + $(this).parent().html(''); + }) + .appendTo('.tblFooters'); + } else { + PMA_ajaxShowMessage(data.error, false); + } + } + ); + return false; + }); + $('.tblFooters').on('click', '#saveNewPrimary', function () { + var datastring = $('#newCols :input').serialize(); + var argsep = PMA_commonParams.get('arg_separator'); + datastring += argsep + 'field_key[0]=primary_0' + argsep + 'ajax_request=1' + argsep + 'do_save_data=1' + argsep + 'field_where=last'; + $.post('tbl_addfield.php', datastring, function (data) { + if (data.success === true) { + $('#mainContent h4').html(PMA_messages.strPrimaryKeyAdded); + $('#mainContent p').html(PMA_messages.strToNextStep); + $('#mainContent #extra').html(''); + $('#mainContent #newCols').html(''); + $('.tblFooters').html(''); + setTimeout(function () { + goToStep3(); + }, 2000); + } else { + PMA_ajaxShowMessage(data.error, false); + } + }); + }); + $('#extra').on('click', '#removeRedundant', function () { + var dropQuery = 'ALTER TABLE `' + PMA_commonParams.get('table') + '` '; + $('#extra input[type=checkbox]:checked').each(function () { + dropQuery += 'DROP `' + $(this).val() + '`, '; + }); + dropQuery = dropQuery.slice(0, -2); + $.post( + 'sql.php', + { + 'ajax_request': true, + 'db': PMA_commonParams.get('db'), + 'table': PMA_commonParams.get('table'), + 'sql_query': dropQuery, + 'is_js_confirmed': 1 + }, + function (data) { + if (data.success === true) { + goToStep2('goToFinish1NF'); + } else { + PMA_ajaxShowMessage(data.error, false); + } + } + ); + }); + $('#extra').on('click', '#moveRepeatingGroup', function () { + var repeatingCols = ''; + $('#extra input[type=checkbox]:checked').each(function () { + repeatingCols += $(this).val() + ', '; + }); + + if (repeatingCols !== '') { + var newColName = $('#extra input[type=checkbox]:checked:first').val(); + repeatingCols = repeatingCols.slice(0, -2); + var confirmStr = PMA_sprintf(PMA_messages.strMoveRepeatingGroup, escapeHtml(repeatingCols), escapeHtml(PMA_commonParams.get('table'))); + confirmStr += '' + + '( ' + escapeHtml(NormalizationEnum.primary_key.toString()) + ', )' + + ''; + $('#newCols').html(confirmStr); + + $('') + .attr({ type: 'submit', value: PMA_messages.strCancel }) + .on('click', function () { + $('#newCols').html(''); + $('#extra input[type=checkbox]').prop('checked', false); + }) + .appendTo('.tblFooters'); + $('') + .attr({ type: 'submit', value: PMA_messages.strGo }) + .on('click', function () { + moveRepeatingGroup(repeatingCols); + }) + .appendTo('.tblFooters'); + } + }); + $('#mainContent p').on('click', '#createPrimaryKey', function (event) { + event.preventDefault(); + var url = { create_index: 1, + server: PMA_commonParams.get('server'), + db: PMA_commonParams.get('db'), + table: PMA_commonParams.get('table'), + added_fields: 1, + add_fields:1, + index: { Key_name:'PRIMARY' }, + ajax_request: true + }; + var title = PMA_messages.strAddPrimaryKey; + indexEditorDialog(url, title, function () { + // on success + $('.sqlqueryresults').remove(); + $('.result_query').remove(); + $('.tblFooters').html(''); + goToStep2('goToStep3'); + }); + return false; + }); + $('#mainContent').on('click', '#backEditPd', function () { + $('#mainContent').html(NormalizationEnum.backup); + }); + $('#mainContent').on('click', '#showPossiblePd', function () { + if ($(this).hasClass('hideList')) { + $(this).html('+ ' + PMA_messages.strShowPossiblePd); + $(this).removeClass('hideList'); + $('#newCols').slideToggle('slow'); + return false; + } + if ($('#newCols').html() !== '') { + $('#showPossiblePd').html('- ' + PMA_messages.strHidePd); + $('#showPossiblePd').addClass('hideList'); + $('#newCols').slideToggle('slow'); + return false; + } + $('#newCols').insertAfter('#mainContent h4'); + $('#newCols').html('
    ' + PMA_messages.strLoading + '
    ' + PMA_messages.strWaitForPd + '
    '); + $.post( + 'normalization.php', + { + 'ajax_request': true, + 'db': PMA_commonParams.get('db'), + 'table': PMA_commonParams.get('table'), + 'findPdl': true + }, function (data) { + $('#showPossiblePd').html('- ' + PMA_messages.strHidePd); + $('#showPossiblePd').addClass('hideList'); + $('#newCols').html(data.message); + }); + }); + $('#mainContent').on('click', '.pickPd', function () { + var strColsLeft = $(this).next('.determinants').html(); + var colsLeft = strColsLeft.split(','); + var strColsRight = $(this).next().next().html(); + var colsRight = strColsRight.split(','); + for (var i in colsRight) { + $('form[data-colname="' + colsRight[i].trim() + '"] input[type="checkbox"]').prop('checked', false); + for (var j in colsLeft) { + $('form[data-colname="' + colsRight[i].trim() + '"] input[value="' + colsLeft[j].trim() + '"]').prop('checked', true); + } + } + }); +} diff --git a/js/src/utils/NormalizationEnum.js b/js/src/utils/NormalizationEnum.js new file mode 100644 index 0000000000..e2308a38c1 --- /dev/null +++ b/js/src/utils/NormalizationEnum.js @@ -0,0 +1,13 @@ +/* vim: set expandtab sw=4 ts=4 sts=4: */ + +/** + * @var NormalizationEnum Object to sore data related to Normalization + */ +var NormalizationEnum = { + normalizeto: '1nf', + primary_key: null, + data_parsed: null, + backup: '' +}; + +export default NormalizationEnum; diff --git a/normalization.php b/normalization.php index 6ca8330700..8f4967bef6 100644 --- a/normalization.php +++ b/normalization.php @@ -75,7 +75,7 @@ if (isset($_REQUEST['getNewTables3NF'])) { $header = $response->getHeader(); $scripts = $header->getScripts(); -$scripts->addFile('normalization.js'); +$scripts->addFile('normalization'); $scripts->addFile('vendor/jquery/jquery.uitablefilter.js'); $normalForm = '1nf'; if (Core::isValid($_REQUEST['normalizeTo'], ['1nf', '2nf', '3nf'])) { From 12781a3f9765e740d816c7128eb07806a57885dc Mon Sep 17 00:00:00 2001 From: Piyush Vijay Date: Thu, 20 Sep 2018 04:36:42 +0530 Subject: [PATCH 4/8] Add Routines, Triggers and Events in the modular code. Signed-Off-By: Piyush Vijay --- js/src/classes/RTE.js | 928 ++++++++++++++++++++++++++++++++++++++++++ js/src/rte.js | 166 ++++++++ 2 files changed, 1094 insertions(+) create mode 100644 js/src/classes/RTE.js create mode 100644 js/src/rte.js diff --git a/js/src/classes/RTE.js b/js/src/classes/RTE.js new file mode 100644 index 0000000000..00c375495d --- /dev/null +++ b/js/src/classes/RTE.js @@ -0,0 +1,928 @@ +/* vim: set expandtab sw=4 ts=4 sts=4: */ + +import { PMA_Messages as PMA_messages } from '../variables/export_variables'; +import { PMA_ajaxShowMessage, + PMA_ajaxRemoveMessage, + PMA_slidingMessage +} from '../utils/show_ajax_messages'; +import { PMA_addDatepicker } from '../utils/DateTime'; +import { PMA_getSQLEditor } from '../functions/Sql/SqlEditor'; +import { PMA_reloadNavigation } from '../functions/navigation'; +import { getJSConfirmCommonParam } from '../functions/Common'; + +/** + * JavaScript functionality for Routines, Triggers and Events. + * + * @package PhpMyadmin + */ +/** + * @var RTE Contains all the JavaScript functionality + * for Routines, Triggers and Events + */ +var RTE = { + /** + * Construct for the object that provides the + * functionality for Routines, Triggers and Events + */ + object: function (type) { + $.extend(this, RTE.COMMON); + this.editorType = type; + + switch (type) { + case 'routine': + $.extend(this, RTE.ROUTINE); + break; + case 'trigger': + // nothing extra yet for triggers + break; + case 'event': + $.extend(this, RTE.EVENT); + break; + default: + break; + } + }, + /** + * @var string param_template Template for a row in the routine editor + */ + param_template: '' +}; + +/** + * @var RTE.COMMON a JavaScript namespace containing the functionality + * for Routines, Triggers and Events + * + * This namespace is extended by the functionality required + * to handle a specific item (a routine, trigger or event) + * in the relevant javascript files in this folder + */ +RTE.COMMON = { + /** + * @var $ajaxDialog Query object containing the reference to the + * dialog that contains the editor + */ + $ajaxDialog: null, + /** + * @var syntaxHiglighter Reference to the codemirror editor + */ + syntaxHiglighter: null, + /** + * @var buttonOptions Object containing options for + * the jQueryUI dialog buttons + */ + buttonOptions: {}, + /** + * @var editorType Type of the editor + */ + editorType: null, + /** + * Validate editor form fields. + */ + validate: function () { + /** + * @var $elm a jQuery object containing the reference + * to an element that is being validated + */ + var $elm = null; + // Common validation. At the very least the name + // and the definition must be provided for an item + $elm = $('table.rte_table').last().find('input[name=item_name]'); + if ($elm.val() === '') { + $elm.focus(); + alert(PMA_messages.strFormEmpty); + return false; + } + $elm = $('table.rte_table').find('textarea[name=item_definition]'); + if ($elm.val() === '') { + if (this.syntaxHiglighter !== null) { + this.syntaxHiglighter.focus(); + } else { + $('textarea[name=item_definition]').last().focus(); + } + alert(PMA_messages.strFormEmpty); + return false; + } + // The validation has so far passed, so now + // we can validate item-specific fields. + return this.validateCustom(); + }, // end validate() + /** + * Validate custom editor form fields. + * This function can be overridden by + * other files in this folder + */ + validateCustom: function () { + return true; + }, // end validateCustom() + /** + * Execute some code after the ajax + * dialog for the editor is shown. + * This function can be overridden by + * other files in this folder + */ + postDialogShow: function () { + // Nothing by default + }, // end postDialogShow() + + exportDialog: function ($this) { + var $msg = PMA_ajaxShowMessage(); + if ($this.hasClass('mult_submit')) { + var combined = { + success: true, + title: PMA_messages.strExport, + message: '', + error: '' + }; + // export anchors of all selected rows + var export_anchors = $('input.checkall:checked').parents('tr').find('.export_anchor'); + var count = export_anchors.length; + var returnCount = 0; + + // No routine is exportable (due to privilege issues) + if (count === 0) { + PMA_ajaxShowMessage(PMA_messages.NoExportable); + } + + export_anchors.each(function () { + $.get($(this).attr('href'), { 'ajax_request': true }, function (data) { + returnCount++; + if (data.success === true) { + combined.message += '\n' + data.message + '\n'; + if (returnCount === count) { + showExport(combined); + } + } else { + // complain even if one export is failing + combined.success = false; + combined.error += '\n' + data.error + '\n'; + if (returnCount === count) { + showExport(combined); + } + } + }); + }); + } else { + $.get($this.attr('href'), { 'ajax_request': true }, showExport); + } + PMA_ajaxRemoveMessage($msg); + + function showExport (data) { + if (data.success === true) { + PMA_ajaxRemoveMessage($msg); + /** + * @var button_options Object containing options + * for jQueryUI dialog buttons + */ + var button_options = {}; + button_options[PMA_messages.strClose] = function () { + $(this).dialog('close').remove(); + }; + /** + * Display the dialog to the user + */ + data.message = ''; + var $ajaxDialog = $('
    ' + data.message + '
    ').dialog({ + width: 500, + buttons: button_options, + title: data.title + }); + // Attach syntax highlighted editor to export dialog + /** + * @var $elm jQuery object containing the reference + * to the Export textarea. + */ + var $elm = $ajaxDialog.find('textarea'); + PMA_getSQLEditor($elm); + } else { + PMA_ajaxShowMessage(data.error, false); + } + } // end showExport() + }, // end exportDialog() + editorDialog: function (is_new, $this) { + var that = this; + /** + * @var $edit_row jQuery object containing the reference to + * the row of the the item being edited + * from the list of items + */ + var $edit_row = null; + if ($this.hasClass('edit_anchor')) { + // Remeber the row of the item being edited for later, + // so that if the edit is successful, we can replace the + // row with info about the modified item. + $edit_row = $this.parents('tr'); + } + /** + * @var $msg jQuery object containing the reference to + * the AJAX message shown to the user + */ + var $msg = PMA_ajaxShowMessage(); + $.get($this.attr('href'), { 'ajax_request': true }, function (data) { + if (data.success === true) { + // We have successfully fetched the editor form + PMA_ajaxRemoveMessage($msg); + // Now define the function that is called when + // the user presses the "Go" button + that.buttonOptions[PMA_messages.strGo] = function () { + // Move the data from the codemirror editor back to the + // textarea, where it can be used in the form submission. + if (typeof CodeMirror !== 'undefined') { + that.syntaxHiglighter.save(); + } + // Validate editor and submit request, if passed. + if (that.validate()) { + /** + * @var data Form data to be sent in the AJAX request + */ + var data = $('form.rte_form').last().serialize(); + $msg = PMA_ajaxShowMessage( + PMA_messages.strProcessingRequest + ); + var url = $('form.rte_form').last().attr('action'); + $.post(url, data, function (data) { + if (data.success === true) { + // Item created successfully + PMA_ajaxRemoveMessage($msg); + PMA_slidingMessage(data.message); + that.$ajaxDialog.dialog('close'); + // If we are in 'edit' mode, we must + // remove the reference to the old row. + if (mode === 'edit' && $edit_row !== null) { + $edit_row.remove(); + } + // Sometimes, like when moving a trigger from + // a table to another one, the new row should + // not be inserted into the list. In this case + // "data.insert" will be set to false. + if (data.insert) { + // Insert the new row at the correct + // location in the list of items + /** + * @var text Contains the name of an item from + * the list that is used in comparisons + * to find the correct location where + * to insert a new row. + */ + var text = ''; + /** + * @var inserted Whether a new item has been + * inserted in the list or not + */ + var inserted = false; + $('table.data').find('tr').each(function () { + text = $(this) + .children('td') + .eq(0) + .find('strong') + .text() + .toUpperCase(); + text = $.trim(text); + if (text !== '' && text > data.name) { + $(this).before(data.new_row); + inserted = true; + return false; + } + }); + if (! inserted) { + // If we didn't manage to insert the row yet, + // it must belong at the end of the list, + // so we insert it there. + $('table.data').append(data.new_row); + } + // Fade-in the new row + $('tr.ajaxInsert') + .show('slow') + .removeClass('ajaxInsert'); + } else if ($('table.data').find('tr').has('td').length === 0) { + // If we are not supposed to insert the new row, + // we will now check if the table is empty and + // needs to be hidden. This will be the case if + // we were editing the only item in the list, + // which we removed and will not be inserting + // something else in its place. + $('table.data').hide('slow', function () { + $('#nothing2display').show('slow'); + }); + } + // Now we have inserted the row at the correct + // position, but surely at least some row classes + // are wrong now. So we will itirate throught + // all rows and assign correct classes to them + /** + * @var ct Count of processed rows + */ + var ct = 0; + /** + * @var rowclass Class to be attached to the row + * that is being processed + */ + var rowclass = ''; + $('table.data').find('tr').has('td').each(function () { + rowclass = (ct % 2 === 0) ? 'odd' : 'even'; + $(this).removeClass().addClass(rowclass); + ct++; + }); + // If this is the first item being added, remove + // the "No items" message and show the list. + if ($('table.data').find('tr').has('td').length > 0 && + $('#nothing2display').is(':visible') + ) { + $('#nothing2display').hide('slow', function () { + $('table.data').show('slow'); + }); + } + PMA_reloadNavigation(); + } else { + PMA_ajaxShowMessage(data.error, false); + } + }); // end $.post() + } // end "if (that.validate())" + }; // end of function that handles the submission of the Editor + that.buttonOptions[PMA_messages.strClose] = function () { + $(this).dialog('close'); + }; + /** + * Display the dialog to the user + */ + that.$ajaxDialog = $('
    ' + data.message + '
    ').dialog({ + width: 700, + minWidth: 500, + maxHeight: $(window).height(), + buttons: that.buttonOptions, + title: data.title, + modal: true, + open: function () { + if ($('#rteDialog').parents('.ui-dialog').height() > $(window).height()) { + $('#rteDialog').dialog('option', 'height', $(window).height()); + } + $(this).find('input[name=item_name]').focus(); + $(this).find('input.datefield').each(function () { + PMA_addDatepicker($(this).css('width', '95%'), 'date'); + }); + $(this).find('input.datetimefield').each(function () { + PMA_addDatepicker($(this).css('width', '95%'), 'datetime'); + }); + $.datepicker.initialized = false; + }, + close: function () { + $(this).remove(); + } + }); + /** + * @var mode Used to remeber whether the editor is in + * "Edit" or "Add" mode + */ + var mode = 'add'; + if ($('input[name=editor_process_edit]').length > 0) { + mode = 'edit'; + } + // Attach syntax highlighted editor to the definition + /** + * @var elm jQuery object containing the reference to + * the Definition textarea. + */ + var $elm = $('textarea[name=item_definition]').last(); + var linterOptions = {}; + linterOptions[that.editorType + '_editor'] = true; + that.syntaxHiglighter = PMA_getSQLEditor($elm, {}, null, linterOptions); + + // Execute item-specific code + that.postDialogShow(data); + } else { + PMA_ajaxShowMessage(data.error, false); + } + }); // end $.get() + }, + + dropDialog: function ($this) { + /** + * @var $curr_row Object containing reference to the current row + */ + var $curr_row = $this.parents('tr'); + /** + * @var question String containing the question to be asked for confirmation + */ + var question = $('
    ').text( + $curr_row.children('td').children('.drop_sql').html() + ); + // We ask for confirmation first here, before submitting the ajax request + $this.PMA_confirm(question, $this.attr('href'), function (url) { + /** + * @var msg jQuery object containing the reference to + * the AJAX message shown to the user + */ + var $msg = PMA_ajaxShowMessage(PMA_messages.strProcessingRequest); + var params = getJSConfirmCommonParam(this, $this.getPostData()); + $.post(url, params, function (data) { + if (data.success === true) { + /** + * @var $table Object containing reference + * to the main list of elements + */ + var $table = $curr_row.parent(); + // Check how many rows will be left after we remove + // the one that the user has requested us to remove + if ($table.find('tr').length === 3) { + // If there are two rows left, it means that they are + // the header of the table and the rows that we are + // about to remove, so after the removal there will be + // nothing to show in the table, so we hide it. + $table.hide('slow', function () { + $(this).find('tr.even, tr.odd').remove(); + $('.withSelected').remove(); + $('#nothing2display').show('slow'); + }); + } else { + $curr_row.hide('slow', function () { + $(this).remove(); + // Now we have removed the row from the list, but maybe + // some row classes are wrong now. So we will itirate + // throught all rows and assign correct classes to them. + /** + * @var ct Count of processed rows + */ + var ct = 0; + /** + * @var rowclass Class to be attached to the row + * that is being processed + */ + var rowclass = ''; + $table.find('tr').has('td').each(function () { + rowclass = (ct % 2 === 1) ? 'odd' : 'even'; + $(this).removeClass().addClass(rowclass); + ct++; + }); + }); + } + // Get rid of the "Loading" message + PMA_ajaxRemoveMessage($msg); + // Show the query that we just executed + PMA_slidingMessage(data.sql_query); + PMA_reloadNavigation(); + } else { + PMA_ajaxShowMessage(data.error, false); + } + }); // end $.post() + }); // end $.PMA_confirm() + }, + + dropMultipleDialog: function ($this) { + // We ask for confirmation here + $this.PMA_confirm(PMA_messages.strDropRTEitems, '', function () { + /** + * @var msg jQuery object containing the reference to + * the AJAX message shown to the user + */ + var $msg = PMA_ajaxShowMessage(PMA_messages.strProcessingRequest); + + // drop anchors of all selected rows + var drop_anchors = $('input.checkall:checked').parents('tr').find('.drop_anchor'); + var success = true; + var count = drop_anchors.length; + var returnCount = 0; + + drop_anchors.each(function () { + var $anchor = $(this); + /** + * @var $curr_row Object containing reference to the current row + */ + var $curr_row = $anchor.parents('tr'); + var params = getJSConfirmCommonParam(this, $anchor.getPostData()); + $.post($anchor.attr('href'), params, function (data) { + returnCount++; + if (data.success === true) { + /** + * @var $table Object containing reference + * to the main list of elements + */ + var $table = $curr_row.parent(); + // Check how many rows will be left after we remove + // the one that the user has requested us to remove + if ($table.find('tr').length === 3) { + // If there are two rows left, it means that they are + // the header of the table and the rows that we are + // about to remove, so after the removal there will be + // nothing to show in the table, so we hide it. + $table.hide('slow', function () { + $(this).find('tr.even, tr.odd').remove(); + $('.withSelected').remove(); + $('#nothing2display').show('slow'); + }); + } else { + $curr_row.hide('fast', function () { + $(this).remove(); + // Now we have removed the row from the list, but maybe + // some row classes are wrong now. So we will itirate + // throught all rows and assign correct classes to them. + /** + * @var ct Count of processed rows + */ + var ct = 0; + /** + * @var rowclass Class to be attached to the row + * that is being processed + */ + var rowclass = ''; + $table.find('tr').has('td').each(function () { + rowclass = (ct % 2 === 1) ? 'odd' : 'even'; + $(this).removeClass().addClass(rowclass); + ct++; + }); + }); + } + if (returnCount === count) { + if (success) { + // Get rid of the "Loading" message + PMA_ajaxRemoveMessage($msg); + $('#rteListForm_checkall').prop({ checked: false, indeterminate: false }); + } + PMA_reloadNavigation(); + } + } else { + PMA_ajaxShowMessage(data.error, false); + success = false; + if (returnCount === count) { + PMA_reloadNavigation(); + } + } + }); // end $.post() + }); // end drop_anchors.each() + }); // end $.PMA_confirm() + } +}; // end RTE namespace + +/** + * @var RTE.EVENT JavaScript functionality for events + */ +RTE.EVENT = { + validateCustom: function () { + /** + * @var elm a jQuery object containing the reference + * to an element that is being validated + */ + var $elm = null; + if (this.$ajaxDialog.find('select[name=item_type]').find(':selected').val() === 'RECURRING') { + // The interval field must not be empty for recurring events + $elm = this.$ajaxDialog.find('input[name=item_interval_value]'); + if ($elm.val() === '') { + $elm.focus(); + alert(PMA_messages.strFormEmpty); + return false; + } + } else { + // The execute_at field must not be empty for "once off" events + $elm = this.$ajaxDialog.find('input[name=item_execute_at]'); + if ($elm.val() === '') { + $elm.focus(); + alert(PMA_messages.strFormEmpty); + return false; + } + } + return true; + } +}; + +/** + * @var RTE.ROUTINE JavaScript functionality for routines + */ +RTE.ROUTINE = { + /** + * Overriding the postDialogShow() function defined in common.js + * + * @param data JSON-encoded data from the ajax request + */ + postDialogShow: function (data) { + // Cache the template for a parameter table row + RTE.param_template = data.param_template; + var that = this; + // Make adjustments in the dialog to make it AJAX compatible + $('td.routine_param_remove').show(); + $('input[name=routine_removeparameter]').remove(); + $('input[name=routine_addparameter]').css('width', '100%'); + // Enable/disable the 'options' dropdowns for parameters as necessary + $('table.routine_params_table').last().find('th[colspan=2]').attr('colspan', '1'); + $('table.routine_params_table').last().find('tr').has('td').each(function () { + that.setOptionsForParameter( + $(this).find('select[name^=item_param_type]'), + $(this).find('input[name^=item_param_length]'), + $(this).find('select[name^=item_param_opts_text]'), + $(this).find('select[name^=item_param_opts_num]') + ); + }); + // Enable/disable the 'options' dropdowns for + // function return value as necessary + this.setOptionsForParameter( + $('table.rte_table').last().find('select[name=item_returntype]'), + $('table.rte_table').last().find('input[name=item_returnlength]'), + $('table.rte_table').last().find('select[name=item_returnopts_text]'), + $('table.rte_table').last().find('select[name=item_returnopts_num]') + ); + // Allow changing parameter order + $('.routine_params_table tbody').sortable({ + containment: '.routine_params_table tbody', + handle: '.dragHandle', + stop: function () { + that.reindexParameters(); + }, + }); + }, + /** + * Reindexes the parameters after dropping a parameter or reordering parameters + */ + reindexParameters: function () { + /** + * @var index Counter used for reindexing the input + * fields in the routine parameters table + */ + var index = 0; + $('table.routine_params_table tbody').find('tr').each(function () { + $(this).find(':input').each(function () { + /** + * @var inputname The value of the name attribute of + * the input field being reindexed + */ + var inputname = $(this).attr('name'); + if (inputname.substr(0, 14) === 'item_param_dir') { + $(this).attr('name', inputname.substr(0, 14) + '[' + index + ']'); + } else if (inputname.substr(0, 15) === 'item_param_name') { + $(this).attr('name', inputname.substr(0, 15) + '[' + index + ']'); + } else if (inputname.substr(0, 15) === 'item_param_type') { + $(this).attr('name', inputname.substr(0, 15) + '[' + index + ']'); + } else if (inputname.substr(0, 17) === 'item_param_length') { + $(this).attr('name', inputname.substr(0, 17) + '[' + index + ']'); + $(this).attr('id', 'item_param_length_' + index); + } else if (inputname.substr(0, 20) === 'item_param_opts_text') { + $(this).attr('name', inputname.substr(0, 20) + '[' + index + ']'); + } else if (inputname.substr(0, 19) === 'item_param_opts_num') { + $(this).attr('name', inputname.substr(0, 19) + '[' + index + ']'); + } + }); + index++; + }); + }, + /** + * Overriding the validateCustom() function defined in common.js + */ + validateCustom: function () { + /** + * @var isSuccess Stores the outcome of the validation + */ + var isSuccess = true; + /** + * @var inputname The value of the "name" attribute for + * the field that is being processed + */ + var inputname = ''; + this.$ajaxDialog.find('table.routine_params_table').last().find('tr').each(function () { + // Every parameter of a routine must have + // a non-empty direction, name and type + if (isSuccess) { + $(this).find(':input').each(function () { + inputname = $(this).attr('name'); + if (inputname.substr(0, 14) === 'item_param_dir' || + inputname.substr(0, 15) === 'item_param_name' || + inputname.substr(0, 15) === 'item_param_type') { + if ($(this).val() === '') { + $(this).focus(); + isSuccess = false; + return false; + } + } + }); + } else { + return false; + } + }); + if (! isSuccess) { + alert(PMA_messages.strFormEmpty); + return false; + } + this.$ajaxDialog.find('table.routine_params_table').last().find('tr').each(function () { + // SET, ENUM, VARCHAR and VARBINARY fields must have length/values + var $inputtyp = $(this).find('select[name^=item_param_type]'); + var $inputlen = $(this).find('input[name^=item_param_length]'); + if ($inputtyp.length && $inputlen.length) { + if (($inputtyp.val() === 'ENUM' || $inputtyp.val() === 'SET' || $inputtyp.val().substr(0, 3) === 'VAR') && + $inputlen.val() === '' + ) { + $inputlen.focus(); + isSuccess = false; + return false; + } + } + }); + if (! isSuccess) { + alert(PMA_messages.strFormEmpty); + return false; + } + if (this.$ajaxDialog.find('select[name=item_type]').find(':selected').val() === 'FUNCTION') { + // The length/values of return variable for functions must + // be set, if the type is SET, ENUM, VARCHAR or VARBINARY. + var $returntyp = this.$ajaxDialog.find('select[name=item_returntype]'); + var $returnlen = this.$ajaxDialog.find('input[name=item_returnlength]'); + if (($returntyp.val() === 'ENUM' || $returntyp.val() === 'SET' || $returntyp.val().substr(0, 3) === 'VAR') && + $returnlen.val() === '' + ) { + $returnlen.focus(); + alert(PMA_messages.strFormEmpty); + return false; + } + } + if ($('select[name=item_type]').find(':selected').val() === 'FUNCTION') { + // A function must contain a RETURN statement in its definition + if (this.$ajaxDialog.find('table.rte_table').find('textarea[name=item_definition]').val().toUpperCase().indexOf('RETURN') < 0) { + this.syntaxHiglighter.focus(); + alert(PMA_messages.MissingReturn); + return false; + } + } + return true; + }, + /** + * Enable/disable the "options" dropdown and "length" input for + * parameters and the return variable in the routine editor + * as necessary. + * + * @param type a jQuery object containing the reference + * to the "Type" dropdown box + * @param len a jQuery object containing the reference + * to the "Length" input box + * @param text a jQuery object containing the reference + * to the dropdown box with options for + * parameters of text type + * @param num a jQuery object containing the reference + * to the dropdown box with options for + * parameters of numeric type + */ + setOptionsForParameter: function ($type, $len, $text, $num) { + /** + * @var no_opts a jQuery object containing the reference + * to an element to be displayed when no + * options are available + */ + var $no_opts = $text.parent().parent().find('.no_opts'); + /** + * @var no_len a jQuery object containing the reference + * to an element to be displayed when no + * "length/values" field is available + */ + var $no_len = $len.parent().parent().find('.no_len'); + + // Process for parameter options + switch ($type.val()) { + case 'TINYINT': + case 'SMALLINT': + case 'MEDIUMINT': + case 'INT': + case 'BIGINT': + case 'DECIMAL': + case 'FLOAT': + case 'DOUBLE': + case 'REAL': + $text.parent().hide(); + $num.parent().show(); + $no_opts.hide(); + break; + case 'TINYTEXT': + case 'TEXT': + case 'MEDIUMTEXT': + case 'LONGTEXT': + case 'CHAR': + case 'VARCHAR': + case 'SET': + case 'ENUM': + $text.parent().show(); + $num.parent().hide(); + $no_opts.hide(); + break; + default: + $text.parent().hide(); + $num.parent().hide(); + $no_opts.show(); + break; + } + // Process for parameter length + switch ($type.val()) { + case 'DATE': + case 'TINYBLOB': + case 'TINYTEXT': + case 'BLOB': + case 'TEXT': + case 'MEDIUMBLOB': + case 'MEDIUMTEXT': + case 'LONGBLOB': + case 'LONGTEXT': + $text.closest('tr').find('a:first').hide(); + $len.parent().hide(); + $no_len.show(); + break; + default: + if ($type.val() === 'ENUM' || $type.val() === 'SET') { + $text.closest('tr').find('a:first').show(); + } else { + $text.closest('tr').find('a:first').hide(); + } + $len.parent().show(); + $no_len.hide(); + break; + } + }, + executeDialog: function ($this) { + var that = this; + /** + * @var msg jQuery object containing the reference to + * the AJAX message shown to the user + */ + var $msg = PMA_ajaxShowMessage(); + var params = { + 'ajax_request': true + }; + $.post($this.attr('href'), params, function (data) { + if (data.success === true) { + PMA_ajaxRemoveMessage($msg); + // If 'data.dialog' is true we show a dialog with a form + // to get the input parameters for routine, otherwise + // we just show the results of the query + if (data.dialog) { + // Define the function that is called when + // the user presses the "Go" button + that.buttonOptions[PMA_messages.strGo] = function () { + /** + * @var data Form data to be sent in the AJAX request + */ + var data = $('form.rte_form').last().serialize(); + $msg = PMA_ajaxShowMessage( + PMA_messages.strProcessingRequest + ); + $.post('db_routines.php', data, function (data) { + if (data.success === true) { + // Routine executed successfully + PMA_ajaxRemoveMessage($msg); + PMA_slidingMessage(data.message); + $ajaxDialog.dialog('close'); + } else { + PMA_ajaxShowMessage(data.error, false); + } + }); + }; + that.buttonOptions[PMA_messages.strClose] = function () { + $(this).dialog('close'); + }; + /** + * Display the dialog to the user + */ + var $ajaxDialog = $('
    ' + data.message + '
    ').dialog({ + width: 650, + buttons: that.buttonOptions, + title: data.title, + modal: true, + close: function () { + $(this).remove(); + } + }); + $ajaxDialog.find('input[name^=params]').first().focus(); + /** + * Attach the datepickers to the relevant form fields + */ + $ajaxDialog.find('input.datefield, input.datetimefield').each(function () { + PMA_addDatepicker($(this).css('width', '95%')); + }); + /* + * Define the function if the user presses enter + */ + $('form.rte_form').on('keyup', function (event) { + event.preventDefault(); + if (event.keyCode === 13) { + /** + * @var data Form data to be sent in the AJAX request + */ + var data = $(this).serialize(); + $msg = PMA_ajaxShowMessage( + PMA_messages.strProcessingRequest + ); + var url = $(this).attr('action'); + $.post(url, data, function (data) { + if (data.success === true) { + // Routine executed successfully + PMA_ajaxRemoveMessage($msg); + PMA_slidingMessage(data.message); + $('form.rte_form').off('keyup'); + $ajaxDialog.remove(); + } else { + PMA_ajaxShowMessage(data.error, false); + } + }); + } + }); + } else { + // Routine executed successfully + PMA_slidingMessage(data.message); + } + } else { + PMA_ajaxShowMessage(data.error, false); + } + }); // end $.post() + } +}; + +export default RTE; diff --git a/js/src/rte.js b/js/src/rte.js new file mode 100644 index 0000000000..b5da79a06a --- /dev/null +++ b/js/src/rte.js @@ -0,0 +1,166 @@ +/* vim: set expandtab sw=4 ts=4 sts=4: */ + +/* Module import */ +import RTE from './classes/RTE'; + +/** + * Attach Ajax event handlers for the Routines, Triggers and Events editor + */ +$(function () { + /** + * Attach Ajax event handlers for the Add/Edit functionality. + */ + $(document).on('click', 'a.ajax.add_anchor, a.ajax.edit_anchor', function (event) { + event.preventDefault(); + var type = $(this).attr('href').substr(0, $(this).attr('href').indexOf('?')); + if (type.indexOf('routine') !== -1) { + type = 'routine'; + } else if (type.indexOf('trigger') !== -1) { + type = 'trigger'; + } else if (type.indexOf('event') !== -1) { + type = 'event'; + } else { + type = ''; + } + var dialog = new RTE.object(type); + dialog.editorDialog($(this).hasClass('add_anchor'), $(this)); + }); // end $(document).on() + + /** + * Attach Ajax event handlers for the Execute routine functionality + */ + $(document).on('click', 'a.ajax.exec_anchor', function (event) { + event.preventDefault(); + var dialog = new RTE.object('routine'); + dialog.executeDialog($(this)); + }); // end $(document).on() + + /** + * Attach Ajax event handlers for Export of Routines, Triggers and Events + */ + $(document).on('click', 'a.ajax.export_anchor', function (event) { + event.preventDefault(); + var dialog = new RTE.object(); + dialog.exportDialog($(this)); + }); // end $(document).on() + + $(document).on('click', '#rteListForm.ajax .mult_submit[value="export"]', function (event) { + event.preventDefault(); + var dialog = new RTE.object(); + dialog.exportDialog($(this)); + }); // end $(document).on() + + /** + * Attach Ajax event handlers for Drop functionality + * of Routines, Triggers and Events. + */ + $(document).on('click', 'a.ajax.drop_anchor', function (event) { + event.preventDefault(); + var dialog = new RTE.object(); + dialog.dropDialog($(this)); + }); // end $(document).on() + + $(document).on('click', '#rteListForm.ajax .mult_submit[value="drop"]', function (event) { + event.preventDefault(); + var dialog = new RTE.object(); + dialog.dropMultipleDialog($(this)); + }); // end $(document).on() + + /** + * Attach Ajax event handlers for the "Change event/routine type" + * functionality in the events editor, so that the correct + * rows are shown in the editor when changing the event type + */ + $(document).on('change', 'select[name=item_type]', function () { + $(this) + .closest('table') + .find('tr.recurring_event_row, tr.onetime_event_row, tr.routine_return_row, .routine_direction_cell') + .toggle(); + }); // end $(document).on() + + /** + * Attach Ajax event handlers for the "Change parameter type" + * functionality in the routines editor, so that the correct + * option/length fields, if any, are shown when changing + * a parameter type + */ + $(document).on('change', 'select[name^=item_param_type]', function () { + /** + * @var row jQuery object containing the reference to + * a row in the routine parameters table + */ + var $row = $(this).parents('tr').first(); + var rte = new RTE.object('routine'); + rte.setOptionsForParameter( + $row.find('select[name^=item_param_type]'), + $row.find('input[name^=item_param_length]'), + $row.find('select[name^=item_param_opts_text]'), + $row.find('select[name^=item_param_opts_num]') + ); + }); // end $(document).on() + + /** + * Attach Ajax event handlers for the "Change the type of return + * variable of function" functionality, so that the correct fields, + * if any, are shown when changing the function return type type + */ + $(document).on('change', 'select[name=item_returntype]', function () { + var rte = new RTE.object('routine'); + var $table = $(this).closest('table.rte_table'); + rte.setOptionsForParameter( + $table.find('select[name=item_returntype]'), + $table.find('input[name=item_returnlength]'), + $table.find('select[name=item_returnopts_text]'), + $table.find('select[name=item_returnopts_num]') + ); + }); // end $(document).on() + + /** + * Attach Ajax event handlers for the "Add parameter to routine" functionality + */ + $(document).on('click', 'input[name=routine_addparameter]', function (event) { + event.preventDefault(); + /** + * @var routine_params_table jQuery object containing the reference + * to the routine parameters table + */ + var $routine_params_table = $(this).closest('div.ui-dialog').find('.routine_params_table'); + /** + * @var new_param_row A string containing the HTML code for the + * new row for the routine parameters table + */ + var new_param_row = RTE.param_template.replace(/%s/g, $routine_params_table.find('tr').length - 1); + // Append the new row to the parameters table + $routine_params_table.append(new_param_row); + // Make sure that the row is correctly shown according to the type of routine + if ($(this).closest('div.ui-dialog').find('table.rte_table select[name=item_type]').val() === 'FUNCTION') { + $('tr.routine_return_row').show(); + $('td.routine_direction_cell').hide(); + } + /** + * @var newrow jQuery object containing the reference to the newly + * inserted row in the routine parameters table + */ + var $newrow = $(this).closest('div.ui-dialog').find('table.routine_params_table').find('tr').has('td').last(); + // Enable/disable the 'options' dropdowns for parameters as necessary + var rte = new RTE.object('routine'); + rte.setOptionsForParameter( + $newrow.find('select[name^=item_param_type]'), + $newrow.find('input[name^=item_param_length]'), + $newrow.find('select[name^=item_param_opts_text]'), + $newrow.find('select[name^=item_param_opts_num]') + ); + }); // end $(document).on() + + /** + * Attach Ajax event handlers for the + * "Remove parameter from routine" functionality + */ + $(document).on('click', 'a.routine_param_remove_anchor', function (event) { + event.preventDefault(); + $(this).parent().parent().remove(); + // After removing a parameter, the indices of the name attributes in + // the input fields lose the correct order and need to be reordered. + RTE.ROUTINE.reindexParameters(); + }); // end $(document).on() +}); // end of $() From 074c5063ab9ae01be717cd42500308497e16390d Mon Sep 17 00:00:00 2001 From: Piyush Vijay Date: Thu, 20 Sep 2018 04:38:09 +0530 Subject: [PATCH 5/8] Whitelist RTE.js in modular code and add some related function for sliding messages in show_ajax_messages.js. Signed-Off-By: Piyush Vijay --- js/src/consts/files.js | 6 +- js/src/navigation.js | 3 + js/src/utils/show_ajax_messages.js | 90 +++++++++++++++++++++++++++++- libraries/classes/Header.php | 2 +- 4 files changed, 97 insertions(+), 4 deletions(-) diff --git a/js/src/consts/files.js b/js/src/consts/files.js index d2606443bd..9ab3ef010a 100644 --- a/js/src/consts/files.js +++ b/js/src/consts/files.js @@ -17,7 +17,8 @@ const PhpToJsFileMapping = { 'indexes', 'key_handler', 'cross_framing_protection', - 'drag_drop_import' + 'drag_drop_import', + 'rte' ], server_privileges: ['server_privileges'], server_databases: ['server_databases'], @@ -100,7 +101,8 @@ const JsFileList = [ 'key_handler', 'cross_framing_protection', 'drag_drop_import', - 'normalization' + 'normalization', + 'rte' ]; export { diff --git a/js/src/navigation.js b/js/src/navigation.js index c09292075b..bfb990e5c9 100644 --- a/js/src/navigation.js +++ b/js/src/navigation.js @@ -1,10 +1,13 @@ /* vim: set expandtab sw=4 ts=4 sts=4: */ + +/* Module import */ import * as Navigation from './functions/navigation'; import { PMA_Messages as PMA_messages } from './variables/export_variables'; import CommonParams from './variables/common_params'; import { PMA_ajaxShowMessage, PMA_ajaxRemoveMessage, PMA_tooltip } from './utils/show_ajax_messages'; import { isStorageSupported } from './functions/config'; import { indexEditorDialog } from './functions/Indexes'; +import RTE from './classes/RTE'; /** * function used in or for navigation panel diff --git a/js/src/utils/show_ajax_messages.js b/js/src/utils/show_ajax_messages.js index b8be628bd9..5aa74b313b 100644 --- a/js/src/utils/show_ajax_messages.js +++ b/js/src/utils/show_ajax_messages.js @@ -220,11 +220,99 @@ function PMA_ajaxRemoveMessage ($thisMsgbox) { } } +/** + * Creates a message inside an object with a sliding effect + * + * @param msg A string containing the text to display + * @param $obj a jQuery object containing the reference + * to the element where to put the message + * This is optional, if no element is + * provided, one will be created below the + * navigation links at the top of the page + * + * @return bool True on success, false on failure + */ +function PMA_slidingMessage (msg, $obj) { + if (msg === undefined || msg.length === 0) { + // Don't show an empty message + return false; + } + if ($obj === undefined || !($obj instanceof jQuery) || $obj.length === 0) { + // If the second argument was not supplied, + // we might have to create a new DOM node. + if ($('#PMA_slidingMessage').length === 0) { + $('#page_content').prepend( + '' + ); + } + $obj = $('#PMA_slidingMessage'); + } + if ($obj.has('div').length > 0) { + // If there already is a message inside the + // target object, we must get rid of it + $obj + .find('div') + .first() + .fadeOut(function () { + $obj + .children() + .remove(); + $obj + .append('
    ' + msg + '
    '); + // highlight any sql before taking height; + PMA_highlightSQL($obj); + $obj.find('div') + .first() + .hide(); + $obj + .animate({ + height: $obj.find('div').first().height() + }) + .find('div') + .first() + .fadeIn(); + }); + } else { + // Object does not already have a message + // inside it, so we simply slide it down + $obj.width('100%') + .html('
    ' + msg + '
    '); + // highlight any sql before taking height; + PMA_highlightSQL($obj); + var h = $obj + .find('div') + .first() + .hide() + .height(); + $obj + .find('div') + .first() + .css('height', 0) + .show() + .animate({ + height: h + }, function () { + // Set the height of the parent + // to the height of the child + $obj + .height( + $obj + .find('div') + .first() + .height() + ); + }); + } + return true; +} // end PMA_slidingMessage() + /** * Module export */ export { PMA_ajaxRemoveMessage, PMA_ajaxShowMessage, - PMA_tooltip + PMA_tooltip, + PMA_slidingMessage }; diff --git a/libraries/classes/Header.php b/libraries/classes/Header.php index c771be2bbc..4d7bdfb6db 100644 --- a/libraries/classes/Header.php +++ b/libraries/classes/Header.php @@ -189,7 +189,7 @@ class Header if ($GLOBALS['cfg']['AllowThirdPartyFraming'] === false) { $this->_scripts->addFile('cross_framing_protection'); } - $this->_scripts->addFile('rte.js'); + $this->_scripts->addFile('rte'); if ($GLOBALS['cfg']['SendErrorReports'] !== 'never') { $this->_scripts->addFile('vendor/tracekit.js'); $this->_scripts->addFile('error_report.js'); From b5824ef13ecb9c8cf5de61b39fcb196435ce846b Mon Sep 17 00:00:00 2001 From: Piyush Vijay Date: Thu, 20 Sep 2018 05:24:35 +0530 Subject: [PATCH 6/8] Structure some code for replication.js and tbl_operation.js Signed-Off-By: Piyush Vijay --- js/src/db_operations.js | 3 ++- js/src/replication.js | 11 ++++++++--- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/js/src/db_operations.js b/js/src/db_operations.js index b45c1b038d..fcb9af1eae 100644 --- a/js/src/db_operations.js +++ b/js/src/db_operations.js @@ -12,6 +12,7 @@ import { escapeHtml } from './utils/Sanitise'; import { PMA_prepareForAjaxRequest } from './functions/AjaxRequest'; import { PMA_sprintf } from './utils/sprintf'; import { getJSConfirmCommonParam } from './functions/Common'; +import { PMA_reloadNavigation } from './functions/navigation'; /** * @fileoverview function used in server privilege pages @@ -74,7 +75,7 @@ export function onloadDbOperations () { PMA_reloadNavigation(function () { $('#pma_navigation_tree') .find('a:not(\'.expander\')') - .each(function (index) { + .each(function () { var $thisAnchor = $(this); if ($thisAnchor.text() === data.newname) { // simulate a click on the new db name diff --git a/js/src/replication.js b/js/src/replication.js index 2bb0d297d2..a5be3886f2 100644 --- a/js/src/replication.js +++ b/js/src/replication.js @@ -1,7 +1,12 @@ /* vim: set expandtab sw=4 ts=4 sts=4: */ + +/* Module Import */ +import { PMA_messages as PMA_messages } from './variables/export_variables'; +import { PMA_ajaxShowMessage } from './utils/show_ajax_messages'; +import { AJAX } from './ajax'; + /** * for server_replication.php - * */ var random_server_id = Math.floor(Math.random() * 10000000); var conf_prefix = 'server-id=' + random_server_id + '\nlog_bin=mysql-bin\nlog_error=mysql-bin.err\n'; @@ -29,7 +34,7 @@ function update_config () { /** * Unbind all event handlers before tearing down a page */ -export function teardown1 () { +export function teardownReplication () { $('#db_type').off('change'); $('#db_select').off('change'); $('#master_status_href').off('click'); @@ -43,7 +48,7 @@ export function teardown1 () { $('#reset_slave').off('click'); } -export function onload1 () { +export function onloadReplication () { $('#rep').text(conf_prefix); $('#db_type').on('change', update_config); $('#db_select').on('change', update_config); From fd4e5f0c54172e34a5b24d9ac0face19a8e3f995 Mon Sep 17 00:00:00 2001 From: Piyush Vijay Date: Thu, 20 Sep 2018 05:25:39 +0530 Subject: [PATCH 7/8] Remove some of the duplicate files for code cleanup. Signed-Off-By: Piyush Vijay --- js/cross_framing_protection.js | 14 - js/drag_drop_import.js | 393 ------------ js/keyhandler.js | 140 ----- js/multi_column_sort.js | 84 --- js/normalization.js | 729 --------------------- js/page_settings.js | 59 -- js/replication.js | 92 --- js/rte.js | 1077 -------------------------------- 8 files changed, 2588 deletions(-) delete mode 100644 js/cross_framing_protection.js delete mode 100644 js/drag_drop_import.js delete mode 100644 js/keyhandler.js delete mode 100644 js/multi_column_sort.js delete mode 100644 js/normalization.js delete mode 100644 js/page_settings.js delete mode 100644 js/replication.js delete mode 100644 js/rte.js diff --git a/js/cross_framing_protection.js b/js/cross_framing_protection.js deleted file mode 100644 index 40f3a398ad..0000000000 --- a/js/cross_framing_protection.js +++ /dev/null @@ -1,14 +0,0 @@ -/* vim: set expandtab sw=4 ts=4 sts=4: */ -/** - * Conditionally included if framing is not allowed - */ -if (self === top) { - var style_element = document.getElementById('cfs-style'); - // check if style_element has already been removed - // to avoid frequently reported js error - if (typeof(style_element) !== 'undefined' && style_element !== null) { - style_element.parentNode.removeChild(style_element); - } -} else { - top.location = self.location; -} diff --git a/js/drag_drop_import.js b/js/drag_drop_import.js deleted file mode 100644 index 73483373dd..0000000000 --- a/js/drag_drop_import.js +++ /dev/null @@ -1,393 +0,0 @@ -/* vim: set expandtab sw=4 ts=4 sts=4: */ - -/* This script handles PMA Drag Drop Import, loaded only when configuration is enabled.*/ - -/** - * Class to handle PMA Drag and Drop Import - * feature - */ -PMA_DROP_IMPORT = { - /** - * @var int, count of total uploads in this view - */ - uploadCount: 0, - /** - * @var int, count of live uploads - */ - liveUploadCount: 0, - /** - * @var string array, allowed extensions - */ - allowedExtensions: ['sql', 'xml', 'ldi', 'mediawiki', 'shp'], - /** - * @var string array, allowed extensions for compressed files - */ - allowedCompressedExtensions: ['gz', 'bz2', 'zip'], - /** - * @var obj array to store message returned by import_status.php - */ - importStatus: [], - /** - * Checks if any dropped file has valid extension or not - * - * @param file filename - * - * @return string, extension for valid extension, '' otherwise - */ - _getExtension: function (file) { - var arr = file.split('.'); - ext = arr[arr.length - 1]; - - // check if compressed - if (jQuery.inArray(ext.toLowerCase(), - PMA_DROP_IMPORT.allowedCompressedExtensions) !== -1) { - ext = arr[arr.length - 2]; - } - - // Now check for extension - if (jQuery.inArray(ext.toLowerCase(), - PMA_DROP_IMPORT.allowedExtensions) !== -1) { - return ext; - } - return ''; - }, - /** - * Shows upload progress for different sql uploads - * - * @param: hash (string), hash for specific file upload - * @param: percent (float), file upload percentage - * - * @return void - */ - _setProgress: function (hash, percent) { - $('.pma_sql_import_status div li[data-hash="' + hash + '"]') - .children('progress').val(percent); - }, - /** - * Function to upload the file asynchronously - * - * @param formData FormData object for a specific file - * @param hash hash of the current file upload - * - * @return void - */ - _sendFileToServer: function (formData, hash) { - var uploadURL = './import.php'; // Upload URL - var extraData = {}; - var jqXHR = $.ajax({ - xhr: function () { - var xhrobj = $.ajaxSettings.xhr(); - if (xhrobj.upload) { - xhrobj.upload.addEventListener('progress', function (event) { - var percent = 0; - var position = event.loaded || event.position; - var total = event.total; - if (event.lengthComputable) { - percent = Math.ceil(position / total * 100); - } - // Set progress - PMA_DROP_IMPORT._setProgress(hash, percent); - }, false); - } - return xhrobj; - }, - url: uploadURL, - type: 'POST', - contentType:false, - processData: false, - cache: false, - data: formData, - success: function (data) { - PMA_DROP_IMPORT._importFinished(hash, false, data.success); - if (!data.success) { - PMA_DROP_IMPORT.importStatus[PMA_DROP_IMPORT.importStatus.length] = { - hash: hash, - message: data.error - }; - } - } - }); - - // -- provide link to cancel the upload - $('.pma_sql_import_status div li[data-hash="' + hash + - '"] span.filesize').html('' + - PMA_messages.dropImportMessageCancel + ''); - - // -- add event listener to this link to abort upload operation - $('.pma_sql_import_status div li[data-hash="' + hash + - '"] span.filesize span.pma_drop_file_status') - .on('click', function () { - if ($(this).attr('task') === 'cancel') { - jqXHR.abort(); - $(this).html('' + PMA_messages.dropImportMessageAborted + ''); - PMA_DROP_IMPORT._importFinished(hash, true, false); - } else if ($(this).children('span').html() === - PMA_messages.dropImportMessageFailed) { - // -- view information - var $this = $(this); - $.each(PMA_DROP_IMPORT.importStatus, - function (key, value) { - if (value.hash === hash) { - $('.pma_drop_result:visible').remove(); - var filename = $this.parent('span').attr('data-filename'); - $('body').append('

    ' + - PMA_messages.dropImportImportResultHeader + ' - ' + - filename + 'x

    ' + value.message + '
    '); - $('.pma_drop_result').draggable(); // to make this dialog draggable - } - }); - } - }); - }, - /** - * Triggered when an object is dragged into the PMA UI - * - * @param event obj - * - * @return void - */ - _dragenter : function (event) { - // We don't want to prevent users from using - // browser's default drag-drop feature on some page(s) - if ($('.noDragDrop').length !== 0) { - return; - } - - event.stopPropagation(); - event.preventDefault(); - if (!PMA_DROP_IMPORT._hasFiles(event)) { - return; - } - if (PMA_commonParams.get('db') === '') { - $('.pma_drop_handler').html(PMA_messages.dropImportSelectDB); - } else { - $('.pma_drop_handler').html(PMA_messages.dropImportDropFiles); - } - $('.pma_drop_handler').fadeIn(); - }, - /** - * Check if dragged element contains Files - * - * @param event the event object - * - * @return bool - */ - _hasFiles: function (event) { - return !(typeof event.originalEvent.dataTransfer.types === 'undefined' || - $.inArray('Files', event.originalEvent.dataTransfer.types) < 0 || - $.inArray( - 'application/x-moz-nativeimage', - event.originalEvent.dataTransfer.types - ) >= 0); - }, - /** - * Triggered when dragged file is being dragged over PMA UI - * - * @param event obj - * - * @return void - */ - _dragover: function (event) { - // We don't want to prevent users from using - // browser's default drag-drop feature on some page(s) - if ($('.noDragDrop').length !== 0) { - return; - } - - event.stopPropagation(); - event.preventDefault(); - if (!PMA_DROP_IMPORT._hasFiles(event)) { - return; - } - $('.pma_drop_handler').fadeIn(); - }, - /** - * Triggered when dragged objects are left - * - * @param event obj - * - * @return void - */ - _dragleave: function (event) { - // We don't want to prevent users from using - // browser's default drag-drop feature on some page(s) - if ($('.noDragDrop').length !== 0) { - return; - } - event.stopPropagation(); - event.preventDefault(); - var $pma_drop_handler = $('.pma_drop_handler'); - $pma_drop_handler.clearQueue().stop(); - $pma_drop_handler.fadeOut(); - $pma_drop_handler.html(PMA_messages.dropImportDropFiles); - }, - /** - * Called when upload has finished - * - * @param string, unique hash for a certain upload - * @param bool, true if upload was aborted - * @param bool, status of sql upload, as sent by server - * - * @return void - */ - _importFinished: function (hash, aborted, status) { - $('.pma_sql_import_status div li[data-hash="' + hash + '"]') - .children('progress').hide(); - var icon = 'icon ic_s_success'; - // -- provide link to view upload status - if (!aborted) { - if (status) { - $('.pma_sql_import_status div li[data-hash="' + hash + - '"] span.filesize span.pma_drop_file_status') - .html('' + PMA_messages.dropImportMessageSuccess + ''); - } else { - $('.pma_sql_import_status div li[data-hash="' + hash + - '"] span.filesize span.pma_drop_file_status') - .html('' + PMA_messages.dropImportMessageFailed + - ''); - icon = 'icon ic_s_error'; - } - } else { - icon = 'icon ic_s_notice'; - } - $('.pma_sql_import_status div li[data-hash="' + hash + - '"] span.filesize span.pma_drop_file_status') - .attr('task', 'info'); - - // Set icon - $('.pma_sql_import_status div li[data-hash="' + hash + '"]') - .prepend(' '); - - // Decrease liveUploadCount by one - $('.pma_import_count').html(--PMA_DROP_IMPORT.liveUploadCount); - if (!PMA_DROP_IMPORT.liveUploadCount) { - $('.pma_sql_import_status h2 .close').fadeIn(); - } - }, - /** - * Triggered when dragged objects are dropped to UI - * From this function, the AJAX Upload operation is initiated - * - * @param event object - * - * @return void - */ - _drop: function (event) { - // We don't want to prevent users from using - // browser's default drag-drop feature on some page(s) - if ($('.noDragDrop').length !== 0) { - return; - } - - var dbname = PMA_commonParams.get('db'); - var server = PMA_commonParams.get('server'); - - // if no database is selected -- no - if (dbname !== '') { - var files = event.originalEvent.dataTransfer.files; - if (!files || files.length === 0) { - // No files actually transferred - $('.pma_drop_handler').fadeOut(); - event.stopPropagation(); - event.preventDefault(); - return; - } - $('.pma_sql_import_status').slideDown(); - for (var i = 0; i < files.length; i++) { - var ext = (PMA_DROP_IMPORT._getExtension(files[i].name)); - var hash = AJAX.hash(++PMA_DROP_IMPORT.uploadCount); - - var $pma_sql_import_status_div = $('.pma_sql_import_status div'); - $pma_sql_import_status_div.append('
  • ' + - ((ext !== '') ? '' : ' ') + - escapeHtml(files[i].name) + '' + (files[i].size / 1024).toFixed(2) + - ' kb
  • '); - - // scroll the UI to bottom - $pma_sql_import_status_div.scrollTop( - $pma_sql_import_status_div.scrollTop() + 50 - ); // 50 hardcoded for now - - if (ext !== '') { - // Increment liveUploadCount by one - $('.pma_import_count').html(++PMA_DROP_IMPORT.liveUploadCount); - $('.pma_sql_import_status h2 .close').fadeOut(); - - $('.pma_sql_import_status div li[data-hash="' + hash + '"]') - .append('
    '); - - // uploading - var fd = new FormData(); - fd.append('import_file', files[i]); - fd.append('noplugin', Math.random().toString(36).substring(2, 12)); - fd.append('db', dbname); - fd.append('server', server); - fd.append('token', PMA_commonParams.get('token')); - fd.append('import_type', 'database'); - // todo: method to find the value below - fd.append('MAX_FILE_SIZE', '4194304'); - // todo: method to find the value below - fd.append('charset_of_file','utf-8'); - // todo: method to find the value below - fd.append('allow_interrupt', 'yes'); - fd.append('skip_queries', '0'); - fd.append('format',ext); - fd.append('sql_compatibility','NONE'); - fd.append('sql_no_auto_value_on_zero','something'); - fd.append('ajax_request','true'); - fd.append('hash', hash); - - // init uploading - PMA_DROP_IMPORT._sendFileToServer(fd, hash); - } else if (!PMA_DROP_IMPORT.liveUploadCount) { - $('.pma_sql_import_status h2 .close').fadeIn(); - } - } - } - $('.pma_drop_handler').fadeOut(); - event.stopPropagation(); - event.preventDefault(); - } -}; - -/** - * Called when some user drags, dragover, leave - * a file to the PMA UI - * @param object Event data - * @return void - */ -$(document).on('dragenter', PMA_DROP_IMPORT._dragenter); -$(document).on('dragover', PMA_DROP_IMPORT._dragover); -$(document).on('dragleave', '.pma_drop_handler', PMA_DROP_IMPORT._dragleave); - -// when file is dropped to PMA UI -$(document).on('drop', 'body', PMA_DROP_IMPORT._drop); - -// minimizing-maximising the sql ajax upload status -$(document).on('click', '.pma_sql_import_status h2 .minimize', function () { - if ($(this).attr('toggle') === 'off') { - $('.pma_sql_import_status div').css('height','270px'); - $(this).attr('toggle','on'); - $(this).html('-'); // to minimize - } else { - $('.pma_sql_import_status div').css('height','0px'); - $(this).attr('toggle','off'); - $(this).html('+'); // to maximise - } -}); - -// closing sql ajax upload status -$(document).on('click', '.pma_sql_import_status h2 .close', function () { - $('.pma_sql_import_status').fadeOut(function () { - $('.pma_sql_import_status div').html(''); - PMA_DROP_IMPORT.importStatus = []; // clear the message array - }); -}); - -// Closing the import result box -$(document).on('click', '.pma_drop_result h2 .close', function () { - $(this).parent('h2').parent('div').remove(); -}); diff --git a/js/keyhandler.js b/js/keyhandler.js deleted file mode 100644 index a5e459fa1a..0000000000 --- a/js/keyhandler.js +++ /dev/null @@ -1,140 +0,0 @@ -/* vim: set expandtab sw=4 ts=4 sts=4: */ - -// global var that holds: 0- if ctrl key is not pressed 1- if ctrl key is pressed -var ctrlKeyHistory = 0; - -/** - * Allows moving around inputs/select by Ctrl+arrows - * - * @param object event data - */ -function onKeyDownArrowsHandler (e) { - e = e || window.event; - - var o = (e.srcElement || e.target); - if (!o) { - return; - } - if (o.tagName !== 'TEXTAREA' && o.tagName !== 'INPUT' && o.tagName !== 'SELECT') { - return; - } - if ((e.which !== 17) && (e.which !== 37) && (e.which !== 38) && (e.which !== 39) && (e.which !== 40)) { - return; - } - if (!o.id) { - return; - } - - if (e.type === 'keyup') { - if (e.which === 17) { - ctrlKeyHistory = 0; - } - return; - } else if (e.type === 'keydown') { - if (e.which === 17) { - ctrlKeyHistory = 1; - } - } - - if (ctrlKeyHistory !== 1) { - return; - } - - e.preventDefault(); - - var pos = o.id.split('_'); - if (pos[0] !== 'field' || typeof pos[2] === 'undefined') { - return; - } - - var x = pos[2]; - var y = pos[1]; - - switch (e.keyCode) { - case 38: - // up - y--; - break; - case 40: - // down - y++; - break; - case 37: - // left - x--; - break; - case 39: - // right - x++; - break; - default: - return; - } - - var is_firefox = navigator.userAgent.toLowerCase().indexOf('firefox/') > -1; - - var id = 'field_' + y + '_' + x; - - var nO = document.getElementById(id); - if (! nO) { - id = 'field_' + y + '_' + x + '_0'; - nO = document.getElementById(id); - } - - // skip non existent fields - if (! nO) { - return; - } - - // for firefox select tag - var lvalue = o.selectedIndex; - var nOvalue = nO.selectedIndex; - - nO.focus(); - - if (is_firefox) { - var ffcheck = 0; - var ffversion; - for (ffversion = 3 ; ffversion < 25 ; ffversion++) { - var is_firefox_v_24 = navigator.userAgent.toLowerCase().indexOf('firefox/' + ffversion) > -1; - if (is_firefox_v_24) { - ffcheck = 1; - break; - } - } - if (ffcheck === 1) { - if (e.which === 38 || e.which === 37) { - nOvalue++; - } else if (e.which === 40 || e.which === 39) { - nOvalue--; - } - nO.selectedIndex = nOvalue; - } else { - if (e.which === 38 || e.which === 37) { - lvalue++; - } else if (e.which === 40 || e.which === 39) { - lvalue--; - } - o.selectedIndex = lvalue; - } - } - - if (nO.tagName !== 'SELECT') { - nO.select(); - } - e.returnValue = false; -} - -AJAX.registerTeardown('keyhandler.js', function () { - $(document).off('keydown keyup', '#table_columns'); - $(document).off('keydown keyup', 'table.insertRowTable'); -}); - -AJAX.registerOnload('keyhandler.js', function () { - $(document).on('keydown keyup', '#table_columns', function (event) { - onKeyDownArrowsHandler(event.originalEvent); - }); - $(document).on('keydown keyup', 'table.insertRowTable', function (event) { - onKeyDownArrowsHandler(event.originalEvent); - }); -}); diff --git a/js/multi_column_sort.js b/js/multi_column_sort.js deleted file mode 100644 index cc9b92150f..0000000000 --- a/js/multi_column_sort.js +++ /dev/null @@ -1,84 +0,0 @@ -/* vim: set expandtab sw=4 ts=4 sts=4: */ -/** - * @fileoverview Implements the shiftkey + click remove column - * from order by clause funcationality - * @name columndelete - * - * @requires jQuery - */ - -function captureURL (url) { - var URL = {}; - url = '' + url; - // Exclude the url part till HTTP - url = url.substr(url.search('sql.php'), url.length); - // The url part between ORDER BY and &session_max_rows needs to be replaced. - URL.head = url.substr(0, url.indexOf('ORDER+BY') + 9); - URL.tail = url.substr(url.indexOf('&session_max_rows'), url.length); - return URL; -} - -/** - * This function is for navigating to the generated URL - * - * @param object target HTMLAnchor element - * @param object parent HTMLDom Object - */ - -function removeColumnFromMultiSort (target, parent) { - var URL = captureURL(target); - var begin = target.indexOf('ORDER+BY') + 8; - var end = target.indexOf(PMA_commonParams.get('arg_separator') + 'session_max_rows'); - // get the names of the columns involved - var between_part = target.substr(begin, end - begin); - var columns = between_part.split('%2C+'); - // If the given column is not part of the order clause exit from this function - var index = parent.find('small').length ? parent.find('small').text() : ''; - if (index === '') { - return ''; - } - // Remove the current clicked column - columns.splice(index - 1, 1); - // If all the columns have been removed dont submit a query with nothing - // After order by clause. - if (columns.length === 0) { - var head = URL.head; - head = head.slice(0,head.indexOf('ORDER+BY')); - URL.head = head; - // removing the last sort order should have priority over what - // is remembered via the RememberSorting directive - URL.tail += PMA_commonParams.get('arg_separator') + 'discard_remembered_sort=1'; - } - URL.head = URL.head.substring(URL.head.indexOf('?') + 1); - var middle_part = columns.join('%2C+'); - params = URL.head + middle_part + URL.tail; - return params; -} - -AJAX.registerOnload('keyhandler.js', function () { - $('th.draggable.column_heading.pointer.marker a').on('click', function (event) { - var url = $(this).parent().find('input').val(); - var argsep = PMA_commonParams.get('arg_separator'); - if (event.ctrlKey || event.altKey) { - event.preventDefault(); - var params = removeColumnFromMultiSort(url, $(this).parent()); - if (params) { - AJAX.source = $(this); - PMA_ajaxShowMessage(); - params += argsep + 'ajax_request=true' + argsep + 'ajax_page_request=true'; - $.post('sql.php', params, AJAX.responseHandler); - } - } else if (event.shiftKey) { - event.preventDefault(); - AJAX.source = $(this); - PMA_ajaxShowMessage(); - var params = url.substring(url.indexOf('?') + 1); - params += argsep + 'ajax_request=true' + argsep + 'ajax_page_request=true'; - $.post('sql.php', params, AJAX.responseHandler); - } - }); -}); - -AJAX.registerTeardown('keyhandler.js', function () { - $(document).off('click', 'th.draggable.column_heading.pointer.marker a'); -}); diff --git a/js/normalization.js b/js/normalization.js deleted file mode 100644 index 41de567f29..0000000000 --- a/js/normalization.js +++ /dev/null @@ -1,729 +0,0 @@ -/* vim: set expandtab sw=4 ts=4 sts=4: */ -/** - * @fileoverview events handling from normalization page - * @name normalization - * - * @requires jQuery - */ - -/** - * AJAX scripts for normalization.php - * - */ - -var normalizeto = '1nf'; -var primary_key; -var data_parsed = null; -function appendHtmlColumnsList () { - $.get( - 'normalization.php', - { - 'ajax_request': true, - 'db': PMA_commonParams.get('db'), - 'table': PMA_commonParams.get('table'), - 'getColumns': true - }, - function (data) { - if (data.success === true) { - $('select[name=makeAtomic]').html(data.message); - } - } - ); -} -function goTo3NFStep1 (newTables) { - if (Object.keys(newTables).length === 1) { - newTables = [PMA_commonParams.get('table')]; - } - $.post( - 'normalization.php', - { - 'ajax_request': true, - 'db': PMA_commonParams.get('db'), - 'tables': newTables, - 'step': '3.1' - }, function (data) { - $('#page_content').find('h3').html(PMA_messages.str3NFNormalization); - $('#mainContent').find('legend').html(data.legendText); - $('#mainContent').find('h4').html(data.headText); - $('#mainContent').find('p').html(data.subText); - $('#mainContent').find('#extra').html(data.extra); - $('#extra').find('form').each(function () { - var form_id = $(this).attr('id'); - var colname = $(this).data('colname'); - $('#' + form_id + ' input[value=\'' + colname + '\']').next().remove(); - $('#' + form_id + ' input[value=\'' + colname + '\']').remove(); - }); - $('#mainContent').find('#newCols').html(''); - $('.tblFooters').html(''); - - if (data.subText !== '') { - $('') - .attr({ type: 'button', value: PMA_messages.strDone }) - .on('click', function () { - processDependencies('', true); - }) - .appendTo('.tblFooters'); - } - } - ); -} -function goTo2NFStep1 () { - $.post( - 'normalization.php', - { - 'ajax_request': true, - 'db': PMA_commonParams.get('db'), - 'table': PMA_commonParams.get('table'), - 'step': '2.1' - }, function (data) { - $('#page_content h3').html(PMA_messages.str2NFNormalization); - $('#mainContent legend').html(data.legendText); - $('#mainContent h4').html(data.headText); - $('#mainContent p').html(data.subText); - $('#mainContent #extra').html(data.extra); - $('#mainContent #newCols').html(''); - if (data.subText !== '') { - var doneButton = $('') - .attr({ type: 'submit', value: PMA_messages.strDone, }) - .on('click', function () { - processDependencies(data.primary_key); - }) - .appendTo('.tblFooters'); - } else { - if (normalizeto === '3nf') { - $('#mainContent #newCols').html(PMA_messages.strToNextStep); - setTimeout(function () { - goTo3NFStep1([PMA_commonParams.get('table')]); - }, 3000); - } - } - }); -} - -function goToFinish1NF () { - if (normalizeto !== '1nf') { - goTo2NFStep1(); - return true; - } - $('#mainContent legend').html(PMA_messages.strEndStep); - $('#mainContent h4').html( - '

    ' + PMA_sprintf(PMA_messages.strFinishMsg, escapeHtml(PMA_commonParams.get('table'))) + '

    ' - ); - $('#mainContent p').html(''); - $('#mainContent #extra').html(''); - $('#mainContent #newCols').html(''); - $('.tblFooters').html(''); -} - -function goToStep4 () { - $.post( - 'normalization.php', - { - 'ajax_request': true, - 'db': PMA_commonParams.get('db'), - 'table': PMA_commonParams.get('table'), - 'step4': true - }, function (data) { - $('#mainContent legend').html(data.legendText); - $('#mainContent h4').html(data.headText); - $('#mainContent p').html(data.subText); - $('#mainContent #extra').html(data.extra); - $('#mainContent #newCols').html(''); - $('.tblFooters').html(''); - for (var pk in primary_key) { - $('#extra input[value=\'' + escapeJsString(primary_key[pk]) + '\']').attr('disabled','disabled'); - } - } - ); -} - -function goToStep3 () { - $.post( - 'normalization.php', - { - 'ajax_request': true, - 'db': PMA_commonParams.get('db'), - 'table': PMA_commonParams.get('table'), - 'step3': true - }, function (data) { - $('#mainContent legend').html(data.legendText); - $('#mainContent h4').html(data.headText); - $('#mainContent p').html(data.subText); - $('#mainContent #extra').html(data.extra); - $('#mainContent #newCols').html(''); - $('.tblFooters').html(''); - primary_key = JSON.parse(data.primary_key); - for (var pk in primary_key) { - $('#extra input[value=\'' + escapeJsString(primary_key[pk]) + '\']').attr('disabled','disabled'); - } - } - ); -} - -function goToStep2 (extra) { - $.post( - 'normalization.php', - { - 'ajax_request': true, - 'db': PMA_commonParams.get('db'), - 'table': PMA_commonParams.get('table'), - 'step2': true - }, function (data) { - $('#mainContent legend').html(data.legendText); - $('#mainContent h4').html(data.headText); - $('#mainContent p').html(data.subText); - $('#mainContent #extra,#mainContent #newCols').html(''); - $('.tblFooters').html(''); - if (data.hasPrimaryKey === '1') { - if (extra === 'goToStep3') { - $('#mainContent h4').html(PMA_messages.strPrimaryKeyAdded); - $('#mainContent p').html(PMA_messages.strToNextStep); - } - if (extra === 'goToFinish1NF') { - goToFinish1NF(); - } else { - setTimeout(function () { - goToStep3(); - }, 3000); - } - } else { - // form to select columns to make primary - $('#mainContent #extra').html(data.extra); - } - } - ); -} - -function goTo2NFFinish (pd) { - var tables = {}; - for (var dependson in pd) { - tables[dependson] = $('#extra input[name="' + dependson + '"]').val(); - } - datastring = { - 'ajax_request': true, - 'db': PMA_commonParams.get('db'), - 'table': PMA_commonParams.get('table'), - 'pd': JSON.stringify(pd), - 'newTablesName':JSON.stringify(tables), - 'createNewTables2NF':1 }; - $.ajax({ - type: 'POST', - url: 'normalization.php', - data: datastring, - async:false, - success: function (data) { - if (data.success === true) { - if (data.queryError === false) { - if (normalizeto === '3nf') { - $('#pma_navigation_reload').trigger('click'); - goTo3NFStep1(tables); - return true; - } - $('#mainContent legend').html(data.legendText); - $('#mainContent h4').html(data.headText); - $('#mainContent p').html(''); - $('#mainContent #extra').html(''); - $('.tblFooters').html(''); - } else { - PMA_ajaxShowMessage(data.extra, false); - } - $('#pma_navigation_reload').trigger('click'); - } else { - PMA_ajaxShowMessage(data.error, false); - } - } - }); -} - -function goTo3NFFinish (newTables) { - for (var table in newTables) { - for (var newtbl in newTables[table]) { - var updatedname = $('#extra input[name="' + newtbl + '"]').val(); - newTables[table][updatedname] = newTables[table][newtbl]; - if (updatedname !== newtbl) { - delete newTables[table][newtbl]; - } - } - } - datastring = { - 'ajax_request': true, - 'db': PMA_commonParams.get('db'), - 'newTables':JSON.stringify(newTables), - 'createNewTables3NF':1 }; - $.ajax({ - type: 'POST', - url: 'normalization.php', - data: datastring, - async:false, - success: function (data) { - if (data.success === true) { - if (data.queryError === false) { - $('#mainContent legend').html(data.legendText); - $('#mainContent h4').html(data.headText); - $('#mainContent p').html(''); - $('#mainContent #extra').html(''); - $('.tblFooters').html(''); - } else { - PMA_ajaxShowMessage(data.extra, false); - } - $('#pma_navigation_reload').trigger('click'); - } else { - PMA_ajaxShowMessage(data.error, false); - } - } - }); -} -var backup = ''; -function goTo2NFStep2 (pd, primary_key) { - $('#newCols').html(''); - $('#mainContent legend').html(PMA_messages.strStep + ' 2.2 ' + PMA_messages.strConfirmPd); - $('#mainContent h4').html(PMA_messages.strSelectedPd); - $('#mainContent p').html(PMA_messages.strPdHintNote); - var extra = '
    '; - var pdFound = false; - for (var dependson in pd) { - if (dependson !== primary_key) { - pdFound = true; - extra += '

    ' + escapeHtml(dependson) + ' -> ' + escapeHtml(pd[dependson].toString()) + '

    '; - } - } - if (!pdFound) { - extra += '

    ' + PMA_messages.strNoPdSelected + '

    '; - extra += '
    '; - } else { - extra += '
    '; - datastring = { - 'ajax_request': true, - 'db': PMA_commonParams.get('db'), - 'table': PMA_commonParams.get('table'), - 'pd': JSON.stringify(pd), - 'getNewTables2NF':1 }; - $.ajax({ - type: 'POST', - url: 'normalization.php', - data: datastring, - async:false, - success: function (data) { - if (data.success === true) { - extra += data.message; - } else { - PMA_ajaxShowMessage(data.error, false); - } - } - }); - } - $('#mainContent #extra').html(extra); - $('.tblFooters').html(''); - $('#goTo2NFFinish').on('click', function () { - goTo2NFFinish(pd); - }); -} - -function goTo3NFStep2 (pd, tablesTds) { - $('#newCols').html(''); - $('#mainContent legend').html(PMA_messages.strStep + ' 3.2 ' + PMA_messages.strConfirmTd); - $('#mainContent h4').html(PMA_messages.strSelectedTd); - $('#mainContent p').html(PMA_messages.strPdHintNote); - var extra = '
    '; - var pdFound = false; - for (var table in tablesTds) { - for (var i in tablesTds[table]) { - dependson = tablesTds[table][i]; - if (dependson !== '' && dependson !== table) { - pdFound = true; - extra += '

    ' + escapeHtml(dependson) + ' -> ' + escapeHtml(pd[dependson].toString()) + '

    '; - } - } - } - if (!pdFound) { - extra += '

    ' + PMA_messages.strNoTdSelected + '

    '; - extra += '
    '; - } else { - extra += ''; - datastring = { - 'ajax_request': true, - 'db': PMA_commonParams.get('db'), - 'tables': JSON.stringify(tablesTds), - 'pd': JSON.stringify(pd), - 'getNewTables3NF':1 }; - $.ajax({ - type: 'POST', - url: 'normalization.php', - data: datastring, - async:false, - success: function (data) { - data_parsed = data; - if (data.success === true) { - extra += data_parsed.html; - } else { - PMA_ajaxShowMessage(data.error, false); - } - } - }); - } - $('#mainContent #extra').html(extra); - $('.tblFooters').html(''); - $('#goTo3NFFinish').on('click', function () { - if (!pdFound) { - goTo3NFFinish([]); - } else { - goTo3NFFinish(data_parsed.newTables); - } - }); -} -function processDependencies (primary_key, isTransitive) { - var pd = {}; - var tablesTds = {}; - var dependsOn; - pd[primary_key] = []; - $('#extra form').each(function () { - var tblname; - if (isTransitive === true) { - tblname = $(this).data('tablename'); - primary_key = tblname; - if (!(tblname in tablesTds)) { - tablesTds[tblname] = []; - } - tablesTds[tblname].push(primary_key); - } - var form_id = $(this).attr('id'); - $('#' + form_id + ' input[type=checkbox]:not(:checked)').prop('checked', false); - dependsOn = ''; - $('#' + form_id + ' input[type=checkbox]:checked').each(function () { - dependsOn += $(this).val() + ', '; - $(this).attr('checked','checked'); - }); - if (dependsOn === '') { - dependsOn = primary_key; - } else { - dependsOn = dependsOn.slice(0, -2); - } - if (! (dependsOn in pd)) { - pd[dependsOn] = []; - } - pd[dependsOn].push($(this).data('colname')); - if (isTransitive === true) { - if (!(tblname in tablesTds)) { - tablesTds[tblname] = []; - } - if ($.inArray(dependsOn, tablesTds[tblname]) === -1) { - tablesTds[tblname].push(dependsOn); - } - } - }); - backup = $('#mainContent').html(); - if (isTransitive === true) { - goTo3NFStep2(pd, tablesTds); - } else { - goTo2NFStep2(pd, primary_key); - } - return false; -} - -function moveRepeatingGroup (repeatingCols) { - var newTable = $('input[name=repeatGroupTable]').val(); - var newColumn = $('input[name=repeatGroupColumn]').val(); - if (!newTable) { - $('input[name=repeatGroupTable]').focus(); - return false; - } - if (!newColumn) { - $('input[name=repeatGroupColumn]').focus(); - return false; - } - datastring = { - 'ajax_request': true, - 'db': PMA_commonParams.get('db'), - 'table': PMA_commonParams.get('table'), - 'repeatingColumns': repeatingCols, - 'newTable':newTable, - 'newColumn':newColumn, - 'primary_columns':primary_key.toString() - }; - $.ajax({ - type: 'POST', - url: 'normalization.php', - data: datastring, - async:false, - success: function (data) { - if (data.success === true) { - if (data.queryError === false) { - goToStep3(); - } - PMA_ajaxShowMessage(data.message, false); - $('#pma_navigation_reload').trigger('click'); - } else { - PMA_ajaxShowMessage(data.error, false); - } - } - }); -} -AJAX.registerTeardown('normalization.js', function () { - $('#extra').off('click', '#selectNonAtomicCol'); - $('#splitGo').off('click'); - $('.tblFooters').off('click', '#saveSplit'); - $('#extra').off('click', '#addNewPrimary'); - $('.tblFooters').off('click', '#saveNewPrimary'); - $('#extra').off('click', '#removeRedundant'); - $('#mainContent p').off('click', '#createPrimaryKey'); - $('#mainContent').off('click', '#backEditPd'); - $('#mainContent').off('click', '#showPossiblePd'); - $('#mainContent').off('click', '.pickPd'); -}); - -AJAX.registerOnload('normalization.js', function () { - var selectedCol; - normalizeto = $('#mainContent').data('normalizeto'); - $('#extra').on('click', '#selectNonAtomicCol', function () { - if ($(this).val() === 'no_such_col') { - goToStep2(); - } else { - selectedCol = $(this).val(); - } - }); - - $('#splitGo').on('click', function () { - if (!selectedCol || selectedCol === '') { - return false; - } - var numField = $('#numField').val(); - $.get( - 'normalization.php', - { - 'ajax_request': true, - 'db': PMA_commonParams.get('db'), - 'table': PMA_commonParams.get('table'), - 'splitColumn': true, - 'numFields': numField - }, - function (data) { - if (data.success === true) { - $('#newCols').html(data.message); - $('.default_value').hide(); - $('.enum_notice').hide(); - - $('') - .attr({ type: 'submit', id: 'saveSplit', value: PMA_messages.strSave }) - .appendTo('.tblFooters'); - - var cancelSplitButton = $('') - .attr({ type: 'submit', id: 'cancelSplit', value: PMA_messages.strCancel }) - .on('click', function () { - $('#newCols').html(''); - $(this).parent().html(''); - }) - .appendTo('.tblFooters'); - } - } - ); - return false; - }); - $('.tblFooters').on('click','#saveSplit', function () { - central_column_list = []; - if ($('#newCols #field_0_1').val() === '') { - $('#newCols #field_0_1').focus(); - return false; - } - var argsep = PMA_commonParams.get('arg_separator'); - datastring = $('#newCols :input').serialize(); - datastring += argsep + 'ajax_request=1' + argsep + 'do_save_data=1' + argsep + 'field_where=last'; - $.post('tbl_addfield.php', datastring, function (data) { - if (data.success) { - $.post( - 'sql.php', - { - 'ajax_request': true, - 'db': PMA_commonParams.get('db'), - 'table': PMA_commonParams.get('table'), - 'dropped_column': selectedCol, - 'purge' : 1, - 'sql_query': 'ALTER TABLE `' + PMA_commonParams.get('table') + '` DROP `' + selectedCol + '`;', - 'is_js_confirmed': 1 - }, - function (data) { - if (data.success === true) { - appendHtmlColumnsList(); - $('#newCols').html(''); - $('.tblFooters').html(''); - } else { - PMA_ajaxShowMessage(data.error, false); - } - selectedCol = ''; - } - ); - } else { - PMA_ajaxShowMessage(data.error, false); - } - }); - }); - - $('#extra').on('click', '#addNewPrimary', function () { - $.get( - 'normalization.php', - { - 'ajax_request': true, - 'db': PMA_commonParams.get('db'), - 'table': PMA_commonParams.get('table'), - 'addNewPrimary': true - }, - function (data) { - if (data.success === true) { - $('#newCols').html(data.message); - $('.default_value').hide(); - $('.enum_notice').hide(); - - $('') - .attr({ type: 'submit', id: 'saveNewPrimary', value: PMA_messages.strSave }) - .appendTo('.tblFooters'); - $('') - .attr({ type: 'submit', id: 'cancelSplit', value: PMA_messages.strCancel }) - .on('click', function () { - $('#newCols').html(''); - $(this).parent().html(''); - }) - .appendTo('.tblFooters'); - } else { - PMA_ajaxShowMessage(data.error, false); - } - } - ); - return false; - }); - $('.tblFooters').on('click', '#saveNewPrimary', function () { - var datastring = $('#newCols :input').serialize(); - var argsep = PMA_commonParams.get('arg_separator'); - datastring += argsep + 'field_key[0]=primary_0' + argsep + 'ajax_request=1' + argsep + 'do_save_data=1' + argsep + 'field_where=last'; - $.post('tbl_addfield.php', datastring, function (data) { - if (data.success === true) { - $('#mainContent h4').html(PMA_messages.strPrimaryKeyAdded); - $('#mainContent p').html(PMA_messages.strToNextStep); - $('#mainContent #extra').html(''); - $('#mainContent #newCols').html(''); - $('.tblFooters').html(''); - setTimeout(function () { - goToStep3(); - }, 2000); - } else { - PMA_ajaxShowMessage(data.error, false); - } - }); - }); - $('#extra').on('click', '#removeRedundant', function () { - var dropQuery = 'ALTER TABLE `' + PMA_commonParams.get('table') + '` '; - $('#extra input[type=checkbox]:checked').each(function () { - dropQuery += 'DROP `' + $(this).val() + '`, '; - }); - dropQuery = dropQuery.slice(0, -2); - $.post( - 'sql.php', - { - 'ajax_request': true, - 'db': PMA_commonParams.get('db'), - 'table': PMA_commonParams.get('table'), - 'sql_query': dropQuery, - 'is_js_confirmed': 1 - }, - function (data) { - if (data.success === true) { - goToStep2('goToFinish1NF'); - } else { - PMA_ajaxShowMessage(data.error, false); - } - } - ); - }); - $('#extra').on('click', '#moveRepeatingGroup', function () { - var repeatingCols = ''; - $('#extra input[type=checkbox]:checked').each(function () { - repeatingCols += $(this).val() + ', '; - }); - - if (repeatingCols !== '') { - var newColName = $('#extra input[type=checkbox]:checked:first').val(); - repeatingCols = repeatingCols.slice(0, -2); - var confirmStr = PMA_sprintf(PMA_messages.strMoveRepeatingGroup, escapeHtml(repeatingCols), escapeHtml(PMA_commonParams.get('table'))); - confirmStr += '' + - '( ' + escapeHtml(primary_key.toString()) + ', )' + - ''; - $('#newCols').html(confirmStr); - - $('') - .attr({ type: 'submit', value: PMA_messages.strCancel }) - .on('click', function () { - $('#newCols').html(''); - $('#extra input[type=checkbox]').prop('checked', false); - }) - .appendTo('.tblFooters'); - $('') - .attr({ type: 'submit', value: PMA_messages.strGo }) - .on('click', function () { - moveRepeatingGroup(repeatingCols); - }) - .appendTo('.tblFooters'); - } - }); - $('#mainContent p').on('click', '#createPrimaryKey', function (event) { - event.preventDefault(); - var url = { create_index: 1, - server: PMA_commonParams.get('server'), - db: PMA_commonParams.get('db'), - table: PMA_commonParams.get('table'), - added_fields: 1, - add_fields:1, - index: { Key_name:'PRIMARY' }, - ajax_request: true - }; - var title = PMA_messages.strAddPrimaryKey; - indexEditorDialog(url, title, function () { - // on success - $('.sqlqueryresults').remove(); - $('.result_query').remove(); - $('.tblFooters').html(''); - goToStep2('goToStep3'); - }); - return false; - }); - $('#mainContent').on('click', '#backEditPd', function () { - $('#mainContent').html(backup); - }); - $('#mainContent').on('click', '#showPossiblePd', function () { - if ($(this).hasClass('hideList')) { - $(this).html('+ ' + PMA_messages.strShowPossiblePd); - $(this).removeClass('hideList'); - $('#newCols').slideToggle('slow'); - return false; - } - if ($('#newCols').html() !== '') { - $('#showPossiblePd').html('- ' + PMA_messages.strHidePd); - $('#showPossiblePd').addClass('hideList'); - $('#newCols').slideToggle('slow'); - return false; - } - $('#newCols').insertAfter('#mainContent h4'); - $('#newCols').html('
    ' + PMA_messages.strLoading + '
    ' + PMA_messages.strWaitForPd + '
    '); - $.post( - 'normalization.php', - { - 'ajax_request': true, - 'db': PMA_commonParams.get('db'), - 'table': PMA_commonParams.get('table'), - 'findPdl': true - }, function (data) { - $('#showPossiblePd').html('- ' + PMA_messages.strHidePd); - $('#showPossiblePd').addClass('hideList'); - $('#newCols').html(data.message); - }); - }); - $('#mainContent').on('click', '.pickPd', function () { - var strColsLeft = $(this).next('.determinants').html(); - var colsLeft = strColsLeft.split(','); - var strColsRight = $(this).next().next().html(); - var colsRight = strColsRight.split(','); - for (var i in colsRight) { - $('form[data-colname="' + colsRight[i].trim() + '"] input[type="checkbox"]').prop('checked', false); - for (var j in colsLeft) { - $('form[data-colname="' + colsRight[i].trim() + '"] input[value="' + colsLeft[j].trim() + '"]').prop('checked', true); - } - } - }); -}); diff --git a/js/page_settings.js b/js/page_settings.js deleted file mode 100644 index 7de9c03819..0000000000 --- a/js/page_settings.js +++ /dev/null @@ -1,59 +0,0 @@ -/* vim: set expandtab sw=4 ts=4 sts=4: */ -/** - * @fileoverview function used for page-related settings - * @name Page-related settings - * - * @requires jQuery - * @requires jQueryUI - * @required js/functions.js - */ - -function showSettings (selector) { - var buttons = {}; - buttons[PMA_messages.strApply] = function () { - $('.config-form').submit(); - }; - - buttons[PMA_messages.strCancel] = function () { - $(this).dialog('close'); - }; - - // Keeping a clone to restore in case the user cancels the operation - var $clone = $(selector + ' .page_settings').clone(true); - $(selector) - .dialog({ - title: PMA_messages.strPageSettings, - width: 700, - minHeight: 250, - modal: true, - open: function () { - $(this).dialog('option', 'maxHeight', $(window).height() - $(this).offset().top); - }, - close: function () { - $(selector + ' .page_settings').replaceWith($clone); - }, - buttons: buttons - }); -} - -function showPageSettings () { - showSettings('#page_settings_modal'); -} - -function showNaviSettings () { - showSettings('#pma_navigation_settings'); -} - -AJAX.registerTeardown('page_settings.js', function () { - $('#page_settings_icon').css('display', 'none'); - $('#page_settings_icon').off('click'); - $('#pma_navigation_settings_icon').off('click'); -}); - -AJAX.registerOnload('page_settings.js', function () { - if ($('#page_settings_modal').length) { - $('#page_settings_icon').css('display', 'inline'); - $('#page_settings_icon').on('click', showPageSettings); - } - $('#pma_navigation_settings_icon').on('click', showNaviSettings); -}); diff --git a/js/replication.js b/js/replication.js deleted file mode 100644 index 51b360650b..0000000000 --- a/js/replication.js +++ /dev/null @@ -1,92 +0,0 @@ -/* vim: set expandtab sw=4 ts=4 sts=4: */ -/** - * for server_replication.php - * - */ - -var random_server_id = Math.floor(Math.random() * 10000000); -var conf_prefix = 'server-id=' + random_server_id + '\nlog_bin=mysql-bin\nlog_error=mysql-bin.err\n'; - -function update_config () { - var conf_ignore = 'binlog_ignore_db='; - var conf_do = 'binlog_do_db='; - var database_list = ''; - - if ($('#db_select option:selected').size() === 0) { - $('#rep').text(conf_prefix); - } else if ($('#db_type option:selected').val() === 'all') { - $('#db_select option:selected').each(function () { - database_list += conf_ignore + $(this).val() + '\n'; - }); - $('#rep').text(conf_prefix + database_list); - } else { - $('#db_select option:selected').each(function () { - database_list += conf_do + $(this).val() + '\n'; - }); - $('#rep').text(conf_prefix + database_list); - } -} - -/** - * Unbind all event handlers before tearing down a page - */ -AJAX.registerTeardown('replication.js', function () { - $('#db_type').off('change'); - $('#db_select').off('change'); - $('#master_status_href').off('click'); - $('#master_slaves_href').off('click'); - $('#slave_status_href').off('click'); - $('#slave_control_href').off('click'); - $('#slave_errormanagement_href').off('click'); - $('#slave_synchronization_href').off('click'); - $('#db_reset_href').off('click'); - $('#db_select_href').off('click'); - $('#reset_slave').off('click'); -}); - -AJAX.registerOnload('replication.js', function () { - $('#rep').text(conf_prefix); - $('#db_type').on('change', update_config); - $('#db_select').on('change', update_config); - - $('#master_status_href').on('click', function () { - $('#replication_master_section').toggle(); - }); - $('#master_slaves_href').on('click', function () { - $('#replication_slaves_section').toggle(); - }); - $('#slave_status_href').on('click', function () { - $('#replication_slave_section').toggle(); - }); - $('#slave_control_href').on('click', function () { - $('#slave_control_gui').toggle(); - }); - $('#slave_errormanagement_href').on('click', function () { - $('#slave_errormanagement_gui').toggle(); - }); - $('#slave_synchronization_href').on('click', function () { - $('#slave_synchronization_gui').toggle(); - }); - $('#db_reset_href').on('click', function () { - $('#db_select option:selected').prop('selected', false); - $('#db_select').trigger('change'); - }); - $('#db_select_href').on('click', function () { - $('#db_select option').prop('selected', true); - $('#db_select').trigger('change'); - }); - $('#reset_slave').on('click', function (e) { - e.preventDefault(); - var $anchor = $(this); - var question = PMA_messages.strResetSlaveWarning; - $anchor.PMA_confirm(question, $anchor.attr('href'), function (url) { - PMA_ajaxShowMessage(); - AJAX.source = $anchor; - var params = { - 'ajax_page_request': true, - 'ajax_request': true, - }; - $.post(url, params, AJAX.responseHandler); - }); - }); -}); diff --git a/js/rte.js b/js/rte.js deleted file mode 100644 index 17cfaace74..0000000000 --- a/js/rte.js +++ /dev/null @@ -1,1077 +0,0 @@ -/* vim: set expandtab sw=4 ts=4 sts=4: */ -/** - * JavaScript functionality for Routines, Triggers and Events. - * - * @package PhpMyadmin - */ -/** - * @var RTE Contains all the JavaScript functionality - * for Routines, Triggers and Events - */ -var RTE = { - /** - * Construct for the object that provides the - * functionality for Routines, Triggers and Events - */ - object: function (type) { - $.extend(this, RTE.COMMON); - this.editorType = type; - - switch (type) { - case 'routine': - $.extend(this, RTE.ROUTINE); - break; - case 'trigger': - // nothing extra yet for triggers - break; - case 'event': - $.extend(this, RTE.EVENT); - break; - default: - break; - } - }, - /** - * @var string param_template Template for a row in the routine editor - */ - param_template: '' -}; - -/** - * @var RTE.COMMON a JavaScript namespace containing the functionality - * for Routines, Triggers and Events - * - * This namespace is extended by the functionality required - * to handle a specific item (a routine, trigger or event) - * in the relevant javascript files in this folder - */ -RTE.COMMON = { - /** - * @var $ajaxDialog Query object containing the reference to the - * dialog that contains the editor - */ - $ajaxDialog: null, - /** - * @var syntaxHiglighter Reference to the codemirror editor - */ - syntaxHiglighter: null, - /** - * @var buttonOptions Object containing options for - * the jQueryUI dialog buttons - */ - buttonOptions: {}, - /** - * @var editorType Type of the editor - */ - editorType: null, - /** - * Validate editor form fields. - */ - validate: function () { - /** - * @var $elm a jQuery object containing the reference - * to an element that is being validated - */ - var $elm = null; - // Common validation. At the very least the name - // and the definition must be provided for an item - $elm = $('table.rte_table').last().find('input[name=item_name]'); - if ($elm.val() === '') { - $elm.focus(); - alert(PMA_messages.strFormEmpty); - return false; - } - $elm = $('table.rte_table').find('textarea[name=item_definition]'); - if ($elm.val() === '') { - if (this.syntaxHiglighter !== null) { - this.syntaxHiglighter.focus(); - } else { - $('textarea[name=item_definition]').last().focus(); - } - alert(PMA_messages.strFormEmpty); - return false; - } - // The validation has so far passed, so now - // we can validate item-specific fields. - return this.validateCustom(); - }, // end validate() - /** - * Validate custom editor form fields. - * This function can be overridden by - * other files in this folder - */ - validateCustom: function () { - return true; - }, // end validateCustom() - /** - * Execute some code after the ajax - * dialog for the editor is shown. - * This function can be overridden by - * other files in this folder - */ - postDialogShow: function () { - // Nothing by default - }, // end postDialogShow() - - exportDialog: function ($this) { - var $msg = PMA_ajaxShowMessage(); - if ($this.hasClass('mult_submit')) { - var combined = { - success: true, - title: PMA_messages.strExport, - message: '', - error: '' - }; - // export anchors of all selected rows - var export_anchors = $('input.checkall:checked').parents('tr').find('.export_anchor'); - var count = export_anchors.length; - var returnCount = 0; - - // No routine is exportable (due to privilege issues) - if (count === 0) { - PMA_ajaxShowMessage(PMA_messages.NoExportable); - } - - export_anchors.each(function () { - $.get($(this).attr('href'), { 'ajax_request': true }, function (data) { - returnCount++; - if (data.success === true) { - combined.message += '\n' + data.message + '\n'; - if (returnCount === count) { - showExport(combined); - } - } else { - // complain even if one export is failing - combined.success = false; - combined.error += '\n' + data.error + '\n'; - if (returnCount === count) { - showExport(combined); - } - } - }); - }); - } else { - $.get($this.attr('href'), { 'ajax_request': true }, showExport); - } - PMA_ajaxRemoveMessage($msg); - - function showExport (data) { - if (data.success === true) { - PMA_ajaxRemoveMessage($msg); - /** - * @var button_options Object containing options - * for jQueryUI dialog buttons - */ - var button_options = {}; - button_options[PMA_messages.strClose] = function () { - $(this).dialog('close').remove(); - }; - /** - * Display the dialog to the user - */ - data.message = ''; - var $ajaxDialog = $('
    ' + data.message + '
    ').dialog({ - width: 500, - buttons: button_options, - title: data.title - }); - // Attach syntax highlighted editor to export dialog - /** - * @var $elm jQuery object containing the reference - * to the Export textarea. - */ - var $elm = $ajaxDialog.find('textarea'); - PMA_getSQLEditor($elm); - } else { - PMA_ajaxShowMessage(data.error, false); - } - } // end showExport() - }, // end exportDialog() - editorDialog: function (is_new, $this) { - var that = this; - /** - * @var $edit_row jQuery object containing the reference to - * the row of the the item being edited - * from the list of items - */ - var $edit_row = null; - if ($this.hasClass('edit_anchor')) { - // Remeber the row of the item being edited for later, - // so that if the edit is successful, we can replace the - // row with info about the modified item. - $edit_row = $this.parents('tr'); - } - /** - * @var $msg jQuery object containing the reference to - * the AJAX message shown to the user - */ - var $msg = PMA_ajaxShowMessage(); - $.get($this.attr('href'), { 'ajax_request': true }, function (data) { - if (data.success === true) { - // We have successfully fetched the editor form - PMA_ajaxRemoveMessage($msg); - // Now define the function that is called when - // the user presses the "Go" button - that.buttonOptions[PMA_messages.strGo] = function () { - // Move the data from the codemirror editor back to the - // textarea, where it can be used in the form submission. - if (typeof CodeMirror !== 'undefined') { - that.syntaxHiglighter.save(); - } - // Validate editor and submit request, if passed. - if (that.validate()) { - /** - * @var data Form data to be sent in the AJAX request - */ - var data = $('form.rte_form').last().serialize(); - $msg = PMA_ajaxShowMessage( - PMA_messages.strProcessingRequest - ); - var url = $('form.rte_form').last().attr('action'); - $.post(url, data, function (data) { - if (data.success === true) { - // Item created successfully - PMA_ajaxRemoveMessage($msg); - PMA_slidingMessage(data.message); - that.$ajaxDialog.dialog('close'); - // If we are in 'edit' mode, we must - // remove the reference to the old row. - if (mode === 'edit' && $edit_row !== null) { - $edit_row.remove(); - } - // Sometimes, like when moving a trigger from - // a table to another one, the new row should - // not be inserted into the list. In this case - // "data.insert" will be set to false. - if (data.insert) { - // Insert the new row at the correct - // location in the list of items - /** - * @var text Contains the name of an item from - * the list that is used in comparisons - * to find the correct location where - * to insert a new row. - */ - var text = ''; - /** - * @var inserted Whether a new item has been - * inserted in the list or not - */ - var inserted = false; - $('table.data').find('tr').each(function () { - text = $(this) - .children('td') - .eq(0) - .find('strong') - .text() - .toUpperCase(); - text = $.trim(text); - if (text !== '' && text > data.name) { - $(this).before(data.new_row); - inserted = true; - return false; - } - }); - if (! inserted) { - // If we didn't manage to insert the row yet, - // it must belong at the end of the list, - // so we insert it there. - $('table.data').append(data.new_row); - } - // Fade-in the new row - $('tr.ajaxInsert') - .show('slow') - .removeClass('ajaxInsert'); - } else if ($('table.data').find('tr').has('td').length === 0) { - // If we are not supposed to insert the new row, - // we will now check if the table is empty and - // needs to be hidden. This will be the case if - // we were editing the only item in the list, - // which we removed and will not be inserting - // something else in its place. - $('table.data').hide('slow', function () { - $('#nothing2display').show('slow'); - }); - } - // Now we have inserted the row at the correct - // position, but surely at least some row classes - // are wrong now. So we will itirate throught - // all rows and assign correct classes to them - /** - * @var ct Count of processed rows - */ - var ct = 0; - /** - * @var rowclass Class to be attached to the row - * that is being processed - */ - var rowclass = ''; - $('table.data').find('tr').has('td').each(function () { - rowclass = (ct % 2 === 0) ? 'odd' : 'even'; - $(this).removeClass().addClass(rowclass); - ct++; - }); - // If this is the first item being added, remove - // the "No items" message and show the list. - if ($('table.data').find('tr').has('td').length > 0 && - $('#nothing2display').is(':visible') - ) { - $('#nothing2display').hide('slow', function () { - $('table.data').show('slow'); - }); - } - PMA_reloadNavigation(); - } else { - PMA_ajaxShowMessage(data.error, false); - } - }); // end $.post() - } // end "if (that.validate())" - }; // end of function that handles the submission of the Editor - that.buttonOptions[PMA_messages.strClose] = function () { - $(this).dialog('close'); - }; - /** - * Display the dialog to the user - */ - that.$ajaxDialog = $('
    ' + data.message + '
    ').dialog({ - width: 700, - minWidth: 500, - maxHeight: $(window).height(), - buttons: that.buttonOptions, - title: data.title, - modal: true, - open: function () { - if ($('#rteDialog').parents('.ui-dialog').height() > $(window).height()) { - $('#rteDialog').dialog('option', 'height', $(window).height()); - } - $(this).find('input[name=item_name]').focus(); - $(this).find('input.datefield').each(function () { - PMA_addDatepicker($(this).css('width', '95%'), 'date'); - }); - $(this).find('input.datetimefield').each(function () { - PMA_addDatepicker($(this).css('width', '95%'), 'datetime'); - }); - $.datepicker.initialized = false; - }, - close: function () { - $(this).remove(); - } - }); - /** - * @var mode Used to remeber whether the editor is in - * "Edit" or "Add" mode - */ - var mode = 'add'; - if ($('input[name=editor_process_edit]').length > 0) { - mode = 'edit'; - } - // Attach syntax highlighted editor to the definition - /** - * @var elm jQuery object containing the reference to - * the Definition textarea. - */ - var $elm = $('textarea[name=item_definition]').last(); - var linterOptions = {}; - linterOptions[that.editorType + '_editor'] = true; - that.syntaxHiglighter = PMA_getSQLEditor($elm, {}, null, linterOptions); - - // Execute item-specific code - that.postDialogShow(data); - } else { - PMA_ajaxShowMessage(data.error, false); - } - }); // end $.get() - }, - - dropDialog: function ($this) { - /** - * @var $curr_row Object containing reference to the current row - */ - var $curr_row = $this.parents('tr'); - /** - * @var question String containing the question to be asked for confirmation - */ - var question = $('
    ').text( - $curr_row.children('td').children('.drop_sql').html() - ); - // We ask for confirmation first here, before submitting the ajax request - $this.PMA_confirm(question, $this.attr('href'), function (url) { - /** - * @var msg jQuery object containing the reference to - * the AJAX message shown to the user - */ - var $msg = PMA_ajaxShowMessage(PMA_messages.strProcessingRequest); - var params = getJSConfirmCommonParam(this, $this.getPostData()); - $.post(url, params, function (data) { - if (data.success === true) { - /** - * @var $table Object containing reference - * to the main list of elements - */ - var $table = $curr_row.parent(); - // Check how many rows will be left after we remove - // the one that the user has requested us to remove - if ($table.find('tr').length === 3) { - // If there are two rows left, it means that they are - // the header of the table and the rows that we are - // about to remove, so after the removal there will be - // nothing to show in the table, so we hide it. - $table.hide('slow', function () { - $(this).find('tr.even, tr.odd').remove(); - $('.withSelected').remove(); - $('#nothing2display').show('slow'); - }); - } else { - $curr_row.hide('slow', function () { - $(this).remove(); - // Now we have removed the row from the list, but maybe - // some row classes are wrong now. So we will itirate - // throught all rows and assign correct classes to them. - /** - * @var ct Count of processed rows - */ - var ct = 0; - /** - * @var rowclass Class to be attached to the row - * that is being processed - */ - var rowclass = ''; - $table.find('tr').has('td').each(function () { - rowclass = (ct % 2 === 1) ? 'odd' : 'even'; - $(this).removeClass().addClass(rowclass); - ct++; - }); - }); - } - // Get rid of the "Loading" message - PMA_ajaxRemoveMessage($msg); - // Show the query that we just executed - PMA_slidingMessage(data.sql_query); - PMA_reloadNavigation(); - } else { - PMA_ajaxShowMessage(data.error, false); - } - }); // end $.post() - }); // end $.PMA_confirm() - }, - - dropMultipleDialog: function ($this) { - // We ask for confirmation here - $this.PMA_confirm(PMA_messages.strDropRTEitems, '', function (url) { - /** - * @var msg jQuery object containing the reference to - * the AJAX message shown to the user - */ - var $msg = PMA_ajaxShowMessage(PMA_messages.strProcessingRequest); - - // drop anchors of all selected rows - var drop_anchors = $('input.checkall:checked').parents('tr').find('.drop_anchor'); - var success = true; - var count = drop_anchors.length; - var returnCount = 0; - - drop_anchors.each(function () { - var $anchor = $(this); - /** - * @var $curr_row Object containing reference to the current row - */ - var $curr_row = $anchor.parents('tr'); - var params = getJSConfirmCommonParam(this, $anchor.getPostData()); - $.post($anchor.attr('href'), params, function (data) { - returnCount++; - if (data.success === true) { - /** - * @var $table Object containing reference - * to the main list of elements - */ - var $table = $curr_row.parent(); - // Check how many rows will be left after we remove - // the one that the user has requested us to remove - if ($table.find('tr').length === 3) { - // If there are two rows left, it means that they are - // the header of the table and the rows that we are - // about to remove, so after the removal there will be - // nothing to show in the table, so we hide it. - $table.hide('slow', function () { - $(this).find('tr.even, tr.odd').remove(); - $('.withSelected').remove(); - $('#nothing2display').show('slow'); - }); - } else { - $curr_row.hide('fast', function () { - $(this).remove(); - // Now we have removed the row from the list, but maybe - // some row classes are wrong now. So we will itirate - // throught all rows and assign correct classes to them. - /** - * @var ct Count of processed rows - */ - var ct = 0; - /** - * @var rowclass Class to be attached to the row - * that is being processed - */ - var rowclass = ''; - $table.find('tr').has('td').each(function () { - rowclass = (ct % 2 === 1) ? 'odd' : 'even'; - $(this).removeClass().addClass(rowclass); - ct++; - }); - }); - } - if (returnCount === count) { - if (success) { - // Get rid of the "Loading" message - PMA_ajaxRemoveMessage($msg); - $('#rteListForm_checkall').prop({ checked: false, indeterminate: false }); - } - PMA_reloadNavigation(); - } - } else { - PMA_ajaxShowMessage(data.error, false); - success = false; - if (returnCount === count) { - PMA_reloadNavigation(); - } - } - }); // end $.post() - }); // end drop_anchors.each() - }); // end $.PMA_confirm() - } -}; // end RTE namespace - -/** - * @var RTE.EVENT JavaScript functionality for events - */ -RTE.EVENT = { - validateCustom: function () { - /** - * @var elm a jQuery object containing the reference - * to an element that is being validated - */ - var $elm = null; - if (this.$ajaxDialog.find('select[name=item_type]').find(':selected').val() === 'RECURRING') { - // The interval field must not be empty for recurring events - $elm = this.$ajaxDialog.find('input[name=item_interval_value]'); - if ($elm.val() === '') { - $elm.focus(); - alert(PMA_messages.strFormEmpty); - return false; - } - } else { - // The execute_at field must not be empty for "once off" events - $elm = this.$ajaxDialog.find('input[name=item_execute_at]'); - if ($elm.val() === '') { - $elm.focus(); - alert(PMA_messages.strFormEmpty); - return false; - } - } - return true; - } -}; - -/** - * @var RTE.ROUTINE JavaScript functionality for routines - */ -RTE.ROUTINE = { - /** - * Overriding the postDialogShow() function defined in common.js - * - * @param data JSON-encoded data from the ajax request - */ - postDialogShow: function (data) { - // Cache the template for a parameter table row - RTE.param_template = data.param_template; - var that = this; - // Make adjustments in the dialog to make it AJAX compatible - $('td.routine_param_remove').show(); - $('input[name=routine_removeparameter]').remove(); - $('input[name=routine_addparameter]').css('width', '100%'); - // Enable/disable the 'options' dropdowns for parameters as necessary - $('table.routine_params_table').last().find('th[colspan=2]').attr('colspan', '1'); - $('table.routine_params_table').last().find('tr').has('td').each(function () { - that.setOptionsForParameter( - $(this).find('select[name^=item_param_type]'), - $(this).find('input[name^=item_param_length]'), - $(this).find('select[name^=item_param_opts_text]'), - $(this).find('select[name^=item_param_opts_num]') - ); - }); - // Enable/disable the 'options' dropdowns for - // function return value as necessary - this.setOptionsForParameter( - $('table.rte_table').last().find('select[name=item_returntype]'), - $('table.rte_table').last().find('input[name=item_returnlength]'), - $('table.rte_table').last().find('select[name=item_returnopts_text]'), - $('table.rte_table').last().find('select[name=item_returnopts_num]') - ); - // Allow changing parameter order - $('.routine_params_table tbody').sortable({ - containment: '.routine_params_table tbody', - handle: '.dragHandle', - stop: function (event, ui) { - that.reindexParameters(); - }, - }); - }, - /** - * Reindexes the parameters after dropping a parameter or reordering parameters - */ - reindexParameters: function () { - /** - * @var index Counter used for reindexing the input - * fields in the routine parameters table - */ - var index = 0; - $('table.routine_params_table tbody').find('tr').each(function () { - $(this).find(':input').each(function () { - /** - * @var inputname The value of the name attribute of - * the input field being reindexed - */ - var inputname = $(this).attr('name'); - if (inputname.substr(0, 14) === 'item_param_dir') { - $(this).attr('name', inputname.substr(0, 14) + '[' + index + ']'); - } else if (inputname.substr(0, 15) === 'item_param_name') { - $(this).attr('name', inputname.substr(0, 15) + '[' + index + ']'); - } else if (inputname.substr(0, 15) === 'item_param_type') { - $(this).attr('name', inputname.substr(0, 15) + '[' + index + ']'); - } else if (inputname.substr(0, 17) === 'item_param_length') { - $(this).attr('name', inputname.substr(0, 17) + '[' + index + ']'); - $(this).attr('id', 'item_param_length_' + index); - } else if (inputname.substr(0, 20) === 'item_param_opts_text') { - $(this).attr('name', inputname.substr(0, 20) + '[' + index + ']'); - } else if (inputname.substr(0, 19) === 'item_param_opts_num') { - $(this).attr('name', inputname.substr(0, 19) + '[' + index + ']'); - } - }); - index++; - }); - }, - /** - * Overriding the validateCustom() function defined in common.js - */ - validateCustom: function () { - /** - * @var isSuccess Stores the outcome of the validation - */ - var isSuccess = true; - /** - * @var inputname The value of the "name" attribute for - * the field that is being processed - */ - var inputname = ''; - this.$ajaxDialog.find('table.routine_params_table').last().find('tr').each(function () { - // Every parameter of a routine must have - // a non-empty direction, name and type - if (isSuccess) { - $(this).find(':input').each(function () { - inputname = $(this).attr('name'); - if (inputname.substr(0, 14) === 'item_param_dir' || - inputname.substr(0, 15) === 'item_param_name' || - inputname.substr(0, 15) === 'item_param_type') { - if ($(this).val() === '') { - $(this).focus(); - isSuccess = false; - return false; - } - } - }); - } else { - return false; - } - }); - if (! isSuccess) { - alert(PMA_messages.strFormEmpty); - return false; - } - this.$ajaxDialog.find('table.routine_params_table').last().find('tr').each(function () { - // SET, ENUM, VARCHAR and VARBINARY fields must have length/values - var $inputtyp = $(this).find('select[name^=item_param_type]'); - var $inputlen = $(this).find('input[name^=item_param_length]'); - if ($inputtyp.length && $inputlen.length) { - if (($inputtyp.val() === 'ENUM' || $inputtyp.val() === 'SET' || $inputtyp.val().substr(0, 3) === 'VAR') && - $inputlen.val() === '' - ) { - $inputlen.focus(); - isSuccess = false; - return false; - } - } - }); - if (! isSuccess) { - alert(PMA_messages.strFormEmpty); - return false; - } - if (this.$ajaxDialog.find('select[name=item_type]').find(':selected').val() === 'FUNCTION') { - // The length/values of return variable for functions must - // be set, if the type is SET, ENUM, VARCHAR or VARBINARY. - var $returntyp = this.$ajaxDialog.find('select[name=item_returntype]'); - var $returnlen = this.$ajaxDialog.find('input[name=item_returnlength]'); - if (($returntyp.val() === 'ENUM' || $returntyp.val() === 'SET' || $returntyp.val().substr(0, 3) === 'VAR') && - $returnlen.val() === '' - ) { - $returnlen.focus(); - alert(PMA_messages.strFormEmpty); - return false; - } - } - if ($('select[name=item_type]').find(':selected').val() === 'FUNCTION') { - // A function must contain a RETURN statement in its definition - if (this.$ajaxDialog.find('table.rte_table').find('textarea[name=item_definition]').val().toUpperCase().indexOf('RETURN') < 0) { - this.syntaxHiglighter.focus(); - alert(PMA_messages.MissingReturn); - return false; - } - } - return true; - }, - /** - * Enable/disable the "options" dropdown and "length" input for - * parameters and the return variable in the routine editor - * as necessary. - * - * @param type a jQuery object containing the reference - * to the "Type" dropdown box - * @param len a jQuery object containing the reference - * to the "Length" input box - * @param text a jQuery object containing the reference - * to the dropdown box with options for - * parameters of text type - * @param num a jQuery object containing the reference - * to the dropdown box with options for - * parameters of numeric type - */ - setOptionsForParameter: function ($type, $len, $text, $num) { - /** - * @var no_opts a jQuery object containing the reference - * to an element to be displayed when no - * options are available - */ - var $no_opts = $text.parent().parent().find('.no_opts'); - /** - * @var no_len a jQuery object containing the reference - * to an element to be displayed when no - * "length/values" field is available - */ - var $no_len = $len.parent().parent().find('.no_len'); - - // Process for parameter options - switch ($type.val()) { - case 'TINYINT': - case 'SMALLINT': - case 'MEDIUMINT': - case 'INT': - case 'BIGINT': - case 'DECIMAL': - case 'FLOAT': - case 'DOUBLE': - case 'REAL': - $text.parent().hide(); - $num.parent().show(); - $no_opts.hide(); - break; - case 'TINYTEXT': - case 'TEXT': - case 'MEDIUMTEXT': - case 'LONGTEXT': - case 'CHAR': - case 'VARCHAR': - case 'SET': - case 'ENUM': - $text.parent().show(); - $num.parent().hide(); - $no_opts.hide(); - break; - default: - $text.parent().hide(); - $num.parent().hide(); - $no_opts.show(); - break; - } - // Process for parameter length - switch ($type.val()) { - case 'DATE': - case 'TINYBLOB': - case 'TINYTEXT': - case 'BLOB': - case 'TEXT': - case 'MEDIUMBLOB': - case 'MEDIUMTEXT': - case 'LONGBLOB': - case 'LONGTEXT': - $text.closest('tr').find('a:first').hide(); - $len.parent().hide(); - $no_len.show(); - break; - default: - if ($type.val() === 'ENUM' || $type.val() === 'SET') { - $text.closest('tr').find('a:first').show(); - } else { - $text.closest('tr').find('a:first').hide(); - } - $len.parent().show(); - $no_len.hide(); - break; - } - }, - executeDialog: function ($this) { - var that = this; - /** - * @var msg jQuery object containing the reference to - * the AJAX message shown to the user - */ - var $msg = PMA_ajaxShowMessage(); - var params = { - 'ajax_request': true - }; - $.post($this.attr('href'), params, function (data) { - if (data.success === true) { - PMA_ajaxRemoveMessage($msg); - // If 'data.dialog' is true we show a dialog with a form - // to get the input parameters for routine, otherwise - // we just show the results of the query - if (data.dialog) { - // Define the function that is called when - // the user presses the "Go" button - that.buttonOptions[PMA_messages.strGo] = function () { - /** - * @var data Form data to be sent in the AJAX request - */ - var data = $('form.rte_form').last().serialize(); - $msg = PMA_ajaxShowMessage( - PMA_messages.strProcessingRequest - ); - $.post('db_routines.php', data, function (data) { - if (data.success === true) { - // Routine executed successfully - PMA_ajaxRemoveMessage($msg); - PMA_slidingMessage(data.message); - $ajaxDialog.dialog('close'); - } else { - PMA_ajaxShowMessage(data.error, false); - } - }); - }; - that.buttonOptions[PMA_messages.strClose] = function () { - $(this).dialog('close'); - }; - /** - * Display the dialog to the user - */ - var $ajaxDialog = $('
    ' + data.message + '
    ').dialog({ - width: 650, - buttons: that.buttonOptions, - title: data.title, - modal: true, - close: function () { - $(this).remove(); - } - }); - $ajaxDialog.find('input[name^=params]').first().focus(); - /** - * Attach the datepickers to the relevant form fields - */ - $ajaxDialog.find('input.datefield, input.datetimefield').each(function () { - PMA_addDatepicker($(this).css('width', '95%')); - }); - /* - * Define the function if the user presses enter - */ - $('form.rte_form').on('keyup', function (event) { - event.preventDefault(); - if (event.keyCode === 13) { - /** - * @var data Form data to be sent in the AJAX request - */ - var data = $(this).serialize(); - $msg = PMA_ajaxShowMessage( - PMA_messages.strProcessingRequest - ); - var url = $(this).attr('action'); - $.post(url, data, function (data) { - if (data.success === true) { - // Routine executed successfully - PMA_ajaxRemoveMessage($msg); - PMA_slidingMessage(data.message); - $('form.rte_form').off('keyup'); - $ajaxDialog.remove(); - } else { - PMA_ajaxShowMessage(data.error, false); - } - }); - } - }); - } else { - // Routine executed successfully - PMA_slidingMessage(data.message); - } - } else { - PMA_ajaxShowMessage(data.error, false); - } - }); // end $.post() - } -}; - -/** - * Attach Ajax event handlers for the Routines, Triggers and Events editor - */ -$(function () { - /** - * Attach Ajax event handlers for the Add/Edit functionality. - */ - $(document).on('click', 'a.ajax.add_anchor, a.ajax.edit_anchor', function (event) { - event.preventDefault(); - var type = $(this).attr('href').substr(0, $(this).attr('href').indexOf('?')); - if (type.indexOf('routine') !== -1) { - type = 'routine'; - } else if (type.indexOf('trigger') !== -1) { - type = 'trigger'; - } else if (type.indexOf('event') !== -1) { - type = 'event'; - } else { - type = ''; - } - var dialog = new RTE.object(type); - dialog.editorDialog($(this).hasClass('add_anchor'), $(this)); - }); // end $(document).on() - - /** - * Attach Ajax event handlers for the Execute routine functionality - */ - $(document).on('click', 'a.ajax.exec_anchor', function (event) { - event.preventDefault(); - var dialog = new RTE.object('routine'); - dialog.executeDialog($(this)); - }); // end $(document).on() - - /** - * Attach Ajax event handlers for Export of Routines, Triggers and Events - */ - $(document).on('click', 'a.ajax.export_anchor', function (event) { - event.preventDefault(); - var dialog = new RTE.object(); - dialog.exportDialog($(this)); - }); // end $(document).on() - - $(document).on('click', '#rteListForm.ajax .mult_submit[value="export"]', function (event) { - event.preventDefault(); - var dialog = new RTE.object(); - dialog.exportDialog($(this)); - }); // end $(document).on() - - /** - * Attach Ajax event handlers for Drop functionality - * of Routines, Triggers and Events. - */ - $(document).on('click', 'a.ajax.drop_anchor', function (event) { - event.preventDefault(); - var dialog = new RTE.object(); - dialog.dropDialog($(this)); - }); // end $(document).on() - - $(document).on('click', '#rteListForm.ajax .mult_submit[value="drop"]', function (event) { - event.preventDefault(); - var dialog = new RTE.object(); - dialog.dropMultipleDialog($(this)); - }); // end $(document).on() - - /** - * Attach Ajax event handlers for the "Change event/routine type" - * functionality in the events editor, so that the correct - * rows are shown in the editor when changing the event type - */ - $(document).on('change', 'select[name=item_type]', function () { - $(this) - .closest('table') - .find('tr.recurring_event_row, tr.onetime_event_row, tr.routine_return_row, .routine_direction_cell') - .toggle(); - }); // end $(document).on() - - /** - * Attach Ajax event handlers for the "Change parameter type" - * functionality in the routines editor, so that the correct - * option/length fields, if any, are shown when changing - * a parameter type - */ - $(document).on('change', 'select[name^=item_param_type]', function () { - /** - * @var row jQuery object containing the reference to - * a row in the routine parameters table - */ - var $row = $(this).parents('tr').first(); - var rte = new RTE.object('routine'); - rte.setOptionsForParameter( - $row.find('select[name^=item_param_type]'), - $row.find('input[name^=item_param_length]'), - $row.find('select[name^=item_param_opts_text]'), - $row.find('select[name^=item_param_opts_num]') - ); - }); // end $(document).on() - - /** - * Attach Ajax event handlers for the "Change the type of return - * variable of function" functionality, so that the correct fields, - * if any, are shown when changing the function return type type - */ - $(document).on('change', 'select[name=item_returntype]', function () { - var rte = new RTE.object('routine'); - var $table = $(this).closest('table.rte_table'); - rte.setOptionsForParameter( - $table.find('select[name=item_returntype]'), - $table.find('input[name=item_returnlength]'), - $table.find('select[name=item_returnopts_text]'), - $table.find('select[name=item_returnopts_num]') - ); - }); // end $(document).on() - - /** - * Attach Ajax event handlers for the "Add parameter to routine" functionality - */ - $(document).on('click', 'input[name=routine_addparameter]', function (event) { - event.preventDefault(); - /** - * @var routine_params_table jQuery object containing the reference - * to the routine parameters table - */ - var $routine_params_table = $(this).closest('div.ui-dialog').find('.routine_params_table'); - /** - * @var new_param_row A string containing the HTML code for the - * new row for the routine parameters table - */ - var new_param_row = RTE.param_template.replace(/%s/g, $routine_params_table.find('tr').length - 1); - // Append the new row to the parameters table - $routine_params_table.append(new_param_row); - // Make sure that the row is correctly shown according to the type of routine - if ($(this).closest('div.ui-dialog').find('table.rte_table select[name=item_type]').val() === 'FUNCTION') { - $('tr.routine_return_row').show(); - $('td.routine_direction_cell').hide(); - } - /** - * @var newrow jQuery object containing the reference to the newly - * inserted row in the routine parameters table - */ - var $newrow = $(this).closest('div.ui-dialog').find('table.routine_params_table').find('tr').has('td').last(); - // Enable/disable the 'options' dropdowns for parameters as necessary - var rte = new RTE.object('routine'); - rte.setOptionsForParameter( - $newrow.find('select[name^=item_param_type]'), - $newrow.find('input[name^=item_param_length]'), - $newrow.find('select[name^=item_param_opts_text]'), - $newrow.find('select[name^=item_param_opts_num]') - ); - }); // end $(document).on() - - /** - * Attach Ajax event handlers for the - * "Remove parameter from routine" functionality - */ - $(document).on('click', 'a.routine_param_remove_anchor', function (event) { - event.preventDefault(); - $(this).parent().parent().remove(); - // After removing a parameter, the indices of the name attributes in - // the input fields lose the correct order and need to be reordered. - RTE.ROUTINE.reindexParameters(); - }); // end $(document).on() -}); // end of $() From 673e82e6a64dbe0078cff10282503f1b03ff9698 Mon Sep 17 00:00:00 2001 From: Piyush Vijay Date: Wed, 10 Oct 2018 08:37:05 +0530 Subject: [PATCH 8/8] version fixture for webpack to prevent updated version installation. Signed-Off-By: Piyush Vijay --- package.json | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/package.json b/package.json index 90964803a8..41a4ee173e 100644 --- a/package.json +++ b/package.json @@ -17,13 +17,13 @@ "jquery": "3.3.1", "jquery-migrate": "3.0.0", "jquery-mousewheel": "3.1.13", - "jquery-ui": "^1.12.1", - "jquery-ui-bundle": "^1.12.1-migrate", + "jquery-ui": "1.12.1", + "jquery-ui-bundle": "1.12.1-migrate", "jquery-ui-timepicker-addon": "1.6.3", "jquery-validation": "1.17.0", "jquery.event.drag": "2.2.2", "js-cookie": "2.2.0", - "sprintf-js": "^1.1.1", + "sprintf-js": "1.1.1", "tracekit": "0.4.5", "updated-jqplot": "1.0.9-2", "zxcvbn": "4.4.2" @@ -39,9 +39,9 @@ "eslint": "^4.9.0", "jsdoc": "^3.5.5", "minami": "^1.2.3", - "webpack": "^4.8.3", - "webpack-bundle-analyzer": "^2.13.1", - "webpack-cli": "^2.1.3", - "webpack-dev-server": "^3.1.4" + "webpack": "4.8.3", + "webpack-bundle-analyzer": "2.13.1", + "webpack-cli": "2.1.3", + "webpack-dev-server": "3.1.4" } }