/* vim: set expandtab sw=4 ts=4 sts=4: */ /** * Used in or for console * * @package phpMyAdmin-Console */ /** * Console object */ var PMA_console = { /** * @var object, jQuery object, selector is '#pma_console>.content' * @access private */ $consoleContent: null, /** * @var object, jQuery object, selector is '#pma_console .content', * used for resizer * @access private */ $consoleAllContents: null, /** * @var object, jQuery object, selector is '#pma_console .toolbar' * @access private */ $consoleToolbar: null, /** * @var object, jQuery object, selector is '#pma_console .template' * @access private */ $consoleTemplates: null, /** * @var object, jQuery object, form for submit * @access private */ $requestForm: null, /** * @var object, contain console config * @access private */ config: null, /** * @var bool, if console element exist, it'll be true * @access public */ isEnabled: false, /** * @var bool, make sure console events bind only once * @access private */ isInitialized: false, /** * Used for console initialize, reinit is ok, just some variable assignment * * @return void */ initialize: function () { if ($('#pma_console').length === 0) { return; } PMA_console.config = configGet('Console', false); PMA_console.isEnabled = true; // Vars init PMA_console.$consoleToolbar = $('#pma_console').find('>.toolbar'); PMA_console.$consoleContent = $('#pma_console').find('>.content'); PMA_console.$consoleAllContents = $('#pma_console').find('.content'); PMA_console.$consoleTemplates = $('#pma_console').find('>.templates'); // Generate a from for post PMA_console.$requestForm = $('
' + '' + '' + '' + '' + '' + '' + '' + '
' ); PMA_console.$requestForm.children('[name=token]').val(PMA_commonParams.get('token')); PMA_console.$requestForm.on('submit', AJAX.requestHandler); // Event binds shouldn't run again if (PMA_console.isInitialized === false) { // Load config first if (PMA_console.config.AlwaysExpand === true) { $('#pma_console_options input[name=always_expand]').prop('checked', true); } if (PMA_console.config.StartHistory === true) { $('#pma_console_options').find('input[name=start_history]').prop('checked', true); } if (PMA_console.config.CurrentQuery === true) { $('#pma_console_options').find('input[name=current_query]').prop('checked', true); } if (PMA_console.config.EnterExecutes === true) { $('#pma_console_options').find('input[name=enter_executes]').prop('checked', true); } if (PMA_console.config.DarkTheme === true) { $('#pma_console_options').find('input[name=dark_theme]').prop('checked', true); $('#pma_console').find('>.content').addClass('console_dark_theme'); } PMA_consoleResizer.initialize(); PMA_consoleInput.initialize(); PMA_consoleMessages.initialize(); PMA_consoleBookmarks.initialize(); PMA_consoleDebug.initialize(); PMA_console.$consoleToolbar.children('.console_switch').click(PMA_console.toggle); $('#pma_console').find('.toolbar').children().mousedown(function (event) { event.preventDefault(); event.stopImmediatePropagation(); }); $('#pma_console').find('.button.clear').click(function () { PMA_consoleMessages.clear(); }); $('#pma_console').find('.button.history').click(function () { PMA_consoleMessages.showHistory(); }); $('#pma_console').find('.button.options').click(function () { PMA_console.showCard('#pma_console_options'); }); $('#pma_console').find('.button.debug').click(function () { PMA_console.showCard('#debug_console'); }); PMA_console.$consoleContent.click(function (event) { if (event.target === this) { PMA_consoleInput.focus(); } }); $('#pma_console').find('.mid_layer').click(function () { PMA_console.hideCard($(this).parent().children('.card')); }); $('#debug_console').find('.switch_button').click(function () { PMA_console.hideCard($(this).closest('.card')); }); $('#pma_bookmarks').find('.switch_button').click(function () { PMA_console.hideCard($(this).closest('.card')); }); $('#pma_console_options').find('.switch_button').click(function () { PMA_console.hideCard($(this).closest('.card')); }); $('#pma_console_options').find('input[type=checkbox]').change(function () { PMA_console.updateConfig(); }); $('#pma_console_options').find('.button.default').click(function () { $('#pma_console_options input[name=always_expand]').prop('checked', false); $('#pma_console_options').find('input[name=start_history]').prop('checked', false); $('#pma_console_options').find('input[name=current_query]').prop('checked', true); $('#pma_console_options').find('input[name=enter_executes]').prop('checked', false); $('#pma_console_options').find('input[name=dark_theme]').prop('checked', false); PMA_console.updateConfig(); }); $('#pma_console_options').find('input[name=enter_executes]').change(function () { PMA_consoleMessages.showInstructions(PMA_console.config.EnterExecutes); }); $(document).ajaxComplete(function (event, xhr, ajaxOptions) { if (ajaxOptions.dataType && ajaxOptions.dataType.indexOf('json') !== -1) { return; } if (xhr.status !== 200) { return; } try { var data = JSON.parse(xhr.responseText); PMA_console.ajaxCallback(data); } catch (e) { console.trace(); console.log('Failed to parse JSON: ' + e.message); } }); PMA_console.isInitialized = true; } // Change console mode from cookie switch (PMA_console.config.Mode) { case 'collapse': PMA_console.collapse(); break; /* jshint -W086 */// no break needed in default section default: PMA_console.setConfig('Mode', 'info'); case 'info': /* jshint +W086 */ PMA_console.info(); break; case 'show': PMA_console.show(true); PMA_console.scrollBottom(); break; } }, /** * Execute query and show results in console * * @return void */ execute: function (queryString, options) { if (typeof(queryString) !== 'string' || ! /[a-z]|[A-Z]/.test(queryString)) { return; } PMA_console.$requestForm.children('textarea').val(queryString); PMA_console.$requestForm.children('[name=server]').attr('value', PMA_commonParams.get('server')); if (options && options.db) { PMA_console.$requestForm.children('[name=db]').val(options.db); if (options.table) { PMA_console.$requestForm.children('[name=table]').val(options.table); } else { PMA_console.$requestForm.children('[name=table]').val(''); } } else { PMA_console.$requestForm.children('[name=db]').val( (PMA_commonParams.get('db').length > 0 ? PMA_commonParams.get('db') : '')); } PMA_console.$requestForm.find('[name=profiling]').remove(); if (options && options.profiling === true) { PMA_console.$requestForm.append(''); } if (! confirmQuery(PMA_console.$requestForm[0], PMA_console.$requestForm.children('textarea')[0].value)) { return; } PMA_console.$requestForm.children('[name=console_message_id]') .val(PMA_consoleMessages.appendQuery({ sql_query: queryString }).message_id); PMA_console.$requestForm.trigger('submit'); PMA_consoleInput.clear(); PMA_reloadNavigation(); }, ajaxCallback: function (data) { if (data && data.console_message_id) { PMA_consoleMessages.updateQuery(data.console_message_id, data.success, (data._reloadQuerywindow ? data._reloadQuerywindow : false)); } else if (data && data._reloadQuerywindow) { if (data._reloadQuerywindow.sql_query.length > 0) { PMA_consoleMessages.appendQuery(data._reloadQuerywindow, 'successed') .$message.addClass(PMA_console.config.CurrentQuery ? '' : 'hide'); } } }, /** * Change console to collapse mode * * @return void */ collapse: function () { PMA_console.setConfig('Mode', 'collapse'); var pmaConsoleHeight = Math.max(92, PMA_console.config.Height); PMA_console.$consoleToolbar.addClass('collapsed'); PMA_console.$consoleAllContents.height(pmaConsoleHeight); PMA_console.$consoleContent.stop(); PMA_console.$consoleContent.animate({ 'margin-bottom': -1 * PMA_console.$consoleContent.outerHeight() + 'px' }, 'fast', 'easeOutQuart', function () { PMA_console.$consoleContent.css({ display:'none' }); $(window).trigger('resize'); }); PMA_console.hideCard(); }, /** * Show console * * @param bool inputFocus If true, focus the input line after show() * @return void */ show: function (inputFocus) { PMA_console.setConfig('Mode', 'show'); var pmaConsoleHeight = Math.max(92, PMA_console.config.Height); pmaConsoleHeight = Math.min(PMA_console.config.Height, (window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight) - 25); PMA_console.$consoleContent.css({ display:'block' }); if (PMA_console.$consoleToolbar.hasClass('collapsed')) { PMA_console.$consoleToolbar.removeClass('collapsed'); } PMA_console.$consoleAllContents.height(pmaConsoleHeight); PMA_console.$consoleContent.stop(); PMA_console.$consoleContent.animate({ 'margin-bottom': 0 }, 'fast', 'easeOutQuart', function () { $(window).trigger('resize'); if (inputFocus) { PMA_consoleInput.focus(); } }); }, /** * Change console to SQL information mode * this mode shows current SQL query * This mode is the default mode * * @return void */ info: function () { // Under construction PMA_console.collapse(); }, /** * Toggle console mode between collapse/show * Used for toggle buttons and shortcuts * * @return void */ toggle: function () { switch (PMA_console.config.Mode) { case 'collapse': case 'info': PMA_console.show(true); break; case 'show': PMA_console.collapse(); break; default: PMA_consoleInitialize(); } }, /** * Scroll console to bottom * * @return void */ scrollBottom: function () { PMA_console.$consoleContent.scrollTop(PMA_console.$consoleContent.prop('scrollHeight')); }, /** * Show card * * @param string cardSelector Selector, select string will be "#pma_console " + cardSelector * this param also can be JQuery object, if you need. * * @return void */ showCard: function (cardSelector) { var $card = null; if (typeof(cardSelector) !== 'string') { if (cardSelector.length > 0) { $card = cardSelector; } else { return; } } else { $card = $('#pma_console ' + cardSelector); } if ($card.length === 0) { return; } $card.parent().children('.mid_layer').show().fadeTo(0, 0.15); $card.addClass('show'); PMA_consoleInput.blur(); if ($card.parents('.card').length > 0) { PMA_console.showCard($card.parents('.card')); } }, /** * Scroll console to bottom * * @param object $targetCard Target card JQuery object, if it's empty, function will hide all cards * @return void */ hideCard: function ($targetCard) { if (! $targetCard) { $('#pma_console').find('.mid_layer').fadeOut(140); $('#pma_console').find('.card').removeClass('show'); } else if ($targetCard.length > 0) { $targetCard.parent().find('.mid_layer').fadeOut(140); $targetCard.find('.card').removeClass('show'); $targetCard.removeClass('show'); } }, /** * Used for update console config * * @return void */ updateConfig: function () { PMA_console.setConfig('AlwaysExpand', $('#pma_console_options input[name=always_expand]').prop('checked')); PMA_console.setConfig('StartHistory', $('#pma_console_options').find('input[name=start_history]').prop('checked')); PMA_console.setConfig('CurrentQuery', $('#pma_console_options').find('input[name=current_query]').prop('checked')); PMA_console.setConfig('EnterExecutes', $('#pma_console_options').find('input[name=enter_executes]').prop('checked')); PMA_console.setConfig('DarkTheme', $('#pma_console_options').find('input[name=dark_theme]').prop('checked')); /* Setting the dark theme of the console*/ if (PMA_console.config.DarkTheme) { $('#pma_console').find('>.content').addClass('console_dark_theme'); } else { $('#pma_console').find('>.content').removeClass('console_dark_theme'); } }, setConfig: function (key, value) { PMA_console.config[key] = value; configSet('Console/' + key, value); }, isSelect: function (queryString) { var reg_exp = /^SELECT\s+/i; return reg_exp.test(queryString); } }; /** * Resizer object * Careful: this object UI logics highly related with functions under PMA_console * Resizing min-height is 32, if small than it, console will collapse */ var PMA_consoleResizer = { _posY: 0, _height: 0, _resultHeight: 0, /** * Mousedown event handler for bind to resizer * * @return void */ _mousedown: function (event) { if (PMA_console.config.Mode !== 'show') { return; } PMA_consoleResizer._posY = event.pageY; PMA_consoleResizer._height = PMA_console.$consoleContent.height(); $(document).mousemove(PMA_consoleResizer._mousemove); $(document).mouseup(PMA_consoleResizer._mouseup); // Disable text selection while resizing $(document).on('selectstart', function () { return false; }); }, /** * Mousemove event handler for bind to resizer * * @return void */ _mousemove: function (event) { if (event.pageY < 35) { event.pageY = 35; } PMA_consoleResizer._resultHeight = PMA_consoleResizer._height + (PMA_consoleResizer._posY - event.pageY); // Content min-height is 32, if adjusting height small than it we'll move it out of the page if (PMA_consoleResizer._resultHeight <= 32) { PMA_console.$consoleAllContents.height(32); PMA_console.$consoleContent.css('margin-bottom', PMA_consoleResizer._resultHeight - 32); } else { // Logic below makes viewable area always at bottom when adjusting height and content already at bottom if (PMA_console.$consoleContent.scrollTop() + PMA_console.$consoleContent.innerHeight() + 16 >= PMA_console.$consoleContent.prop('scrollHeight')) { PMA_console.$consoleAllContents.height(PMA_consoleResizer._resultHeight); PMA_console.scrollBottom(); } else { PMA_console.$consoleAllContents.height(PMA_consoleResizer._resultHeight); } } }, /** * Mouseup event handler for bind to resizer * * @return void */ _mouseup: function () { PMA_console.setConfig('Height', PMA_consoleResizer._resultHeight); PMA_console.show(); $(document).off('mousemove'); $(document).off('mouseup'); $(document).off('selectstart'); }, /** * Used for console resizer initialize * * @return void */ initialize: function () { $('#pma_console').find('.toolbar').off('mousedown'); $('#pma_console').find('.toolbar').mousedown(PMA_consoleResizer._mousedown); } }; /** * Console input object */ var PMA_consoleInput = { /** * @var array, contains Codemirror objects or input jQuery objects * @access private */ _inputs: null, /** * @var bool, if codemirror enabled * @access private */ _codemirror: false, /** * @var int, count for history navigation, 0 for current input * @access private */ _historyCount: 0, /** * @var string, current input when navigating through history * @access private */ _historyPreserveCurrent: null, /** * Used for console input initialize * * @return void */ initialize: function () { // _cm object can't be reinitialize if (PMA_consoleInput._inputs !== null) { return; } if (typeof CodeMirror !== 'undefined') { PMA_consoleInput._codemirror = true; } PMA_consoleInput._inputs = []; if (PMA_consoleInput._codemirror) { PMA_consoleInput._inputs.console = CodeMirror($('#pma_console').find('.console_query_input')[0], { theme: 'pma', mode: 'text/x-sql', lineWrapping: true, extraKeys: { 'Ctrl-Space': 'autocomplete' }, hintOptions: { 'completeSingle': false, 'completeOnSingleClick': true }, gutters: ['CodeMirror-lint-markers'], lint: { 'getAnnotations': CodeMirror.sqlLint, 'async': true, } }); PMA_consoleInput._inputs.console.on('inputRead', codemirrorAutocompleteOnInputRead); PMA_consoleInput._inputs.console.on('keydown', function (instance, event) { PMA_consoleInput._historyNavigate(event); }); if ($('#pma_bookmarks').length !== 0) { PMA_consoleInput._inputs.bookmark = CodeMirror($('#pma_console').find('.bookmark_add_input')[0], { theme: 'pma', mode: 'text/x-sql', lineWrapping: true, extraKeys: { 'Ctrl-Space': 'autocomplete' }, hintOptions: { 'completeSingle': false, 'completeOnSingleClick': true }, gutters: ['CodeMirror-lint-markers'], lint: { 'getAnnotations': CodeMirror.sqlLint, 'async': true, } }); PMA_consoleInput._inputs.bookmark.on('inputRead', codemirrorAutocompleteOnInputRead); } } else { PMA_consoleInput._inputs.console = $('