1/* vim: set expandtab sw=4 ts=4 sts=4: */ 2/** 3 * Used in or for console 4 * 5 * @package phpMyAdmin-Console 6 */ 7 8/** 9 * Console object 10 */ 11var PMA_console = { 12 /** 13 * @var object, jQuery object, selector is '#pma_console>.content' 14 * @access private 15 */ 16 $consoleContent: null, 17 /** 18 * @var object, jQuery object, selector is '#pma_console .content', 19 * used for resizer 20 * @access private 21 */ 22 $consoleAllContents: null, 23 /** 24 * @var object, jQuery object, selector is '#pma_console .toolbar' 25 * @access private 26 */ 27 $consoleToolbar: null, 28 /** 29 * @var object, jQuery object, selector is '#pma_console .template' 30 * @access private 31 */ 32 $consoleTemplates: null, 33 /** 34 * @var object, jQuery object, form for submit 35 * @access private 36 */ 37 $requestForm: null, 38 /** 39 * @var object, contain console config 40 * @access private 41 */ 42 config: null, 43 /** 44 * @var bool, if console element exist, it'll be true 45 * @access public 46 */ 47 isEnabled: false, 48 /** 49 * @var bool, make sure console events bind only once 50 * @access private 51 */ 52 isInitialized: false, 53 /**
54 * Used for console initialize, reinit is ok, just some variable assignment 55 * 56 * @return void 57 */ 58 initialize: function () { 59 if ($('#pma_console').length === 0) { 60 return; 61 } 62 63 PMA_console.config = configGet('Console', false); 64 65 PMA_console.isEnabled = true; 66 67 // Vars init 68 PMA_console.$consoleToolbar = $('#pma_console').find('>.toolbar'); 69 PMA_console.$consoleContent = $('#pma_console').find('>.content'); 70 PMA_console.$consoleAllContents = $('#pma_console').find('.content'); 71 PMA_console.$consoleTemplates = $('#pma_console').find('>.templates'); 72 73 // Generate a from for post 74 PMA_console.$requestForm = $('<form method="post" action="import.php">' + 75 '<input name="is_js_confirmed" value="0">' + 76 '<textarea name="sql_query"></textarea>' + 77 '<input name="console_message_id" value="0">' + 78 '<input name="server" value="">' + 79 '<input name="db" value="">' + 80 '<input name="table" value="">' + 81 '<input name="token" value="">' + 82 '</form>' 83 ); 84 PMA_console.$requestForm.children('[name=token]').val(PMA_commonParams.get('token')); 85 PMA_console.$requestForm.on('submit', AJAX.requestHandler); 86 87 // Event binds shouldn't run again 88 if (PMA_console.isInitialized === false) { 89 // Load config first 90 if (PMA_console.config.AlwaysExpand === true) { 91 $('#pma_console_options input[name=always_expand]').prop('checked', true); 92 } 93 if (PMA_console.config.StartHistory === true) { 94 $('#pma_console_options').find('input[name=start_history]').prop('checked', true); 95 } 96 if (PMA_console.config.CurrentQuery === true) { 97 $('#pma_console_options').find('input[name=current_query]').prop('checked', true); 98 } 99 if (PMA_console.config.EnterExecutes === true) { 100 $('#pma_console_options').find('input[name=enter_executes]').prop('checked', true); 101 } 102 if (PMA_console.config.DarkTheme === true) { 103 $('#pma_console_options').find('input[name=dark_theme]').prop('checked', true); 104 $('#pma_console').find('>.content').addClass('console_dark_theme'); 105 } 106 107 PMA_consoleResizer.initialize(); 108 PMA_consoleInput.initialize(); 109 PMA_consoleMessages.initialize(); 110 PMA_consoleBookmarks.initialize(); 111 PMA_consoleDebug.initialize(); 112 113 PMA_console.$consoleToolbar.children('.console_switch').click(PMA_console.toggle); 114 115 $('#pma_console').find('.toolbar').children().mousedown(function (event) { 116 event.preventDefault(); 117 event.stopImmediatePropagation(); 118 }); 119 120 $('#pma_console').find('.button.clear').click(function () { 121 PMA_consoleMessages.clear(); 122 }); 123 124 $('#pma_console').find('.button.history').click(function () { 125 PMA_consoleMessages.showHistory(); 126 }); 127 128 $('#pma_console').find('.button.options').click(function () { 129 PMA_console.showCard('#pma_console_options'); 130 }); 131 132 $('#pma_console').find('.button.debug').click(function () { 133 PMA_console.showCard('#debug_console'); 134 }); 135 136 PMA_console.$consoleContent.click(function (event) { 137 if (event.target === this) { 138 PMA_consoleInput.focus(); 139 } 140 }); 141 142 $('#pma_console').find('.mid_layer').click(function () { 143 PMA_console.hideCard($(this).parent().children('.card')); 144 }); 145 $('#debug_console').find('.switch_button').click(function () { 146 PMA_console.hideCard($(this).closest('.card')); 147 }); 148 $('#pma_bookmarks').find('.switch_button').click(function () { 149 PMA_console.hideCard($(this).closest('.card')); 150 }); 151 $('#pma_console_options').find('.switch_button').click(function () { 152 PMA_console.hideCard($(this).closest('.card')); 153 }); 154 155 $('#pma_console_options').find('input[type=checkbox]').change(function () { 156 PMA_console.updateConfig(); 157 }); 158 159 $('#pma_console_options').find('.button.default').click(function () { 160 $('#pma_console_options input[name=always_expand]').prop('checked', false); 161 $('#pma_console_options').find('input[name=start_history]').prop('checked', false); 162 $('#pma_console_options').find('input[name=current_query]').prop('checked', true); 163 $('#pma_console_options').find('input[name=enter_executes]').prop('checked', false); 164 $('#pma_console_options').find('input[name=dark_theme]').prop('checked', false); 165 PMA_console.updateConfig(); 166 }); 167 168 $('#pma_console_options').find('input[name=enter_executes]').change(function () { 169 PMA_consoleMessages.showInstructions(PMA_console.config.EnterExecutes); 170 }); 171 172 $(document).ajaxComplete(function (event, xhr, ajaxOptions) { 173 if (ajaxOptions.dataType && ajaxOptions.dataType.indexOf('json') !== -1) { 174 return; 175 } 176 if (xhr.status !== 200) { 177 return; 178 } 179 try { 180 var data = JSON.parse(xhr.responseText); 181 PMA_console.ajaxCallback(data); 182 } catch (e) { 183 console.trace(); 184 console.log('Failed to parse JSON: ' + e.message); 185 } 186 }); 187 188 PMA_console.isInitialized = true; 189 } 190 191 // Change console mode from cookie 192 switch (PMA_console.config.Mode) { 193 case 'collapse': 194 PMA_console.collapse(); 195 break; 196 /* jshint -W086 */// no break needed in default section 197 default: 198 PMA_console.setConfig('Mode', 'info'); 199 case 'info': 200 /* jshint +W086 */ 201 PMA_console.info(); 202 break; 203 case 'show': 204 PMA_console.show(true); 205 PMA_console.scrollBottom(); 206 break; 207 } 208 }, 209 /** 210 * Execute query and show results in console 211 * 212 * @return void 213 */ 214 execute: function (queryString, options) { 215 if (typeof(queryString) !== 'string' || ! /[a-z]|[A-Z]/.test(queryString)) { 216 return; 217 } 218 PMA_console.$requestForm.children('textarea').val(queryString); 219 PMA_console.$requestForm.children('[name=server]').attr('value', PMA_commonParams.get('server')); 220 if (options && options.db) { 221 PMA_console.$requestForm.children('[name=db]').val(options.db); 222 if (options.table) { 223 PMA_console.$requestForm.children('[name=table]').val(options.table); 224 } else { 225 PMA_console.$requestForm.children('[name=table]').val(''); 226 } 227 } else { 228 PMA_console.$requestForm.children('[name=db]').val( 229 (PMA_commonParams.get('db').length > 0 ? PMA_commonParams.get('db') : '')); 230 } 231 PMA_console.$requestForm.find('[name=profiling]').remove(); 232 if (options && options.profiling === true) { 233 PMA_console.$requestForm.append('<input name="profiling" value="on">'); 234 } 235 if (! confirmQuery(PMA_console.$requestForm[0], PMA_console.$requestForm.children('textarea')[0].value)) { 236 return; 237 } 238 PMA_console.$requestForm.children('[name=console_message_id]') 239 .val(PMA_consoleMessages.appendQuery({ sql_query: queryString }).message_id); 240 PMA_console.$requestForm.trigger('submit'); 241 PMA_consoleInput.clear(); 242 PMA_reloadNavigation(); 243 }, 244 ajaxCallback: function (data) { 245 if (data && data.console_message_id) { 246 PMA_consoleMessages.updateQuery(data.console_message_id, data.success, 247 (data._reloadQuerywindow ? data._reloadQuerywindow : false)); 248 } else if (data && data._reloadQuerywindow) { 249 if (data._reloadQuerywindow.sql_query.length > 0) { 250 PMA_consoleMessages.appendQuery(data._reloadQuerywindow, 'successed') 251 .$message.addClass(PMA_console.config.CurrentQuery ? '' : 'hide'); 252 } 253 } 254 }, 255 /** 256 * Change console to collapse mode 257 * 258 * @return void 259 */ 260 collapse: function () { 261 PMA_console.setConfig('Mode', 'collapse'); 262 var pmaConsoleHeight = Math.max(92, PMA_console.config.Height); 263 264 PMA_console.$consoleToolbar.addClass('collapsed'); 265 PMA_console.$consoleAllContents.height(pmaConsoleHeight); 266 PMA_console.$consoleContent.stop(); 267 PMA_console.$consoleContent.animate({ 'margin-bottom': -1 * PMA_console.$consoleContent.outerHeight() + 'px' }, 268 'fast', 'easeOutQuart', function () { 269 PMA_console.$consoleContent.css({ display:'none' }); 270 $(window).trigger('resize'); 271 }); 272 PMA_console.hideCard(); 273 }, 274 /** 275 * Show console 276 * 277 * @param bool inputFocus If true, focus the input line after show() 278 * @return void 279 */ 280 show: function (inputFocus) { 281 PMA_console.setConfig('Mode', 'show'); 282 283 var pmaConsoleHeight = Math.max(92, PMA_console.config.Height); 284 pmaConsoleHeight = Math.min(PMA_console.config.Height, (window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight) - 25); 285 PMA_console.$consoleContent.css({ display:'block' }); 286 if (PMA_console.$consoleToolbar.hasClass('collapsed')) { 287 PMA_console.$consoleToolbar.removeClass('collapsed'); 288 } 289 PMA_console.$consoleAllContents.height(pmaConsoleHeight); 290 PMA_console.$consoleContent.stop(); 291 PMA_console.$consoleContent.animate({ 'margin-bottom': 0 }, 292 'fast', 'easeOutQuart', function () { 293 $(window).trigger('resize'); 294 if (inputFocus) { 295 PMA_consoleInput.focus(); 296 } 297 }); 298 }, 299 /** 300 * Change console to SQL information mode 301 * this mode shows current SQL query 302 * This mode is the default mode 303 * 304 * @return void 305 */ 306 info: function () { 307 // Under construction 308 PMA_console.collapse(); 309 }, 310 /** 311 * Toggle console mode between collapse/show 312 * Used for toggle buttons and shortcuts 313 * 314 * @return void 315 */ 316 toggle: function () { 317 switch (PMA_console.config.Mode) { 318 case 'collapse': 319 case 'info': 320 PMA_console.show(true); 321 break; 322 case 'show': 323 PMA_console.collapse(); 324 break; 325 default: 326 PMA_consoleInitialize(); 327 } 328 }, 329 /** 330 * Scroll console to bottom 331 * 332 * @return void 333 */ 334 scrollBottom: function () { 335 PMA_console.$consoleContent.scrollTop(PMA_console.$consoleContent.prop('scrollHeight')); 336 }, 337 /** 338 * Show card 339 * 340 * @param string cardSelector Selector, select string will be "#pma_console " + cardSelector 341 * this param also can be JQuery object, if you need. 342 * 343 * @return void 344 */ 345 showCard: function (cardSelector) { 346 var $card = null; 347 if (typeof(cardSelector) !== 'string') { 348 if (cardSelector.length > 0) { 349 $card = cardSelector; 350 } else { 351 return; 352 } 353 } else { 354 $card = $('#pma_console ' + cardSelector); 355 } 356 if ($card.length === 0) { 357 return; 358 } 359 $card.parent().children('.mid_layer').show().fadeTo(0, 0.15); 360 $card.addClass('show'); 361 PMA_consoleInput.blur(); 362 if ($card.parents('.card').length > 0) { 363 PMA_console.showCard($card.parents('.card')); 364 } 365 }, 366 /** 367 * Scroll console to bottom 368 * 369 * @param object $targetCard Target card JQuery object, if it's empty, function will hide all cards 370 * @return void 371 */ 372 hideCard: function ($targetCard) { 373 if (! $targetCard) {
374 $('#pma_console').find('.mid_layer').fadeOut(140); 375 $('#pma_console').find('.card').removeClass('show'); 376 } else if ($targetCard.length > 0) { 377 $targetCard.parent().find('.mid_layer').fadeOut(140); 378 $targetCard.find('.card').removeClass('show'); 379 $targetCard.removeClass('show'); 380 } 381 }, 382 /** 383 * Used for update console config 384 * 385 * @return void 386 */ 387 updateConfig: function () { 388 PMA_console.setConfig('AlwaysExpand', $('#pma_console_options input[name=always_expand]').prop('checked')); 389 PMA_console.setConfig('StartHistory', $('#pma_console_options').find('input[name=start_history]').prop('checked')); 390 PMA_console.setConfig('CurrentQuery', $('#pma_console_options').find('input[name=current_query]').prop('checked')); 391 PMA_console.setConfig('EnterExecutes', $('#pma_console_options').find('input[name=enter_executes]').prop('checked')); 392 PMA_console.setConfig('DarkTheme', $('#pma_console_options').find('input[name=dark_theme]').prop('checked')); 393 /* Setting the dark theme of the console*/ 394 if (PMA_console.config.DarkTheme) { 395 $('#pma_console').find('>.content').addClass('console_dark_theme'); 396 } else { 397 $('#pma_console').find('>.content').removeClass('console_dark_theme'); 398 } 399 }, 400 setConfig: function (key, value) { 401 PMA_console.config[key] = value; 402 configSet('Console/' + key, value); 403 }, 404 isSelect: function (queryString) { 405 var reg_exp = /^SELECT\s+/i; 406 return reg_exp.test(queryString); 407 } 408}; 409 410/** 411 * Resizer object 412 * Careful: this object UI logics highly related with functions under PMA_console 413 * Resizing min-height is 32, if small than it, console will collapse 414 */ 415var PMA_consoleResizer = { 416 _posY: 0, 417 _height: 0, 418 _resultHeight: 0, 419 /** 420 * Mousedown event handler for bind to resizer 421 * 422 * @return void 423 */ 424 _mousedown: function (event) { 425 if (PMA_console.config.Mode !== 'show') { 426 return; 427 } 428 PMA_consoleResizer._posY = event.pageY; 429 PMA_consoleResizer._height = PMA_console.$consoleContent.height(); 430 $(document).mousemove(PMA_consoleResizer._mousemove); 431 $(document).mouseup(PMA_consoleResizer._mouseup); 432 // Disable text selection while resizing 433 $(document).on('selectstart', function () { 434 return false; 435 }); 436 }, 437 /** 438 * Mousemove event handler for bind to resizer 439 * 440 * @return void 441 */ 442 _mousemove: function (event) { 443 if (event.pageY < 35) { 444 event.pageY = 35; 445 } 446 PMA_consoleResizer._resultHeight = PMA_consoleResizer._height + (PMA_consoleResizer._posY - event.pageY); 447 // Content min-height is 32, if adjusting height small than it we'll move it out of the page 448 if (PMA_consoleResizer._resultHeight <= 32) { 449 PMA_console.$consoleAllContents.height(32); 450 PMA_console.$consoleContent.css('margin-bottom', PMA_consoleResizer._resultHeight - 32); 451 } else { 452 // Logic below makes viewable area always at bottom when adjusting height and content already at bottom 453 if (PMA_console.$consoleContent.scrollTop() + PMA_console.$consoleContent.innerHeight() + 16 454 >= PMA_console.$consoleContent.prop('scrollHeight')) { 455 PMA_console.$consoleAllContents.height(PMA_consoleResizer._resultHeight); 456 PMA_console.scrollBottom(); 457 } else { 458 PMA_console.$consoleAllContents.height(PMA_consoleResizer._resultHeight); 459 } 460 } 461 }, 462 /** 463 * Mouseup event handler for bind to resizer 464 * 465 * @return void 466 */ 467 _mouseup: function () { 468 PMA_console.setConfig('Height', PMA_consoleResizer._resultHeight); 469 PMA_console.show(); 470 $(document).off('mousemove'); 471 $(document).off('mouseup'); 472 $(document).off('selectstart'); 473 }, 474 /**
475 * Used for console resizer initialize 476 * 477 * @return void 478 */ 479 initialize: function () { 480 $('#pma_console').find('.toolbar').off('mousedown'); 481 $('#pma_console').find('.toolbar').mousedown(PMA_consoleResizer._mousedown); 482 } 483}; 484 485 486/** 487 * Console input object 488 */ 489var PMA_consoleInput = { 490 /** 491 * @var array, contains Codemirror objects or input jQuery objects 492 * @access private 493 */ 494 _inputs: null, 495 /** 496 * @var bool, if codemirror enabled 497 * @access private 498 */ 499 _codemirror: false, 500 /** 501 * @var int, count for history navigation, 0 for current input 502 * @access private 503 */ 504 _historyCount: 0, 505 /** 506 * @var string, current input when navigating through history 507 * @access private 508 */ 509 _historyPreserveCurrent: null, 510 /** 511 * Used for console input initialize 512 * 513 * @return void 514 */ 515 initialize: function () { 516 // _cm object can't be reinitialize 517 if (PMA_consoleInput._inputs !== null) { 518 return; 519 } 520 if (typeof CodeMirror !== 'undefined') { 521 PMA_consoleInput._codemirror = true; 522 } 523 PMA_consoleInput._inputs = []; 524 if (PMA_consoleInput._codemirror) { 525 PMA_consoleInput._inputs.console = CodeMirror($('#pma_console').find('.console_query_input')[0], { 526 theme: 'pma', 527 mode: 'text/x-sql', 528 lineWrapping: true, 529 extraKeys: { 'Ctrl-Space': 'autocomplete' }, 530 hintOptions: { 'completeSingle': false, 'completeOnSingleClick': true }, 531 gutters: ['CodeMirror-lint-markers'], 532 lint: { 533 'getAnnotations': CodeMirror.sqlLint, 534 'async': true, 535 } 536 }); 537 PMA_consoleInput._inputs.console.on('inputRead', codemirrorAutocompleteOnInputRead); 538 PMA_consoleInput._inputs.console.on('keydown', function (instance, event) { 539 PMA_consoleInput._historyNavigate(event); 540 }); 541 if ($('#pma_bookmarks').length !== 0) { 542 PMA_consoleInput._inputs.bookmark = CodeMirror($('#pma_console').find('.bookmark_add_input')[0], { 543 theme: 'pma', 544 mode: 'text/x-sql', 545 lineWrapping: true, 546 extraKeys: { 'Ctrl-Space': 'autocomplete' }, 547 hintOptions: { 'completeSingle': false, 'completeOnSingleClick': true }, 548 gutters: ['CodeMirror-lint-markers'], 549 lint: { 550 'getAnnotations': CodeMirror.sqlLint, 551 'async': true, 552 } 553 }); 554 PMA_consoleInput._inputs.bookmark.on('inputRead', codemirrorAutocompleteOnInputRead); 555 } 556 } else { 557 PMA_consoleInput._inputs.console = 558 $('<textarea>').appendTo('#pma_console .console_query_input') 559 .on('keydown', PMA_consoleInput._historyNavigate); 560 if ($('#pma_bookmarks').length !== 0) { 561 PMA_consoleInput._inputs.bookmark = 562 $('<textarea>').appendTo('#pma_console .bookmark_add_input'); 563 } 564 } 565 $('#pma_console').find('.console_query_input').keydown(PMA_consoleInput._keydown); 566 }, 567 _historyNavigate: function (event) { 568 if (event.keyCode === 38 || event.keyCode === 40) { 569 var upPermitted = false; 570 var downPermitted = false; 571 var editor = PMA_consoleInput._inputs.console; 572 var cursorLine; 573 var totalLine; 574 if (PMA_consoleInput._codemirror) { 575 cursorLine = editor.getCursor().line; 576 totalLine = editor.lineCount(); 577 } else { 578 // Get cursor position from textarea 579 var text = PMA_consoleInput.getText(); 580 cursorLine = text.substr(0, editor.prop('selectionStart')).split('\n').length - 1; 581 totalLine = text.split(/\r*\n/).length; 582 } 583 if (cursorLine === 0) { 584 upPermitted = true; 585 } 586 if (cursorLine === totalLine - 1) { 587 downPermitted = true; 588 } 589 var nextCount; 590 var queryString = false;
591 if (upPermitted && event.keyCode === 38) { 592 // Navigate up in history 593 if (PMA_consoleInput._historyCount === 0) { 594 PMA_consoleInput._historyPreserveCurrent = PMA_consoleInput.getText(); 595 } 596 nextCount = PMA_consoleInput._historyCount + 1; 597 queryString = PMA_consoleMessages.getHistory(nextCount); 598 } else if (downPermitted && event.keyCode === 40) { 599 // Navigate down in history 600 if (PMA_consoleInput._historyCount === 0) { 601 return; 602 } 603 nextCount = PMA_consoleInput._historyCount - 1; 604 if (nextCount === 0) { 605 queryString = PMA_consoleInput._historyPreserveCurrent; 606 } else { 607 queryString = PMA_consoleMessages.getHistory(nextCount); 608 } 609 } 610 if (queryString !== false) { 611 PMA_consoleInput._historyCount = nextCount; 612 PMA_consoleInput.setText(queryString, 'console'); 613 if (PMA_consoleInput._codemirror) { 614 editor.setCursor(editor.lineCount(), 0); 615 } 616 event.preventDefault(); 617 } 618 } 619 }, 620 /** 621 * Mousedown event handler for bind to input 622 * Shortcut is Ctrl+Enter key or just ENTER, depending on console's 623 * configuration. 624 * 625 * @return void 626 */ 627 _keydown: function (event) { 628 if (PMA_console.config.EnterExecutes) { 629 // Enter, but not in combination with Shift (which writes a new line). 630 if (!event.shiftKey && event.keyCode === 13) { 631 PMA_consoleInput.execute(); 632 } 633 } else { 634 // Ctrl+Enter 635 if (event.ctrlKey && event.keyCode === 13) { 636 PMA_consoleInput.execute(); 637 } 638 } 639 }, 640 /** 641 * Used for send text to PMA_console.execute() 642 * 643 * @return void 644 */ 645 execute: function () { 646 if (PMA_consoleInput._codemirror) { 647 PMA_console.execute(PMA_consoleInput._inputs.console.getValue()); 648 } else { 649 PMA_console.execute(PMA_consoleInput._inputs.console.val()); 650 } 651 }, 652 /** 653 * Used for clear the input 654 * 655 * @param string target, default target is console input 656 * @return void 657 */ 658 clear: function (target) { 659 PMA_consoleInput.setText('', target); 660 }, 661 /** 662 * Used for set focus to input 663 * 664 * @return void 665 */ 666 focus: function () { 667 PMA_consoleInput._inputs.console.focus(); 668 }, 669 /** 670 * Used for blur input 671 * 672 * @return void 673 */ 674 blur: function () { 675 if (PMA_consoleInput._codemirror) { 676 PMA_consoleInput._inputs.console.getInputField().blur(); 677 } else { 678 PMA_consoleInput._inputs.console.blur(); 679 } 680 }, 681 /** 682 * Used for set text in input 683 * 684 * @param string text 685 * @param string target 686 * @return void 687 */ 688 setText: function (text, target) { 689 if (PMA_consoleInput._codemirror) { 690 switch (target) { 691 case 'bookmark': 692 PMA_console.execute(PMA_consoleInput._inputs.bookmark.setValue(text)); 693 break; 694 default: 695 case 'console': 696 PMA_console.execute(PMA_consoleInput._inputs.console.setValue(text)); 697 } 698 } else { 699 switch (target) { 700 case 'bookmark': 701 PMA_console.execute(PMA_consoleInput._inputs.bookmark.val(text)); 702 break; 703 default: 704 case 'console': 705 PMA_console.execute(PMA_consoleInput._inputs.console.val(text)); 706 } 707 } 708 }, 709 getText: function (target) { 710 if (PMA_consoleInput._codemirror) { 711 switch (target) { 712 case 'bookmark': 713 return PMA_consoleInput._inputs.bookmark.getValue(); 714 default: 715 case 'console': 716 return PMA_consoleInput._inputs.console.getValue(); 717 } 718 } else { 719 switch (target) { 720 case 'bookmark': 721 return PMA_consoleInput._inputs.bookmark.val(); 722 default: 723 case 'console': 724 return PMA_consoleInput._inputs.console.val(); 725 } 726 } 727 } 728 729}; 730 731 732/** 733 * Console messages, and message items management object 734 */ 735var PMA_consoleMessages = { 736 /** 737 * Used for clear the messages 738 * 739 * @return void 740 */ 741 clear: function () { 742 $('#pma_console').find('.content .console_message_container .message:not(.welcome)').addClass('hide'); 743 $('#pma_console').find('.content .console_message_container .message.failed').remove(); 744 $('#pma_console').find('.content .console_message_container .message.expanded').find('.action.collapse').click(); 745 }, 746 /** 747 * Used for show history messages 748 * 749 * @return void 750 */ 751 showHistory: function () { 752 $('#pma_console').find('.content .console_message_container .message.hide').removeClass('hide'); 753 }, 754 /** 755 * Used for getting a perticular history query 756 * 757 * @param int nthLast get nth query message from latest, i.e 1st is last 758 * @return string message 759 */ 760 getHistory: function (nthLast) { 761 var $queries = $('#pma_console').find('.content .console_message_container .query'); 762 var length = $queries.length; 763 var $query = $queries.eq(length - nthLast); 764 if (!$query || (length - nthLast) < 0) { 765 return false;
766 } else { 767 return $query.text(); 768 } 769 }, 770 /** 771 * Used to show the correct message depending on which key 772 * combination executes the query (Ctrl+Enter or Enter). 773 * 774 * @param bool enterExecutes Only Enter has to be pressed to execute query. 775 * @return void 776 */ 777 showInstructions: function (enterExecutes) { 778 enterExecutes = +enterExecutes || 0; // conversion to int 779 var $welcomeMsg = $('#pma_console').find('.content .console_message_container .message.welcome span'); 780 $welcomeMsg.children('[id^=instructions]').hide(); 781 $welcomeMsg.children('#instructions-' + enterExecutes).show(); 782 }, 783 /** 784 * Used for log new message 785 * 786 * @param string msgString Message to show 787 * @param string msgType Message type 788 * @return object, {message_id, $message} 789 */ 790 append: function (msgString, msgType) { 791 if (typeof(msgString) !== 'string') { 792 return false; 793 } 794 // Generate an ID for each message, we can find them later 795 var msgId = Math.round(Math.random() * (899999999999) + 100000000000); 796 var now = new Date(); 797 var $newMessage = 798 $('<div class="message ' + 799 (PMA_console.config.AlwaysExpand ? 'expanded' : 'collapsed') + 800 '" msgid="' + msgId + '"><div class="action_content"></div></div>'); 801 switch (msgType) { 802 case 'query': 803 $newMessage.append('<div class="query highlighted"></div>'); 804 if (PMA_consoleInput._codemirror) { 805 CodeMirror.runMode(msgString, 806 'text/x-sql', $newMessage.children('.query')[0]); 807 } else { 808 $newMessage.children('.query').text(msgString); 809 } 810 $newMessage.children('.action_content') 811 .append(PMA_console.$consoleTemplates.children('.query_actions').html()); 812 break; 813 default: 814 case 'normal': 815 $newMessage.append('<div>' + msgString + '</div>'); 816 } 817 PMA_consoleMessages._msgEventBinds($newMessage); 818 $newMessage.find('span.text.query_time span') 819 .text(now.getHours() + ':' + now.getMinutes() + ':' + now.getSeconds()) 820 .parent().attr('title', now); 821 return { message_id: msgId, 822 $message: $newMessage.appendTo('#pma_console .content .console_message_container') }; 823 }, 824 /** 825 * Used for log new query 826 * 827 * @param string queryData Struct should be 828 * {sql_query: "Query string", db: "Target DB", table: "Target Table"} 829 * @param string state Message state 830 * @return object, {message_id: string message id, $message: JQuery object} 831 */ 832 appendQuery: function (queryData, state) { 833 var targetMessage = PMA_consoleMessages.append(queryData.sql_query, 'query'); 834 if (! targetMessage) { 835 return false; 836 } 837 if (queryData.db && queryData.table) { 838 targetMessage.$message.attr('targetdb', queryData.db); 839 targetMessage.$message.attr('targettable', queryData.table); 840 targetMessage.$message.find('.text.targetdb span').text(queryData.db); 841 } 842 if (PMA_console.isSelect(queryData.sql_query)) { 843 targetMessage.$message.addClass('select'); 844 } 845 switch (state) { 846 case 'failed': 847 targetMessage.$message.addClass('failed'); 848 break; 849 case 'successed': 850 targetMessage.$message.addClass('successed'); 851 break; 852 default: 853 case 'pending': 854 targetMessage.$message.addClass('pending'); 855 } 856 return targetMessage; 857 }, 858 _msgEventBinds: function ($targetMessage) { 859 // Leave unbinded elements, remove binded. 860 $targetMessage = $targetMessage.filter(':not(.binded)'); 861 if ($targetMessage.length === 0) { 862 return; 863 } 864 $targetMessage.addClass('binded'); 865 866 $targetMessage.find('.action.expand').click(function () { 867 $(this).closest('.message').removeClass('collapsed'); 868 $(this).closest('.message').addClass('expanded'); 869 }); 870 $targetMessage.find('.action.collapse').click(function () { 871 $(this).closest('.message').addClass('collapsed'); 872 $(this).closest('.message').removeClass('expanded'); 873 }); 874 $targetMessage.find('.action.edit').click(function () { 875 PMA_consoleInput.setText($(this).parent().siblings('.query').text()); 876 PMA_consoleInput.focus(); 877 }); 878 $targetMessage.find('.action.requery').click(function () { 879 var query = $(this).parent().siblings('.query').text(); 880 var $message = $(this).closest('.message'); 881 if (confirm(PMA_messages.strConsoleRequeryConfirm + '\n' + 882 (query.length < 100 ? query : query.slice(0, 100) + '...')) 883 ) { 884 PMA_console.execute(query, { db: $message.attr('targetdb'), table: $message.attr('targettable') }); 885 } 886 }); 887 $targetMessage.find('.action.bookmark').click(function () { 888 var query = $(this).parent().siblings('.query').text(); 889 var $message = $(this).closest('.message'); 890 PMA_consoleBookmarks.addBookmark(query, $message.attr('targetdb')); 891 PMA_console.showCard('#pma_bookmarks .card.add'); 892 }); 893 $targetMessage.find('.action.edit_bookmark').click(function () { 894 var query = $(this).parent().siblings('.query').text(); 895 var $message = $(this).closest('.message'); 896 var isShared = $message.find('span.bookmark_label').hasClass('shared'); 897 var label = $message.find('span.bookmark_label').text(); 898 PMA_consoleBookmarks.addBookmark(query, $message.attr('targetdb'), label, isShared); 899 PMA_console.showCard('#pma_bookmarks .card.add'); 900 }); 901 $targetMessage.find('.action.delete_bookmark').click(function () { 902 var $message = $(this).closest('.message'); 903 if (confirm(PMA_messages.strConsoleDeleteBookmarkConfirm + '\n' + $message.find('.bookmark_label').text())) { 904 $.post('import.php', 905 { 906 server: PMA_commonParams.get('server'), 907 action_bookmark: 2, 908 ajax_request: true, 909 id_bookmark: $message.attr('bookmarkid') }, 910 function () { 911 PMA_consoleBookmarks.refresh(); 912 }); 913 } 914 }); 915 $targetMessage.find('.action.profiling').click(function () { 916 var $message = $(this).closest('.message'); 917 PMA_console.execute($(this).parent().siblings('.query').text(), 918 { db: $message.attr('targetdb'), 919 table: $message.attr('targettable'), 920 profiling: true }); 921 }); 922 $targetMessage.find('.action.explain').click(function () { 923 var $message = $(this).closest('.message'); 924 PMA_console.execute('EXPLAIN ' + $(this).parent().siblings('.query').text(), 925 { db: $message.attr('targetdb'), 926 table: $message.attr('targettable') }); 927 }); 928 $targetMessage.find('.action.dbg_show_trace').click(function () { 929 var $message = $(this).closest('.message'); 930 if (!$message.find('.trace').length) { 931 PMA_consoleDebug.getQueryDetails( 932 $message.data('queryInfo'), 933 $message.data('totalTime'), 934 $message 935 ); 936 PMA_consoleMessages._msgEventBinds($message.find('.message:not(.binded)')); 937 } 938 $message.addClass('show_trace'); 939 $message.removeClass('hide_trace'); 940 }); 941 $targetMessage.find('.action.dbg_hide_trace').click(function () { 942 var $message = $(this).closest('.message'); 943 $message.addClass('hide_trace'); 944 $message.removeClass('show_trace'); 945 }); 946 $targetMessage.find('.action.dbg_show_args').click(function () { 947 var $message = $(this).closest('.message'); 948 $message.addClass('show_args expanded'); 949 $message.removeClass('hide_args collapsed'); 950 }); 951 $targetMessage.find('.action.dbg_hide_args').click(function () { 952 var $message = $(this).closest('.message'); 953 $message.addClass('hide_args collapsed'); 954 $message.removeClass('show_args expanded'); 955 });
956 if (PMA_consoleInput._codemirror) { 957 $targetMessage.find('.query:not(.highlighted)').each(function (index, elem) { 958 CodeMirror.runMode($(elem).text(), 959 'text/x-sql', elem); 960 $(this).addClass('highlighted'); 961 }); 962 } 963 }, 964 msgAppend: function (msgId, msgString, msgType) { 965 var $targetMessage = $('#pma_console').find('.content .console_message_container .message[msgid=' + msgId + ']'); 966 if ($targetMessage.length === 0 || isNaN(parseInt(msgId)) || typeof(msgString) !== 'string') { 967 return false; 968 } 969 $targetMessage.append('<div>' + msgString + '</div>'); 970 }, 971 updateQuery: function (msgId, isSuccessed, queryData) { 972 var $targetMessage = $('#pma_console').find('.console_message_container .message[msgid=' + parseInt(msgId) + ']'); 973 if ($targetMessage.length === 0 || isNaN(parseInt(msgId))) { 974 return false; 975 } 976 $targetMessage.removeClass('pending failed successed'); 977 if (isSuccessed) { 978 $targetMessage.addClass('successed'); 979 if (queryData) { 980 $targetMessage.children('.query').text(''); 981 $targetMessage.removeClass('select'); 982 if (PMA_console.isSelect(queryData.sql_query)) { 983 $targetMessage.addClass('select'); 984 } 985 if (PMA_consoleInput._codemirror) { 986 CodeMirror.runMode(queryData.sql_query, 'text/x-sql', $targetMessage.children('.query')[0]); 987 } else { 988 $targetMessage.children('.query').text(queryData.sql_query); 989 } 990 $targetMessage.attr('targetdb', queryData.db); 991 $targetMessage.attr('targettable', queryData.table); 992 $targetMessage.find('.text.targetdb span').text(queryData.db); 993 } 994 } else { 995 $targetMessage.addClass('failed'); 996 } 997 }, 998 /**
999 * Used for console messages initialize 1000 * 1001 * @return void 1002 */ 1003 initialize: function () { 1004 PMA_consoleMessages._msgEventBinds($('#pma_console').find('.message:not(.binded)')); 1005 if (PMA_console.config.StartHistory) { 1006 PMA_consoleMessages.showHistory(); 1007 } 1008 PMA_consoleMessages.showInstructions(PMA_console.config.EnterExecutes); 1009 } 1010}; 1011 1012 1013/** 1014 * Console bookmarks card, and bookmarks items management object 1015 */ 1016var PMA_consoleBookmarks = { 1017 _bookmarks: [], 1018 addBookmark: function (queryString, targetDb, label, isShared, id) { 1019 $('#pma_bookmarks').find('.add [name=shared]').prop('checked', false); 1020 $('#pma_bookmarks').find('.add [name=label]').val(''); 1021 $('#pma_bookmarks').find('.add [name=targetdb]').val(''); 1022 $('#pma_bookmarks').find('.add [name=id_bookmark]').val(''); 1023 PMA_consoleInput.setText('', 'bookmark'); 1024 1025 switch (arguments.length) { 1026 case 4: 1027 $('#pma_bookmarks').find('.add [name=shared]').prop('checked', isShared); 1028 case 3: 1029 $('#pma_bookmarks').find('.add [name=label]').val(label); 1030 case 2: 1031 $('#pma_bookmarks').find('.add [name=targetdb]').val(targetDb); 1032 case 1: 1033 PMA_consoleInput.setText(queryString, 'bookmark'); 1034 default: 1035 break; 1036 } 1037 }, 1038 refresh: function () { 1039 $.get('import.php', 1040 { ajax_request: true, 1041 server: PMA_commonParams.get('server'), 1042 console_bookmark_refresh: 'refresh' }, 1043 function (data) { 1044 if (data.console_message_bookmark) { 1045 $('#pma_bookmarks').find('.content.bookmark').html(data.console_message_bookmark); 1046 PMA_consoleMessages._msgEventBinds($('#pma_bookmarks').find('.message:not(.binded)')); 1047 } 1048 }); 1049 }, 1050 /**
1051 * Used for console bookmarks initialize 1052 * message events are already binded by PMA_consoleMsg._msgEventBinds 1053 * 1054 * @return void 1055 */ 1056 initialize: function () { 1057 if ($('#pma_bookmarks').length === 0) { 1058 return; 1059 } 1060 $('#pma_console').find('.button.bookmarks').click(function () { 1061 PMA_console.showCard('#pma_bookmarks'); 1062 }); 1063 $('#pma_bookmarks').find('.button.add').click(function () { 1064 PMA_console.showCard('#pma_bookmarks .card.add'); 1065 }); 1066 $('#pma_bookmarks').find('.card.add [name=submit]').click(function () { 1067 if ($('#pma_bookmarks').find('.card.add [name=label]').val().length === 0 1068 || PMA_consoleInput.getText('bookmark').length === 0) { 1069 alert(PMA_messages.strFormEmpty); 1070 return; 1071 } 1072 $(this).prop('disabled', true); 1073 $.post('import.php', 1074 { 1075 ajax_request: true, 1076 console_bookmark_add: 'true', 1077 label: $('#pma_bookmarks').find('.card.add [name=label]').val(), 1078 server: PMA_commonParams.get('server'), 1079 db: $('#pma_bookmarks').find('.card.add [name=targetdb]').val(), 1080 bookmark_query: PMA_consoleInput.getText('bookmark'), 1081 shared: $('#pma_bookmarks').find('.card.add [name=shared]').prop('checked') }, 1082 function () { 1083 PMA_consoleBookmarks.refresh(); 1084 $('#pma_bookmarks').find('.card.add [name=submit]').prop('disabled', false); 1085 PMA_console.hideCard($('#pma_bookmarks').find('.card.add')); 1086 }); 1087 }); 1088 $('#pma_console').find('.button.refresh').click(function () { 1089 PMA_consoleBookmarks.refresh(); 1090 }); 1091 } 1092}; 1093 1094var PMA_consoleDebug; 1095PMA_consoleDebug = { 1096 _config: { 1097 groupQueries: false, 1098 orderBy: 'exec', // Possible 'exec' => Execution order, 'time' => Time taken, 'count' 1099 order: 'asc' // Possible 'asc', 'desc' 1100 }, 1101 _lastDebugInfo: { 1102 debugInfo: null, 1103 url: null 1104 }, 1105 initialize: function () { 1106 // Try to get debug info after every AJAX request 1107 $(document).ajaxSuccess(function (event, xhr, settings, data) { 1108 if (data._debug) { 1109 PMA_consoleDebug.showLog(data._debug, settings.url); 1110 } 1111 }); 1112 1113 if (PMA_console.config.GroupQueries) { 1114 $('#debug_console').addClass('grouped'); 1115 } else { 1116 $('#debug_console').addClass('ungrouped'); 1117 if (PMA_console.config.OrderBy === 'count') { 1118 $('#debug_console').find('.button.order_by.sort_exec').addClass('active'); 1119 } 1120 } 1121 var orderBy = PMA_console.config.OrderBy; 1122 var order = PMA_console.config.Order; 1123 $('#debug_console').find('.button.order_by.sort_' + orderBy).addClass('active'); 1124 $('#debug_console').find('.button.order.order_' + order).addClass('active'); 1125 1126 // Initialize actions in toolbar 1127 $('#debug_console').find('.button.group_queries').click(function () { 1128 $('#debug_console').addClass('grouped'); 1129 $('#debug_console').removeClass('ungrouped'); 1130 PMA_console.setConfig('GroupQueries', true); 1131 PMA_consoleDebug.refresh(); 1132 if (PMA_console.config.OrderBy === 'count') { 1133 $('#debug_console').find('.button.order_by.sort_exec').removeClass('active'); 1134 } 1135 }); 1136 $('#debug_console').find('.button.ungroup_queries').click(function () { 1137 $('#debug_console').addClass('ungrouped'); 1138 $('#debug_console').removeClass('grouped'); 1139 PMA_console.setConfig('GroupQueries', false); 1140 PMA_consoleDebug.refresh(); 1141 if (PMA_console.config.OrderBy === 'count') { 1142 $('#debug_console').find('.button.order_by.sort_exec').addClass('active'); 1143 } 1144 }); 1145 $('#debug_console').find('.button.order_by').click(function () { 1146 var $this = $(this); 1147 $('#debug_console').find('.button.order_by').removeClass('active'); 1148 $this.addClass('active'); 1149 if ($this.hasClass('sort_time')) { 1150 PMA_console.setConfig('OrderBy', 'time'); 1151 } else if ($this.hasClass('sort_exec')) { 1152 PMA_console.setConfig('OrderBy', 'exec'); 1153 } else if ($this.hasClass('sort_count')) { 1154 PMA_console.setConfig('OrderBy', 'count'); 1155 } 1156 PMA_consoleDebug.refresh(); 1157 }); 1158 $('#debug_console').find('.button.order').click(function () { 1159 var $this = $(this); 1160 $('#debug_console').find('.button.order').removeClass('active'); 1161 $this.addClass('active'); 1162 if ($this.hasClass('order_asc')) { 1163 PMA_console.setConfig('Order', 'asc'); 1164 } else if ($this.hasClass('order_desc')) { 1165 PMA_console.setConfig('Order', 'desc'); 1166 } 1167 PMA_consoleDebug.refresh(); 1168 }); 1169 1170 // Show SQL debug info for first page load 1171 if (typeof debugSQLInfo !== 'undefined' && debugSQLInfo !== 'null') { 1172 $('#pma_console').find('.button.debug').removeClass('hide'); 1173 } else { 1174 return; 1175 } 1176 PMA_consoleDebug.showLog(debugSQLInfo); 1177 }, 1178 _formatFunctionCall: function (dbgStep) { 1179 var functionName = '';
1180 if ('class' in dbgStep) { 1181 functionName += dbgStep.class; 1182 functionName += dbgStep.type; 1183 } 1184 functionName += dbgStep.function; 1185 if (dbgStep.args && dbgStep.args.length) { 1186 functionName += '(...)'; 1187 } else { 1188 functionName += '()'; 1189 } 1190 return functionName; 1191 }, 1192 _formatFunctionArgs: function (dbgStep) { 1193 var $args = $('<div>'); 1194 if (dbgStep.args.length) { 1195 $args.append('<div class="message welcome">') 1196 .append( 1197 $('<div class="message welcome">') 1198 .text( 1199 PMA_sprintf( 1200 PMA_messages.strConsoleDebugArgsSummary, 1201 dbgStep.args.length 1202 ) 1203 ) 1204 ); 1205 for (var i = 0; i < dbgStep.args.length; i++) { 1206 $args.append( 1207 $('<div class="message">') 1208 .html( 1209 '<pre>' + 1210 escapeHtml(JSON.stringify(dbgStep.args[i], null, ' ')) + 1211 '</pre>' 1212 ) 1213 ); 1214 } 1215 } 1216 return $args; 1217 }, 1218 _formatFileName: function (dbgStep) { 1219 var fileName = ''; 1220 if ('file' in dbgStep) { 1221 fileName += dbgStep.file; 1222 fileName += '#' + dbgStep.line; 1223 } 1224 return fileName; 1225 }, 1226 _formatBackTrace: function (dbgTrace) { 1227 var $traceElem = $('<div class="trace">'); 1228 $traceElem.append( 1229 $('<div class="message welcome">') 1230 ); 1231 var step; 1232 var $stepElem; 1233 for (var stepId in dbgTrace) { 1234 if (dbgTrace.hasOwnProperty(stepId)) { 1235 step = dbgTrace[stepId]; 1236 if (!Array.isArray(step) && typeof step !== 'object') { 1237 $stepElem = 1238 $('<div class="message traceStep collapsed hide_args">') 1239 .append( 1240 $('<span>').text(step) 1241 ); 1242 } else { 1243 if (typeof step.args === 'string' && step.args) { 1244 step.args = [step.args]; 1245 } 1246 $stepElem = 1247 $('<div class="message traceStep collapsed hide_args">') 1248 .append( 1249 $('<span class="function">').text(this._formatFunctionCall(step)) 1250 ) 1251 .append( 1252 $('<span class="file">').text(this._formatFileName(step)) 1253 ); 1254 if (step.args && step.args.length) { 1255 $stepElem 1256 .append( 1257 $('<span class="args">').html(this._formatFunctionArgs(step)) 1258 ) 1259 .prepend( 1260 $('<div class="action_content">') 1261 .append( 1262 '<span class="action dbg_show_args">' + 1263 PMA_messages.strConsoleDebugShowArgs + 1264 '</span> ' 1265 ) 1266 .append( 1267 '<span class="action dbg_hide_args">' + 1268 PMA_messages.strConsoleDebugHideArgs + 1269 '</span> ' 1270 ) 1271 ); 1272 } 1273 } 1274 $traceElem.append($stepElem); 1275 } 1276 } 1277 return $traceElem; 1278 }, 1279 _formatQueryOrGroup: function (queryInfo, totalTime) { 1280 var grouped; 1281 var queryText; 1282 var queryTime; 1283 var count; 1284 var i; 1285 if (Array.isArray(queryInfo)) { 1286 // It is grouped
1287 grouped = true; 1288 1289 queryText = queryInfo[0].query; 1290 1291 queryTime = 0; 1292 for (i in queryInfo) { 1293 queryTime += queryInfo[i].time; 1294 } 1295 1296 count = queryInfo.length; 1297 } else { 1298 queryText = queryInfo.query; 1299 queryTime = queryInfo.time; 1300 } 1301 1302 var $query = $('<div class="message collapsed hide_trace">') 1303 .append( 1304 $('#debug_console').find('.templates .debug_query').clone() 1305 ) 1306 .append( 1307 $('<div class="query">') 1308 .text(queryText) 1309 ) 1310 .data('queryInfo', queryInfo) 1311 .data('totalTime', totalTime); 1312 if (grouped) { 1313 $query.find('.text.count').removeClass('hide'); 1314 $query.find('.text.count span').text(count); 1315 } 1316 $query.find('.text.time span').text(queryTime + 's (' + ((queryTime * 100) / totalTime).toFixed(3) + '%)'); 1317 1318 return $query; 1319 }, 1320 _appendQueryExtraInfo: function (query, $elem) { 1321 if ('error' in query) {
1322 $elem.append( 1323 $('<div>').html(query.error) 1324 ); 1325 } 1326 $elem.append(this._formatBackTrace(query.trace)); 1327 }, 1328 getQueryDetails: function (queryInfo, totalTime, $query) { 1329 if (Array.isArray(queryInfo)) { 1330 var $singleQuery; 1331 for (var i in queryInfo) { 1332 $singleQuery = $('<div class="message welcome trace">') 1333 .text((parseInt(i) + 1) + '.') 1334 .append( 1335 $('<span class="time">').text( 1336 PMA_messages.strConsoleDebugTimeTaken + 1337 ' ' + queryInfo[i].time + 's' + 1338 ' (' + ((queryInfo[i].time * 100) / totalTime).toFixed(3) + '%)' 1339 ) 1340 ); 1341 this._appendQueryExtraInfo(queryInfo[i], $singleQuery); 1342 $query 1343 .append('<div class="message welcome trace">') 1344 .append($singleQuery); 1345 } 1346 } else { 1347 this._appendQueryExtraInfo(queryInfo, $query); 1348 } 1349 }, 1350 showLog: function (debugInfo, url) { 1351 this._lastDebugInfo.debugInfo = debugInfo; 1352 this._lastDebugInfo.url = url; 1353 1354 $('#debug_console').find('.debugLog').empty(); 1355 $('#debug_console').find('.debug>.welcome').empty(); 1356 1357 var debugJson = false; 1358 var i; 1359 if (typeof debugInfo === 'object' && 'queries' in debugInfo) { 1360 // Copy it to debugJson, so that it doesn't get changed 1361 if (!('queries' in debugInfo)) { 1362 debugJson = false; 1363 } else { 1364 debugJson = { queries: [] }; 1365 for (i in debugInfo.queries) { 1366 debugJson.queries[i] = debugInfo.queries[i]; 1367 } 1368 } 1369 } else if (typeof debugInfo === 'string') { 1370 try { 1371 debugJson = JSON.parse(debugInfo); 1372 } catch (e) { 1373 debugJson = false; 1374 } 1375 if (debugJson && !('queries' in debugJson)) { 1376 debugJson = false; 1377 } 1378 } 1379 if (debugJson === false) { 1380 $('#debug_console').find('.debug>.welcome').text( 1381 PMA_messages.strConsoleDebugError 1382 ); 1383 return; 1384 } 1385 var allQueries = debugJson.queries; 1386 var uniqueQueries = {}; 1387 1388 var totalExec = allQueries.length; 1389 1390 // Calculate total time and make unique query array 1391 var totalTime = 0; 1392 for (i = 0; i < totalExec; ++i) { 1393 totalTime += allQueries[i].time; 1394 if (!(allQueries[i].hash in uniqueQueries)) { 1395 uniqueQueries[allQueries[i].hash] = []; 1396 } 1397 uniqueQueries[allQueries[i].hash].push(allQueries[i]); 1398 } 1399 // Count total unique queries, convert uniqueQueries to Array 1400 var totalUnique = 0; 1401 var uniqueArray = []; 1402 for (var hash in uniqueQueries) { 1403 if (uniqueQueries.hasOwnProperty(hash)) { 1404 ++totalUnique; 1405 uniqueArray.push(uniqueQueries[hash]); 1406 } 1407 } 1408 uniqueQueries = uniqueArray; 1409 // Show summary 1410 $('#debug_console').find('.debug>.welcome').append( 1411 $('<span class="debug_summary">').text( 1412 PMA_sprintf( 1413 PMA_messages.strConsoleDebugSummary, 1414 totalUnique, 1415 totalExec, 1416 totalTime 1417 ) 1418 ) 1419 ); 1420 if (url) { 1421 $('#debug_console').find('.debug>.welcome').append( 1422 $('<span class="script_name">').text(url.split('?')[0]) 1423 ); 1424 } 1425 1426 // For sorting queries 1427 function sortByTime (a, b) { 1428 var order = ((PMA_console.config.Order === 'asc') ? 1 : -1); 1429 if (Array.isArray(a) && Array.isArray(b)) { 1430 // It is grouped 1431 var timeA = 0; 1432 var timeB = 0; 1433 var i; 1434 for (i in a) { 1435 timeA += a[i].time; 1436 } 1437 for (i in b) { 1438 timeB += b[i].time; 1439 } 1440 return (timeA - timeB) * order; 1441 } else { 1442 return (a.time - b.time) * order; 1443 } 1444 } 1445
1446 function sortByCount (a, b) { 1447 var order = ((PMA_console.config.Oorder === 'asc') ? 1 : -1); 1448 return (a.length - b.length) * order; 1449 } 1450 1451 var orderBy = PMA_console.config.OrderBy; 1452 var order = PMA_console.config.Order; 1453 1454 if (PMA_console.config.GroupQueries) { 1455 // Sort queries 1456 if (orderBy === 'time') { 1457 uniqueQueries.sort(sortByTime); 1458 } else if (orderBy === 'count') { 1459 uniqueQueries.sort(sortByCount); 1460 } else if (orderBy === 'exec' && order === 'desc') { 1461 uniqueQueries.reverse(); 1462 } 1463 for (i in uniqueQueries) { 1464 if (orderBy === 'time') { 1465 uniqueQueries[i].sort(sortByTime); 1466 } else if (orderBy === 'exec' && order === 'desc') { 1467 uniqueQueries[i].reverse(); 1468 } 1469 $('#debug_console').find('.debugLog').append(this._formatQueryOrGroup(uniqueQueries[i], totalTime)); 1470 } 1471 } else { 1472 if (orderBy === 'time') { 1473 allQueries.sort(sortByTime); 1474 } else if (order === 'desc') { 1475 allQueries.reverse(); 1476 } 1477 for (i = 0; i < totalExec; ++i) { 1478 $('#debug_console').find('.debugLog').append(this._formatQueryOrGroup(allQueries[i], totalTime)); 1479 } 1480 } 1481 1482 PMA_consoleMessages._msgEventBinds($('#debug_console').find('.message:not(.binded)')); 1483 }, 1484 refresh: function () { 1485 var last = this._lastDebugInfo; 1486 PMA_consoleDebug.showLog(last.debugInfo, last.url); 1487 } 1488}; 1489 1490/** s 1491 * Executed on page load 1492 */ 1493$(function () { 1494 PMA_console.initialize(); 1495});
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.