rte.js 40 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934
  1. /* vim: set expandtab sw=4 ts=4 sts=4: */
  2. /**
  3. * JavaScript functionality for Routines, Triggers and Events.
  4. *
  5. * @package PhpMyadmin
  6. */
  7. /**
  8. * @var RTE Contains all the JavaScript functionality
  9. * for Routines, Triggers and Events
  10. */
  11. var RTE = {
  12. /**
  13. * Construct for the object that provides the
  14. * functionality for Routines, Triggers and Events
  15. */
  16. object: function (type) {
  17. $.extend(this, RTE.COMMON);
  18. switch (type) {
  19. case 'routine':
  20. $.extend(this, RTE.ROUTINE);
  21. break;
  22. case 'trigger':
  23. // nothing extra yet for triggers
  24. break;
  25. case 'event':
  26. $.extend(this, RTE.EVENT);
  27. break;
  28. default:
  29. break;
  30. }
  31. },
  32. /**
  33. * @var string param_template Template for a row in the routine editor
  34. */
  35. param_template: ''
  36. };
  37. /**
  38. * @var RTE.COMMON a JavaScript namespace containing the functionality
  39. * for Routines, Triggers and Events
  40. *
  41. * This namespace is extended by the functionality required
  42. * to handle a specific item (a routine, trigger or event)
  43. * in the relevant javascript files in this folder
  44. */
  45. RTE.COMMON = {
  46. /**
  47. * @var $ajaxDialog Query object containing the reference to the
  48. * dialog that contains the editor
  49. */
  50. $ajaxDialog: null,
  51. /**
  52. * @var syntaxHiglighter Reference to the codemirror editor
  53. */
  54. syntaxHiglighter: null,
  55. /**
  56. * @var buttonOptions Object containing options for
  57. * the jQueryUI dialog buttons
  58. */
  59. buttonOptions: {},
  60. /**
  61. * Validate editor form fields.
  62. */
  63. validate: function () {
  64. /**
  65. * @var $elm a jQuery object containing the reference
  66. * to an element that is being validated
  67. */
  68. var $elm = null;
  69. // Common validation. At the very least the name
  70. // and the definition must be provided for an item
  71. $elm = $('table.rte_table').last().find('input[name=item_name]');
  72. if ($elm.val() === '') {
  73. $elm.focus();
  74. alert(PMA_messages.strFormEmpty);
  75. return false;
  76. }
  77. $elm = $('table.rte_table').find('textarea[name=item_definition]');
  78. if ($elm.val() === '') {
  79. if (this.syntaxHiglighter !== null) {
  80. this.syntaxHiglighter.focus();
  81. }
  82. else {
  83. $('textarea[name=item_definition]').last().focus();
  84. }
  85. alert(PMA_messages.strFormEmpty);
  86. return false;
  87. }
  88. // The validation has so far passed, so now
  89. // we can validate item-specific fields.
  90. return this.validateCustom();
  91. }, // end validate()
  92. /**
  93. * Validate custom editor form fields.
  94. * This function can be overridden by
  95. * other files in this folder
  96. */
  97. validateCustom: function () {
  98. return true;
  99. }, // end validateCustom()
  100. /**
  101. * Execute some code after the ajax
  102. * dialog for the editor is shown.
  103. * This function can be overridden by
  104. * other files in this folder
  105. */
  106. postDialogShow: function () {
  107. // Nothing by default
  108. }, // end postDialogShow()
  109. exportDialog: function ($this) {
  110. var $msg = PMA_ajaxShowMessage();
  111. // Fire the ajax request straight away
  112. $.get($this.attr('href'), {'ajax_request': true}, function (data) {
  113. if (data.success === true) {
  114. PMA_ajaxRemoveMessage($msg);
  115. /**
  116. * @var button_options Object containing options
  117. * for jQueryUI dialog buttons
  118. */
  119. var button_options = {};
  120. button_options[PMA_messages.strClose] = function () {
  121. $(this).dialog("close").remove();
  122. };
  123. /**
  124. * Display the dialog to the user
  125. */
  126. var $ajaxDialog = $('<div>' + data.message + '</div>').dialog({
  127. width: 500,
  128. buttons: button_options,
  129. title: data.title
  130. });
  131. // Attach syntax highlighted editor to export dialog
  132. /**
  133. * @var $elm jQuery object containing the reference
  134. * to the Export textarea.
  135. */
  136. var $elm = $ajaxDialog.find('textarea');
  137. /**
  138. * @var opts Options to pass to the codemirror editor
  139. */
  140. var opts = {
  141. lineNumbers: true,
  142. matchBrackets: true,
  143. indentUnit: 4,
  144. mode: "text/x-mysql",
  145. lineWrapping: true
  146. };
  147. CodeMirror.fromTextArea($elm[0], opts);
  148. } else {
  149. PMA_ajaxShowMessage(data.error, false);
  150. }
  151. }); // end $.get()
  152. }, // end exportDialog()
  153. editorDialog: function (is_new, $this) {
  154. var that = this;
  155. /**
  156. * @var $edit_row jQuery object containing the reference to
  157. * the row of the the item being edited
  158. * from the list of items
  159. */
  160. var $edit_row = null;
  161. if ($this.hasClass('edit_anchor')) {
  162. // Remeber the row of the item being edited for later,
  163. // so that if the edit is successful, we can replace the
  164. // row with info about the modified item.
  165. $edit_row = $this.parents('tr');
  166. }
  167. /**
  168. * @var $msg jQuery object containing the reference to
  169. * the AJAX message shown to the user
  170. */
  171. var $msg = PMA_ajaxShowMessage();
  172. $.get($this.attr('href'), {'ajax_request': true}, function (data) {
  173. if (data.success === true) {
  174. // We have successfully fetched the editor form
  175. PMA_ajaxRemoveMessage($msg);
  176. // Now define the function that is called when
  177. // the user presses the "Go" button
  178. that.buttonOptions[PMA_messages.strGo] = function () {
  179. // Move the data from the codemirror editor back to the
  180. // textarea, where it can be used in the form submission.
  181. if (typeof CodeMirror != 'undefined') {
  182. that.syntaxHiglighter.save();
  183. }
  184. // Validate editor and submit request, if passed.
  185. if (that.validate()) {
  186. /**
  187. * @var data Form data to be sent in the AJAX request
  188. */
  189. var data = $('form.rte_form').last().serialize();
  190. $msg = PMA_ajaxShowMessage(
  191. PMA_messages.strProcessingRequest
  192. );
  193. var url = $('form.rte_form').last().attr('action');
  194. $.post(url, data, function (data) {
  195. if (data.success === true) {
  196. // Item created successfully
  197. PMA_ajaxRemoveMessage($msg);
  198. PMA_slidingMessage(data.message);
  199. that.$ajaxDialog.dialog('close');
  200. // If we are in 'edit' mode, we must
  201. // remove the reference to the old row.
  202. if (mode === 'edit' && $edit_row !== null ) {
  203. $edit_row.remove();
  204. }
  205. // Sometimes, like when moving a trigger from
  206. // a table to another one, the new row should
  207. // not be inserted into the list. In this case
  208. // "data.insert" will be set to false.
  209. if (data.insert) {
  210. // Insert the new row at the correct
  211. // location in the list of items
  212. /**
  213. * @var text Contains the name of an item from
  214. * the list that is used in comparisons
  215. * to find the correct location where
  216. * to insert a new row.
  217. */
  218. var text = '';
  219. /**
  220. * @var inserted Whether a new item has been
  221. * inserted in the list or not
  222. */
  223. var inserted = false;
  224. $('table.data').find('tr').each(function () {
  225. text = $(this)
  226. .children('td')
  227. .eq(0)
  228. .find('strong')
  229. .text()
  230. .toUpperCase();
  231. text = $.trim(text);
  232. if (text !== '' && text > data.name) {
  233. $(this).before(data.new_row);
  234. inserted = true;
  235. return false;
  236. }
  237. });
  238. if (! inserted) {
  239. // If we didn't manage to insert the row yet,
  240. // it must belong at the end of the list,
  241. // so we insert it there.
  242. $('table.data').append(data.new_row);
  243. }
  244. // Fade-in the new row
  245. $('tr.ajaxInsert')
  246. .show('slow')
  247. .removeClass('ajaxInsert');
  248. } else if ($('table.data').find('tr').has('td').length === 0) {
  249. // If we are not supposed to insert the new row,
  250. // we will now check if the table is empty and
  251. // needs to be hidden. This will be the case if
  252. // we were editing the only item in the list,
  253. // which we removed and will not be inserting
  254. // something else in its place.
  255. $('table.data').hide("slow", function () {
  256. $('#nothing2display').show("slow");
  257. });
  258. }
  259. // Now we have inserted the row at the correct
  260. // position, but surely at least some row classes
  261. // are wrong now. So we will itirate throught
  262. // all rows and assign correct classes to them
  263. /**
  264. * @var ct Count of processed rows
  265. */
  266. var ct = 0;
  267. /**
  268. * @var rowclass Class to be attached to the row
  269. * that is being processed
  270. */
  271. var rowclass = '';
  272. $('table.data').find('tr').has('td').each(function () {
  273. rowclass = (ct % 2 === 0) ? 'odd' : 'even';
  274. $(this).removeClass().addClass(rowclass);
  275. ct++;
  276. });
  277. // If this is the first item being added, remove
  278. // the "No items" message and show the list.
  279. if ($('table.data').find('tr').has('td').length > 0 &&
  280. $('#nothing2display').is(':visible')
  281. ) {
  282. $('#nothing2display').hide("slow", function () {
  283. $('table.data').show("slow");
  284. });
  285. }
  286. PMA_reloadNavigation();
  287. } else {
  288. PMA_ajaxShowMessage(data.error, false);
  289. }
  290. }); // end $.post()
  291. } // end "if (that.validate())"
  292. }; // end of function that handles the submission of the Editor
  293. that.buttonOptions[PMA_messages.strClose] = function () {
  294. $(this).dialog("close");
  295. };
  296. /**
  297. * Display the dialog to the user
  298. */
  299. that.$ajaxDialog = $('<div>' + data.message + '</div>').dialog({
  300. width: 700,
  301. minWidth: 500,
  302. buttons: that.buttonOptions,
  303. title: data.title,
  304. modal: true,
  305. open: function () {
  306. $(this).find('input[name=item_name]').focus();
  307. $(this).find('input.datefield').each(function () {
  308. PMA_addDatepicker($(this).css('width', '95%'), 'date');
  309. });
  310. $(this).find('input.datetimefield').each(function () {
  311. PMA_addDatepicker($(this).css('width', '95%'), 'datetime');
  312. });
  313. $.datepicker.initialized = false;
  314. },
  315. close: function () {
  316. $(this).remove();
  317. }
  318. });
  319. /**
  320. * @var mode Used to remeber whether the editor is in
  321. * "Edit" or "Add" mode
  322. */
  323. var mode = 'add';
  324. if ($('input[name=editor_process_edit]').length > 0) {
  325. mode = 'edit';
  326. }
  327. // Attach syntax highlighted editor to the definition
  328. /**
  329. * @var elm jQuery object containing the reference to
  330. * the Definition textarea.
  331. */
  332. var $elm = $('textarea[name=item_definition]').last();
  333. /**
  334. * @var opts Options to pass to the codemirror editor
  335. */
  336. var opts = {
  337. lineNumbers: true,
  338. matchBrackets: true,
  339. indentUnit: 4,
  340. mode: "text/x-mysql",
  341. lineWrapping: true
  342. };
  343. if (typeof CodeMirror != 'undefined') {
  344. that.syntaxHiglighter = CodeMirror.fromTextArea($elm[0], opts);
  345. }
  346. // Execute item-specific code
  347. that.postDialogShow(data);
  348. } else {
  349. PMA_ajaxShowMessage(data.error, false);
  350. }
  351. }); // end $.get()
  352. },
  353. dropDialog: function ($this) {
  354. /**
  355. * @var $curr_row Object containing reference to the current row
  356. */
  357. var $curr_row = $this.parents('tr');
  358. /**
  359. * @var question String containing the question to be asked for confirmation
  360. */
  361. var question = $('<div/>').text(
  362. $curr_row.children('td').children('.drop_sql').html()
  363. );
  364. // We ask for confirmation first here, before submitting the ajax request
  365. $this.PMA_confirm(question, $this.attr('href'), function (url) {
  366. /**
  367. * @var msg jQuery object containing the reference to
  368. * the AJAX message shown to the user
  369. */
  370. var $msg = PMA_ajaxShowMessage(PMA_messages.strProcessingRequest);
  371. $.get(url, {'is_js_confirmed': 1, 'ajax_request': true}, function (data) {
  372. if (data.success === true) {
  373. /**
  374. * @var $table Object containing reference
  375. * to the main list of elements
  376. */
  377. var $table = $curr_row.parent();
  378. // Check how many rows will be left after we remove
  379. // the one that the user has requested us to remove
  380. if ($table.find('tr').length === 3) {
  381. // If there are two rows left, it means that they are
  382. // the header of the table and the rows that we are
  383. // about to remove, so after the removal there will be
  384. // nothing to show in the table, so we hide it.
  385. $table.hide("slow", function () {
  386. $(this).find('tr.even, tr.odd').remove();
  387. $('#nothing2display').show("slow");
  388. });
  389. } else {
  390. $curr_row.hide("slow", function () {
  391. $(this).remove();
  392. // Now we have removed the row from the list, but maybe
  393. // some row classes are wrong now. So we will itirate
  394. // throught all rows and assign correct classes to them.
  395. /**
  396. * @var ct Count of processed rows
  397. */
  398. var ct = 0;
  399. /**
  400. * @var rowclass Class to be attached to the row
  401. * that is being processed
  402. */
  403. var rowclass = '';
  404. $table.find('tr').has('td').each(function () {
  405. rowclass = (ct % 2 === 0) ? 'odd' : 'even';
  406. $(this).removeClass().addClass(rowclass);
  407. ct++;
  408. });
  409. });
  410. }
  411. // Get rid of the "Loading" message
  412. PMA_ajaxRemoveMessage($msg);
  413. // Show the query that we just executed
  414. PMA_slidingMessage(data.sql_query);
  415. PMA_reloadNavigation();
  416. } else {
  417. PMA_ajaxShowMessage(data.error, false);
  418. }
  419. }); // end $.get()
  420. }); // end $.PMA_confirm()
  421. }
  422. }; // end RTE namespace
  423. /**
  424. * @var RTE.EVENT JavaScript functionality for events
  425. */
  426. RTE.EVENT = {
  427. validateCustom: function () {
  428. /**
  429. * @var elm a jQuery object containing the reference
  430. * to an element that is being validated
  431. */
  432. var $elm = null;
  433. if (this.$ajaxDialog.find('select[name=item_type]').find(':selected').val() === 'RECURRING') {
  434. // The interval field must not be empty for recurring events
  435. $elm = this.$ajaxDialog.find('input[name=item_interval_value]');
  436. if ($elm.val() === '') {
  437. $elm.focus();
  438. alert(PMA_messages.strFormEmpty);
  439. return false;
  440. }
  441. } else {
  442. // The execute_at field must not be empty for "once off" events
  443. $elm = this.$ajaxDialog.find('input[name=item_execute_at]');
  444. if ($elm.val() === '') {
  445. $elm.focus();
  446. alert(PMA_messages.strFormEmpty);
  447. return false;
  448. }
  449. }
  450. return true;
  451. }
  452. };
  453. /**
  454. * @var RTE.ROUTINE JavaScript functionality for routines
  455. */
  456. RTE.ROUTINE = {
  457. /**
  458. * Overriding the postDialogShow() function defined in common.js
  459. *
  460. * @param data JSON-encoded data from the ajax request
  461. */
  462. postDialogShow: function (data) {
  463. // Cache the template for a parameter table row
  464. RTE.param_template = data.param_template;
  465. var that = this;
  466. // Make adjustments in the dialog to make it AJAX compatible
  467. $('td.routine_param_remove').show();
  468. $('input[name=routine_removeparameter]').remove();
  469. $('input[name=routine_addparameter]').css('width', '100%');
  470. // Enable/disable the 'options' dropdowns for parameters as necessary
  471. $('table.routine_params_table').last().find('th[colspan=2]').attr('colspan', '1');
  472. $('table.routine_params_table').last().find('tr').has('td').each(function () {
  473. that.setOptionsForParameter(
  474. $(this).find('select[name^=item_param_type]'),
  475. $(this).find('input[name^=item_param_length]'),
  476. $(this).find('select[name^=item_param_opts_text]'),
  477. $(this).find('select[name^=item_param_opts_num]')
  478. );
  479. });
  480. // Enable/disable the 'options' dropdowns for
  481. // function return value as necessary
  482. this.setOptionsForParameter(
  483. $('table.rte_table').last().find('select[name=item_returntype]'),
  484. $('table.rte_table').last().find('input[name=item_returnlength]'),
  485. $('table.rte_table').last().find('select[name=item_returnopts_text]'),
  486. $('table.rte_table').last().find('select[name=item_returnopts_num]')
  487. );
  488. },
  489. /**
  490. * Overriding the validateCustom() function defined in common.js
  491. */
  492. validateCustom: function () {
  493. /**
  494. * @var isSuccess Stores the outcome of the validation
  495. */
  496. var isSuccess = true;
  497. /**
  498. * @var inputname The value of the "name" attribute for
  499. * the field that is being processed
  500. */
  501. var inputname = '';
  502. this.$ajaxDialog.find('table.routine_params_table').last().find('tr').each(function () {
  503. // Every parameter of a routine must have
  504. // a non-empty direction, name and type
  505. if (isSuccess) {
  506. $(this).find(':input').each(function () {
  507. inputname = $(this).attr('name');
  508. if (inputname.substr(0, 14) === 'item_param_dir' ||
  509. inputname.substr(0, 15) === 'item_param_name' ||
  510. inputname.substr(0, 15) === 'item_param_type') {
  511. if ($(this).val() === '') {
  512. $(this).focus();
  513. isSuccess = false;
  514. return false;
  515. }
  516. }
  517. });
  518. } else {
  519. return false;
  520. }
  521. });
  522. if (! isSuccess) {
  523. alert(PMA_messages.strFormEmpty);
  524. return false;
  525. }
  526. this.$ajaxDialog.find('table.routine_params_table').last().find('tr').each(function () {
  527. // SET, ENUM, VARCHAR and VARBINARY fields must have length/values
  528. var $inputtyp = $(this).find('select[name^=item_param_type]');
  529. var $inputlen = $(this).find('input[name^=item_param_length]');
  530. if ($inputtyp.length && $inputlen.length) {
  531. if (($inputtyp.val() === 'ENUM' || $inputtyp.val() === 'SET' || $inputtyp.val().substr(0, 3) === 'VAR') &&
  532. $inputlen.val() === ''
  533. ) {
  534. $inputlen.focus();
  535. isSuccess = false;
  536. return false;
  537. }
  538. }
  539. });
  540. if (! isSuccess) {
  541. alert(PMA_messages.strFormEmpty);
  542. return false;
  543. }
  544. if (this.$ajaxDialog.find('select[name=item_type]').find(':selected').val() === 'FUNCTION') {
  545. // The length/values of return variable for functions must
  546. // be set, if the type is SET, ENUM, VARCHAR or VARBINARY.
  547. var $returntyp = this.$ajaxDialog.find('select[name=item_returntype]');
  548. var $returnlen = this.$ajaxDialog.find('input[name=item_returnlength]');
  549. if (($returntyp.val() === 'ENUM' || $returntyp.val() === 'SET' || $returntyp.val().substr(0, 3) === 'VAR') &&
  550. $returnlen.val() === ''
  551. ) {
  552. $returnlen.focus();
  553. alert(PMA_messages.strFormEmpty);
  554. return false;
  555. }
  556. }
  557. if ($('select[name=item_type]').find(':selected').val() === 'FUNCTION') {
  558. // A function must contain a RETURN statement in its definition
  559. if (this.$ajaxDialog.find('table.rte_table').find('textarea[name=item_definition]').val().toUpperCase().indexOf('RETURN') < 0) {
  560. this.syntaxHiglighter.focus();
  561. alert(PMA_messages.MissingReturn);
  562. return false;
  563. }
  564. }
  565. return true;
  566. },
  567. /**
  568. * Enable/disable the "options" dropdown and "length" input for
  569. * parameters and the return variable in the routine editor
  570. * as necessary.
  571. *
  572. * @param type a jQuery object containing the reference
  573. * to the "Type" dropdown box
  574. * @param len a jQuery object containing the reference
  575. * to the "Length" input box
  576. * @param text a jQuery object containing the reference
  577. * to the dropdown box with options for
  578. * parameters of text type
  579. * @param num a jQuery object containing the reference
  580. * to the dropdown box with options for
  581. * parameters of numeric type
  582. */
  583. setOptionsForParameter: function ($type, $len, $text, $num) {
  584. /**
  585. * @var no_opts a jQuery object containing the reference
  586. * to an element to be displayed when no
  587. * options are available
  588. */
  589. var $no_opts = $text.parent().parent().find('.no_opts');
  590. /**
  591. * @var no_len a jQuery object containing the reference
  592. * to an element to be displayed when no
  593. * "length/values" field is available
  594. */
  595. var $no_len = $len.parent().parent().find('.no_len');
  596. // Process for parameter options
  597. switch ($type.val()) {
  598. case 'TINYINT':
  599. case 'SMALLINT':
  600. case 'MEDIUMINT':
  601. case 'INT':
  602. case 'BIGINT':
  603. case 'DECIMAL':
  604. case 'FLOAT':
  605. case 'DOUBLE':
  606. case 'REAL':
  607. $text.parent().hide();
  608. $num.parent().show();
  609. $no_opts.hide();
  610. break;
  611. case 'TINYTEXT':
  612. case 'TEXT':
  613. case 'MEDIUMTEXT':
  614. case 'LONGTEXT':
  615. case 'CHAR':
  616. case 'VARCHAR':
  617. case 'SET':
  618. case 'ENUM':
  619. $text.parent().show();
  620. $num.parent().hide();
  621. $no_opts.hide();
  622. break;
  623. default:
  624. $text.parent().hide();
  625. $num.parent().hide();
  626. $no_opts.show();
  627. break;
  628. }
  629. // Process for parameter length
  630. switch ($type.val()) {
  631. case 'DATE':
  632. case 'DATETIME':
  633. case 'TIME':
  634. case 'TINYBLOB':
  635. case 'TINYTEXT':
  636. case 'BLOB':
  637. case 'TEXT':
  638. case 'MEDIUMBLOB':
  639. case 'MEDIUMTEXT':
  640. case 'LONGBLOB':
  641. case 'LONGTEXT':
  642. $text.closest('tr').find('a:first').hide();
  643. $len.parent().hide();
  644. $no_len.show();
  645. break;
  646. default:
  647. if ($type.val() == 'ENUM' || $type.val() == 'SET') {
  648. $text.closest('tr').find('a:first').show();
  649. } else {
  650. $text.closest('tr').find('a:first').hide();
  651. }
  652. $len.parent().show();
  653. $no_len.hide();
  654. break;
  655. }
  656. },
  657. executeDialog: function ($this) {
  658. var that = this;
  659. /**
  660. * @var msg jQuery object containing the reference to
  661. * the AJAX message shown to the user
  662. */
  663. var $msg = PMA_ajaxShowMessage();
  664. $.get($this.attr('href'), {'ajax_request': true}, function (data) {
  665. if (data.success === true) {
  666. PMA_ajaxRemoveMessage($msg);
  667. // If 'data.dialog' is true we show a dialog with a form
  668. // to get the input parameters for routine, otherwise
  669. // we just show the results of the query
  670. if (data.dialog) {
  671. // Define the function that is called when
  672. // the user presses the "Go" button
  673. that.buttonOptions[PMA_messages.strGo] = function () {
  674. /**
  675. * @var data Form data to be sent in the AJAX request
  676. */
  677. var data = $('form.rte_form').last().serialize();
  678. $msg = PMA_ajaxShowMessage(
  679. PMA_messages.strProcessingRequest
  680. );
  681. $.post('db_routines.php', data, function (data) {
  682. if (data.success === true) {
  683. // Routine executed successfully
  684. PMA_ajaxRemoveMessage($msg);
  685. PMA_slidingMessage(data.message);
  686. $ajaxDialog.dialog('close');
  687. } else {
  688. PMA_ajaxShowMessage(data.error, false);
  689. }
  690. });
  691. };
  692. that.buttonOptions[PMA_messages.strClose] = function () {
  693. $(this).dialog("close");
  694. };
  695. /**
  696. * Display the dialog to the user
  697. */
  698. $ajaxDialog = $('<div>' + data.message + '</div>').dialog({
  699. width: 650,
  700. buttons: that.buttonOptions,
  701. title: data.title,
  702. modal: true,
  703. close: function () {
  704. $(this).remove();
  705. }
  706. });
  707. $ajaxDialog.find('input[name^=params]').first().focus();
  708. /**
  709. * Attach the datepickers to the relevant form fields
  710. */
  711. $ajaxDialog.find('input.datefield, input.datetimefield').each(function () {
  712. PMA_addDatepicker($(this).css('width', '95%'));
  713. });
  714. /*
  715. * Define the function if the user presses enter
  716. */
  717. $('form.rte_form').on('keyup', function (event) {
  718. event.preventDefault();
  719. if (event.keyCode === 13) {
  720. /**
  721. * @var data Form data to be sent in the AJAX request
  722. */
  723. var data = $(this).serialize();
  724. $msg = PMA_ajaxShowMessage(
  725. PMA_messages.strProcessingRequest
  726. );
  727. var url = $(this).attr('action');
  728. $.post(url, data, function (data) {
  729. if (data.success === true) {
  730. // Routine executed successfully
  731. PMA_ajaxRemoveMessage($msg);
  732. PMA_slidingMessage(data.message);
  733. $('form.rte_form').off('keyup');
  734. $ajaxDialog.remove();
  735. } else {
  736. PMA_ajaxShowMessage(data.error, false);
  737. }
  738. });
  739. }
  740. });
  741. } else {
  742. // Routine executed successfully
  743. PMA_slidingMessage(data.message);
  744. }
  745. } else {
  746. PMA_ajaxShowMessage(data.error, false);
  747. }
  748. }); // end $.get()
  749. }
  750. };
  751. /**
  752. * Attach Ajax event handlers for the Routines, Triggers and Events editor
  753. */
  754. $(function () {
  755. /**
  756. * Attach Ajax event handlers for the Add/Edit functionality.
  757. */
  758. $('a.ajax.add_anchor, a.ajax.edit_anchor').live('click', function (event) {
  759. event.preventDefault();
  760. var type = $(this).attr('href').substr(0, $(this).attr('href').indexOf('?'));
  761. if (type.indexOf('routine') != -1) {
  762. type = 'routine';
  763. } else if (type.indexOf('trigger') != -1) {
  764. type = 'trigger';
  765. } else if (type.indexOf('event') != -1) {
  766. type = 'event';
  767. } else {
  768. type = '';
  769. }
  770. var dialog = new RTE.object(type);
  771. dialog.editorDialog($(this).hasClass('add_anchor'), $(this));
  772. }); // end $.live()
  773. /**
  774. * Attach Ajax event handlers for the Execute routine functionality
  775. */
  776. $('a.ajax.exec_anchor').live('click', function (event) {
  777. event.preventDefault();
  778. var dialog = new RTE.object('routine');
  779. dialog.executeDialog($(this));
  780. }); // end $.live()
  781. /**
  782. * Attach Ajax event handlers for Export of Routines, Triggers and Events
  783. */
  784. $('a.ajax.export_anchor').live('click', function (event) {
  785. event.preventDefault();
  786. var dialog = new RTE.object();
  787. dialog.exportDialog($(this));
  788. }); // end $.live()
  789. /**
  790. * Attach Ajax event handlers for Drop functionality
  791. * of Routines, Triggers and Events.
  792. */
  793. $('a.ajax.drop_anchor').live('click', function (event) {
  794. event.preventDefault();
  795. var dialog = new RTE.object();
  796. dialog.dropDialog($(this));
  797. }); // end $.live()
  798. /**
  799. * Attach Ajax event handlers for the "Change event/routine type"
  800. * functionality in the events editor, so that the correct
  801. * rows are shown in the editor when changing the event type
  802. */
  803. $('select[name=item_type]').live('change', function () {
  804. $(this)
  805. .closest('table')
  806. .find('tr.recurring_event_row, tr.onetime_event_row, tr.routine_return_row, td.routine_direction_cell')
  807. .toggle();
  808. }); // end $.live()
  809. /**
  810. * Attach Ajax event handlers for the "Change parameter type"
  811. * functionality in the routines editor, so that the correct
  812. * option/length fields, if any, are shown when changing
  813. * a parameter type
  814. */
  815. $('select[name^=item_param_type]').live('change', function () {
  816. /**
  817. * @var row jQuery object containing the reference to
  818. * a row in the routine parameters table
  819. */
  820. var $row = $(this).parents('tr').first();
  821. var rte = new RTE.object('routine');
  822. rte.setOptionsForParameter(
  823. $row.find('select[name^=item_param_type]'),
  824. $row.find('input[name^=item_param_length]'),
  825. $row.find('select[name^=item_param_opts_text]'),
  826. $row.find('select[name^=item_param_opts_num]')
  827. );
  828. }); // end $.live()
  829. /**
  830. * Attach Ajax event handlers for the "Change the type of return
  831. * variable of function" functionality, so that the correct fields,
  832. * if any, are shown when changing the function return type type
  833. */
  834. $('select[name=item_returntype]').live('change', function () {
  835. var rte = new RTE.object('routine');
  836. var $table = $(this).closest('table.rte_table');
  837. rte.setOptionsForParameter(
  838. $table.find('select[name=item_returntype]'),
  839. $table.find('input[name=item_returnlength]'),
  840. $table.find('select[name=item_returnopts_text]'),
  841. $table.find('select[name=item_returnopts_num]')
  842. );
  843. }); // end $.live()
  844. /**
  845. * Attach Ajax event handlers for the "Add parameter to routine" functionality
  846. */
  847. $('input[name=routine_addparameter]').live('click', function (event) {
  848. event.preventDefault();
  849. /**
  850. * @var routine_params_table jQuery object containing the reference
  851. * to the routine parameters table
  852. */
  853. var $routine_params_table = $(this).closest('div.ui-dialog').find('.routine_params_table');
  854. /**
  855. * @var new_param_row A string containing the HTML code for the
  856. * new row for the routine parameters table
  857. */
  858. var new_param_row = RTE.param_template.replace(/%s/g, $routine_params_table.find('tr').length - 1);
  859. // Append the new row to the parameters table
  860. $routine_params_table.append(new_param_row);
  861. // Make sure that the row is correctly shown according to the type of routine
  862. if ($(this).closest('div.ui-dialog').find('table.rte_table select[name=item_type]').val() === 'FUNCTION') {
  863. $('tr.routine_return_row').show();
  864. $('td.routine_direction_cell').hide();
  865. }
  866. /**
  867. * @var newrow jQuery object containing the reference to the newly
  868. * inserted row in the routine parameters table
  869. */
  870. var $newrow = $(this).closest('div.ui-dialog').find('table.routine_params_table').find('tr').has('td').last();
  871. // Enable/disable the 'options' dropdowns for parameters as necessary
  872. var rte = new RTE.object('routine');
  873. rte.setOptionsForParameter(
  874. $newrow.find('select[name^=item_param_type]'),
  875. $newrow.find('input[name^=item_param_length]'),
  876. $newrow.find('select[name^=item_param_opts_text]'),
  877. $newrow.find('select[name^=item_param_opts_num]')
  878. );
  879. }); // end $.live()
  880. /**
  881. * Attach Ajax event handlers for the
  882. * "Remove parameter from routine" functionality
  883. */
  884. $('a.routine_param_remove_anchor').live('click', function (event) {
  885. event.preventDefault();
  886. $(this).parent().parent().remove();
  887. // After removing a parameter, the indices of the name attributes in
  888. // the input fields lose the correct order and need to be reordered.
  889. /**
  890. * @var index Counter used for reindexing the input
  891. * fields in the routine parameters table
  892. */
  893. var index = 0;
  894. $(this).closest('div.ui-dialog').find('table.routine_params_table').find('tr').has('td').each(function () {
  895. $(this).find(':input').each(function () {
  896. /**
  897. * @var inputname The value of the name attribute of
  898. * the input field being reindexed
  899. */
  900. var inputname = $(this).attr('name');
  901. if (inputname.substr(0, 14) === 'item_param_dir') {
  902. $(this).attr('name', inputname.substr(0, 14) + '[' + index + ']');
  903. } else if (inputname.substr(0, 15) === 'item_param_name') {
  904. $(this).attr('name', inputname.substr(0, 15) + '[' + index + ']');
  905. } else if (inputname.substr(0, 15) === 'item_param_type') {
  906. $(this).attr('name', inputname.substr(0, 15) + '[' + index + ']');
  907. } else if (inputname.substr(0, 17) === 'item_param_length') {
  908. $(this).attr('name', inputname.substr(0, 17) + '[' + index + ']');
  909. $(this).attr('id', 'item_param_length_' + index);
  910. } else if (inputname.substr(0, 20) === 'item_param_opts_text') {
  911. $(this).attr('name', inputname.substr(0, 20) + '[' + index + ']');
  912. } else if (inputname.substr(0, 19) === 'item_param_opts_num') {
  913. $(this).attr('name', inputname.substr(0, 19) + '[' + index + ']');
  914. }
  915. });
  916. index++;
  917. });
  918. }); // end $.live()
  919. }); // end of $()