One Hat Cyber Team
  • Dir : ~/var/www/pma/js/
  • View File Name : functions.js
    \n'; new_content += getForeignKeyCheckboxLoader(); new_content += '\n'; new_content += '\n'; var $editor_area = $('div#inline_editor'); if ($editor_area.length === 0) { $editor_area = $('
    '); $editor_area.insertBefore($inner_sql); } $editor_area.html(new_content); loadForeignKeyCheckbox(); $inner_sql.hide(); bindCodeMirrorToInlineEditor(); return false; }); $(document).on('click', 'input#sql_query_edit_save', function () { // hide already existing success message var sql_query; if (codemirror_inline_editor) { codemirror_inline_editor.save(); sql_query = codemirror_inline_editor.getValue(); } else { sql_query = $(this).parent().find('#sql_query_edit').val(); } var fk_check = $(this).parent().find('#fk_checks').is(':checked'); var $form = $('a.inline_edit_sql').prev('form'); var $fake_form = $('
    ', { action: 'import.php', method: 'post' }) .append($form.find('input[name=server], input[name=db], input[name=table], input[name=token]').clone()) .append($('', { type: 'hidden', name: 'show_query', value: 1 })) .append($('', { type: 'hidden', name: 'is_js_confirmed', value: 0 })) .append($('', { type: 'hidden', name: 'sql_query', value: sql_query })) .append($('', { type: 'hidden', name: 'fk_checks', value: fk_check ? 1 : 0 })); if (! checkSqlQuery($fake_form[0])) { return false; } $('.success').hide(); $fake_form.appendTo($('body')).submit(); }); $(document).on('click', 'input#sql_query_edit_discard', function () { var $divEditor = $('div#inline_editor_outer'); $divEditor.siblings('code.sql').show(); $divEditor.remove(); }); $(document).on('click', 'input.sqlbutton', function (evt) { insertQuery(evt.target.id); PMA_handleSimulateQueryButton(); return false; }); $(document).on('change', '#parameterized', updateQueryParameters); var $inputUsername = $('#input_username'); if ($inputUsername) { if ($inputUsername.val() === '') { $inputUsername.trigger('focus'); } else { $('#input_password').trigger('focus'); } } }); /** * "inputRead" event handler for CodeMirror SQL query editors for autocompletion */ function codemirrorAutocompleteOnInputRead (instance) { if (!sql_autocomplete_in_progress && (!instance.options.hintOptions.tables || !sql_autocomplete)) { if (!sql_autocomplete) { // Reset after teardown instance.options.hintOptions.tables = false; instance.options.hintOptions.defaultTable = ''; sql_autocomplete_in_progress = true; var href = 'db_sql_autocomplete.php'; var params = { 'ajax_request': true, 'server': PMA_commonParams.get('server'), 'db': PMA_commonParams.get('db'), 'no_debug': true }; var columnHintRender = function (elem, self, data) { $('
    ') .text(data.columnName) .appendTo(elem); $('
    ') .text(data.columnHint) .appendTo(elem); }; $.ajax({ type: 'POST', url: href, data: params, success: function (data) { if (data.success) { var tables = JSON.parse(data.tables); sql_autocomplete_default_table = PMA_commonParams.get('table'); sql_autocomplete = []; for (var table in tables) { if (tables.hasOwnProperty(table)) { var columns = tables[table]; table = { text: table, columns: [] }; for (var column in columns) { if (columns.hasOwnProperty(column)) { var displayText = columns[column].Type; if (columns[column].Key === 'PRI') { displayText += ' | Primary'; } else if (columns[column].Key === 'UNI') { displayText += ' | Unique'; } table.columns.push({ text: column, displayText: column + ' | ' + displayText, columnName: column, columnHint: displayText, render: columnHintRender }); } } } sql_autocomplete.push(table); } instance.options.hintOptions.tables = sql_autocomplete; instance.options.hintOptions.defaultTable = sql_autocomplete_default_table; } }, complete: function () { sql_autocomplete_in_progress = false; } }); } else { instance.options.hintOptions.tables = sql_autocomplete; instance.options.hintOptions.defaultTable = sql_autocomplete_default_table; } } if (instance.state.completionActive) { return; } var cur = instance.getCursor(); var token = instance.getTokenAt(cur); var string = ''; if (token.string.match(/^[.`\w@]\w*$/)) { string = token.string; } if (string.length > 0) { CodeMirror.commands.autocomplete(instance); } } /** * Remove autocomplete information before tearing down a page */ AJAX.registerTeardown('functions.js', function () { sql_autocomplete = false; sql_autocomplete_default_table = ''; }); /** * Binds the CodeMirror to the text area used to inline edit a query. */ function bindCodeMirrorToInlineEditor () { var $inline_editor = $('#sql_query_edit'); if ($inline_editor.length > 0) { if (typeof CodeMirror !== 'undefined') { var height = $inline_editor.css('height'); codemirror_inline_editor = PMA_getSQLEditor($inline_editor); codemirror_inline_editor.getWrapperElement().style.height = height; codemirror_inline_editor.refresh(); codemirror_inline_editor.focus(); $(codemirror_inline_editor.getWrapperElement()) .on('keydown', catchKeypressesFromSqlInlineEdit); } else { $inline_editor .focus() .on('keydown', catchKeypressesFromSqlInlineEdit); } } } function catchKeypressesFromSqlInlineEdit (event) { // ctrl-enter is 10 in chrome and ie, but 13 in ff if ((event.ctrlKey || event.metaKey) && (event.keyCode === 13 || event.keyCode === 10)) { $('#sql_query_edit_save').trigger('click'); } } /** * Adds doc link to single highlighted SQL element */ function PMA_doc_add ($elm, params) { if (typeof mysql_doc_template === 'undefined') { return; } var url = PMA_sprintf( decodeURIComponent(mysql_doc_template), params[0] ); if (params.length > 1) { url += '#' + params[1]; } var content = $elm.text(); $elm.text(''); $elm.append('' + content + ''); } /** * Generates doc links for keywords inside highlighted SQL */ function PMA_doc_keyword (idx, elm) { var $elm = $(elm); /* Skip already processed ones */ if ($elm.find('a').length > 0) { return; } var keyword = $elm.text().toUpperCase(); var $next = $elm.next('.cm-keyword'); if ($next) { var next_keyword = $next.text().toUpperCase(); var full = keyword + ' ' + next_keyword; var $next2 = $next.next('.cm-keyword'); if ($next2) { var next2_keyword = $next2.text().toUpperCase(); var full2 = full + ' ' + next2_keyword; if (full2 in mysql_doc_keyword) { PMA_doc_add($elm, mysql_doc_keyword[full2]); PMA_doc_add($next, mysql_doc_keyword[full2]); PMA_doc_add($next2, mysql_doc_keyword[full2]); return; } } if (full in mysql_doc_keyword) { PMA_doc_add($elm, mysql_doc_keyword[full]); PMA_doc_add($next, mysql_doc_keyword[full]); return; } } if (keyword in mysql_doc_keyword) { PMA_doc_add($elm, mysql_doc_keyword[keyword]); } } /** * Generates doc links for builtins inside highlighted SQL */ function PMA_doc_builtin (idx, elm) { var $elm = $(elm); var builtin = $elm.text().toUpperCase(); if (builtin in mysql_doc_builtin) { PMA_doc_add($elm, mysql_doc_builtin[builtin]); } } /** * Higlights SQL using CodeMirror. */ function PMA_highlightSQL ($base) { var $elm = $base.find('code.sql'); $elm.each(function () { var $sql = $(this); var $pre = $sql.find('pre'); /* We only care about visible elements to avoid double processing */ if ($pre.is(':visible')) { var $highlight = $('
    '); $sql.append($highlight); if (typeof CodeMirror !== 'undefined') { CodeMirror.runMode($sql.text(), 'text/x-mysql', $highlight[0]); $pre.hide(); $highlight.find('.cm-keyword').each(PMA_doc_keyword); $highlight.find('.cm-builtin').each(PMA_doc_builtin); } } }); } /** * Updates an element containing code. * * @param jQuery Object $base base element which contains the raw and the * highlighted code. * * @param string htmlValue code in HTML format, displayed if code cannot be * highlighted * * @param string rawValue raw code, used as a parameter for highlighter * * @return bool whether content was updated or not */ function PMA_updateCode ($base, htmlValue, rawValue) { var $code = $base.find('code'); if ($code.length === 0) { return false; } // Determines the type of the content and appropriate CodeMirror mode. var type = ''; var mode = ''; if ($code.hasClass('json')) { type = 'json'; mode = 'application/json'; } else if ($code.hasClass('sql')) { type = 'sql'; mode = 'text/x-mysql'; } else if ($code.hasClass('xml')) { type = 'xml'; mode = 'application/xml'; } else { return false; } // Element used to display unhighlighted code. var $notHighlighted = $('
    ' + htmlValue + '
    '); // Tries to highlight code using CodeMirror. if (typeof CodeMirror !== 'undefined') { var $highlighted = $('
    '); CodeMirror.runMode(rawValue, mode, $highlighted[0]); $notHighlighted.hide(); $code.html('').append($notHighlighted, $highlighted[0]); } else { $code.html('').append($notHighlighted); } return true; } /** * Show a message on the top of the page for an Ajax request * * Sample usage: * * 1) var $msg = PMA_ajaxShowMessage(); * This will show a message that reads "Loading...". Such a message will not * disappear automatically and cannot be dismissed by the user. To remove this * message either the PMA_ajaxRemoveMessage($msg) function must be called or * another message must be show with PMA_ajaxShowMessage() function. * * 2) var $msg = PMA_ajaxShowMessage(PMA_messages.strProcessingRequest); * This is a special case. The behaviour is same as above, * just with a different message * * 3) var $msg = PMA_ajaxShowMessage('The operation was successful'); * This will show a message that will disappear automatically and it can also * be dismissed by the user. * * 4) var $msg = PMA_ajaxShowMessage('Some error', false); * This will show a message that will not disappear automatically, but it * can be dismissed by the user after he has finished reading it. * * @param string message string containing the message to be shown. * optional, defaults to 'Loading...' * @param mixed timeout number of milliseconds for the message to be visible * optional, defaults to 5000. If set to 'false', the * notification will never disappear * @param string type string to dictate the type of message shown. * optional, defaults to normal notification. * If set to 'error', the notification will show message * with red background. * If set to 'success', the notification will show with * a green background. * @return jQuery object jQuery Element that holds the message div * this object can be passed to PMA_ajaxRemoveMessage() * to remove the notification */ function PMA_ajaxShowMessage (message, timeout, type) { /** * @var self_closing Whether the notification will automatically disappear */ var self_closing = true; /** * @var dismissable Whether the user will be able to remove * the notification by clicking on it */ var dismissable = true; // Handle the case when a empty data.message is passed. // We don't want the empty message if (message === '') { return true; } else if (! message) { // If the message is undefined, show the default message = PMA_messages.strLoading; dismissable = false; self_closing = false; } else if (message === PMA_messages.strProcessingRequest) { // This is another case where the message should not disappear dismissable = false; self_closing = false; } // Figure out whether (or after how long) to remove the notification if (timeout === undefined) { timeout = 5000; } else if (timeout === false) { self_closing = false; } // Determine type of message, add styling as required if (type === 'error') { message = '
    ' + message + '
    '; } else if (type === 'success') { message = '
    ' + message + '
    '; } // Create a parent element for the AJAX messages, if necessary if ($('#loading_parent').length === 0) { $('
    ') .prependTo('#page_content'); } // Update message count to create distinct message elements every time ajax_message_count++; // Remove all old messages, if any $('span.ajax_notification[id^=ajax_message_num]').remove(); /** * @var $retval a jQuery object containing the reference * to the created AJAX message */ var $retval = $( '' ) .hide() .appendTo('#loading_parent') .html(message) .show(); // If the notification is self-closing we should create a callback to remove it if (self_closing) { $retval .delay(timeout) .fadeOut('medium', function () { if ($(this).is(':data(tooltip)')) { $(this).tooltip('destroy'); } // Remove the notification $(this).remove(); }); } // If the notification is dismissable we need to add the relevant class to it // and add a tooltip so that the users know that it can be removed if (dismissable) { $retval.addClass('dismissable').css('cursor', 'pointer'); /** * Add a tooltip to the notification to let the user know that (s)he * can dismiss the ajax notification by clicking on it. */ PMA_tooltip( $retval, 'span', PMA_messages.strDismiss ); } PMA_highlightSQL($retval); return $retval; } /** * Removes the message shown for an Ajax operation when it's completed * * @param jQuery object jQuery Element that holds the notification * * @return nothing */ function PMA_ajaxRemoveMessage ($this_msgbox) { if ($this_msgbox !== undefined && $this_msgbox instanceof jQuery) { $this_msgbox .stop(true, true) .fadeOut('medium'); if ($this_msgbox.is(':data(tooltip)')) { $this_msgbox.tooltip('destroy'); } else { $this_msgbox.remove(); } } } /** * Requests SQL for previewing before executing. * * @param jQuery Object $form Form containing query data * * @return void */ function PMA_previewSQL ($form) { var form_url = $form.attr('action'); var sep = PMA_commonParams.get('arg_separator'); var form_data = $form.serialize() + sep + 'do_save_data=1' + sep + 'preview_sql=1' + sep + 'ajax_request=1'; var $msgbox = PMA_ajaxShowMessage(); $.ajax({ type: 'POST', url: form_url, data: form_data, success: function (response) { PMA_ajaxRemoveMessage($msgbox); if (response.success) { var $dialog_content = $('
    ') .append(response.sql_data); var button_options = {}; button_options[PMA_messages.strClose] = function () { $(this).dialog('close'); }; var $response_dialog = $dialog_content.dialog({ minWidth: 550, maxHeight: 400, modal: true, buttons: button_options, title: PMA_messages.strPreviewSQL, close: function () { $(this).remove(); }, open: function () { // Pretty SQL printing. PMA_highlightSQL($(this)); } }); } else { PMA_ajaxShowMessage(response.message); } }, error: function () { PMA_ajaxShowMessage(PMA_messages.strErrorProcessingRequest); } }); } /** * check for reserved keyword column name * * @param jQuery Object $form Form * * @returns true|false */ function PMA_checkReservedWordColumns ($form) { var is_confirmed = true; $.ajax({ type: 'POST', url: 'tbl_structure.php', data: $form.serialize() + PMA_commonParams.get('arg_separator') + 'reserved_word_check=1', success: function (data) { if (typeof data.success !== 'undefined' && data.success === true) { is_confirmed = confirm(data.message); } }, async:false }); return is_confirmed; } // This event only need to be fired once after the initial page load $(function () { /** * Allows the user to dismiss a notification * created with PMA_ajaxShowMessage() */ $(document).on('click', 'span.ajax_notification.dismissable', function () { PMA_ajaxRemoveMessage($(this)); }); /** * The below two functions hide the "Dismiss notification" tooltip when a user * is hovering a link or button that is inside an ajax message */ $(document).on('mouseover', 'span.ajax_notification a, span.ajax_notification button, span.ajax_notification input', function () { if ($(this).parents('span.ajax_notification').is(':data(tooltip)')) { $(this).parents('span.ajax_notification').tooltip('disable'); } }); $(document).on('mouseout', 'span.ajax_notification a, span.ajax_notification button, span.ajax_notification input', function () { if ($(this).parents('span.ajax_notification').is(':data(tooltip)')) { $(this).parents('span.ajax_notification').tooltip('enable'); } }); }); /** * Hides/shows the "Open in ENUM/SET editor" message, depending on the data type of the column currently selected */ function PMA_showNoticeForEnum (selectElement) { var enum_notice_id = selectElement.attr('id').split('_')[1]; enum_notice_id += '_' + (parseInt(selectElement.attr('id').split('_')[2], 10) + 1); var selectedType = selectElement.val(); if (selectedType === 'ENUM' || selectedType === 'SET') { $('p#enum_notice_' + enum_notice_id).show(); } else { $('p#enum_notice_' + enum_notice_id).hide(); } } /** * Creates a Profiling Chart. Used in sql.js * and in server_status_monitor.js */ function PMA_createProfilingChart (target, data) { // create the chart var factory = new JQPlotChartFactory(); var chart = factory.createChart(ChartType.PIE, target); // create the data table and add columns var dataTable = new DataTable(); dataTable.addColumn(ColumnType.STRING, ''); dataTable.addColumn(ColumnType.NUMBER, ''); dataTable.setData(data); var windowWidth = $(window).width(); var location = 's'; if (windowWidth > 768) { var location = 'se'; } // draw the chart and return the chart object chart.draw(dataTable, { seriesDefaults: { rendererOptions: { showDataLabels: true } }, highlighter: { tooltipLocation: 'se', sizeAdjust: 0, tooltipAxes: 'pieref', formatString: '%s, %.9Ps' }, legend: { show: true, location: location, rendererOptions: { numberColumns: 2 } }, // from http://tango.freedesktop.org/Tango_Icon_Theme_Guidelines#Color_Palette seriesColors: [ '#fce94f', '#fcaf3e', '#e9b96e', '#8ae234', '#729fcf', '#ad7fa8', '#ef2929', '#888a85', '#c4a000', '#ce5c00', '#8f5902', '#4e9a06', '#204a87', '#5c3566', '#a40000', '#babdb6', '#2e3436' ] }); return chart; } /** * Formats a profiling duration nicely (in us and ms time). * Used in server_status_monitor.js * * @param integer Number to be formatted, should be in the range of microsecond to second * @param integer Accuracy, how many numbers right to the comma should be * @return string The formatted number */ function PMA_prettyProfilingNum (num, acc) { if (!acc) { acc = 2; } acc = Math.pow(10, acc); if (num * 1000 < 0.1) { num = Math.round(acc * (num * 1000 * 1000)) / acc + 'µ'; } else if (num < 0.1) { num = Math.round(acc * (num * 1000)) / acc + 'm'; } else { num = Math.round(acc * num) / acc; } return num + 's'; } /** * Formats a SQL Query nicely with newlines and indentation. Depends on Codemirror and MySQL Mode! * * @param string Query to be formatted * @return string The formatted query */ function PMA_SQLPrettyPrint (string) { if (typeof CodeMirror === 'undefined') { return string; } var mode = CodeMirror.getMode({}, 'text/x-mysql'); var stream = new CodeMirror.StringStream(string); var state = mode.startState(); var token; var tokens = []; var output = ''; var tabs = function (cnt) { var ret = ''; for (var i = 0; i < 4 * cnt; i++) { ret += ' '; } return ret; }; // "root-level" statements var statements = { 'select': ['select', 'from', 'on', 'where', 'having', 'limit', 'order by', 'group by'], 'update': ['update', 'set', 'where'], 'insert into': ['insert into', 'values'] }; // don't put spaces before these tokens var spaceExceptionsBefore = { ';': true, ',': true, '.': true, '(': true }; // don't put spaces after these tokens var spaceExceptionsAfter = { '.': true }; // Populate tokens array var str = ''; while (! stream.eol()) { stream.start = stream.pos; token = mode.token(stream, state); if (token !== null) { tokens.push([token, stream.current().toLowerCase()]); } } var currentStatement = tokens[0][1]; if (! statements[currentStatement]) { return string; } // Holds all currently opened code blocks (statement, function or generic) var blockStack = []; // Holds the type of block from last iteration (the current is in blockStack[0]) var previousBlock; // If a new code block is found, newBlock contains its type for one iteration and vice versa for endBlock var newBlock; var endBlock; // How much to indent in the current line var indentLevel = 0; // Holds the "root-level" statements var statementPart; var lastStatementPart = statements[currentStatement][0]; blockStack.unshift('statement'); // Iterate through every token and format accordingly for (var i = 0; i < tokens.length; i++) { previousBlock = blockStack[0]; // New block => push to stack if (tokens[i][1] === '(') { if (i < tokens.length - 1 && tokens[i + 1][0] === 'statement-verb') { blockStack.unshift(newBlock = 'statement'); } else if (i > 0 && tokens[i - 1][0] === 'builtin') { blockStack.unshift(newBlock = 'function'); } else { blockStack.unshift(newBlock = 'generic'); } } else { newBlock = null; } // Block end => pop from stack if (tokens[i][1] === ')') { endBlock = blockStack[0]; blockStack.shift(); } else { endBlock = null; } // A subquery is starting if (i > 0 && newBlock === 'statement') { indentLevel++; output += '\n' + tabs(indentLevel) + tokens[i][1] + ' ' + tokens[i + 1][1].toUpperCase() + '\n' + tabs(indentLevel + 1); currentStatement = tokens[i + 1][1]; i++; continue; } // A subquery is ending if (endBlock === 'statement' && indentLevel > 0) { output += '\n' + tabs(indentLevel); indentLevel--; } // One less indentation for statement parts (from, where, order by, etc.) and a newline statementPart = statements[currentStatement].indexOf(tokens[i][1]); if (statementPart !== -1) { if (i > 0) { output += '\n'; } output += tabs(indentLevel) + tokens[i][1].toUpperCase(); output += '\n' + tabs(indentLevel + 1); lastStatementPart = tokens[i][1]; // Normal indentation and spaces for everything else } else { if (! spaceExceptionsBefore[tokens[i][1]] && ! (i > 0 && spaceExceptionsAfter[tokens[i - 1][1]]) && output.charAt(output.length - 1) !== ' ') { output += ' '; } if (tokens[i][0] === 'keyword') { output += tokens[i][1].toUpperCase(); } else { output += tokens[i][1]; } } // split columns in select and 'update set' clauses, but only inside statements blocks if ((lastStatementPart === 'select' || lastStatementPart === 'where' || lastStatementPart === 'set') && tokens[i][1] === ',' && blockStack[0] === 'statement') { output += '\n' + tabs(indentLevel + 1); } // split conditions in where clauses, but only inside statements blocks if (lastStatementPart === 'where' && (tokens[i][1] === 'and' || tokens[i][1] === 'or' || tokens[i][1] === 'xor')) { if (blockStack[0] === 'statement') { output += '\n' + tabs(indentLevel + 1); } // Todo: Also split and or blocks in newlines & indentation++ // if (blockStack[0] === 'generic') // output += ... } } return output; } /** * jQuery function that uses jQueryUI's dialogs to confirm with user. Does not * return a jQuery object yet and hence cannot be chained * * @param string question * @param string url URL to be passed to the callbackFn to make * an Ajax call to * @param function callbackFn callback to execute after user clicks on OK * @param function openCallback optional callback to run when dialog is shown */ jQuery.fn.PMA_confirm = function (question, url, callbackFn, openCallback) { var confirmState = PMA_commonParams.get('confirm'); if (! confirmState) { // user does not want to confirm if ($.isFunction(callbackFn)) { callbackFn.call(this, url); return true; } } if (PMA_messages.strDoYouReally === '') { return true; } /** * @var button_options Object that stores the options passed to jQueryUI * dialog */ var button_options = [ { text: PMA_messages.strOK, 'class': 'submitOK', click: function () { $(this).dialog('close'); if ($.isFunction(callbackFn)) { callbackFn.call(this, url); } } }, { text: PMA_messages.strCancel, 'class': 'submitCancel', click: function () { $(this).dialog('close'); } } ]; $('
    ', { 'id': 'confirm_dialog', 'title': PMA_messages.strConfirm }) .prepend(question) .dialog({ buttons: button_options, close: function () { $(this).remove(); }, open: openCallback, modal: true }); }; /** * jQuery function to sort a table's body after a new row has been appended to it. * * @param string text_selector string to select the sortKey's text * * @return jQuery Object for chaining purposes */ jQuery.fn.PMA_sort_table = function (text_selector) { return this.each(function () { /** * @var table_body Object referring to the table's element */ var table_body = $(this); /** * @var rows Object referring to the collection of rows in {@link table_body} */ var rows = $(this).find('tr').get(); // get the text of the field that we will sort by $.each(rows, function (index, row) { row.sortKey = $.trim($(row).find(text_selector).text().toLowerCase()); }); // get the sorted order rows.sort(function (a, b) { if (a.sortKey < b.sortKey) { return -1; } if (a.sortKey > b.sortKey) { return 1; } return 0; }); // pull out each row from the table and then append it according to it's order $.each(rows, function (index, row) { $(table_body).append(row); row.sortKey = null; }); }); }; /** * Unbind all event handlers before tearing down a page */ AJAX.registerTeardown('functions.js', function () { $(document).off('submit', '#create_table_form_minimal.ajax'); $(document).off('submit', 'form.create_table_form.ajax'); $(document).off('click', 'form.create_table_form.ajax input[name=submit_num_fields]'); $(document).off('keyup', 'form.create_table_form.ajax input'); $(document).off('change', 'input[name=partition_count],input[name=subpartition_count],select[name=partition_by]'); }); /** * jQuery coding for 'Create Table'. Used on db_operations.php, * db_structure.php and db_tracking.php (i.e., wherever * PhpMyAdmin\Display\CreateTable is used) * * Attach Ajax Event handlers for Create Table */ AJAX.registerOnload('functions.js', function () { /** * Attach event handler for submission of create table form (save) */ $(document).on('submit', 'form.create_table_form.ajax', function (event) { event.preventDefault(); /** * @var the_form object referring to the create table form */ var $form = $(this); /* * First validate the form; if there is a problem, avoid submitting it * * checkTableEditForm() needs a pure element and not a jQuery object, * this is why we pass $form[0] as a parameter (the jQuery object * is actually an array of DOM elements) */ if (checkTableEditForm($form[0], $form.find('input[name=orig_num_fields]').val())) { PMA_prepareForAjaxRequest($form); if (PMA_checkReservedWordColumns($form)) { PMA_ajaxShowMessage(PMA_messages.strProcessingRequest); // User wants to submit the form $.post($form.attr('action'), $form.serialize() + PMA_commonParams.get('arg_separator') + 'do_save_data=1', function (data) { if (typeof data !== 'undefined' && data.success === true) { $('#properties_message') .removeClass('error') .html(''); PMA_ajaxShowMessage(data.message); // Only if the create table dialog (distinct panel) exists var $createTableDialog = $('#create_table_dialog'); if ($createTableDialog.length > 0) { $createTableDialog.dialog('close').remove(); } $('#tableslistcontainer').before(data.formatted_sql); /** * @var tables_table Object referring to the element that holds the list of tables */ var tables_table = $('#tablesForm').find('tbody').not('#tbl_summary_row'); // this is the first table created in this db if (tables_table.length === 0) { PMA_commonActions.refreshMain( PMA_commonParams.get('opendb_url') ); } else { /** * @var curr_last_row Object referring to the last element in {@link tables_table} */ var curr_last_row = $(tables_table).find('tr:last'); /** * @var curr_last_row_index_string String containing the index of {@link curr_last_row} */ var curr_last_row_index_string = $(curr_last_row).find('input:checkbox').attr('id').match(/\d+/)[0]; /** * @var curr_last_row_index Index of {@link curr_last_row} */ var curr_last_row_index = parseFloat(curr_last_row_index_string); /** * @var new_last_row_index Index of the new row to be appended to {@link tables_table} */ var new_last_row_index = curr_last_row_index + 1; /** * @var new_last_row_id String containing the id of the row to be appended to {@link tables_table} */ var new_last_row_id = 'checkbox_tbl_' + new_last_row_index; data.new_table_string = data.new_table_string.replace(/checkbox_tbl_/, new_last_row_id); // append to table $(data.new_table_string) .appendTo(tables_table); // Sort the table $(tables_table).PMA_sort_table('th'); // Adjust summary row PMA_adjustTotals(); } // Refresh navigation as a new table has been added PMA_reloadNavigation(); // Redirect to table structure page on creation of new table var argsep = PMA_commonParams.get('arg_separator'); var params_12 = 'ajax_request=true' + argsep + 'ajax_page_request=true'; if (! (history && history.pushState)) { params_12 += PMA_MicroHistory.menus.getRequestParam(); } tblStruct_url = 'tbl_structure.php?server=' + data._params.server + argsep + 'db=' + data._params.db + argsep + 'token=' + data._params.token + argsep + 'goto=db_structure.php' + argsep + 'table=' + data._params.table + ''; $.get(tblStruct_url, params_12, AJAX.responseHandler); } else { PMA_ajaxShowMessage( '
    ' + data.error + '
    ', false ); } }); // end $.post() } } // end if (checkTableEditForm() ) }); // end create table form (save) /** * Submits the intermediate changes in the table creation form * to refresh the UI accordingly */ function submitChangesInCreateTableForm (actionParam) { /** * @var the_form object referring to the create table form */ var $form = $('form.create_table_form.ajax'); var $msgbox = PMA_ajaxShowMessage(PMA_messages.strProcessingRequest); PMA_prepareForAjaxRequest($form); // User wants to add more fields to the table $.post($form.attr('action'), $form.serialize() + '&' + actionParam, function (data) { if (typeof data !== 'undefined' && data.success) { var $pageContent = $('#page_content'); $pageContent.html(data.message); PMA_highlightSQL($pageContent); PMA_verifyColumnsProperties(); PMA_hideShowConnection($('.create_table_form select[name=tbl_storage_engine]')); PMA_ajaxRemoveMessage($msgbox); } else { PMA_ajaxShowMessage(data.error); } }); // end $.post() } /** * Attach event handler for create table form (add fields) */ $(document).on('click', 'form.create_table_form.ajax input[name=submit_num_fields]', function (event) { event.preventDefault(); submitChangesInCreateTableForm('submit_num_fields=1'); }); // end create table form (add fields) $(document).on('keydown', 'form.create_table_form.ajax input[name=added_fields]', function (event) { if (event.keyCode === 13) { event.preventDefault(); event.stopImmediatePropagation(); $(this) .closest('form') .find('input[name=submit_num_fields]') .click(); } }); /** * Attach event handler to manage changes in number of partitions and subpartitions */ $(document).on('change', 'input[name=partition_count],input[name=subpartition_count],select[name=partition_by]', function (event) { $this = $(this); $form = $this.parents('form'); if ($form.is('.create_table_form.ajax')) { submitChangesInCreateTableForm('submit_partition_change=1'); } else { $form.submit(); } }); $(document).on('change', 'input[value=AUTO_INCREMENT]', function () { if (this.checked) { var col = /\d/.exec($(this).attr('name')); col = col[0]; var $selectFieldKey = $('select[name="field_key[' + col + ']"]'); if ($selectFieldKey.val() === 'none_' + col) { $selectFieldKey.val('primary_' + col).change(); } } }); $('body') .off('click', 'input.preview_sql') .on('click', 'input.preview_sql', function () { var $form = $(this).closest('form'); PMA_previewSQL($form); }); }); /** * Validates the password field in a form * * @see PMA_messages.strPasswordEmpty * @see PMA_messages.strPasswordNotSame * @param object $the_form The form to be validated * @return bool */ function PMA_checkPassword ($the_form) { // Did the user select 'no password'? if ($the_form.find('#nopass_1').is(':checked')) { return true; } else { var $pred = $the_form.find('#select_pred_password'); if ($pred.length && ($pred.val() === 'none' || $pred.val() === 'keep')) { return true; } } var $password = $the_form.find('input[name=pma_pw]'); var $password_repeat = $the_form.find('input[name=pma_pw2]'); var alert_msg = false; if ($password.val() === '') { alert_msg = PMA_messages.strPasswordEmpty; } else if ($password.val() !== $password_repeat.val()) { alert_msg = PMA_messages.strPasswordNotSame; } if (alert_msg) { alert(alert_msg); $password.val(''); $password_repeat.val(''); $password.focus(); return false; } return true; } /** * Attach Ajax event handlers for 'Change Password' on index.php */ AJAX.registerOnload('functions.js', function () { /* Handler for hostname type */ $(document).on('change', '#select_pred_hostname', function () { var hostname = $('#pma_hostname'); if (this.value === 'any') { hostname.val('%'); } else if (this.value === 'localhost') { hostname.val('localhost'); } else if (this.value === 'thishost' && $(this).data('thishost')) { hostname.val($(this).data('thishost')); } else if (this.value === 'hosttable') { hostname.val('').prop('required', false); } else if (this.value === 'userdefined') { hostname.focus().select().prop('required', true); } }); /* Handler for editing hostname */ $(document).on('change', '#pma_hostname', function () { $('#select_pred_hostname').val('userdefined'); $('#pma_hostname').prop('required', true); }); /* Handler for username type */ $(document).on('change', '#select_pred_username', function () { if (this.value === 'any') { $('#pma_username').val('').prop('required', false); $('#user_exists_warning').css('display', 'none'); } else if (this.value === 'userdefined') { $('#pma_username').focus().select().prop('required', true); } }); /* Handler for editing username */ $(document).on('change', '#pma_username', function () { $('#select_pred_username').val('userdefined'); $('#pma_username').prop('required', true); }); /* Handler for password type */ $(document).on('change', '#select_pred_password', function () { if (this.value === 'none') { $('#text_pma_pw2').prop('required', false).val(''); $('#text_pma_pw').prop('required', false).val(''); } else if (this.value === 'userdefined') { $('#text_pma_pw2').prop('required', true); $('#text_pma_pw').prop('required', true).focus().select(); } else { $('#text_pma_pw2').prop('required', false); $('#text_pma_pw').prop('required', false); } }); /* Handler for editing password */ $(document).on('change', '#text_pma_pw,#text_pma_pw2', function () { $('#select_pred_password').val('userdefined'); $('#text_pma_pw2').prop('required', true); $('#text_pma_pw').prop('required', true); }); /** * Unbind all event handlers before tearing down a page */ $(document).off('click', '#change_password_anchor.ajax'); /** * Attach Ajax event handler on the change password anchor */ $(document).on('click', '#change_password_anchor.ajax', function (event) { event.preventDefault(); var $msgbox = PMA_ajaxShowMessage(); /** * @var button_options Object containing options to be passed to jQueryUI's dialog */ var button_options = {}; button_options[PMA_messages.strGo] = function () { event.preventDefault(); /** * @var $the_form Object referring to the change password form */ var $the_form = $('#change_password_form'); if (! PMA_checkPassword($the_form)) { return false; } /** * @var this_value String containing the value of the submit button. * Need to append this for the change password form on Server Privileges * page to work */ var this_value = $(this).val(); var $msgbox = PMA_ajaxShowMessage(PMA_messages.strProcessingRequest); $the_form.append(''); $.post($the_form.attr('action'), $the_form.serialize() + PMA_commonParams.get('arg_separator') + 'change_pw=' + this_value, function (data) { if (typeof data === 'undefined' || data.success !== true) { PMA_ajaxShowMessage(data.error, false); return; } var $pageContent = $('#page_content'); $pageContent.prepend(data.message); PMA_highlightSQL($pageContent); $('#change_password_dialog').hide().remove(); $('#edit_user_dialog').dialog('close').remove(); PMA_ajaxRemoveMessage($msgbox); }); // end $.post() }; button_options[PMA_messages.strCancel] = function () { $(this).dialog('close'); }; $.get($(this).attr('href'), { 'ajax_request': true }, function (data) { if (typeof data === 'undefined' || !data.success) { PMA_ajaxShowMessage(data.error, false); return; } if (data._scripts) { AJAX.scriptHandler.load(data._scripts); } $('
    ') .dialog({ title: PMA_messages.strChangePassword, width: 600, close: function (ev, ui) { $(this).remove(); }, buttons: button_options, modal: true }) .append(data.message); // for this dialog, we remove the fieldset wrapping due to double headings $('fieldset#fieldset_change_password') .find('legend').remove().end() .find('table.noclick').unwrap().addClass('some-margin') .find('input#text_pma_pw').focus(); $('#fieldset_change_password_footer').hide(); PMA_ajaxRemoveMessage($msgbox); $('#change_password_form').on('submit', function (e) { e.preventDefault(); $(this) .closest('.ui-dialog') .find('.ui-dialog-buttonpane .ui-button') .first() .click(); }); }); // end $.get() }); // end handler for change password anchor }); // end $() for Change Password /** * Unbind all event handlers before tearing down a page */ AJAX.registerTeardown('functions.js', function () { $(document).off('change', 'select.column_type'); $(document).off('change', 'select.default_type'); $(document).off('change', 'select.virtuality'); $(document).off('change', 'input.allow_null'); $(document).off('change', '.create_table_form select[name=tbl_storage_engine]'); }); /** * Toggle the hiding/showing of the "Open in ENUM/SET editor" message when * the page loads and when the selected data type changes */ AJAX.registerOnload('functions.js', function () { // is called here for normal page loads and also when opening // the Create table dialog PMA_verifyColumnsProperties(); // // needs on() to work also in the Create Table dialog $(document).on('change', 'select.column_type', function () { PMA_showNoticeForEnum($(this)); }); $(document).on('change', 'select.default_type', function () { PMA_hideShowDefaultValue($(this)); }); $(document).on('change', 'select.virtuality', function () { PMA_hideShowExpression($(this)); }); $(document).on('change', 'input.allow_null', function () { PMA_validateDefaultValue($(this)); }); $(document).on('change', '.create_table_form select[name=tbl_storage_engine]', function () { PMA_hideShowConnection($(this)); }); }); /** * If the chosen storage engine is FEDERATED show connection field. Hide otherwise * * @param $engine_selector storage engine selector */ function PMA_hideShowConnection ($engine_selector) { var $connection = $('.create_table_form input[name=connection]'); var index = $connection.parent('td').index() + 1; var $labelTh = $connection.parents('tr').prev('tr').children('th:nth-child(' + index + ')'); if ($engine_selector.val() !== 'FEDERATED') { $connection .prop('disabled', true) .parent('td').hide(); $labelTh.hide(); } else { $connection .prop('disabled', false) .parent('td').show(); $labelTh.show(); } } /** * If the column does not allow NULL values, makes sure that default is not NULL */ function PMA_validateDefaultValue ($null_checkbox) { if (! $null_checkbox.prop('checked')) { var $default = $null_checkbox.closest('tr').find('.default_type'); if ($default.val() === 'NULL') { $default.val('NONE'); } } } /** * function to populate the input fields on picking a column from central list * * @param string input_id input id of the name field for the column to be populated * @param integer offset of the selected column in central list of columns */ function autoPopulate (input_id, offset) { var db = PMA_commonParams.get('db'); var table = PMA_commonParams.get('table'); input_id = input_id.substring(0, input_id.length - 1); $('#' + input_id + '1').val(central_column_list[db + '_' + table][offset].col_name); var col_type = central_column_list[db + '_' + table][offset].col_type.toUpperCase(); $('#' + input_id + '2').val(col_type); var $input3 = $('#' + input_id + '3'); $input3.val(central_column_list[db + '_' + table][offset].col_length); if (col_type === 'ENUM' || col_type === 'SET') { $input3.next().show(); } else { $input3.next().hide(); } var col_default = central_column_list[db + '_' + table][offset].col_default.toUpperCase(); var $input4 = $('#' + input_id + '4'); if (col_default !== '' && col_default !== 'NULL' && col_default !== 'CURRENT_TIMESTAMP' && col_default !== 'CURRENT_TIMESTAMP()') { $input4.val('USER_DEFINED'); $input4.next().next().show(); $input4.next().next().val(central_column_list[db + '_' + table][offset].col_default); } else { $input4.val(central_column_list[db + '_' + table][offset].col_default); $input4.next().next().hide(); } $('#' + input_id + '5').val(central_column_list[db + '_' + table][offset].col_collation); var $input6 = $('#' + input_id + '6'); $input6.val(central_column_list[db + '_' + table][offset].col_attribute); if (central_column_list[db + '_' + table][offset].col_extra === 'on update CURRENT_TIMESTAMP') { $input6.val(central_column_list[db + '_' + table][offset].col_extra); } if (central_column_list[db + '_' + table][offset].col_extra.toUpperCase() === 'AUTO_INCREMENT') { $('#' + input_id + '9').prop('checked',true).change(); } else { $('#' + input_id + '9').prop('checked',false); } if (central_column_list[db + '_' + table][offset].col_isNull !== '0') { $('#' + input_id + '7').prop('checked',true); } else { $('#' + input_id + '7').prop('checked',false); } } /** * Unbind all event handlers before tearing down a page */ AJAX.registerTeardown('functions.js', function () { $(document).off('click', 'a.open_enum_editor'); $(document).off('click', 'input.add_value'); $(document).off('click', '#enum_editor td.drop'); $(document).off('click', 'a.central_columns_dialog'); }); /** * @var $enum_editor_dialog An object that points to the jQuery * dialog of the ENUM/SET editor */ var $enum_editor_dialog = null; /** * Opens the ENUM/SET editor and controls its functions */ AJAX.registerOnload('functions.js', function () { $(document).on('click', 'a.open_enum_editor', function () { // Get the name of the column that is being edited var colname = $(this).closest('tr').find('input:first').val(); var title; var i; // And use it to make up a title for the page if (colname.length < 1) { title = PMA_messages.enum_newColumnVals; } else { title = PMA_messages.enum_columnVals.replace( /%s/, '"' + escapeHtml(decodeURIComponent(colname)) + '"' ); } // Get the values as a string var inputstring = $(this) .closest('td') .find('input') .val(); // Escape html entities inputstring = $('
    ') .text(inputstring) .html(); // Parse the values, escaping quotes and // slashes on the fly, into an array var values = []; var in_string = false; var curr; var next; var buffer = ''; for (i = 0; i < inputstring.length; i++) { curr = inputstring.charAt(i); next = i === inputstring.length ? '' : inputstring.charAt(i + 1); if (! in_string && curr === '\'') { in_string = true; } else if (in_string && curr === '\\' && next === '\\') { buffer += '\'; i++; } else if (in_string && next === '\'' && (curr === '\'' || curr === '\\')) { buffer += '''; i++; } else if (in_string && curr === '\'') { in_string = false; values.push(buffer); buffer = ''; } else if (in_string) { buffer += curr; } } if (buffer.length > 0) { // The leftovers in the buffer are the last value (if any) values.push(buffer); } var fields = ''; // If there are no values, maybe the user is about to make a // new list so we add a few for him/her to get started with. if (values.length === 0) { values.push('', '', '', ''); } // Add the parsed values to the editor var drop_icon = PMA_getImage('b_drop'); for (i = 0; i < values.length; i++) { fields += '' + '' + '' + drop_icon + ''; } /** * @var dialog HTML code for the ENUM/SET dialog */ var dialog = '
    ' + '
    ' + '' + title + '' + '

    ' + PMA_getImage('s_notice') + PMA_messages.enum_hint + '

    ' + '' + fields + '
    ' + '
    ' + '
    ' + '
    ' + '
    ' + '
    ' + '
    ' + '' + '
    ' + '
    '; /** * @var Defines functions to be called when the buttons in * the buttonOptions jQuery dialog bar are pressed */ var buttonOptions = {}; buttonOptions[PMA_messages.strGo] = function () { // When the submit button is clicked, // put the data back into the original form var value_array = []; $(this).find('.values input').each(function (index, elm) { var val = elm.value.replace(/\\/g, '\\\\').replace(/'/g, '\'\''); value_array.push('\'' + val + '\''); }); // get the Length/Values text field where this value belongs var values_id = $(this).find('input[type=\'hidden\']').val(); $('input#' + values_id).val(value_array.join(',')); $(this).dialog('close'); }; buttonOptions[PMA_messages.strClose] = function () { $(this).dialog('close'); }; // Show the dialog var width = parseInt( (parseInt($('html').css('font-size'), 10) / 13) * 340, 10 ); if (! width) { width = 340; } $enum_editor_dialog = $(dialog).dialog({ minWidth: width, maxHeight: 450, modal: true, title: PMA_messages.enum_editor, buttons: buttonOptions, open: function () { // Focus the "Go" button after opening the dialog $(this).closest('.ui-dialog').find('.ui-dialog-buttonpane button:first').focus(); }, close: function () { $(this).remove(); } }); // slider for choosing how many fields to add $enum_editor_dialog.find('.slider').slider({ animate: true, range: 'min', value: 1, min: 1, max: 9, slide: function (event, ui) { $(this).closest('table').find('input[type=submit]').val( PMA_sprintf(PMA_messages.enum_addValue, ui.value) ); } }); // Focus the slider, otherwise it looks nearly transparent $('a.ui-slider-handle').addClass('ui-state-focus'); return false; }); $(document).on('click', 'a.central_columns_dialog', function (e) { var href = 'db_central_columns.php'; var db = PMA_commonParams.get('db'); var table = PMA_commonParams.get('table'); var maxRows = $(this).data('maxrows'); var pick = $(this).data('pick'); if (pick !== false) { pick = true; } var params = { 'ajax_request' : true, 'server' : PMA_commonParams.get('server'), 'db' : PMA_commonParams.get('db'), 'cur_table' : PMA_commonParams.get('table'), 'getColumnList':true }; var colid = $(this).closest('td').find('input').attr('id'); var fields = ''; if (! (db + '_' + table in central_column_list)) { central_column_list.push(db + '_' + table); $.ajax({ type: 'POST', url: href, data: params, success: function (data) { central_column_list[db + '_' + table] = JSON.parse(data.message); }, async:false }); } var i = 0; var list_size = central_column_list[db + '_' + table].length; var min = (list_size <= maxRows) ? list_size : maxRows; for (i = 0; i < min; i++) { fields += '
    ' + escapeHtml(central_column_list[db + '_' + table][i].col_name) + '
    ' + central_column_list[db + '_' + table][i].col_type; if (central_column_list[db + '_' + table][i].col_attribute !== '') { fields += '(' + escapeHtml(central_column_list[db + '_' + table][i].col_attribute) + ') '; } if (central_column_list[db + '_' + table][i].col_length !== '') { fields += '(' + escapeHtml(central_column_list[db + '_' + table][i].col_length) + ') '; } fields += escapeHtml(central_column_list[db + '_' + table][i].col_extra) + '' + '
    '; if (pick) { fields += ''; } fields += ''; } var result_pointer = i; var search_in = ''; if (fields === '') { fields = PMA_sprintf(PMA_messages.strEmptyCentralList, '\'' + escapeHtml(db) + '\''); search_in = ''; } var seeMore = ''; if (list_size > maxRows) { seeMore = '
    ' + '' + PMA_messages.seeMore + '
    '; } var central_columns_dialog = '
    ' + '
    ' + search_in + '' + fields + '
    ' + '
    ' + seeMore + '
    '; var width = parseInt( (parseInt($('html').css('font-size'), 10) / 13) * 500, 10 ); if (! width) { width = 500; } var buttonOptions = {}; var $central_columns_dialog = $(central_columns_dialog).dialog({ minWidth: width, maxHeight: 450, modal: true, title: PMA_messages.pickColumnTitle, buttons: buttonOptions, open: function () { $('#col_list').on('click', '.pick', function () { $central_columns_dialog.remove(); }); $('.filter_rows').on('keyup', function () { $.uiTableFilter($('#col_list'), $(this).val()); }); $('#seeMore').click(function () { fields = ''; min = (list_size <= maxRows + result_pointer) ? list_size : maxRows + result_pointer; for (i = result_pointer; i < min; i++) { fields += '
    ' + central_column_list[db + '_' + table][i].col_name + '
    ' + central_column_list[db + '_' + table][i].col_type; if (central_column_list[db + '_' + table][i].col_attribute !== '') { fields += '(' + central_column_list[db + '_' + table][i].col_attribute + ') '; } if (central_column_list[db + '_' + table][i].col_length !== '') { fields += '(' + central_column_list[db + '_' + table][i].col_length + ') '; } fields += central_column_list[db + '_' + table][i].col_extra + '' + '
    '; if (pick) { fields += ''; } fields += ''; } $('#col_list').append(fields); result_pointer = i; if (result_pointer === list_size) { $('.tblFooters').hide(); } return false; }); $(this).closest('.ui-dialog').find('.ui-dialog-buttonpane button:first').focus(); }, close: function () { $('#col_list').off('click', '.pick'); $('.filter_rows').off('keyup'); $(this).remove(); } }); return false; }); // $(document).on('click', 'a.show_central_list',function(e) { // }); // When "add a new value" is clicked, append an empty text field $(document).on('click', 'input.add_value', function (e) { e.preventDefault(); var num_new_rows = $enum_editor_dialog.find('div.slider').slider('value'); while (num_new_rows--) { $enum_editor_dialog.find('.values') .append( '' + '' + '' + PMA_getImage('b_drop') + '' ) .find('tr:last') .show('fast'); } }); // Removes the specified row from the enum editor $(document).on('click', '#enum_editor td.drop', function () { $(this).closest('tr').hide('fast', function () { $(this).remove(); }); }); }); /** * Ensures indexes names are valid according to their type and, for a primary * key, lock index name to 'PRIMARY' * @param string form_id Variable which parses the form name as * the input * @return boolean false if there is no index form, true else */ function checkIndexName (form_id) { if ($('#' + form_id).length === 0) { return false; } // Gets the elements pointers var $the_idx_name = $('#input_index_name'); var $the_idx_choice = $('#select_index_choice'); // Index is a primary key if ($the_idx_choice.find('option:selected').val() === 'PRIMARY') { $the_idx_name.val('PRIMARY'); $the_idx_name.prop('disabled', true); } else { if ($the_idx_name.val() === 'PRIMARY') { $the_idx_name.val(''); } $the_idx_name.prop('disabled', false); } return true; } // end of the 'checkIndexName()' function AJAX.registerTeardown('functions.js', function () { $(document).off('click', '#index_frm input[type=submit]'); }); AJAX.registerOnload('functions.js', function () { /** * Handler for adding more columns to an index in the editor */ $(document).on('click', '#index_frm input[type=submit]', function (event) { event.preventDefault(); var rows_to_add = $(this) .closest('fieldset') .find('.slider') .slider('value'); var tempEmptyVal = function () { $(this).val(''); }; var tempSetFocus = function () { if ($(this).find('option:selected').val() === '') { return true; } $(this).closest('tr').find('input').focus(); }; while (rows_to_add--) { var $indexColumns = $('#index_columns'); var $newrow = $indexColumns .find('tbody > tr:first') .clone() .appendTo( $indexColumns.find('tbody') ); $newrow.find(':input').each(tempEmptyVal); // focus index size input on column picked $newrow.find('select').change(tempSetFocus); } }); }); function indexEditorDialog (url, title, callback_success, callback_failure) { /* Remove the hidden dialogs if there are*/ var $editIndexDialog = $('#edit_index_dialog'); if ($editIndexDialog.length !== 0) { $editIndexDialog.remove(); } var $div = $('
    '); /** * @var button_options Object that stores the options * passed to jQueryUI dialog */ var button_options = {}; button_options[PMA_messages.strGo] = function () { /** * @var the_form object referring to the export form */ var $form = $('#index_frm'); var $msgbox = PMA_ajaxShowMessage(PMA_messages.strProcessingRequest); PMA_prepareForAjaxRequest($form); // User wants to submit the form $.post($form.attr('action'), $form.serialize() + PMA_commonParams.get('arg_separator') + 'do_save_data=1', function (data) { var $sqlqueryresults = $('.sqlqueryresults'); if ($sqlqueryresults.length !== 0) { $sqlqueryresults.remove(); } if (typeof data !== 'undefined' && data.success === true) { PMA_ajaxShowMessage(data.message); var $resultQuery = $('.result_query'); if ($resultQuery.length) { $resultQuery.remove(); } if (data.sql_query) { $('
    ') .html(data.sql_query) .prependTo('#page_content'); PMA_highlightSQL($('#page_content')); } $('.result_query .notice').remove(); $resultQuery.prepend(data.message); /* Reload the field form*/ $('#table_index').remove(); $('
    ') .append(data.index_table) .find('#table_index') .insertAfter('#index_header'); var $editIndexDialog = $('#edit_index_dialog'); if ($editIndexDialog.length > 0) { $editIndexDialog.dialog('close'); } $('div.no_indexes_defined').hide(); if (callback_success) { callback_success(); } PMA_reloadNavigation(); } else { var $temp_div = $('
    ').append(data.error); var $error; if ($temp_div.find('.error code').length !== 0) { $error = $temp_div.find('.error code').addClass('error'); } else { $error = $temp_div; } if (callback_failure) { callback_failure(); } PMA_ajaxShowMessage($error, false); } }); // end $.post() }; button_options[PMA_messages.strPreviewSQL] = function () { // Function for Previewing SQL var $form = $('#index_frm'); PMA_previewSQL($form); }; button_options[PMA_messages.strCancel] = function () { $(this).dialog('close'); }; var $msgbox = PMA_ajaxShowMessage(); $.post('tbl_indexes.php', url, function (data) { if (typeof data !== 'undefined' && data.success === false) { // in the case of an error, show the error message returned. PMA_ajaxShowMessage(data.error, false); } else { PMA_ajaxRemoveMessage($msgbox); // Show dialog if the request was successful $div .append(data.message) .dialog({ title: title, width: 'auto', open: PMA_verifyColumnsProperties, modal: true, buttons: button_options, close: function () { $(this).remove(); } }); $div.find('.tblFooters').remove(); showIndexEditDialog($div); } }); // end $.get() } function showIndexEditDialog ($outer) { checkIndexType(); checkIndexName('index_frm'); var $indexColumns = $('#index_columns'); $indexColumns.find('td').each(function () { $(this).css('width', $(this).width() + 'px'); }); $indexColumns.find('tbody').sortable({ axis: 'y', containment: $indexColumns.find('tbody'), tolerance: 'pointer' }); PMA_showHints($outer); PMA_init_slider(); // Add a slider for selecting how many columns to add to the index $outer.find('.slider').slider({ animate: true, value: 1, min: 1, max: 16, slide: function (event, ui) { $(this).closest('fieldset').find('input[type=submit]').val( PMA_sprintf(PMA_messages.strAddToIndex, ui.value) ); } }); $('div.add_fields').removeClass('hide'); // focus index size input on column picked $outer.find('table#index_columns select').change(function () { if ($(this).find('option:selected').val() === '') { return true; } $(this).closest('tr').find('input').focus(); }); // Focus the slider, otherwise it looks nearly transparent $('a.ui-slider-handle').addClass('ui-state-focus'); // set focus on index name input, if empty var input = $outer.find('input#input_index_name'); if (! input.val()) { input.focus(); } } /** * Function to display tooltips that were * generated on the PHP side by PhpMyAdmin\Util::showHint() * * @param object $div a div jquery object which specifies the * domain for searching for tooltips. If we * omit this parameter the function searches * in the whole body **/ function PMA_showHints ($div) { if ($div === undefined || ! $div instanceof jQuery || $div.length === 0) { $div = $('body'); } $div.find('.pma_hint').each(function () { PMA_tooltip( $(this).children('img'), 'img', $(this).children('span').html() ); }); } AJAX.registerOnload('functions.js', function () { PMA_showHints(); }); function PMA_mainMenuResizerCallback () { // 5 px margin for jumping menu in Chrome return $(document.body).width() - 5; } // This must be fired only once after the initial page load $(function () { // Initialise the menu resize plugin $('#topmenu').menuResizer(PMA_mainMenuResizerCallback); // register resize event $(window).on('resize', function () { $('#topmenu').menuResizer('resize'); }); }); /** * Get the row number from the classlist (for example, row_1) */ function PMA_getRowNumber (classlist) { return parseInt(classlist.split(/\s+row_/)[1], 10); } /** * Changes status of slider */ function PMA_set_status_label ($element) { var text; if ($element.css('display') === 'none') { text = '+ '; } else { text = '- '; } $element.closest('.slide-wrapper').prev().find('span').text(text); } /** * var toggleButton This is a function that creates a toggle * sliding button given a jQuery reference * to the correct DOM element */ var toggleButton = function ($obj) { // In rtl mode the toggle switch is flipped horizontally // so we need to take that into account var right; if ($('span.text_direction', $obj).text() === 'ltr') { right = 'right'; } else { right = 'left'; } /** * var h Height of the button, used to scale the * background image and position the layers */ var h = $obj.height(); $('img', $obj).height(h); $('table', $obj).css('bottom', h - 1); /** * var on Width of the "ON" part of the toggle switch * var off Width of the "OFF" part of the toggle switch */ var on = $('td.toggleOn', $obj).width(); var off = $('td.toggleOff', $obj).width(); // Make the "ON" and "OFF" parts of the switch the same size // + 2 pixels to avoid overflowed $('td.toggleOn > div', $obj).width(Math.max(on, off) + 2); $('td.toggleOff > div', $obj).width(Math.max(on, off) + 2); /** * var w Width of the central part of the switch */ var w = parseInt(($('img', $obj).height() / 16) * 22, 10); // Resize the central part of the switch on the top // layer to match the background $('table td:nth-child(2) > div', $obj).width(w); /** * var imgw Width of the background image * var tblw Width of the foreground layer * var offset By how many pixels to move the background * image, so that it matches the top layer */ var imgw = $('img', $obj).width(); var tblw = $('table', $obj).width(); var offset = parseInt(((imgw - tblw) / 2), 10); // Move the background to match the layout of the top layer $obj.find('img').css(right, offset); /** * var offw Outer width of the "ON" part of the toggle switch * var btnw Outer width of the central part of the switch */ var offw = $('td.toggleOff', $obj).outerWidth(); var btnw = $('table td:nth-child(2)', $obj).outerWidth(); // Resize the main div so that exactly one side of // the switch plus the central part fit into it. $obj.width(offw + btnw + 2); /** * var move How many pixels to move the * switch by when toggling */ var move = $('td.toggleOff', $obj).outerWidth(); // If the switch is initialized to the // OFF state we need to move it now. if ($('div.container', $obj).hasClass('off')) { if (right === 'right') { $('div.container', $obj).animate({ 'left': '-=' + move + 'px' }, 0); } else { $('div.container', $obj).animate({ 'left': '+=' + move + 'px' }, 0); } } // Attach an 'onclick' event to the switch $('div.container', $obj).click(function () { if ($(this).hasClass('isActive')) { return false; } else { $(this).addClass('isActive'); } var $msg = PMA_ajaxShowMessage(); var $container = $(this); var callback = $('span.callback', this).text(); var operator; var url; var removeClass; var addClass; // Perform the actual toggle if ($(this).hasClass('on')) { if (right === 'right') { operator = '-='; } else { operator = '+='; } url = $(this).find('td.toggleOff > span').text(); removeClass = 'on'; addClass = 'off'; } else { if (right === 'right') { operator = '+='; } else { operator = '-='; } url = $(this).find('td.toggleOn > span').text(); removeClass = 'off'; addClass = 'on'; } var parts = url.split('?'); $.post(parts[0], parts[1] + '&ajax_request=true', function (data) { if (typeof data !== 'undefined' && data.success === true) { PMA_ajaxRemoveMessage($msg); $container .removeClass(removeClass) .addClass(addClass) .animate({ 'left': operator + move + 'px' }, function () { $container.removeClass('isActive'); }); eval(callback); } else { PMA_ajaxShowMessage(data.error, false); $container.removeClass('isActive'); } }); }); }; /** * Unbind all event handlers before tearing down a page */ AJAX.registerTeardown('functions.js', function () { $('div.container').off('click'); }); /** * Initialise all toggle buttons */ AJAX.registerOnload('functions.js', function () { $('div.toggleAjax').each(function () { var $button = $(this).show(); $button.find('img').each(function () { if (this.complete) { toggleButton($button); } else { $(this).load(function () { toggleButton($button); }); } }); }); }); /** * Unbind all event handlers before tearing down a page */ AJAX.registerTeardown('functions.js', function () { $(document).off('change', 'select.pageselector'); $('#update_recent_tables').off('ready'); $('#sync_favorite_tables').off('ready'); }); AJAX.registerOnload('functions.js', function () { /** * Autosubmit page selector */ $(document).on('change', 'select.pageselector', function (event) { event.stopPropagation(); // Check where to load the new content if ($(this).closest('#pma_navigation').length === 0) { // For the main page we don't need to do anything, $(this).closest('form').submit(); } else { // but for the navigation we need to manually replace the content PMA_navigationTreePagination($(this)); } }); /** * Load version information asynchronously. */ if ($('li.jsversioncheck').length > 0) { $.ajax({ dataType: 'json', url: 'version_check.php', method: 'POST', data: { 'server': PMA_commonParams.get('server') }, success: PMA_current_version }); } if ($('#is_git_revision').length > 0) { setTimeout(PMA_display_git_revision, 10); } /** * Slider effect. */ PMA_init_slider(); var $updateRecentTables = $('#update_recent_tables'); if ($updateRecentTables.length) { $.get( $updateRecentTables.attr('href'), { no_debug: true }, function (data) { if (typeof data !== 'undefined' && data.success === true) { $('#pma_recent_list').html(data.list); } } ); } // Sync favorite tables from localStorage to pmadb. if ($('#sync_favorite_tables').length) { $.ajax({ url: $('#sync_favorite_tables').attr('href'), cache: false, type: 'POST', data: { favorite_tables: (isStorageSupported('localStorage') && typeof window.localStorage.favorite_tables !== 'undefined') ? window.localStorage.favorite_tables : '', server: PMA_commonParams.get('server'), no_debug: true }, success: function (data) { // Update localStorage. if (isStorageSupported('localStorage')) { window.localStorage.favorite_tables = data.favorite_tables; } $('#pma_favorite_list').html(data.list); } }); } }); // end of $() /** * Submits the form placed in place of a link due to the excessive url length * * @param $link anchor * @returns {Boolean} */ function submitFormLink ($link) { if ($link.attr('href').indexOf('=') !== -1) { var data = $link.attr('href').substr($link.attr('href').indexOf('#') + 1).split('=', 2); $link.parents('form').append(''); } $link.parents('form').submit(); } /** * Initializes slider effect. */ function PMA_init_slider () { $('div.pma_auto_slider').each(function () { var $this = $(this); if ($this.data('slider_init_done')) { return; } var $wrapper = $('
    ', { 'class': 'slide-wrapper' }); $wrapper.toggle($this.is(':visible')); $('', { href: '#' + this.id, 'class': 'ajax' }) .text($this.attr('title')) .prepend($('')) .insertBefore($this) .click(function () { var $wrapper = $this.closest('.slide-wrapper'); var visible = $this.is(':visible'); if (!visible) { $wrapper.show(); } $this[visible ? 'hide' : 'show']('blind', function () { $wrapper.toggle(!visible); $wrapper.parent().toggleClass('print_ignore', visible); PMA_set_status_label($this); }); return false; }); $this.wrap($wrapper); $this.removeAttr('title'); PMA_set_status_label($this); $this.data('slider_init_done', 1); }); } /** * Initializes slider effect. */ AJAX.registerOnload('functions.js', function () { PMA_init_slider(); }); /** * Restores sliders to the state they were in before initialisation. */ AJAX.registerTeardown('functions.js', function () { $('div.pma_auto_slider').each(function () { var $this = $(this); $this.removeData(); $this.parent().replaceWith($this); $this.parent().children('a').remove(); }); }); /** * 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() /** * Attach CodeMirror2 editor to SQL edit area. */ AJAX.registerOnload('functions.js', function () { var $elm = $('#sqlquery'); if ($elm.length > 0) { if (typeof CodeMirror !== 'undefined') { codemirror_editor = PMA_getSQLEditor($elm); codemirror_editor.focus(); codemirror_editor.on('blur', updateQueryParameters); } else { // without codemirror $elm.focus().on('blur', updateQueryParameters); } } PMA_highlightSQL($('body')); }); AJAX.registerTeardown('functions.js', function () { if (codemirror_editor) { $('#sqlquery').text(codemirror_editor.getValue()); codemirror_editor.toTextArea(); codemirror_editor = false; } }); AJAX.registerOnload('functions.js', function () { // initializes all lock-page elements lock-id and // val-hash data property $('#page_content form.lock-page textarea, ' + '#page_content form.lock-page input[type="text"], ' + '#page_content form.lock-page input[type="number"], ' + '#page_content form.lock-page select').each(function (i) { $(this).data('lock-id', i); // val-hash is the hash of default value of the field // so that it can be compared with new value hash // to check whether field was modified or not. $(this).data('val-hash', AJAX.hash($(this).val())); }); // initializes lock-page elements (input types checkbox and radio buttons) // lock-id and val-hash data property $('#page_content form.lock-page input[type="checkbox"], ' + '#page_content form.lock-page input[type="radio"]').each(function (i) { $(this).data('lock-id', i); $(this).data('val-hash', AJAX.hash($(this).is(':checked'))); }); }); /** * jQuery plugin to correctly filter input fields by value, needed * because some nasty values may break selector syntax */ (function ($) { $.fn.filterByValue = function (value) { return this.filter(function () { return $(this).val() === value; }); }; }(jQuery)); /** * Return value of a cell in a table. */ function PMA_getCellValue (td) { var $td = $(td); if ($td.is('.null')) { return ''; } else if ((! $td.is('.to_be_saved') || $td.is('.set')) && $td.data('original_data') ) { return $td.data('original_data'); } else { return $td.text(); } } $(window).on('popstate', function (event, data) { $('#printcss').attr('media','print'); return true; }); /** * Unbind all event handlers before tearing down a page */ AJAX.registerTeardown('functions.js', function () { $(document).off('click', 'a.themeselect'); $(document).off('change', '.autosubmit'); $('a.take_theme').off('click'); }); AJAX.registerOnload('functions.js', function () { /** * Theme selector. */ $(document).on('click', 'a.themeselect', function (e) { window.open( e.target, 'themes', 'left=10,top=20,width=510,height=350,scrollbars=yes,status=yes,resizable=yes' ); return false; }); /** * Automatic form submission on change. */ $(document).on('change', '.autosubmit', function (e) { $(this).closest('form').submit(); }); /** * Theme changer. */ $('a.take_theme').click(function (e) { var what = this.name; if (window.opener && window.opener.document.forms.setTheme.elements.set_theme) { window.opener.document.forms.setTheme.elements.set_theme.value = what; window.opener.document.forms.setTheme.submit(); window.close(); return false; } return true; }); }); /** * Produce print preview */ function printPreview () { $('#printcss').attr('media','all'); createPrintAndBackButtons(); } /** * Create print and back buttons in preview page */ function createPrintAndBackButtons () { var back_button = $('',{ type: 'button', value: PMA_messages.back, id: 'back_button_print_view' }); back_button.click(removePrintAndBackButton); back_button.appendTo('#page_content'); var print_button = $('',{ type: 'button', value: PMA_messages.print, id: 'print_button_print_view' }); print_button.click(printPage); print_button.appendTo('#page_content'); } /** * Remove print and back buttons and revert to normal view */ function removePrintAndBackButton () { $('#printcss').attr('media','print'); $('#back_button_print_view').remove(); $('#print_button_print_view').remove(); } /** * Print page */ function printPage () { if (typeof(window.print) !== 'undefined') { window.print(); } } /** * Unbind all event handlers before tearing down a page */ AJAX.registerTeardown('functions.js', function () { $('input#print').off('click'); $(document).off('click', 'a.create_view.ajax'); $(document).off('keydown', '#createViewDialog input, #createViewDialog select'); $(document).off('change', '#fkc_checkbox'); }); AJAX.registerOnload('functions.js', function () { $('input#print').click(printPage); $('.logout').click(function () { var form = $( '
    ' + '' + '
    ' ); $('body').append(form); form.submit(); return false; }); /** * Ajaxification for the "Create View" action */ $(document).on('click', 'a.create_view.ajax', function (e) { e.preventDefault(); PMA_createViewDialog($(this)); }); /** * Attach Ajax event handlers for input fields in the editor * and used to submit the Ajax request when the ENTER key is pressed. */ if ($('#createViewDialog').length !== 0) { $(document).on('keydown', '#createViewDialog input, #createViewDialog select', function (e) { if (e.which === 13) { // 13 is the ENTER key e.preventDefault(); // with preventing default, selection by