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 | */ |
||
11 | var 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').on('click', PMA_console.toggle); |
||
114 | |||
115 | $('#pma_console').find('.toolbar').children().on('mousedown', function (event) { |
||
116 | event.preventDefault(); |
||
117 | event.stopImmediatePropagation(); |
||
118 | }); |
||
119 | |||
120 | $('#pma_console').find('.button.clear').on('click', function () { |
||
121 | PMA_consoleMessages.clear(); |
||
122 | }); |
||
123 | |||
124 | $('#pma_console').find('.button.history').on('click', function () { |
||
125 | PMA_consoleMessages.showHistory(); |
||
126 | }); |
||
127 | |||
128 | $('#pma_console').find('.button.options').on('click', function () { |
||
129 | PMA_console.showCard('#pma_console_options'); |
||
130 | }); |
||
131 | |||
132 | $('#pma_console').find('.button.debug').on('click', function () { |
||
133 | PMA_console.showCard('#debug_console'); |
||
134 | }); |
||
135 | |||
136 | PMA_console.$consoleContent.on('click', function (event) { |
||
137 | if (event.target === this) { |
||
138 | PMA_consoleInput.focus(); |
||
139 | } |
||
140 | }); |
||
141 | |||
142 | $('#pma_console').find('.mid_layer').on('click', function () { |
||
143 | PMA_console.hideCard($(this).parent().children('.card')); |
||
144 | }); |
||
145 | $('#debug_console').find('.switch_button').on('click', function () { |
||
146 | PMA_console.hideCard($(this).closest('.card')); |
||
147 | }); |
||
148 | $('#pma_bookmarks').find('.switch_button').on('click', function () { |
||
149 | PMA_console.hideCard($(this).closest('.card')); |
||
150 | }); |
||
151 | $('#pma_console_options').find('.switch_button').on('click', function () { |
||
152 | PMA_console.hideCard($(this).closest('.card')); |
||
153 | }); |
||
154 | |||
155 | $('#pma_console_options').find('input[type=checkbox]').on('change', function () { |
||
156 | PMA_console.updateConfig(); |
||
157 | }); |
||
158 | |||
159 | $('#pma_console_options').find('.button.default').on('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]').on('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 | */ |
||
415 | var 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').on('mousedown', PMA_consoleResizer._mousedown); |
||
482 | } |
||
483 | }; |
||
484 | |||
485 | |||
486 | /** |
||
487 | * Console input object |
||
488 | */ |
||
489 | var 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').on('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 | */ |
||
735 | var 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').trigger('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').on('click', function () { |
||
867 | $(this).closest('.message').removeClass('collapsed'); |
||
868 | $(this).closest('.message').addClass('expanded'); |
||
869 | }); |
||
870 | $targetMessage.find('.action.collapse').on('click', function () { |
||
871 | $(this).closest('.message').addClass('collapsed'); |
||
872 | $(this).closest('.message').removeClass('expanded'); |
||
873 | }); |
||
874 | $targetMessage.find('.action.edit').on('click', function () { |
||
875 | PMA_consoleInput.setText($(this).parent().siblings('.query').text()); |
||
876 | PMA_consoleInput.focus(); |
||
877 | }); |
||
878 | $targetMessage.find('.action.requery').on('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').on('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').on('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').on('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').on('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').on('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').on('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').on('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').on('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').on('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 | */ |
||
1016 | var 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); |
||
0 ignored issues
–
show
introduced
by
Loading history...
|
|||
1028 | case 3: |
||
1029 | $('#pma_bookmarks').find('.add [name=label]').val(label); |
||
0 ignored issues
–
show
|
|||
1030 | case 2: |
||
1031 | $('#pma_bookmarks').find('.add [name=targetdb]').val(targetDb); |
||
0 ignored issues
–
show
|
|||
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').on('click', function () { |
||
1061 | PMA_console.showCard('#pma_bookmarks'); |
||
1062 | }); |
||
1063 | $('#pma_bookmarks').find('.button.add').on('click', function () { |
||
1064 | PMA_console.showCard('#pma_bookmarks .card.add'); |
||
1065 | }); |
||
1066 | $('#pma_bookmarks').find('.card.add [name=submit]').on('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').on('click', function () { |
||
1089 | PMA_consoleBookmarks.refresh(); |
||
1090 | }); |
||
1091 | } |
||
1092 | }; |
||
1093 | |||
1094 | var PMA_consoleDebug; |
||
0 ignored issues
–
show
|
|||
1095 | PMA_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').on('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').on('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').on('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').on('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 | }); |
||
1496 |