classes/Console/PMA_consoleInput.js

  1. /* vim: set expandtab sw=4 ts=4 sts=4: */
  2. import CodeMirror from 'codemirror';
  3. import 'codemirror/mode/sql/sql.js';
  4. import 'codemirror/addon/runmode/runmode.js';
  5. import 'codemirror/addon/hint/show-hint.js';
  6. import 'codemirror/addon/hint/sql-hint.js';
  7. import 'codemirror/addon/lint/lint.js';
  8. import '../../plugins/codemirror/sql-lint';
  9. import { codemirrorAutocompleteOnInputRead } from '../../utils/sql';
  10. import CommonParams from '../../variables/common_params';
  11. /**
  12. * Console input object
  13. * @namespace ConsoleInput
  14. */
  15. export default class ConsoleInput {
  16. /**
  17. * @constructor
  18. *
  19. * @param {object} pmaConsoleInstance Instance of pma console
  20. */
  21. constructor (pmaConsoleInstance) {
  22. /**
  23. * @var array, contains Codemirror objects or input jQuery objects
  24. * @access private
  25. */
  26. this._inputs = null;
  27. /**
  28. * @var bool, if codemirror enabled
  29. * @access private
  30. */
  31. this._codemirror = false;
  32. /**
  33. * @var int, count for history navigation, 0 for current input
  34. * @access private
  35. */
  36. this._historyCount = 0;
  37. /**
  38. * @var string, current input when navigating through history
  39. * @access private
  40. */
  41. this._historyPreserveCurrent = null;
  42. /**
  43. * @var object
  44. * @access private
  45. */
  46. this.pmaConsole = null;
  47. /**
  48. * Bindings for accessing the instance of the class using this
  49. * insde the methods.
  50. */
  51. this.setPmaConsole = this.setPmaConsole.bind(this);
  52. this.initialize = this.initialize.bind(this);
  53. this._historyNavigate = this._historyNavigate.bind(this);
  54. this._keydown = this._keydown.bind(this);
  55. this.execute = this.execute.bind(this);
  56. this.clear = this.clear.bind(this);
  57. this.focus = this.focus.bind(this);
  58. this.blur = this.blur.bind(this);
  59. this.setText = this.setText.bind(this);
  60. this.getText = this.getText.bind(this);
  61. this.setPmaConsole(pmaConsoleInstance);
  62. }
  63. setPmaConsole (instance) {
  64. this.pmaConsole = instance;
  65. this.initialize();
  66. }
  67. initialize () {
  68. // _cm object can't be reinitialize
  69. if (this._inputs !== null) {
  70. return;
  71. }
  72. if (CommonParams.get('CodemirrorEnable') === true) {
  73. this._codemirror = true;
  74. }
  75. this._inputs = [];
  76. if (this._codemirror) {
  77. this._inputs.console = CodeMirror($('#pma_console').find('.console_query_input')[0], {
  78. theme: 'pma',
  79. mode: 'text/x-sql',
  80. lineWrapping: true,
  81. extraKeys: { 'Ctrl-Space': 'autocomplete' },
  82. hintOptions: { 'completeSingle': false, 'completeOnSingleClick': true },
  83. gutters: ['CodeMirror-lint-markers'],
  84. lint: {
  85. 'getAnnotations': CodeMirror.sqlLint,
  86. 'async': true,
  87. }
  88. });
  89. this._inputs.console.on('inputRead', codemirrorAutocompleteOnInputRead);
  90. this._inputs.console.on('keydown', function (instance, event) {
  91. this._historyNavigate(event);
  92. }.bind(this));
  93. if ($('#pma_bookmarks').length !== 0) {
  94. this._inputs.bookmark = CodeMirror($('#pma_console').find('.bookmark_add_input')[0], {
  95. theme: 'pma',
  96. mode: 'text/x-sql',
  97. lineWrapping: true,
  98. extraKeys: { 'Ctrl-Space': 'autocomplete' },
  99. hintOptions: { 'completeSingle': false, 'completeOnSingleClick': true },
  100. gutters: ['CodeMirror-lint-markers'],
  101. lint: {
  102. 'getAnnotations': CodeMirror.sqlLint,
  103. 'async': true,
  104. }
  105. });
  106. this._inputs.bookmark.on('inputRead', codemirrorAutocompleteOnInputRead);
  107. }
  108. } else {
  109. this._inputs.console =
  110. $('<textarea>').appendTo('#pma_console .console_query_input')
  111. .on('keydown', this._historyNavigate);
  112. if ($('#pma_bookmarks').length !== 0) {
  113. this._inputs.bookmark =
  114. $('<textarea>').appendTo('#pma_console .bookmark_add_input');
  115. }
  116. }
  117. $('#pma_console').find('.console_query_input').keydown(this._keydown);
  118. }
  119. _historyNavigate (event) {
  120. if (event.keyCode === 38 || event.keyCode === 40) {
  121. var upPermitted = false;
  122. var downPermitted = false;
  123. var editor = this._inputs.console;
  124. var cursorLine;
  125. var totalLine;
  126. if (this._codemirror) {
  127. cursorLine = editor.getCursor().line;
  128. totalLine = editor.lineCount();
  129. } else {
  130. // Get cursor position from textarea
  131. var text = this.getText();
  132. cursorLine = text.substr(0, editor.prop('selectionStart')).split('\n').length - 1;
  133. totalLine = text.split(/\r*\n/).length;
  134. }
  135. if (cursorLine === 0) {
  136. upPermitted = true;
  137. }
  138. if (cursorLine === totalLine - 1) {
  139. downPermitted = true;
  140. }
  141. var nextCount;
  142. var queryString = false;
  143. if (upPermitted && event.keyCode === 38) {
  144. // Navigate up in history
  145. if (this._historyCount === 0) {
  146. this._historyPreserveCurrent = this.getText();
  147. }
  148. nextCount = this._historyCount + 1;
  149. queryString = this.pmaConsole.pmaConsoleMessages.getHistory(nextCount);
  150. } else if (downPermitted && event.keyCode === 40) {
  151. // Navigate down in history
  152. if (this._historyCount === 0) {
  153. return;
  154. }
  155. nextCount = this._historyCount - 1;
  156. if (nextCount === 0) {
  157. queryString = this._historyPreserveCurrent;
  158. } else {
  159. queryString = this.pmaConsole.pmaConsoleMessages.getHistory(nextCount);
  160. }
  161. }
  162. if (queryString !== false) {
  163. this._historyCount = nextCount;
  164. this.setText(queryString, 'console');
  165. if (this._codemirror) {
  166. editor.setCursor(editor.lineCount(), 0);
  167. }
  168. event.preventDefault();
  169. }
  170. }
  171. }
  172. /**
  173. * Mousedown event handler for bind to input
  174. * Shortcut is Ctrl+Enter key or just ENTER, depending on console's
  175. * configuration.
  176. *
  177. * @return void
  178. */
  179. _keydown (event) {
  180. if (this.pmaConsole.config.EnterExecutes) {
  181. // Enter, but not in combination with Shift (which writes a new line).
  182. if (!event.shiftKey && event.keyCode === 13) {
  183. this.execute();
  184. }
  185. } else {
  186. // Ctrl+Enter
  187. if (event.ctrlKey && event.keyCode === 13) {
  188. this.execute();
  189. }
  190. }
  191. }
  192. /**
  193. * Used for send text to PMA_console.execute()
  194. *
  195. * @return void
  196. */
  197. execute () {
  198. if (this._codemirror) {
  199. this.pmaConsole.execute(this._inputs.console.getValue());
  200. } else {
  201. this.pmaConsole.execute(this._inputs.console.val());
  202. }
  203. }
  204. /**
  205. * Used for clear the input
  206. *
  207. * @param string target, default target is console input
  208. * @return void
  209. */
  210. clear (target) {
  211. this.setText('', target);
  212. }
  213. /**
  214. * Used for set focus to input
  215. *
  216. * @return void
  217. */
  218. focus () {
  219. this._inputs.console.focus();
  220. }
  221. /**
  222. * Used for blur input
  223. *
  224. * @return void
  225. */
  226. blur () {
  227. if (this._codemirror) {
  228. this._inputs.console.getInputField().blur();
  229. } else {
  230. this._inputs.console.blur();
  231. }
  232. }
  233. /**
  234. * Used for set text in input
  235. *
  236. * @param string text
  237. * @param string target
  238. *
  239. * @return void
  240. */
  241. setText (text, target) {
  242. if (this._codemirror) {
  243. switch (target) {
  244. case 'bookmark':
  245. this.pmaConsole.execute(this._inputs.bookmark.setValue(text));
  246. break;
  247. default:
  248. case 'console':
  249. this.pmaConsole.execute(this._inputs.console.setValue(text));
  250. }
  251. } else {
  252. switch (target) {
  253. case 'bookmark':
  254. this.pmaConsole.execute(this._inputs.bookmark.val(text));
  255. break;
  256. default:
  257. case 'console':
  258. this.pmaConsole.execute(this._inputs.console.val(text));
  259. }
  260. }
  261. }
  262. /**
  263. * Used for getting the text of input
  264. *
  265. * @param {string} target
  266. *
  267. * @return {string}
  268. */
  269. getText (target) {
  270. if (this._codemirror) {
  271. switch (target) {
  272. case 'bookmark':
  273. return this._inputs.bookmark.getValue();
  274. default:
  275. case 'console':
  276. return this._inputs.console.getValue();
  277. }
  278. } else {
  279. switch (target) {
  280. case 'bookmark':
  281. return this._inputs.bookmark.val();
  282. default:
  283. case 'console':
  284. return this._inputs.console.val();
  285. }
  286. }
  287. }
  288. }