Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/phpmyadmin/phpmyadmin.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPiyush Vijay <piyushvijay.1997@gmail.com>2018-09-20 02:06:42 +0300
committerPiyush Vijay <piyushvijay.1997@gmail.com>2018-09-20 02:06:42 +0300
commit12781a3f9765e740d816c7128eb07806a57885dc (patch)
tree7bfc54f17356979860cbe7b14cfdc461d7a406c7
parentb7371e418d05ac6efb2e835f5b1a312acaf80ba7 (diff)
Add Routines, Triggers and Events in the modular code.
Signed-Off-By: Piyush Vijay <piyushvijay.1997@gmail.com>
-rw-r--r--js/src/classes/RTE.js928
-rw-r--r--js/src/rte.js166
2 files changed, 1094 insertions, 0 deletions
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 = '<textarea cols="40" rows="15" class="all100">' + data.message + '</textarea>';
+ var $ajaxDialog = $('<div>' + data.message + '</div>').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 = $('<div id="rteDialog">' + data.message + '</div>').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 = $('<div/>').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 = $('<div>' + data.message + '</div>').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 $()