diff --git a/ChangeLog b/ChangeLog index 4ae25e9a61..0889f7bc5d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -33,6 +33,11 @@ phpMyAdmin - ChangeLog + Shift/click support in database Structure + Show/hide column in table Browse - bug #3353856 [AJAX] AJAX dialogs use wrong font-size +- bug #3354356 [interface] Timepicker does not work in AJAX dialogs ++ AJAX for table Structure Indexes Edit ++ AJAX for table Structure column Change ++ [interface] Improved support for events ++ [interface] Improved support for triggers 3.4.4.0 (not yet released) - bug #3323060 [parser] SQL parser breaks AJAX requests if query has unclosed quotes @@ -42,6 +47,7 @@ phpMyAdmin - ChangeLog - bug #3353649 [interface] "Create an index on X columns" form not validated - bug #3350790 [interface] JS error in Table->Structure->Index->Edit - bug #3353811 [interface] Info message has "error" class +- bug #3357837 [interface] TABbing through a NULL field in the inline mode resets NULL 3.4.3.1 (2011-07-02) - [security] Fixed possible session manipulation in swekey authentication, see PMASA-2011-5 diff --git a/Documentation.html b/Documentation.html index 29054a28ba..6a8d5dcd16 100644 --- a/Documentation.html +++ b/Documentation.html @@ -2143,7 +2143,7 @@ setfacl -d -m "g:www-data:rwx" tmp identify what they mean. -
$cfg['ShowDisplayDir'] boolean
+
$cfg['ShowDisplayDirection'] boolean
Defines whether or not type display direction option is shown when browsing a table. @@ -2392,23 +2392,6 @@ setfacl -d -m "g:www-data:rwx" tmp first_timestamp, which is used for first timestamp column in table.
-
$cfg['NumOperators'] array
-
Operators available for search operations on numeric and date columns. -
- -
$cfg['TextOperators'] array
-
Operators available for search operations on character columns. - Note that we put LIKE by default instead of - LIKE %...%, to avoid unintended performance problems - in case of huge tables.
- -
$cfg['EnumOperators'] array
-
Operators available for search operations on ENUM columns.
- -
$cfg['NullOperators'] array
-
Additional operators available for search operations when the - column can be null.
- diff --git a/db_events.php b/db_events.php index 7d22f5d8c5..f65960770a 100644 --- a/db_events.php +++ b/db_events.php @@ -1,40 +1,33 @@ diff --git a/db_routines.php b/db_routines.php index b9417fdc18..efac9ea380 100644 --- a/db_routines.php +++ b/db_routines.php @@ -11,440 +11,25 @@ */ require_once './libraries/common.inc.php'; require_once './libraries/common.lib.php'; -require_once './libraries/db_routines.lib.php'; require_once './libraries/mysql_charsets.lib.php'; +require_once './libraries/data_mysql.inc.php'; /** * Include JavaScript libraries */ $GLOBALS['js_include'][] = 'jquery/jquery-ui-1.8.custom.js'; $GLOBALS['js_include'][] = 'jquery/timepicker.js'; -$GLOBALS['js_include'][] = 'db_routines.js'; +$GLOBALS['js_include'][] = 'rte/common.js'; +$GLOBALS['js_include'][] = 'rte/routines.js'; /** - * Create labels for the list + * Include all other files */ -$titles = PMA_buildActionTitles(); - -if ($GLOBALS['is_ajax_request'] != true) { - /** - * Displays the header - */ - require_once './libraries/db_common.inc.php'; - /** - * Displays the tabs - */ - require_once './libraries/db_info.inc.php'; -} else { - if (strlen($db)) { - PMA_DBI_select_db($db); - if (! isset($url_query)) { - $url_query = PMA_generate_common_url($db); - } - } -} +require_once './libraries/rte/rte_routines.lib.php'; /** - * Process all requests + * Do the magic */ - -// Some definitions -$param_directions = array('IN', - 'OUT', - 'INOUT'); -$param_opts_num = array('UNSIGNED', - 'ZEROFILL', - 'UNSIGNED ZEROFILL'); -$param_sqldataaccess = array('NO SQL', - 'CONTAINS SQL', - 'READS SQL DATA', - 'MODIFIES SQL DATA'); - -/** - * Generate the conditional classes that will be used to attach jQuery events to links. - */ -$ajax_class = array( - 'add' => '', - 'edit' => '', - 'exec' => '', - 'drop' => '', - 'export' => '' - ); -if ($GLOBALS['cfg']['AjaxEnable']) { - $ajax_class['add'] = 'class="add_routine_anchor"'; - $ajax_class['edit'] = 'class="edit_routine_anchor"'; - $ajax_class['exec'] = 'class="exec_routine_anchor"'; - $ajax_class['drop'] = 'class="drop_routine_anchor"'; - $ajax_class['export'] = 'class="export_routine_anchor"'; -} - -/** - * Keep a list of errors that occured while processing an 'Add' or 'Edit' operation. - */ -$routine_errors = array(); - -/** - * Handle all user requests other than the default of listing routines - */ -if (! empty($_REQUEST['execute_routine']) && ! empty($_REQUEST['routine_name'])) { - // Build the queries - $routine = PMA_RTN_getRoutineDataFromName($db, $_REQUEST['routine_name'], false); - if ($routine !== false) { - $queries = array(); - $end_query = array(); - $args = array(); - for ($i=0; $i<$routine['num_params']; $i++) { - if (isset($_REQUEST['params'][$routine['param_name'][$i]])) { - $value = $_REQUEST['params'][$routine['param_name'][$i]]; - if (is_array($value)) { // is SET type - $value = implode(',', $value); - } - $value = PMA_sqlAddSlashes($value); - if (! empty($_REQUEST['funcs'][$routine['param_name'][$i]]) - && in_array($_REQUEST['funcs'][$routine['param_name'][$i]], $cfg['Functions'])) { - $queries[] = "SET @p$i={$_REQUEST['funcs'][$routine['param_name'][$i]]}('$value');\n"; - } else { - $queries[] = "SET @p$i='$value';\n"; - } - $args[] = "@p$i"; - } else { - $args[] = "@p$i"; - } - if ($routine['type'] == 'PROCEDURE') { - if ($routine['param_dir'][$i] == 'OUT' || $routine['param_dir'][$i] == 'INOUT') { - $end_query[] = "@p$i AS " . PMA_backquote($routine['param_name'][$i]); - } - } - } - if ($routine['type'] == 'PROCEDURE') { - $queries[] = "CALL " . PMA_backquote($routine['name']) - . "(" . implode(', ', $args) . ");\n"; - if (count($end_query)) { - $queries[] = "SELECT " . implode(', ', $end_query) . ";\n"; - } - } else { - $queries[] = "SELECT " . PMA_backquote($routine['name']) - . "(" . implode(', ', $args) . ") " - . "AS " . PMA_backquote($routine['name']) . ";\n"; - } - // Execute the queries - $affected = 0; - $result = null; - $outcome = true; - foreach ($queries as $num => $query) { - $resource = PMA_DBI_try_query($query); - if ($resource === false) { - $outcome = false; - break; - } - while (true) { - if(! PMA_DBI_more_results()) { - break; - } - PMA_DBI_next_result(); - } - if (substr($query, 0, 6) == 'SELECT') { - $result = $resource; - } else if (substr($query, 0, 4) == 'CALL') { - $affected = PMA_DBI_affected_rows() - PMA_DBI_num_rows($resource); - } - } - // Generate output - if ($outcome) { - $message = __('Your SQL query has been executed successfully'); - if ($routine['type'] == 'PROCEDURE') { - $message .= '
'; - $message .= sprintf(_ngettext('%d row affected by the last statement inside the procedure', '%d rows affected by the last statement inside the procedure', $affected), $affected); - } - $message = PMA_message::success($message); - // Pass the SQL queries through the "pretty printer" - $output = ''; - $output .= PMA_SQP_formatHtml(PMA_SQP_parse(implode($queries))); - $output .= ''; - // Display results - if ($result) { - $output .= "
"; - $output .= sprintf(__('Execution results of routine %s'), - PMA_backquote(htmlspecialchars($routine['name']))); - $output .= ""; - $output .= ""; - foreach (PMA_DBI_get_fields_meta($result) as $key => $field) { - $output .= ""; - } - $output .= ""; - // Stored routines can only ever return ONE ROW. - $data = PMA_DBI_fetch_single_row($result); - foreach ($data as $key => $value) { - if ($value === null) { - $value = 'NULL'; - } else { - $value = htmlspecialchars($value); - } - $output .= ""; - } - $output .= "
" . htmlspecialchars($field->name) . "
" . $value . "
"; - } else { - $notice = __('MySQL returned an empty result set (i.e. zero rows).'); - $output .= PMA_message::notice($notice)->getDisplay(); - } - } else { - $output = ''; - $message = PMA_message::error(sprintf(__('The following query has failed: "%s"'), $query) . '

' - . __('MySQL said: ') . PMA_DBI_getError(null)); - } - // Print/send output - if ($GLOBALS['is_ajax_request']) { - $extra_data = array('dialog' => false); - PMA_ajaxResponse($message->getDisplay() . $output, $message->isSuccess(), $extra_data); - } else { - echo $message->getDisplay() . $output; - if ($message->isError()) { - // At least one query has failed, so shouldn't - // execute any more queries, so we quit. - exit; - } - unset($_POST); - // Now deliberately fall through to displaying the routines list - } - } else { - $message = __('Error in processing request') . ' : ' - . sprintf(__('No routine with name %1$s found in database %2$s'), - htmlspecialchars(PMA_backquote($_REQUEST['routine_name'])), - htmlspecialchars(PMA_backquote($db))); - $message = PMA_message::error($message); - if ($GLOBALS['is_ajax_request']) { - PMA_ajaxResponse($message, $message->isSuccess()); - } else { - echo $message->getDisplay(); - unset($_POST); - } - } -} else if (! empty($_GET['execute_dialog']) && ! empty($_GET['routine_name'])) { - /** - * Display the execute form for a routine. - */ - $routine = PMA_RTN_getRoutineDataFromName($db, $_GET['routine_name'], false); - if ($routine !== false) { - $form = PMA_RTN_getExecuteForm($routine, $GLOBALS['is_ajax_request']); - if ($GLOBALS['is_ajax_request'] == true) { - $extra_data = array(); - $extra_data['dialog'] = true; - $extra_data['title'] = __("Execute routine") . " "; - $extra_data['title'] .= PMA_backquote(htmlentities($_GET['routine_name'], ENT_QUOTES)); - PMA_ajaxResponse($form, true, $extra_data); - } else { - echo "\n\n

" . __("Execute routine") . "

\n\n"; - echo $form; - require './libraries/footer.inc.php'; - // exit; - } - } else if (($GLOBALS['is_ajax_request'] == true)) { - $message = __('Error in processing request') . ' : ' - . sprintf(__('No routine with name %1$s found in database %2$s'), - htmlspecialchars(PMA_backquote($_REQUEST['routine_name'])), - htmlspecialchars(PMA_backquote($db))); - $message = PMA_message::error($message); - PMA_ajaxResponse($message, false); - } -} else if (! empty($_GET['exportroutine']) && ! empty($_GET['routine_name'])) { - /** - * Display the export for a routine. - */ - $routine_name = htmlspecialchars(PMA_backquote($_GET['routine_name'])); - $routine_type = PMA_DBI_fetch_value("SELECT ROUTINE_TYPE " - . "FROM INFORMATION_SCHEMA.ROUTINES " - . "WHERE ROUTINE_SCHEMA='" . PMA_sqlAddSlashes($db) . "' " - . "AND SPECIFIC_NAME='" . PMA_sqlAddSlashes($_GET['routine_name']) . "';"); - if (! empty($routine_type) && $create_proc = PMA_DBI_get_definition($db, $routine_type, $_GET['routine_name'])) { - $create_proc = ''; - if ($GLOBALS['is_ajax_request']) { - $extra_data = array('title' => sprintf(__('Export of routine %s'), $routine_name)); - PMA_ajaxResponse($create_proc, true, $extra_data); - } else { - echo '
' . "\n" - . ' ' . sprintf(__('Export of routine %s'), $routine_name) . '' . "\n" - . $create_proc . "\n" - . '
'; - } - } else { - $response = __('Error in processing request') . ' : ' - . sprintf(__('No routine with name %1$s found in database %2$s'), - $routine_name, htmlspecialchars(PMA_backquote($db))); - $response = PMA_message::error($response); - if ($GLOBALS['is_ajax_request']) { - PMA_ajaxResponse($response, false); - } else { - $response->display(); - } - } -} else if (! empty($_REQUEST['routine_process_addroutine']) || ! empty($_REQUEST['routine_process_editroutine'])) { - /** - * Handle a request to create/edit a routine - */ - $sql_query = ''; - $routine_query = PMA_RTN_getQueryFromRequest(); - if (! count($routine_errors)) { // set by PMA_RTN_getQueryFromRequest() - // Execute the created query - if (! empty($_REQUEST['routine_process_editroutine'])) { - if (! in_array($_REQUEST['routine_original_type'], array('PROCEDURE', 'FUNCTION'))) { - $routine_errors[] = sprintf(__('Invalid routine type: "%s"'), htmlspecialchars($_REQUEST['routine_original_type'])); - } else { - // Backup the old routine, in case something goes wrong - $create_routine = PMA_DBI_get_definition($db, $_REQUEST['routine_original_type'], $_REQUEST['routine_original_name']); - $drop_routine = "DROP {$_REQUEST['routine_original_type']} " . PMA_backquote($_REQUEST['routine_original_name']) . ";\n"; - $result = PMA_DBI_try_query($drop_routine); - if (! $result) { - $routine_errors[] = sprintf(__('The following query has failed: "%s"'), $drop_routine) . '
' - . __('MySQL said: ') . PMA_DBI_getError(null); - } else { - $result = PMA_DBI_try_query($routine_query); - if (! $result) { - $routine_errors[] = sprintf(__('The following query has failed: "%s"'), $routine_query) . '
' - . __('MySQL said: ') . PMA_DBI_getError(null); - // We dropped the old routine, but were unable to create the new one - // Try to restore the backup query - $result = PMA_DBI_try_query($create_routine); - if (! $result) { - // OMG, this is really bad! We dropped the query, failed to create a new one - // and now even the backup query does not execute! - // This should not happen, but we better handle this just in case. - $routine_errors[] = __('Sorry, we failed to restore the dropped routine.') . '
' - . __('The backed up query was:') . "\"$create_routine\"" . '
' - . __('MySQL said: ') . PMA_DBI_getError(null); - } - } else { - $message = PMA_Message::success(__('Routine %1$s has been modified.')); - $message->addParam(PMA_backquote($_REQUEST['routine_name'])); - $sql_query = $drop_routine . $routine_query; - } - } - } - } else { - // 'Add a new routine' mode - $result = PMA_DBI_try_query($routine_query); - if (! $result) { - $routine_errors[] = sprintf(__('The following query has failed: "%s"'), $routine_query) . '

' - . __('MySQL said: ') . PMA_DBI_getError(null); - } else { - $message = PMA_Message::success(__('Routine %1$s has been created.')); - $message->addParam(PMA_backquote($_REQUEST['routine_name'])); - $sql_query = $routine_query; - } - } - } - - if (count($routine_errors)) { - $message = PMA_Message::error(__('One or more errors have occured while processing your request:')); - $message->addString(''); - } - - $output = PMA_showMessage($message, $sql_query); - if ($GLOBALS['is_ajax_request']) { - $extra_data = array(); - if ($message->isSuccess()) { - $columns = "`SPECIFIC_NAME`, `ROUTINE_NAME`, `ROUTINE_TYPE`, `DTD_IDENTIFIER`, `ROUTINE_DEFINITION`"; - $where = "ROUTINE_SCHEMA='" . PMA_sqlAddSlashes($db) . "' AND ROUTINE_NAME='" . PMA_sqlAddSlashes($_REQUEST['routine_name']) . "'"; - $routine = PMA_DBI_fetch_single_row("SELECT $columns FROM `INFORMATION_SCHEMA`.`ROUTINES` WHERE $where;"); - $extra_data['name'] = htmlspecialchars(strtoupper($_REQUEST['routine_name'])); - $extra_data['new_row'] = PMA_RTN_getRowForRoutinesList($routine, 0, true); - $response = $output; - } else { - $response = $message; - } - PMA_ajaxResponse($response, $message->isSuccess(), $extra_data); - } -} - -/** - * Display a form used to add/edit a routine, if necessary - */ -if (count($routine_errors) || ( empty($_REQUEST['routine_process_addroutine']) && empty($_REQUEST['routine_process_editroutine']) && - (! empty($_REQUEST['addroutine']) || ! empty($_REQUEST['editroutine']) - || ! empty($_REQUEST['routine_addparameter']) || ! empty($_REQUEST['routine_removeparameter']) - || ! empty($_REQUEST['routine_changetype'])))) { // FIXME: this must be simpler than that - // Handle requests to add/remove parameters and changing routine type - // This is necessary when JS is disabled - $operation = ''; - if (! empty($_REQUEST['routine_addparameter'])) { - $operation = 'add'; - } else if (! empty($_REQUEST['routine_removeparameter'])) { - $operation = 'remove'; - } else if (! empty($_REQUEST['routine_changetype'])) { - $operation = 'change'; - } - // Get the data for the form (if any) - if (! empty($_REQUEST['addroutine'])) { - $title = __("Create routine"); - $routine = PMA_RTN_getRoutineDataFromRequest(); - $mode = 'add'; - } else if (! empty($_REQUEST['editroutine'])) { - $title = __("Edit routine"); - if (! $operation && ! empty($_REQUEST['routine_name']) && empty($_REQUEST['routine_process_editroutine'])) { - $routine = PMA_RTN_getRoutineDataFromName($db, $_REQUEST['routine_name']); - if ($routine !== false) { - $routine['original_name'] = $routine['name']; - $routine['original_type'] = $routine['type']; - } - } else { - $routine = PMA_RTN_getRoutineDataFromRequest(); - } - $mode = 'edit'; - } - if ($routine !== false) { - // Show form - $editor = PMA_RTN_getEditorForm($mode, $operation, $routine, $routine_errors, $GLOBALS['is_ajax_request']); - if ($GLOBALS['is_ajax_request']) { - $template = PMA_RTN_getParameterRow(); - $extra_data = array('title' => $title, 'param_template' => $template, 'type' => $routine['type']); - PMA_ajaxResponse($editor, true, $extra_data); - } - echo "\n\n

$title

\n\n$editor"; - require './libraries/footer.inc.php'; - // exit; - } else { - $message = __('Error in processing request') . ' : ' - . sprintf(__('No routine with name %1$s found in database %2$s'), - htmlspecialchars(PMA_backquote($_REQUEST['routine_name'])), - htmlspecialchars(PMA_backquote($db))); - $message = PMA_message::error($message); - if ($GLOBALS['is_ajax_request']) { - PMA_ajaxResponse($message, false); - } else { - $message->display(); - } - } -} - -/** - * Display a list of available routines - */ -echo PMA_RTN_getRoutinesList(); - -/** - * Display the form for adding a new routine, if the user has the privileges. - */ -echo PMA_RTN_getAddRoutineLink(); - -/** - * Display a warning for users with PHP's old "mysql" extension. - */ -if ($GLOBALS['cfg']['Server']['extension'] === 'mysql') { - trigger_error(__('You are using PHP\'s deprecated \'mysql\' extension, ' - . 'which is not capable of handling multi queries. ' - . 'The execution of some stored routines may fail! ' - . 'Please use the improved \'mysqli\' extension to ' - . 'avoid any problems.'), E_USER_WARNING); -} - -if ($GLOBALS['is_ajax_request'] != true) { - /** - * Displays the footer - */ - require './libraries/footer.inc.php'; -} +require_once './libraries/rte/rte_main.inc.php'; ?> diff --git a/db_structure.php b/db_structure.php index 0054585bb4..000ab6afbf 100644 --- a/db_structure.php +++ b/db_structure.php @@ -13,6 +13,7 @@ require_once './libraries/common.inc.php'; $GLOBALS['js_include'][] = 'jquery/jquery-ui-1.8.custom.js'; $GLOBALS['js_include'][] = 'db_structure.js'; $GLOBALS['js_include'][] = 'tbl_change.js'; +$GLOBALS['js_include'][] = 'jquery/timepicker.js'; /** * Prepares the tables list if the user where not redirected to this script diff --git a/db_triggers.php b/db_triggers.php index 416be77c15..1bd792ec41 100644 --- a/db_triggers.php +++ b/db_triggers.php @@ -1,38 +1,32 @@ diff --git a/export.php b/export.php index 9471ba0c15..6137b96e7c 100644 --- a/export.php +++ b/export.php @@ -125,8 +125,7 @@ $time_start = time(); * Output handler for all exports, if needed buffering, it stores data into * $dump_buffer, otherwise it prints thems out. * - * @param string the insert statement - * + * @param string $line the insert statement * @return bool Whether output suceeded */ function PMA_exportOutputHandler($line) @@ -512,7 +511,7 @@ if ($export_type == 'server') { } if (function_exists('PMA_exportRoutines') && strpos($GLOBALS['sql_structure_or_data'], 'structure') !== false && isset($GLOBALS['sql_procedure_function'])) { - PMA_exportRoutines($db); + PMA_exportRoutines($db); } $i = 0; diff --git a/js/common.js b/js/common.js index b3e996c022..b595108f83 100644 --- a/js/common.js +++ b/js/common.js @@ -14,78 +14,6 @@ var querywindow = ''; */ var query_to_load = ''; -/** - * attach a function to object event - * - * - * addEvent(window, 'load', PMA_initPage); - * - * @param object or id - * @param string event type (load, mouseover, focus, ...) - * @param function to be attached - */ -function addEvent(obj, type, fn) -{ - if (obj.attachEvent) { - obj['e' + type + fn] = fn; - obj[type + fn] = function() {obj['e' + type + fn](window.event);} - obj.attachEvent('on' + type, obj[type + fn]); - } else { - obj.addEventListener(type, fn, false); - } -} - -/** - * detach/remove a function from an object event - * - * @param object or id - * @param event type (load, mouseover, focus, ...) - * @param function naem of function to be attached - */ -function removeEvent(obj, type, fn) -{ - if (obj.detachEvent) { - obj.detachEvent('on' + type, obj[type + fn]); - obj[type + fn] = null; - } else { - obj.removeEventListener(type, fn, false); - } -} - -/** - * get DOM elements by html class - * - * @param string class_name - name of class - * @param node node - search only sub nodes of this node (optional) - * @param string tag - search only these tags (optional) - */ -function getElementsByClassName(class_name, node, tag) -{ - var classElements = new Array(); - - if (node == null) { - node = document; - } - if (tag == null) { - tag = '*'; - } - - var j = 0, teststr; - var els = node.getElementsByTagName(tag); - var elsLen = els.length; - - for (i = 0; i < elsLen; i++) { - if (els[i].className.indexOf(class_name) != -1) { - teststr = "," + els[i].className.split(" ").join(",") + ","; - if (teststr.indexOf("," + class_name + ",") != -1) { - classElements[j] = els[i]; - j++; - } - } - } - return classElements; -} - /** * sets current selected db * diff --git a/js/db_structure.js b/js/db_structure.js index ad55341b60..b1c2ff05a7 100644 --- a/js/db_structure.js +++ b/js/db_structure.js @@ -61,12 +61,12 @@ $(document).ready(function() { $("td.insert_table a.ajax").live('click', function(event){ event.preventDefault(); currrent_insert_table = $(this); - var url = $(this).attr("href"); - if (url.substring(0, 15) == "tbl_change.php?") { - url = url.substring(15); + var $url = $(this).attr("href"); + if ($url.substring(0, 15) == "tbl_change.php?") { + $url = $url.substring(15); } - var div = $('
'); + var $div = $('
'); var target = "tbl_change.php"; /** @@ -75,38 +75,43 @@ $(document).ready(function() { */ var button_options = {}; // in the following function we need to use $(this) - button_options[PMA_messages['strCancel']] = function() {$(this).parent().dialog('close').remove();} + button_options[PMA_messages['strCancel']] = function() {$(this).dialog('close').remove();} var button_options_error = {}; - button_options_error[PMA_messages['strOK']] = function() {$(this).parent().dialog('close').remove();} + button_options_error[PMA_messages['strOK']] = function() {$(this).dialog('close').remove();} var $msgbox = PMA_ajaxShowMessage(); - $.get( target , url+"&ajax_request=true" , function(data) { + $.get( target , $url+"&ajax_request=true" , function(data) { //in the case of an error, show the error message returned. if (data.success != undefined && data.success == false) { - div + $div .append(data.error) .dialog({ title: PMA_messages['strInsertTable'], height: 230, width: 900, + modal: true, open: PMA_verifyTypeOfAllColumns, buttons : button_options_error })// end dialog options } else { - div - .append(data) - .dialog({ - title: PMA_messages['strInsertTable'], - height: 600, - width: 900, - open: PMA_verifyTypeOfAllColumns, - buttons : button_options - }) + var $dialog = $div + .append(data) + .dialog({ + title: PMA_messages['strInsertTable'], + height: 600, + width: 900, + modal: true, + open: PMA_verifyTypeOfAllColumns, + buttons : button_options + });// end dialog options //Remove the top menu container from the dialog - .find("#topmenucontainer").hide() - ; // end dialog options + $dialog.find("#topmenucontainer").hide(); + //Adding the datetime pikers for the dialog + $dialog.find('.datefield, .datetimefield').each(function () { + PMA_addDatepicker($(this)); + }); $(".insertRowTable").addClass("ajax"); $("#buttonYes").addClass("ajax"); } diff --git a/js/functions.js b/js/functions.js index 1841caf0ad..cbdef19dea 100644 --- a/js/functions.js +++ b/js/functions.js @@ -1827,6 +1827,76 @@ $(document).ready(function() { }, 'top.frame_content'); //end $(document).ready for 'Create Table' +/** + * jQuery coding for 'Change Table'. Used on tbl_structure.php * + * Attach Ajax Event handlers for Change Table + */ +$(document).ready(function() { + /** + *Ajax action for submitting the column change form + **/ + $("#append_fields_form input[name=do_save_data]").live('click', function(event) { + event.preventDefault(); + /** + * @var the_form object referring to the export form + */ + var $form = $("#append_fields_form"); + + /* + * First validate the form; if there is a problem, avoid submitting it + * + * checkTableEditForm() needs a pure element and not a jQuery object, + * this is why we pass $form[0] as a parameter (the jQuery object + * is actually an array of DOM elements) + */ + if (checkTableEditForm($form[0], $form.find('input[name=orig_num_fields]').val())) { + // OK, form passed validation step + if ($form.hasClass('ajax')) { + PMA_prepareForAjaxRequest($form); + //User wants to submit the form + $.post($form.attr('action'), $form.serialize()+"&do_save_data=Save", function(data) { + if ($("#sqlqueryresults").length != 0) { + $("#sqlqueryresults").remove(); + } else if ($(".error").length != 0) { + $(".error").remove(); + } + if (data.success == true) { + PMA_ajaxShowMessage(data.message); + $("
").insertAfter("#topmenucontainer"); + $("#sqlqueryresults").html(data.sql_query); + $("#result_query .notice").remove(); + $("#result_query").prepend((data.message)); + if ($("#change_column_dialog").length > 0) { + $("#change_column_dialog").dialog("close").remove(); + } + /*Reload the field form*/ + $.post($("#fieldsForm").attr('action'), $("#fieldsForm").serialize()+"&ajax_request=true", function(form_data) { + $("#fieldsForm").remove(); + var $temp_div = $("
").append(form_data); + if ($("#sqlqueryresults").length != 0) { + $temp_div.find("#fieldsForm").insertAfter("#sqlqueryresults"); + } else { + $temp_div.find("#fieldsForm").insertAfter(".error"); + } + /*Call the function to display the more options in table*/ + displayMoreTableOpts(); + }); + } else { + var $temp_div = $("
").append(data); + var $error = $temp_div.find(".error code").addClass("error"); + PMA_ajaxShowMessage($error); + } + }) // end $.post() + } else { + // non-Ajax submit + $form.append(''); + $form.submit(); + } + } + }) // end change table button "do_save_data" + +}, 'top.frame_content'); //end $(document).ready for 'Change Table' + /** * Attach Ajax event handlers for Drop Database. Moved here from db_structure.js * as it was also required on db_create.php @@ -2163,9 +2233,45 @@ function displayMoreTableOpts() { } }); } + } $(document).ready(initTooltips); +/** + * Ensures indexes names are valid according to their type and, for a primary + * key, lock index name to 'PRIMARY' + * @param string form_id Variable which parses the form name as + * the input + * @return boolean false if there is no index form, true else + */ +function checkIndexName(form_id) +{ + if ($("#"+form_id).length == 0) { + return false; + } + + // Gets the elements pointers + var $the_idx_name = $("#input_index_name"); + var $the_idx_type = $("#select_index_type"); + + // Index is a primary key + if ($the_idx_type.find("option:selected").attr("value") == 'PRIMARY') { + $the_idx_name.attr("value", 'PRIMARY'); + $the_idx_name.attr("disabled", true); + } + + // Other cases + else { + if ($the_idx_name.attr("value") == 'PRIMARY') { + $the_idx_name.attr("value", ''); + } + $the_idx_name.attr("disabled", false); + } + + return true; +} // end of the 'checkIndexName()' function + + /* Displays tooltips */ function initTooltips() { // Hide the footnotes from the footer (which are displayed for @@ -2294,7 +2400,7 @@ $(function() { * Get the row number from the classlist (for example, row_1) */ function PMA_getRowNumber(classlist) { - return parseInt(classlist.split(/row_/)[1]); + return parseInt(classlist.split(/\s+row_/)[1]); } /** @@ -2330,6 +2436,136 @@ function PMA_init_slider() { }); } +/** + * var toggleButton This is a function that creates a toggle + * sliding button given a jQuery reference + * to the correct DOM element + */ +var toggleButton = function ($obj) { + // In rtl mode the toggle switch is flipped horizontally + // so we need to take that into account + if ($('.text_direction', $obj).text() == 'ltr') { + var right = 'right'; + } else { + var right = 'left'; + } + /** + * var h Height of the button, used to scale the + * background image and position the layers + */ + var h = $obj.height(); + $('img', $obj).height(h); + $('table', $obj).css('bottom', h-1); + /** + * var on Width of the "ON" part of the toggle switch + * var off Width of the "OFF" part of the toggle switch + */ + var on = $('.toggleOn', $obj).width(); + var off = $('.toggleOff', $obj).width(); + // Make the "ON" and "OFF" parts of the switch the same size + $('.toggleOn > div', $obj).width(Math.max(on, off)); + $('.toggleOff > div', $obj).width(Math.max(on, off)); + /** + * var w Width of the central part of the switch + */ + var w = parseInt(($('img', $obj).height() / 16) * 22, 10); + // Resize the central part of the switch on the top + // layer to match the background + $('table td:nth-child(2) > div', $obj).width(w); + /** + * var imgw Width of the background image + * var tblw Width of the foreground layer + * var offset By how many pixels to move the background + * image, so that it matches the top layer + */ + var imgw = $('img', $obj).width(); + var tblw = $('table', $obj).width(); + var offset = parseInt(((imgw - tblw) / 2), 10); + // Move the background to match the layout of the top layer + $obj.find('img').css(right, offset); + /** + * var offw Outer width of the "ON" part of the toggle switch + * var btnw Outer width of the central part of the switch + */ + var offw = $('.toggleOff', $obj).outerWidth(); + var btnw = $('table td:nth-child(2)', $obj).outerWidth(); + // Resize the main div so that exactly one side of + // the switch plus the central part fit into it. + $obj.width(offw + btnw + 2); + /** + * var move How many pixels to move the + * switch by when toggling + */ + var move = $('.toggleOff', $obj).outerWidth(); + // If the switch is initialized to the + // OFF state we need to move it now. + if ($('.container', $obj).hasClass('off')) { + if (right == 'right') { + $('table, img', $obj).animate({'left': '-=' + move + 'px'}, 0); + } else { + $('table, img', $obj).animate({'left': '+=' + move + 'px'}, 0); + } + } + // Attach an 'onclick' event to the switch + $('.container', $obj).click(function () { + if ($(this).hasClass('isActive')) { + return false; + } else { + $(this).addClass('isActive'); + } + var $msg = PMA_ajaxShowMessage(PMA_messages['strLoading']); + var $container = $(this); + var callback = $('.callback', this).text(); + // Perform the actual toggle + if ($(this).hasClass('on')) { + if (right == 'right') { + var operator = '-='; + } else { + var operator = '+='; + } + var url = $(this).find('.toggleOff > span').text(); + var removeClass = 'on'; + var addClass = 'off'; + } else { + if (right == 'right') { + var operator = '+='; + } else { + var operator = '-='; + } + var url = $(this).find('.toggleOn > span').text(); + var removeClass = 'off'; + var addClass = 'on'; + } + $.post(url, {'ajax_request': true}, function(data) { + if(data.success == true) { + PMA_ajaxRemoveMessage($msg); + $container + .removeClass(removeClass) + .addClass(addClass) + .animate({'left': operator + move + 'px'}, function () { + $container.removeClass('isActive'); + }); + eval(callback); + } else { + PMA_ajaxShowMessage(data.error); + $container.removeClass('isActive'); + } + }); + }); +}; + +/** + * Initialise all toggle buttons + */ +$(window).load(function () { + $('.toggleAjax').each(function () { + $(this) + .show() + .find('.toggleButton') + toggleButton($(this)); + }); +}); + /** * Vertical pointer */ @@ -2457,44 +2693,6 @@ $(document).ready(function() { }) // end of $(document).ready() -/** - * Attach Ajax event handlers for Export of Routines, Triggers and Events. - * - * @uses PMA_ajaxShowMessage() - * @uses PMA_ajaxRemoveMessage() - * - * @see $cfg['AjaxEnable'] - */ -$(document).ready(function() { - $('.export_routine_anchor, .export_trigger_anchor, .export_event_anchor').live('click', function(event) { - event.preventDefault(); - var $msg = PMA_ajaxShowMessage(PMA_messages['strLoading']); - $.get($(this).attr('href'), {'ajax_request': true}, function(data) { - if(data.success == true) { - PMA_ajaxRemoveMessage($msg); - /** - * @var button_options Object containing options for jQueryUI dialog buttons - */ - var button_options = {}; - button_options[PMA_messages['strClose']] = function() {$(this).dialog("close").remove();} - /** - * Display the dialog to the user - */ - var $ajaxDialog = $('
'+data.message+'
').dialog({ - width: 500, - buttons: button_options, - title: data.title - }); - // Attach syntax highlited editor to export dialog - var elm = $ajaxDialog.find('textarea'); - CodeMirror.fromTextArea(elm[0], {lineNumbers: true, matchBrackets: true, indentUnit: 4, mode: "text/x-mysql"}); - } else { - PMA_ajaxShowMessage(data.error); - } - }) // end $.get() - }); // end $.live() -}); // end of $(document).ready() for Export of Routines, Triggers and Events. - /** * Creates a message inside an object with a sliding effect * @@ -2572,69 +2770,6 @@ function PMA_slidingMessage(msg, $obj) { return true; } // end PMA_slidingMessage() -/** - * Attach Ajax event handlers for Drop functionality of Routines, Triggers and Events. - * - * @uses $.PMA_confirm() - * @uses PMA_ajaxShowMessage() - * @see $cfg['AjaxEnable'] - */ -$(document).ready(function() { - $('.drop_routine_anchor, .drop_trigger_anchor, .drop_event_anchor').live('click', function(event) { - event.preventDefault(); - /** - * @var $curr_row Object containing reference to the current row - */ - var $curr_row = $(this).parents('tr'); - /** - * @var question String containing the question to be asked for confirmation - */ - var question = $('
').text($curr_row.children('td').children('.drop_sql').html()); - $(this).PMA_confirm(question, $(this).attr('href'), function(url) { - /** - * @var $msg jQuery object containing the reference to - * the AJAX message shown to the user. - */ - var $msg = PMA_ajaxShowMessage(PMA_messages['strProcessingRequest']); - $.get(url, {'is_js_confirmed': 1, 'ajax_request': true}, function(data) { - if(data.success == true) { - /** - * @var $table Object containing reference to the main list of elements. - */ - var $table = $curr_row.parent(); - if ($table.find('tr').length == 2) { - $table.hide("slow", function () { - $(this).find('tr.even, tr.odd').remove(); - $('#nothing2display').show("slow"); - }); - } else { - $curr_row.hide("slow", function () { - $(this).remove(); - // Now we have removed the row from the list, but maybe - // some row classes are wrong now. So we will itirate - // throught all rows and assign correct classes to them. - /** - * @var ct Count of processed rows. - */ - var ct = 0; - $table.find('tr').has('td').each(function() { - rowclass = (ct % 2 == 0) ? 'even' : 'odd'; - $(this).removeClass().addClass(rowclass); - ct++; - }); - }); - } - // Show the query that we just executed - PMA_ajaxRemoveMessage($msg); - PMA_slidingMessage(data.sql_query); - } else { - PMA_ajaxShowMessage(PMA_messages['strErrorProcessingRequest'] + " : " + data.error); - } - }) // end $.get() - }) // end $.PMA_confirm() - }); // end $.live() -}); //end $(document).ready() for Drop functionality of Routines, Triggers and Events. - /** * Attach Ajax event handlers for Drop Table. * diff --git a/js/indexes.js b/js/indexes.js index ef6f877bdd..abbf4d8b49 100644 --- a/js/indexes.js +++ b/js/indexes.js @@ -4,45 +4,6 @@ * */ -/** - * Ensures indexes names are valid according to their type and, for a primary - * key, lock index name to 'PRIMARY' - * - * @return boolean false if there is no index form, true else - */ -function checkIndexName() -{ - if (typeof(document.forms['index_frm']) == 'undefined') { - return false; - } - - // Gets the elements pointers - var the_idx_name = document.forms['index_frm'].elements['index[Key_name]']; - var the_idx_type = document.forms['index_frm'].elements['index[Index_type]']; - - // Index is a primary key - if (the_idx_type.options[0].value == 'PRIMARY' && the_idx_type.options[0].selected) { - document.forms['index_frm'].elements['index[Key_name]'].value = 'PRIMARY'; - if (typeof(the_idx_name.disabled) != 'undefined') { - document.forms['index_frm'].elements['index[Key_name]'].disabled = true; - } - } - - // Other cases - else { - if (the_idx_name.value == 'PRIMARY') { - document.forms['index_frm'].elements['index[Key_name]'].value = ''; - } - if (typeof(the_idx_name.disabled) != 'undefined') { - document.forms['index_frm'].elements['index[Key_name]'].disabled = false; - } - } - - return true; -} // end of the 'checkIndexName()' function - -onload = checkIndexName; - /** * Hides/shows the inputs and submits appropriately depending * on whether the index type chosen is 'SPATIAL' or not. @@ -56,7 +17,7 @@ function checkIndexType() /** * @var Object Table header for the size column. */ - $size_header = $('thead tr th:nth-child(2)'); + $size_header = $('#index_columns thead tr th:nth-child(2)'); /** * @var Object Inputs to specify the columns for the index. */ @@ -132,7 +93,12 @@ function checkIndexType() */ $(document).ready(function() { checkIndexType(); - $('#select_index_type').bind('change', checkIndexType); + checkIndexName("index_frm"); + $('#select_index_type').live('change', function(event){ + event.preventDefault(); + checkIndexType(); + checkIndexName("index_frm"); + }); }); /**#@- */ diff --git a/js/makegrid.js b/js/makegrid.js index 8b1bd7cd0d..970ed595ef 100644 --- a/js/makegrid.js +++ b/js/makegrid.js @@ -6,7 +6,6 @@ minColWidth: 15, // variables, assigned with default value, changed later - alignment: 'horizontal', // 3 possibilities: vertical, horizontal, horizontalflipped actionSpan: 5, colOrder: new Array(), // array of column order colVisib: new Array(), // array of column visibility @@ -32,9 +31,7 @@ n: n, obj: obj, objLeft: $(obj).position().left, - objWidth: this.alignment != 'vertical' ? - $(this.t).find('th.draggable:visible:eq(' + n + ') span').outerWidth() : - $(this.t).find('tr:first td:eq(' + n + ') span').outerWidth() + objWidth: $(this.t).find('th.draggable:visible:eq(' + n + ') span').outerWidth() }; $('body').css('cursor', 'col-resize'); $('body').noSelect(); @@ -44,27 +41,15 @@ // prepare the cCpy and cPointer from the dragged column $(this.cCpy).text($(obj).text()); var objPos = $(obj).position(); - if (this.alignment != 'vertical') { - $(this.cCpy).css({ - top: objPos.top + 20, - left: objPos.left, - height: $(obj).height(), - width: $(obj).width() - }); - $(this.cPointer).css({ - top: objPos.top - }); - } else { // vertical alignment - $(this.cCpy).css({ - top: objPos.top, - left: objPos.left + 30, - height: $(obj).height(), - width: $(obj).width() - }); - $(this.cPointer).css({ - top: objPos.top - }); - } + $(this.cCpy).css({ + top: objPos.top + 20, + left: objPos.left, + height: $(obj).height(), + width: $(obj).width() + }); + $(this.cPointer).css({ + top: objPos.top + }); // get the column index, zero-based var n = this.getHeaderIdx(obj); @@ -90,17 +75,10 @@ $(this.colRsz.obj).css('left', this.colRsz.objLeft + dx + 'px'); } else if (this.colMov) { // dragged column animation - if (this.alignment != 'vertical') { - var dx = e.pageX - this.colMov.x0; - $(this.cCpy) - .css('left', this.colMov.objLeft + dx) - .show(); - } else { // vertical alignment - var dy = e.pageY - this.colMov.y0; - $(this.cCpy) - .css('top', this.colMov.objTop + dy) - .show(); - } + var dx = e.pageX - this.colMov.x0; + $(this.cCpy) + .css('left', this.colMov.objLeft + dx) + .show(); // pointer animation var hoveredCol = this.getHoveredCol(e); @@ -110,25 +88,14 @@ if (newn != this.colMov.n) { // show the column pointer in the right place var colPos = $(hoveredCol).position(); - if (this.alignment != 'vertical') { - var newleft = newn < this.colMov.n ? - colPos.left : - colPos.left + $(hoveredCol).outerWidth(); - $(this.cPointer) - .css({ - left: newleft, - visibility: 'visible' - }); - } else { // vertical alignment - var newtop = newn < this.colMov.n ? - colPos.top : - colPos.top + $(hoveredCol).outerHeight(); - $(this.cPointer) - .css({ - top: newtop, - visibility: 'visible' - }); - } + var newleft = newn < this.colMov.n ? + colPos.left : + colPos.left + $(hoveredCol).outerWidth(); + $(this.cPointer) + .css({ + left: newleft, + visibility: 'visible' + }); } else { // no movement to other column, hide the column pointer $(this.cPointer).css('visibility', 'hidden'); @@ -187,18 +154,11 @@ * Resize column n to new width "nw" */ resize: function(n, nw) { - if (this.alignment != 'vertical') { - $(this.t).find('tr').each(function() { - $(this).find('th.draggable:visible:eq(' + n + ') span,' + - 'td:visible:eq(' + (g.actionSpan + n) + ') span') - .css('width', nw); - }); - } else { // vertical alignment - $(this.t).find('tr').each(function() { - $(this).find('td:eq(' + n + ') span') - .css('width', nw); - }); - } + $(this.t).find('tr').each(function() { + $(this).find('th.draggable:visible:eq(' + n + ') span,' + + 'td:visible:eq(' + (g.actionSpan + n) + ') span') + .css('width', nw); + }); }, /** @@ -206,55 +166,43 @@ */ reposRsz: function() { $(this.cRsz).find('div').hide(); - $firstRowCols = this.alignment != 'vertical' ? - $(this.t).find('tr:first th.draggable:visible') : - $(this.t).find('tr:first td'); + $firstRowCols = $(this.t).find('tr:first th.draggable:visible'); for (var n = 0; n < $firstRowCols.length; n++) { $this = $($firstRowCols[n]); $cb = $(g.cRsz).find('div:eq(' + n + ')'); // column border $cb.css('left', $this.position().left + $this.outerWidth(true)) .show(); } + $(this.cRsz).css('height', $(this.t).height()); }, /** * Shift column from index oldn to newn. */ shiftCol: function(oldn, newn) { - if (this.alignment != 'vertical') { - $(this.t).find('tr').each(function() { - if (newn < oldn) { - $(this).find('th.draggable:eq(' + newn + '),' + - 'td:eq(' + (g.actionSpan + newn) + ')') - .before($(this).find('th.draggable:eq(' + oldn + '),' + - 'td:eq(' + (g.actionSpan + oldn) + ')')); - } else { - $(this).find('th.draggable:eq(' + newn + '),' + - 'td:eq(' + (g.actionSpan + newn) + ')') - .after($(this).find('th.draggable:eq(' + oldn + '),' + - 'td:eq(' + (g.actionSpan + oldn) + ')')); - } - }); - // reposition the column resize bars - this.reposRsz(); - - } else { // vertical alignment - // shift rows + $(this.t).find('tr').each(function() { if (newn < oldn) { - $(this.t).find('tr:eq(' + (g.actionSpan + newn) + ')') - .before($(this.t).find('tr:eq(' + (g.actionSpan + oldn) + ')')); + $(this).find('th.draggable:eq(' + newn + '),' + + 'td:eq(' + (g.actionSpan + newn) + ')') + .before($(this).find('th.draggable:eq(' + oldn + '),' + + 'td:eq(' + (g.actionSpan + oldn) + ')')); } else { - $(this.t).find('tr:eq(' + (g.actionSpan + newn) + ')') - .after($(this.t).find('tr:eq(' + (g.actionSpan + oldn) + ')')); + $(this).find('th.draggable:eq(' + newn + '),' + + 'td:eq(' + (g.actionSpan + newn) + ')') + .after($(this).find('th.draggable:eq(' + oldn + '),' + + 'td:eq(' + (g.actionSpan + oldn) + ')')); } - } + }); + // reposition the column resize bars + this.reposRsz(); + // adjust the column visibility list if (newn < oldn) { - $(g.cList).find('tr:eq(' + newn + ')') - .before($(g.cList).find('tr:eq(' + oldn + ')')); + $(g.cList).find('.lDiv div:eq(' + newn + ')') + .before($(g.cList).find('.lDiv div:eq(' + oldn + ')')); } else { - $(g.cList).find('tr:eq(' + newn + ')') - .after($(g.cList).find('tr:eq(' + oldn + ')')); + $(g.cList).find('.lDiv div:eq(' + newn + ')') + .after($(g.cList).find('.lDiv div:eq(' + oldn + ')')); } // adjust the colOrder var tmp = this.colOrder[oldn]; @@ -273,23 +221,13 @@ getHoveredCol: function(e) { var hoveredCol; $headers = $(this.t).find('th.draggable:visible'); - if (this.alignment != 'vertical') { - $headers.each(function() { - var left = $(this).offset().left; - var right = left + $(this).outerWidth(); - if (left <= e.pageX && e.pageX <= right) { - hoveredCol = this; - } - }); - } else { // vertical alignment - $headers.each(function() { - var top = $(this).offset().top; - var bottom = top + $(this).height(); - if (top <= e.pageY && e.pageY <= bottom) { - hoveredCol = this; - } - }); - } + $headers.each(function() { + var left = $(this).offset().left; + var right = left + $(this).outerWidth(); + if (left <= e.pageX && e.pageX <= right) { + hoveredCol = this; + } + }); return hoveredCol; }, @@ -297,15 +235,7 @@ * Get a zero-based index from a tag in a table. */ getHeaderIdx: function(obj) { - var n; - if (this.alignment != 'vertical') { - n = $(obj).parents('tr').find('th.draggable').index(obj); - } else { - var column_idx = $(obj).index(); - var $th_in_same_column = $(this.t).find('th.draggable:nth-child(' + (column_idx + 1) + ')'); - n = $th_in_same_column.index(obj); - } - return n; + return $(obj).parents('tr').find('th.draggable').index(obj); }, /** @@ -452,36 +382,26 @@ if (this.colVisib[n]) { // can hide if more than one column is visible if (this.visibleHeadersCount > 1) { - if (this.alignment != 'vertical') { - $(this.t).find('tr').each(function() { - $(this).find('th.draggable:eq(' + n + '),' + - 'td:eq(' + (g.actionSpan + n) + ')') - .hide(); - }); - } else { // vertical alignment - $(this.t).find('tr:eq(' + (g.actionSpan + n) + ')') - .hide(); - } - this.colVisib[n] = 0; - $(this.cList).find('tr:eq(' + n + ') input').removeAttr('checked'); - } else { - // cannot hide, force the checkbox to stay checked - $(this.cList).find('tr:eq(' + n + ') input').attr('checked', 'checked'); - return false; - } - } else { // column n is not visible - if (this.alignment != 'vertical') { $(this.t).find('tr').each(function() { $(this).find('th.draggable:eq(' + n + '),' + 'td:eq(' + (g.actionSpan + n) + ')') - .show(); + .hide(); }); - } else { // vertical alignment - $(this.t).find('tr:eq(' + (g.actionSpan + n) + ')') - .show(); + this.colVisib[n] = 0; + $(this.cList).find('.lDiv div:eq(' + n + ') input').removeAttr('checked'); + } else { + // cannot hide, force the checkbox to stay checked + $(this.cList).find('.lDiv div:eq(' + n + ') input').attr('checked', 'checked'); + return false; } + } else { // column n is not visible + $(this.t).find('tr').each(function() { + $(this).find('th.draggable:eq(' + n + '),' + + 'td:eq(' + (g.actionSpan + n) + ')') + .show(); + }); this.colVisib[n] = 1; - $(this.cList).find('tr:eq(' + n + ') input').attr('checked', 'checked'); + $(this.cList).find('.lDiv div:eq(' + n + ') input').attr('checked', 'checked'); } return true; }, @@ -499,9 +419,7 @@ this.sendColPrefs(); // check visible first row headers count - this.visibleHeadersCount = this.alignment != 'vertical' ? - $(this.t).find('tr:first th.draggable:visible').length : - $(this.t).find('th.draggable:nth-child(1):visible').length; + this.visibleHeadersCount = $(this.t).find('tr:first th.draggable:visible').length; this.refreshRestoreButton(); }, @@ -573,15 +491,12 @@ g.cDrop = document.createElement('div'); // column drop-down arrows g.cList = document.createElement('div'); // column visibility list - // assign the table alignment - g.alignment = $("#top_direction_dropdown").val(); - // adjust g.cCpy g.cCpy.className = 'cCpy'; $(g.cCpy).hide(); // adjust g.cPoint - g.cPointer.className = g.alignment != 'vertical' ? 'cPointer' : 'cPointerVer'; + g.cPointer.className = 'cPointer'; $(g.cPointer).css('visibility', 'hidden'); // adjust g.dHint @@ -600,23 +515,14 @@ g.t = t; // get first row data columns - var $firstRowCols = g.alignment != 'vertical' ? - $(t).find('tr:first th.draggable') : - $(t).find('tr:first td'); - - // get first row of data headers (first column of data headers, in vertical mode) - var $firstRowHeaders = g.alignment != 'vertical' ? - $(t).find('tr:first th.draggable') : - $(t).find('th.draggable:nth-child(1)'); + var $firstRowCols = $(t).find('tr:first th.draggable'); // initialize g.visibleHeadersCount - g.visibleHeadersCount = $firstRowHeaders.filter(':visible').length; + g.visibleHeadersCount = $firstRowCols.filter(':visible').length; // assign first column (actions) span if (! $(t).find('tr:first th:first').hasClass('draggable')) { // action header exist - g.actionSpan = g.alignment != 'vertical' ? - $(t).find('tr:first th:first').prop('colspan') : - $(t).find('tr:first th:first').prop('rowspan'); + g.actionSpan = $(t).find('tr:first th:first').prop('colspan'); } else { g.actionSpan = 0; } @@ -641,7 +547,7 @@ } } else { g.colOrder = new Array(); - for (var i = 0; i < $firstRowHeaders.length; i++) { + for (var i = 0; i < $firstRowCols.length; i++) { g.colOrder.push(i); } } @@ -655,12 +561,12 @@ } } else { g.colVisib = new Array(); - for (var i = 0; i < $firstRowHeaders.length; i++) { + for (var i = 0; i < $firstRowCols.length; i++) { g.colVisib.push(1); } } - if ($firstRowHeaders.length > 1) { + if ($firstRowCols.length > 1) { // create column drop-down arrow(s) $(t).find('th:not(.draggable)').each(function() { var cd = document.createElement('div'); // column drop-down arrow @@ -681,16 +587,16 @@ }); // add column visibility control - g.cList.innerHTML = '
'; - var $tbody = $(g.cList).find('tbody'); - for (var i = 0; i < $firstRowHeaders.length; i++) { - var currHeader = $firstRowHeaders[i]; - var tr = document.createElement('tr'); - $(tr).html('' + - '' + $(currHeader).text() + ''); - $tbody.append(tr); + g.cList.innerHTML = '
'; + var $listDiv = $(g.cList).find('div'); + for (var i = 0; i < $firstRowCols.length; i++) { + var currHeader = $firstRowCols[i]; + var listElmt = document.createElement('div'); + $(listElmt).text($(currHeader).text()) + .prepend(''); + $listDiv.append(listElmt); // add event on click - $(tr).click(function() { + $(listElmt).click(function() { if ( g.toggleCol($(this).index()) ) { g.afterToggleCol(); } @@ -705,7 +611,7 @@ g.showAllColumns(); }); // prepend "show all column" button at top if the list is too long - if ($firstRowHeaders.length > 10) { + if ($firstRowCols.length > 10) { var clone = showAll.cloneNode(true); $(g.cList).prepend(clone); $(clone).click(function() { @@ -748,15 +654,17 @@ g.showHint(e); }); } - $(t).find('th:not(.draggable)') - .mouseenter(function(e) { - g.showColVisibHint = true; - g.showHint(e); - }) - .mouseleave(function(e) { - g.showColVisibHint = false; - g.showHint(e); - }); + if ($firstRowCols.length > 1) { + $(t).find('th:not(.draggable)') + .mouseenter(function(e) { + g.showColVisibHint = true; + g.showHint(e); + }) + .mouseleave(function(e) { + g.showColVisibHint = false; + g.showHint(e); + }); + } $(t).find('th.draggable a') .attr('title', '') // hide default tooltip for sorting .mouseenter(function(e) { diff --git a/js/messages.php b/js/messages.php index 20ad557b08..2ab89ddef3 100644 --- a/js/messages.php +++ b/js/messages.php @@ -184,7 +184,6 @@ $js_messages['strDeleting'] = __('Deleting'); /* For db_routines.js */ $js_messages['MissingReturn'] = __('The definition of a stored function must contain a RETURN statement!'); -$js_messages['strValueTooLong'] = __('Value too long in the form!'); /* For import.js */ $js_messages['strImportCSV'] = __('Note: If the file contains multiple tables, they will be combined into one'); diff --git a/js/rte/common.js b/js/rte/common.js new file mode 100644 index 0000000000..4e3893e5c0 --- /dev/null +++ b/js/rte/common.js @@ -0,0 +1,380 @@ +/* vim: set expandtab sw=4 ts=4 sts=4: */ + +/** + * @var RTE a JavaScript namespace containing the functionality + * for Routines, Triggers and Events. + * + * This namespace is extended by the functionality required + * to handle a specific item (a routine, trigger or event) + * in the relevant javascript files in this folder. + */ +var RTE = { + /** + * @var $ajaxDialog jQuery object containing the reference to the + * dialog that contains the editor. + */ + $ajaxDialog: null, + /** + * @var syntaxHiglighter Reference to the codemirror editor. + */ + syntaxHiglighter: null, + /** + * @var buttonOptions Object containing options for + * the jQueryUI dialog buttons + */ + buttonOptions: {}, + /** + * Validate editor form fields. + */ + validate: function () { + /** + * @var $elm a jQuery object containing the reference + * to an element that is being validated. + */ + var $elm = null; + // Common validation. At the very least the name + // and the definition must be provided for an item + $elm = $('.rte_table').last().find('input[name=item_name]'); + if ($elm.val() === '') { + $elm.focus(); + alert(PMA_messages['strFormEmpty']); + return false; + } + $elm = $('.rte_table').find('textarea[name=item_definition]'); + if ($elm.val() === '') { + this.syntaxHiglighter.focus(); + alert(PMA_messages['strFormEmpty']); + return false; + } + // The validation has so far passed, so now + // we can validate item-specific fields. + return RTE.validateCustom(); + }, // end validate() + /** + * Validate custom editor form fields. + * This function can be overridden by + * other files in this folder. + */ + validateCustom: function () { + return true; + }, // end validateCustom() + /** + * Execute some code after the ajax + * dialog for the ditor is shown. + * This function can be overridden by + * other files in this folder. + */ + postDialogShow: function () { + // Nothing by default + } // end postDialogShow() +}; // end RTE namespace + +/** + * Attach Ajax event handlers for the Routines, Triggers and Events editor. + * + * @see $cfg['AjaxEnable'] + */ +$(document).ready(function () { + /** + * Attach Ajax event handlers for the Add/Edit functionality. + */ + $('.ajax_add_anchor, .ajax_edit_anchor').live('click', function (event) { + event.preventDefault(); + /** + * @var $edit_row jQuery object containing the reference to + * the row of the the item being edited + * from the list of items . + */ + var $edit_row = null; + if ($(this).hasClass('ajax_edit_anchor')) { + // Remeber the row of the item being edited for later, + // so that if the edit is successful, we can replace the + // row with info about the modified item. + $edit_row = $(this).parents('tr'); + } + /** + * @var $msg jQuery object containing the reference to + * the AJAX message shown to the user. + */ + var $msg = PMA_ajaxShowMessage(); + $.get($(this).attr('href'), {'ajax_request': true}, function (data) { + if (data.success === true) { + // We have successfully fetched the editor form + PMA_ajaxRemoveMessage($msg); + // Now define the function that is called when + // the user presses the "Go" button + RTE.buttonOptions[PMA_messages['strGo']] = function () { + // Move the data from the codemirror editor back to the + // textarea, where it can be used in the form submission. + RTE.syntaxHiglighter.save(); + // Validate editor and submit request, if passed. + if (RTE.validate()) { + /** + * @var data Form data to be sent in the AJAX request. + */ + var data = $('.rte_form').last().serialize(); + $msg = PMA_ajaxShowMessage(PMA_messages['strProcessingRequest']); + $.post($('.rte_form').last().attr('action'), data, function (data) { + if (data.success === true) { + // Item created successfully + PMA_ajaxRemoveMessage($msg); + PMA_slidingMessage(data.message); + RTE.$ajaxDialog.dialog('close'); + // If we are in 'edit' mode, we must remove the reference to the old row. + if (mode === 'edit') { + $edit_row.remove(); + } + // Sometimes, like when moving a trigger from a table to + // another one, the new row should not be inserted into the + // list. In this case "data.insert" will be set to false. + if (data.insert) { + // Insert the new row at the correct location in the list of items + /** + * @var text Contains the name of an item from the list + * that is used in comparisons to find the correct + * location where to insert a new row. + */ + var text = ''; + /** + * @var inserted Whether a new item has been inserted + * in the list or not. + */ + var inserted = false; + $('table.data').find('tr').each(function () { + text = $(this) + .children('td') + .eq(0) + .find('strong') + .text() + .toUpperCase(); + text = $.trim(text); + if (text !== '' && text > data.name) { + $(this).before(data.new_row); + inserted = true; + return false; + } + }); + if (! inserted) { + // If we didn't manage to insert the row yet, + // it must belong at the end of the list, + // so we insert it there. + $('table.data').append(data.new_row); + } + // Fade-in the new row + $('.ajaxInsert').show('slow').removeClass('ajaxInsert'); + } else if ($('table.data').find('tr').has('td').length === 0) { + // If we are not supposed to insert the new row, we will now + // check if the table is empty and needs to be hidden. This + // will be the case if we were editing the only item in the + // list, which we removed and will not be inserting something + // else in its place. + $('table.data').hide("slow", function () { + $('#nothing2display').show("slow"); + }); + } + // Now we have inserted the row at the correct position, but surely + // at least some row classes are wrong now. So we will itirate + // throught all rows and assign correct classes to them. + /** + * @var ct Count of processed rows. + */ + var ct = 0; + /** + * @var rowclass Class to be attached to the row + * that is being processed + */ + var rowclass = ''; + $('table.data').find('tr').has('td').each(function () { + rowclass = (ct % 2 === 0) ? 'even' : 'odd'; + $(this).removeClass().addClass(rowclass); + ct++; + }); + // If this is the first item being added, remove + // the "No items" message and show the list. + if ($('table.data').find('tr').has('td').length > 0 + && $('#nothing2display').is(':visible')) { + $('#nothing2display').hide("slow", function () { + $('table.data').show("slow"); + }); + } + } else { + PMA_ajaxShowMessage(data.error); + } + }); // end $.post() + } // end "if (RTE.validate())" + }; // end of function that handles the submission of the Editor + RTE.buttonOptions[PMA_messages['strClose']] = function () { + $(this).dialog("close"); + }; + /** + * Display the dialog to the user + */ + RTE.$ajaxDialog = $('
' + data.message + '
').dialog({ + width: 700, + height: 555, + buttons: RTE.buttonOptions, + title: data.title, + modal: true, + close: function () { + $(this).remove(); + } + }); + RTE.$ajaxDialog.find('input[name=item_name]').focus(); + RTE.$ajaxDialog.find('.datefield, .datetimefield').each(function () { + PMA_addDatepicker($(this).css('width', '95%')); + }); + /** + * @var mode Used to remeber whether the editor is in + * "Edit" or "Add" mode. + */ + var mode = 'add'; + if ($('input[name=editor_process_edit]').length > 0) { + mode = 'edit'; + } + // Attach syntax highlited editor to the definition + /** + * @var $elm jQuery object containing the reference to + * the Definition textarea. + */ + var $elm = $('textarea[name=item_definition]').last(); + /** + * @var opts Options to pass to the codemirror editor. + */ + var opts = {lineNumbers: true, matchBrackets: true, indentUnit: 4, mode: "text/x-mysql"}; + RTE.syntaxHiglighter = CodeMirror.fromTextArea($elm[0], opts); + // Hack to prevent the syntax highlighter from expanding beyond dialog boundries + $('.CodeMirror-scroll').find('div').first().css('width', '1px'); + // Execute item-specific code + RTE.postDialogShow(data); + } else { + PMA_ajaxShowMessage(data.error); + } + }); // end $.get() + }); // end $.live() + + /** + * Attach Ajax event handlers for input fields in the editor + * and the routine execution dialog used to submit the Ajax + * request when the ENTER key is pressed. + */ + $('.rte_table').find('input[name^=item], input[name^=params]').live('keydown', function (e) { + if (e.which === 13) { // 13 is the ENTER key + e.preventDefault(); + if (typeof RTE.buttonOptions[PMA_messages['strGo']] === 'function') { + RTE.buttonOptions[PMA_messages['strGo']].call(); + } + } + }); // end $.live() + + /** + * Attach Ajax event handlers for Export of Routines, Triggers and Events. + */ + $('.ajax_export_anchor').live('click', function (event) { + event.preventDefault(); + var $msg = PMA_ajaxShowMessage(); + // Fire the ajax request straight away + $.get($(this).attr('href'), {'ajax_request': true}, function (data) { + if (data.success === true) { + PMA_ajaxRemoveMessage($msg); + /** + * @var button_options Object containing options for jQueryUI dialog buttons + */ + var button_options = {}; + button_options[PMA_messages['strClose']] = function () { + $(this).dialog("close").remove(); + }; + /** + * Display the dialog to the user + */ + var $ajaxDialog = $('
' + data.message + '
').dialog({ + width: 500, + buttons: button_options, + title: data.title + }); + // Attach syntax highlited editor to export dialog + /** + * @var $elm jQuery object containing the reference + * to the Export textarea. + */ + var $elm = $ajaxDialog.find('textarea'); + /** + * @var opts Options to pass to the codemirror editor. + */ + var opts = {lineNumbers: true, matchBrackets: true, indentUnit: 4, mode: "text/x-mysql"}; + CodeMirror.fromTextArea($elm[0], opts); + } else { + PMA_ajaxShowMessage(data.error); + } + }); // end $.get() + }); // end $.live() + + /** + * Attach Ajax event handlers for Drop functionality of Routines, Triggers and Events. + */ + $('.ajax_drop_anchor').live('click', function (event) { + event.preventDefault(); + /** + * @var $curr_row Object containing reference to the current row + */ + var $curr_row = $(this).parents('tr'); + /** + * @var question String containing the question to be asked for confirmation + */ + var question = $('
').text($curr_row.children('td').children('.drop_sql').html()); + // We ask for confirmation first here, before submitting the ajax request + $(this).PMA_confirm(question, $(this).attr('href'), function (url) { + /** + * @var $msg jQuery object containing the reference to + * the AJAX message shown to the user. + */ + var $msg = PMA_ajaxShowMessage(PMA_messages['strProcessingRequest']); + $.get(url, {'is_js_confirmed': 1, 'ajax_request': true}, function (data) { + if (data.success === true) { + /** + * @var $table Object containing reference to the main list of elements. + */ + var $table = $curr_row.parent(); + // Check how many rows will be left after we remove + // the one that the user has requested us to remove + if ($table.find('tr').length === 2) { + // If there are two rows left, it means that they are + // the header of the table and the rows that we are + // about to remove, so after the removal there will be + // nothing to show in the table, so we hide it. + $table.hide("slow", function () { + $(this).find('tr.even, tr.odd').remove(); + $('#nothing2display').show("slow"); + }); + } else { + $curr_row.hide("slow", function () { + $(this).remove(); + // Now we have removed the row from the list, but maybe + // some row classes are wrong now. So we will itirate + // throught all rows and assign correct classes to them. + /** + * @var ct Count of processed rows. + */ + var ct = 0; + /** + * @var rowclass Class to be attached to the row + * that is being processed + */ + var rowclass = ''; + $table.find('tr').has('td').each(function () { + rowclass = (ct % 2 === 0) ? 'even' : 'odd'; + $(this).removeClass().addClass(rowclass); + ct++; + }); + }); + } + // Get rid of the "Loading" message + PMA_ajaxRemoveMessage($msg); + // Show the query that we just executed + PMA_slidingMessage(data.sql_query); + } else { + PMA_ajaxShowMessage(PMA_messages['strErrorProcessingRequest'] + " : " + data.error); + } + }); // end $.get() + }); // end $.PMA_confirm() + }); // end $.live() +}); // end of $(document).ready() diff --git a/js/rte/events.js b/js/rte/events.js new file mode 100644 index 0000000000..257a17dd9f --- /dev/null +++ b/js/rte/events.js @@ -0,0 +1,43 @@ +/* vim: set expandtab sw=4 ts=4 sts=4: */ + +/** + * Overriding the validateCustom() function defined in common.js + */ +RTE.validateCustom = function () { + /** + * @var $elm a jQuery object containing the reference + * to an element that is being validated. + */ + var $elm = null; + if ($('select[name=item_type]').find(':selected').val() === 'RECURRING') { + // The interval field must not be empty for recurring events + $elm = $('input[name=item_interval_value]'); + if ($elm.val() === '') { + $elm.focus(); + alert(PMA_messages['strFormEmpty']); + return false; + } + } else { + // The execute_at field must not be empty for "once off" events + $elm = $('input[name=item_execute_at]'); + if ($elm.val() === '') { + $elm.focus(); + alert(PMA_messages['strFormEmpty']); + return false; + } + } + return true; +}; // end RTE.validateCustom() + +/** + * Attach Ajax event handlers for the "Change event type" + * functionality in the events editor, so that the correct + * rows are shown in the editor when changing the event type + * + * @see $cfg['AjaxEnable'] + */ +$(document).ready(function () { + $('select[name=item_type]').live('change', function () { + $('.recurring_event_row, .onetime_event_row').toggle(); + }); // end $.live() +}); // end of $(document).ready() diff --git a/js/rte/routines.js b/js/rte/routines.js new file mode 100644 index 0000000000..50c4f00051 --- /dev/null +++ b/js/rte/routines.js @@ -0,0 +1,395 @@ +/* vim: set expandtab sw=4 ts=4 sts=4: */ + +/** + * @var param_template This variable contains the template for one row + * of the parameters table that is attached to the + * dialog when a new parameter is added. + */ +RTE.param_template = ''; + +/** + * Overriding the postDialogShow() function defined in common.js + * + * @param data JSON-encoded data from the ajax request + */ +RTE.postDialogShow = function (data) { + // Cache the template for a parameter table row + RTE.param_template = data.param_template; + // Make adjustments in the dialog to make it AJAX compatible + $('.routine_param_remove').show(); + $('input[name=routine_removeparameter]').remove(); + $('input[name=routine_addparameter]').css('width', '100%'); + // Enable/disable the 'options' dropdowns for parameters as necessary + $('.routine_params_table').last().find('th[colspan=2]').attr('colspan', '1'); + $('.routine_params_table').last().find('tr').has('td').each(function () { + RTE.setOptionsForParameter( + $(this).find('select[name^=item_param_type]'), + $(this).find('input[name^=item_param_length]'), + $(this).find('select[name^=item_param_opts_text]'), + $(this).find('select[name^=item_param_opts_num]') + ); + }); + // Enable/disable the 'options' dropdowns for + // function return value as necessary + RTE.setOptionsForParameter( + $('.rte_table').last().find('select[name=item_returntype]'), + $('.rte_table').last().find('input[name=item_returnlength]'), + $('.rte_table').last().find('select[name=item_returnopts_text]'), + $('.rte_table').last().find('select[name=item_returnopts_num]') + ); +}; // end RTE.postDialogShow() + +/** + * Overriding the validateCustom() function defined in common.js + */ +RTE.validateCustom = function () { + /** + * @var isSuccess Stores the outcome of the validation + */ + var isSuccess = true; + /** + * @var inputname The value of the "name" attribute for + * the field that is being processed + */ + var inputname = ''; + $('.routine_params_table').last().find('tr').each(function () { + // Every parameter of a routine must have + // a non-empty direction, name and type + if (isSuccess) { + $(this).find(':input').each(function () { + inputname = $(this).attr('name'); + if (inputname.substr(0, 17) === 'item_param_dir' || + inputname.substr(0, 18) === 'item_param_name' || + inputname.substr(0, 18) === 'item_param_type') { + if ($(this).val() === '') { + $(this).focus(); + isSuccess = false; + return false; + } + } + }); + } else { + return false; + } + }); + if (! isSuccess) { + alert(PMA_messages['strFormEmpty']); + return false; + } + $('.routine_params_table').last().find('tr').each(function () { + // SET, ENUM, VARCHAR and VARBINARY fields must have length/values + var $inputtyp = $(this).find('select[name^=item_param_type]'); + var $inputlen = $(this).find('input[name^=item_param_length]'); + if ($inputtyp.length && $inputlen.length) { + if (($inputtyp.val() === 'ENUM' || $inputtyp.val() === 'SET' || $inputtyp.val().substr(0, 3) === 'VAR') + && $inputlen.val() === '') { + $inputlen.focus(); + isSuccess = false; + return false; + } + } + }); + if (! isSuccess) { + alert(PMA_messages['strFormEmpty']); + return false; + } + if ($('select[name=item_type]').find(':selected').val() === 'FUNCTION') { + // The length/values of return variable for functions must + // be set, if the type is SET, ENUM, VARCHAR or VARBINARY. + var $returntyp = $('select[name=item_returntype]'); + var $returnlen = $('input[name=item_returnlength]'); + if (($returntyp.val() === 'ENUM' || $returntyp.val() === 'SET' || $returntyp.val().substr(0, 3) === 'VAR') + && $returnlen.val() === '') { + $returnlen.focus(); + alert(PMA_messages['strFormEmpty']); + return false; + } + } + if ($('select[name=item_type]').find(':selected').val() === 'FUNCTION') { + // A function must contain a RETURN statement in its definition + if ($('.rte_table').find('textarea[name=item_definition]').val().toUpperCase().indexOf('RETURN') < 0) { + RTE.syntaxHiglighter.focus(); + alert(PMA_messages['MissingReturn']); + return false; + } + } + return true; +}; // end RTE.validateCustom() + +/** + * Enable/disable the "options" dropdown and "length" input for + * parameters and the return variable in the routine editor + * as necessary. + * + * @param $type a jQuery object containing the reference + * to the "Type" dropdown box + * @param $len a jQuery object containing the reference + * to the "Length" input box + * @param $text a jQuery object containing the reference + * to the dropdown box with options for + * parameters of text type + * @param $num a jQuery object containing the reference + * to the dropdown box with options for + * parameters of numeric type + */ +RTE.setOptionsForParameter = function ($type, $len, $text, $num) { + /** + * @var $no_opts a jQuery object containing the reference + * to an element to be displayed when no + * options are available + */ + var $no_opts = $text.parent().parent().find('.no_opts'); + /** + * @var $no_len a jQuery object containing the reference + * to an element to be displayed when no + * "length/values" field is available + */ + var $no_len = $len.parent().parent().find('.no_len'); + + // Process for parameter options + switch ($type.val()) { + case 'TINYINT': + case 'SMALLINT': + case 'MEDIUMINT': + case 'INT': + case 'BIGINT': + case 'DECIMAL': + case 'FLOAT': + case 'DOUBLE': + case 'REAL': + $text.parent().hide(); + $num.parent().show(); + $no_opts.hide(); + break; + case 'TINYTEXT': + case 'TEXT': + case 'MEDIUMTEXT': + case 'LONGTEXT': + case 'CHAR': + case 'VARCHAR': + case 'SET': + case 'ENUM': + $text.parent().show(); + $num.parent().hide(); + $no_opts.hide(); + break; + default: + $text.parent().hide(); + $num.parent().hide(); + $no_opts.show(); + break; + } + // Process for parameter length + switch ($type.val()) { + case 'DATE': + case 'DATETIME': + case 'TIME': + case 'TINYBLOB': + case 'TINYTEXT': + case 'BLOB': + case 'TEXT': + case 'MEDIUMBLOB': + case 'MEDIUMTEXT': + case 'LONGBLOB': + case 'LONGTEXT': + $len.parent().hide(); + $no_len.show(); + break; + default: + $len.parent().show(); + $no_len.hide(); + break; + } +}; // end RTE.setOptionsForParameter() + +/** + * Attach Ajax event handlers for the Routines functionalities. + * + * @see $cfg['AjaxEnable'] + */ +$(document).ready(function () { + /** + * Attach Ajax event handlers for the "Add parameter to routine" functionality. + */ + $('input[name=routine_addparameter]').live('click', function (event) { + event.preventDefault(); + /** + * @var $routine_params_table jQuery object containing the reference + * to the routine parameters table. + */ + var $routine_params_table = $('.routine_params_table').last(); + /** + * @var $new_param_row A string containing the HTML code for the + * new row for the routine paramaters table. + */ + var new_param_row = RTE.param_template.replace(/%s/g, $routine_params_table.find('tr').length - 1); + // Append the new row to the parameters table + $routine_params_table.append(new_param_row); + // Make sure that the row is correctly shown according to the type of routine + if ($('.rte_table').find('select[name=item_type]').val() === 'FUNCTION') { + $('.routine_return_row').show(); + $('.routine_direction_cell').hide(); + } + /** + * @var $newrow jQuery object containing the reference to the newly + * inserted row in the routine parameters table. + */ + var $newrow = $('.routine_params_table').last().find('tr').has('td').last(); + // Enable/disable the 'options' dropdowns for parameters as necessary + RTE.setOptionsForParameter( + $newrow.find('select[name^=item_param_type]'), + $newrow.find('input[name^=item_param_length]'), + $newrow.find('select[name^=item_param_opts_text]'), + $newrow.find('select[name^=item_param_opts_num]') + ); + }); // end $.live() + + /** + * Attach Ajax event handlers for the "Remove parameter from routine" functionality. + */ + $('.routine_param_remove_anchor').live('click', function (event) { + event.preventDefault(); + $(this).parent().parent().remove(); + // After removing a parameter, the indices of the name attributes in + // the input fields lose the correct order and need to be reordered. + /** + * @var index Counter used for reindexing the input + * fields in the routine parameters table. + */ + var index = 0; + $('.routine_params_table').last().find('tr').has('td').each(function () { + $(this).find(':input').each(function () { + /** + * @var inputname The value of the name attribute of + * the input field being reindexed. + */ + var inputname = $(this).attr('name'); + if (inputname.substr(0, 17) === 'item_param_dir') { + $(this).attr('name', inputname.substr(0, 17) + '[' + index + ']'); + } else if (inputname.substr(0, 18) === 'item_param_name') { + $(this).attr('name', inputname.substr(0, 18) + '[' + index + ']'); + } else if (inputname.substr(0, 18) === 'item_param_type') { + $(this).attr('name', inputname.substr(0, 18) + '[' + index + ']'); + } else if (inputname.substr(0, 20) === 'item_param_length') { + $(this).attr('name', inputname.substr(0, 20) + '[' + index + ']'); + } else if (inputname.substr(0, 23) === 'item_param_opts_text') { + $(this).attr('name', inputname.substr(0, 23) + '[' + index + ']'); + } else if (inputname.substr(0, 22) === 'item_param_opts_num') { + $(this).attr('name', inputname.substr(0, 22) + '[' + index + ']'); + } + }); + index++; + }); + }); // end $.live() + + /** + * Attach Ajax event handlers for the "Change routine type" + * functionality in the routines editor, so that the correct + * fields are shown in the editor when changing the routine type + */ + $('select[name=item_type]').live('change', function () { + $('.routine_return_row, .routine_direction_cell').toggle(); + }); // end $.live() + + /** + * Attach Ajax event handlers for the "Change parameter type" + * functionality in the routines editor, so that the correct + * option/length fields, if any, are shown when changing + * a parameter type + */ + $('select[name^=item_param_type]').live('change', function () { + /** + * @var $row jQuery object containing the reference to + * a row in the routine parameters table + */ + var $row = $(this).parents('tr').first(); + RTE.setOptionsForParameter( + $row.find('select[name^=item_param_type]'), + $row.find('input[name^=item_param_length]'), + $row.find('select[name^=item_param_opts_text]'), + $row.find('select[name^=item_param_opts_num]') + ); + }); // end $.live() + + /** + * Attach Ajax event handlers for the "Change the type of return + * variable of function" functionality, so that the correct fields, + * if any, are shown when changing the function return type type + */ + $('select[name=item_returntype]').live('change', function () { + RTE.setOptionsForParameter( + $('.rte_table').find('select[name=item_returntype]'), + $('.rte_table').find('input[name=item_returnlength]'), + $('.rte_table').find('select[name=item_returnopts_text]'), + $('.rte_table').find('select[name=item_returnopts_num]') + ); + }); // end $.live() + + /** + * Attach Ajax event handlers for the Execute routine functionality. + */ + $('.ajax_exec_anchor').live('click', function (event) { + event.preventDefault(); + /** + * @var $msg jQuery object containing the reference to + * the AJAX message shown to the user + */ + var $msg = PMA_ajaxShowMessage(); + $.get($(this).attr('href'), {'ajax_request': true}, function (data) { + if (data.success === true) { + PMA_ajaxRemoveMessage($msg); + // If 'data.dialog' is true we show a dialog with a form + // to get the input parameters for routine, otherwise + // we just show the results of the query + if (data.dialog) { + // Define the function that is called when + // the user presses the "Go" button + RTE.buttonOptions[PMA_messages['strGo']] = function () { + /** + * @var data Form data to be sent in the AJAX request. + */ + var data = $('.rte_form').last().serialize(); + $msg = PMA_ajaxShowMessage(PMA_messages['strProcessingRequest']); + $.post('db_routines.php', data, function (data) { + if (data.success === true) { + // Routine executed successfully + PMA_ajaxRemoveMessage($msg); + PMA_slidingMessage(data.message); + $ajaxDialog.dialog('close'); + } else { + PMA_ajaxShowMessage(data.error); + } + }); + }; + RTE.buttonOptions[PMA_messages['strClose']] = function () { + $(this).dialog("close"); + }; + /** + * Display the dialog to the user + */ + $ajaxDialog = $('
' + data.message + '
').dialog({ + width: 650, + buttons: RTE.buttonOptions, + title: data.title, + modal: true, + close: function () { + $(this).remove(); + } + }); + $ajaxDialog.find('input[name^=params]').first().focus(); + /** + * Attach the datepickers to the relevant form fields + */ + $ajaxDialog.find('.datefield, .datetimefield').each(function () { + PMA_addDatepicker($(this).css('width', '95%')); + }); + } else { + // Routine executed successfully + PMA_slidingMessage(data.message); + } + } else { + PMA_ajaxShowMessage(data.error); + } + }); // end $.get() + }); // end $.live() +}); // end of $(document).ready() for the Routine Functionalities diff --git a/js/rte/triggers.js b/js/rte/triggers.js new file mode 100644 index 0000000000..826cd55cfb --- /dev/null +++ b/js/rte/triggers.js @@ -0,0 +1,8 @@ +/* vim: set expandtab sw=4 ts=4 sts=4: */ + +/** + * So far it looks like triggers don't need + * any special treatment as far as JavaScript + * goes, but leaving this file here in case + * the need for custom code will arise. + */ diff --git a/js/sql.js b/js/sql.js index 48fb65f609..4f41ef906e 100644 --- a/js/sql.js +++ b/js/sql.js @@ -28,28 +28,18 @@ function PMA_urlencode(str) { * for inline editing * * @param $this_field jQuery object that points to the current field's tr - * @param disp_mode string */ -function getFieldName($this_field, disp_mode) { +function getFieldName($this_field) { - if(disp_mode == 'vertical') { - var field_name = $this_field.siblings('th').find('a').text(); - // happens when just one row (headings contain no a) - if ("" == field_name) { - field_name = $this_field.siblings('th').text(); - } - } - else { - var this_field_index = $this_field.index(); - // ltr or rtl direction does not impact how the DOM was generated - // check if the action column in the left exist - var leftActionExist = !$('#table_results').find('th:first').hasClass('draggable'); - // 5 columns to account for the checkbox, edit, appended inline edit, copy and delete anchors but index is zero-based so substract 4 - var field_name = $('#table_results').find('thead').find('th:nth('+ (this_field_index - (leftActionExist ? 4 : 0)) + ') a').text(); - // happens when just one row (headings contain no a) - if ("" == field_name) { - field_name = $('#table_results').find('thead').find('th:nth('+ (this_field_index - (leftActionExist ? 4 : 0)) + ')').text(); - } + var this_field_index = $this_field.index(); + // ltr or rtl direction does not impact how the DOM was generated + // check if the action column in the left exist + var leftActionExist = !$('#table_results').find('th:first').hasClass('draggable'); + // 5 columns to account for the checkbox, edit, appended inline edit, copy and delete anchors but index is zero-based so substract 4 + var field_name = $('#table_results').find('thead').find('th:nth('+ (this_field_index - (leftActionExist ? 4 : 0)) + ') a').text(); + // happens when just one row (headings contain no a) + if ("" == field_name) { + field_name = $('#table_results').find('thead').find('th:nth('+ (this_field_index - (leftActionExist ? 4 : 0)) + ')').text(); } field_name = $.trim(field_name); @@ -63,49 +53,9 @@ function getFieldName($this_field, disp_mode) { * */ function appendInlineAnchor() { + // TODO: remove two lines below if vertical display mode has been completely removed var disp_mode = $("#top_direction_dropdown").val(); - - if (disp_mode == 'vertical') { - // there can be one or two tr containing this class, depending - // on the RowActionLinks cfg parameter - $('#table_results tr') - .find('.edit_row_anchor') - .removeClass('edit_row_anchor') - .parent().each(function() { - var $this_tr = $(this); - var $cloned_tr = $this_tr.clone(); - - var $img_object = $cloned_tr.find('img:first').attr('title', PMA_messages['strInlineEdit']); - if ($img_object.length != 0) { - var img_src = $img_object.attr('src').replace(/b_edit/,'b_inline_edit'); - $img_object.attr('src', img_src); - } - - $cloned_tr.find('td') - .addClass('inline_edit_anchor') - .find('a').attr('href', '#'); - var $edit_span = $cloned_tr.find('span:contains("' + PMA_messages['strEdit'] + '")'); - var $span = $cloned_tr.find('a').find('span'); - if ($edit_span.length > 0) { - $span.text(' ' + PMA_messages['strInlineEdit']); - $span.prepend($img_object); - } else { - $span.text(''); - $span.append($img_object); - } - - $cloned_tr.insertAfter($this_tr); - }); - - $('#resultsForm').find('tbody').find('th').each(function() { - var $this_th = $(this); - if ($this_th.attr('rowspan') == 4) { - $this_th.attr('rowspan', '5'); - } - }); - } - else { - // horizontal mode + if (disp_mode != 'vertical') { $('.edit_row_anchor').each(function() { var $this_td = $(this); @@ -194,23 +144,6 @@ $(document).ready(function() { .toggle($(this).attr('value').length > 0); }).trigger('keyup'); - /** - * current value of the direction in which the table is displayed - * @type String - * @fieldOf jQuery - * @name disp_mode - */ - var disp_mode = $("#top_direction_dropdown").val(); - - /** - * Update value of {@link jQuery.disp_mode} everytime the direction dropdown changes value - * @memberOf jQuery - * @name direction_dropdown_change - */ - $("#top_direction_dropdown, #bottom_direction_dropdown").live('change', function(event) { - disp_mode = $(this).val(); - }) - /** * Attach the {@link appendInlineAnchor} function to a custom event, which * will be triggered manually everytime the table of results is reloaded @@ -229,6 +162,24 @@ $(document).ready(function() { $('#table_results').makegrid(); }) + /** + * Attach the {@link refreshgrid} function to a custom event, which will be + * triggered manually everytime the table of results is manipulated (e.g., by inline edit) + * @memberOf jQuery + */ + $("#sqlqueryresults").live('refreshgrid', function() { + $('#table_results').refreshgrid(); + }) + + /** + * Attach the {@link makegrid} function to a custom event, which will be + * triggered manually everytime the table of results is reloaded + * @memberOf jQuery + */ + $("#sqlqueryresults").live('makegrid', function() { + $('#table_results').makegrid(); + }) + /** * Attach the {@link refreshgrid} function to a custom event, which will be * triggered manually everytime the table of results is manipulated (e.g., by inline edit) @@ -536,95 +487,39 @@ $(document).ready(function() { // Add hide icon and/or text. $edit_td.children('span.nowrap').append($('

')).append($hide_a); - if (disp_mode != 'vertical') { - $('#table_results tbody tr td span a#hide').click(function() { - var $this_hide = $(this).parents('td'); + $('#table_results tbody tr td span a#hide').click(function() { + var $this_hide = $(this).parents('td'); - var $this_span = $this_hide.find('span'); - $this_span.find('a, br').remove(); - $this_span.append($data_a.clone()); + var $this_span = $this_hide.find('span'); + $this_span.find('a, br').remove(); + $this_span.append($data_a.clone()); - $this_hide.removeClass("inline_edit_active hover").addClass("inline_edit_anchor"); - $this_hide.parent().removeClass("hover noclick"); - $this_hide.siblings().removeClass("hover"); + $this_hide.removeClass("inline_edit_active hover").addClass("inline_edit_anchor"); + $this_hide.parent().removeClass("hover noclick"); + $this_hide.siblings().removeClass("hover"); - var $input_siblings = $this_hide.parent('tr').find('.inline_edit'); - var txt = ''; - $input_siblings.each(function() { - var $this_hide_siblings = $(this); - txt = $this_hide_siblings.data('original_data'); - if($this_hide_siblings.children('span').children().length != 0) { - $this_hide_siblings.children('span').empty(); - $this_hide_siblings.children('span').append(txt); - } - }); - $(this).prev().prev().remove(); - $(this).prev().remove(); - $(this).remove(); - - // refresh the grid - $("#sqlqueryresults").trigger('refreshgrid'); - }); - } else { + var $input_siblings = $this_hide.parent('tr').find('.inline_edit'); var txt = ''; - var rows = $edit_td.parent().siblings().length; - - $('#table_results tbody tr td span a#hide').click(function() { - var $hide_a = $(this); - var $this_hide = $(this).parents('td'); - var pos = $this_hide.index(); - - var $this_span = $hide_a.parent(); - $this_span.find('a, br').remove(); - $this_span.append($data_a.clone()); - - var $this_row = $this_span.parents('tr'); - // changing inline_edit_active to inline_edit_anchor - $this_hide.removeClass("inline_edit_active").addClass("inline_edit_anchor"); - - // removing marked and hover classes. - $this_row.parent('tbody').find('tr').find("td:eq(" + pos + ")").removeClass("marked hover"); - - for( var i = 0; i <= rows + 2; i++){ - if( $this_row.siblings("tr:eq(" + i + ") td:eq(" + pos + ")").hasClass("inline_edit") == false) { - continue; - } - $this_row_siblings = $this_row.siblings("tr:eq(" + i + ") td:eq(" + pos + ")"); - txt = $this_row_siblings.data('original_data'); - $this_row_siblings.children('span').empty(); - $this_row_siblings.children('span').append(txt); + $input_siblings.each(function() { + var $this_hide_siblings = $(this); + txt = $this_hide_siblings.data('original_data'); + if($this_hide_siblings.children('span').children().length != 0) { + $this_hide_siblings.children('span').empty(); + $this_hide_siblings.children('span').append(txt); } - $(this).prev().remove(); - $(this).prev().remove(); - $(this).remove(); - - // refresh the grid - $("#sqlqueryresults").trigger('refreshgrid'); }); - } + $(this).prev().prev().remove(); + $(this).prev().remove(); + $(this).remove(); + + // refresh the grid + $("#sqlqueryresults").trigger('refreshgrid'); + }); // Initialize some variables - if(disp_mode == 'vertical') { - /** - * @var this_row_index Index of the current in the parent - * Current is the inline edit anchor. - */ - var this_row_index = $edit_td.index(); - /** - * @var $input_siblings Object referring to all inline editable events from same row - */ - var $input_siblings = $edit_td.parents('tbody').find('tr').find('.inline_edit:nth('+this_row_index+')'); - /** - * @var where_clause String containing the WHERE clause to select this row - */ - var where_clause = $edit_td.parents('tbody').find('tr').find('.where_clause:nth('+this_row_index+')').val(); - } - // horizontal mode - else { - var this_row_index = $edit_td.parent().index(); - var $input_siblings = $edit_td.parent('tr').find('.inline_edit'); - var where_clause = $edit_td.parent('tr').find('.where_clause').val(); - } + var this_row_index = $edit_td.parent().index(); + var $input_siblings = $edit_td.parent('tr').find('.inline_edit'); + var where_clause = $edit_td.parent('tr').find('.where_clause').val(); $input_siblings.each(function() { /** @lends jQuery */ @@ -648,7 +543,7 @@ $(document).ready(function() { * @var field_name String containing the name of this field. * @see getFieldName() */ - var field_name = getFieldName($this_field, disp_mode); + var field_name = getFieldName($this_field); /** * @var relation_curr_value String current value of the field (for fields that are foreign keyed). */ @@ -685,7 +580,10 @@ $(document).ready(function() { }) } else { $this_field.find('textarea').live('keypress', function(e) { - $('.checkbox_null_' + field_name + '_' + this_row_index).attr('checked', false); + // FF errorneously triggers for modifier keys such as tab (bug #3357837) + if (e.which != 0) { + $('.checkbox_null_' + field_name + '_' + this_row_index).attr('checked', false); + } }) } @@ -856,24 +754,8 @@ $(document).ready(function() { var $test_element = ''; // to test the presence of a element // Initialize variables - if(disp_mode == 'vertical') { - /** - * @var this_td_index Index of the current in the parent - * Current is the inline edit anchor. - */ - var this_td_index = $this_td.index(); - /** - * @var $input_siblings Object referring to all inline editable events from same row - */ - var $input_siblings = $this_td.parents('tbody').find('tr').find('.inline_edit:nth('+this_td_index+')'); - /** - * @var where_clause String containing the WHERE clause to select this row - */ - var where_clause = $this_td.parents('tbody').find('tr').find('.where_clause:nth('+this_td_index+')').val(); - } else { - var $input_siblings = $this_td.parent('tr').find('.inline_edit'); - var where_clause = $this_td.parent('tr').find('.where_clause').val(); - } + var $input_siblings = $this_td.parent('tr').find('.inline_edit'); + var where_clause = $this_td.parent('tr').find('.where_clause').val(); /** * @var nonunique Boolean, whether this row is unique or not @@ -924,7 +806,7 @@ $(document).ready(function() { * @var field_name String containing the name of this field. * @see getFieldName() */ - var field_name = getFieldName($this_field, disp_mode); + var field_name = getFieldName($this_field); /** * @var this_field_params Array temporary storage for the name/value of current field @@ -1024,7 +906,6 @@ $(document).ready(function() { */ var post_params = {'ajax_request' : true, 'sql_query' : sql_query, - 'disp_direction' : disp_mode, 'token' : window.parent.token, 'db' : window.parent.db, 'table' : window.parent.table, @@ -1041,19 +922,14 @@ $(document).ready(function() { $.post('tbl_replace.php', post_params, function(data) { if(data.success == true) { PMA_ajaxShowMessage(data.message); - if(disp_mode == 'vertical') { - $this_td.parents('tbody').find('tr').find('.where_clause:nth(' + this_td_index + ')').attr('value', new_clause); - } - else { - $this_td.parent('tr').find('.where_clause').attr('value', new_clause); - } + $this_td.parent('tr').find('.where_clause').attr('value', new_clause); // remove possible previous feedback message $('#result_query').remove(); if (typeof data.sql_query != 'undefined') { // display feedback $('#sqlqueryresults').prepend(data.sql_query); } - PMA_unInlineEditRow($del_hide, $chg_submit, $this_td, $input_siblings, data, disp_mode); + PMA_unInlineEditRow($del_hide, $chg_submit, $this_td, $input_siblings, data); } else { PMA_ajaxShowMessage(data.error); }; @@ -1061,7 +937,7 @@ $(document).ready(function() { } else { // no posting was done but still need to display the row // in its previous format - PMA_unInlineEditRow($del_hide, $chg_submit, $this_td, $input_siblings, '', disp_mode); + PMA_unInlineEditRow($del_hide, $chg_submit, $this_td, $input_siblings, ''); } }) // End After editing, clicking again should post data @@ -1226,7 +1102,7 @@ $(document).ready(function() { * (when called in the situation where no posting was done, the data * parameter is empty) */ -function PMA_unInlineEditRow($del_hide, $chg_submit, $this_td, $input_siblings, data, disp_mode) { +function PMA_unInlineEditRow($del_hide, $chg_submit, $this_td, $input_siblings, data) { // deleting the hide button. remove

tags $del_hide.find('a, br').remove(); @@ -1238,11 +1114,7 @@ function PMA_unInlineEditRow($del_hide, $chg_submit, $this_td, $input_siblings, // removing hover, marked and noclick classes $this_td.parent('tr').removeClass('noclick'); - if(disp_mode != 'vertical') { - $this_td.parent('tr').removeClass('hover').find('td').removeClass('hover'); - } else { - $this_td.parents('tbody').find('tr').find('td:eq(' + $this_td.index() + ')').removeClass('marked hover'); - } + $this_td.parent('tr').removeClass('hover').find('td').removeClass('hover'); $input_siblings.each(function() { // Inline edit post has been successful. @@ -1262,7 +1134,7 @@ function PMA_unInlineEditRow($del_hide, $chg_submit, $this_td, $input_siblings, var new_html = $this_sibling.find('textarea').val(); if($this_sibling.is('.transformed')) { - var field_name = getFieldName($this_sibling, disp_mode); + var field_name = getFieldName($this_sibling); if (typeof data.transformations != 'undefined') { $.each(data.transformations, function(key, value) { if(key == field_name) { @@ -1291,7 +1163,7 @@ function PMA_unInlineEditRow($del_hide, $chg_submit, $this_td, $input_siblings, } if($this_sibling.is('.relation')) { - var field_name = getFieldName($this_sibling, disp_mode); + var field_name = getFieldName($this_sibling); if (typeof data.relations != 'undefined') { $.each(data.relations, function(key, value) { if(key == field_name) { diff --git a/js/tbl_change.js b/js/tbl_change.js index 8fc7eca337..5e6ce842e0 100644 --- a/js/tbl_change.js +++ b/js/tbl_change.js @@ -70,21 +70,8 @@ function daysInFebruary (year){ //function to convert single digit to double digit function fractionReplace(num) { - num=parseInt(num); - var res="00"; - switch(num) - { - case 1:res= "01";break; - case 2:res= "02";break; - case 3:res= "03";break; - case 4:res= "04";break; - case 5:res= "05";break; - case 6:res= "06";break; - case 7:res= "07";break; - case 8:res= "08";break; - case 9:res= "09";break; - } - return res; + num = parseInt(num); + return num >= 1 && num <= 9 ? '0' + num : '00'; } /* function to check the validity of date diff --git a/js/tbl_structure.js b/js/tbl_structure.js index d4ef1cdf97..a9b9adae77 100644 --- a/js/tbl_structure.js +++ b/js/tbl_structure.js @@ -18,7 +18,7 @@ * */ $(document).ready(function() { - + /** * Attach Event Handler for 'Drop Column' * @@ -153,102 +153,33 @@ $(document).ready(function() { event.preventDefault(); /*Check whether atleast one row is selected for change*/ - if($("#tablestructure tbody tr").hasClass("marked")){ - var div = $('
'); - - /** - * @var button_options Object that stores the options passed to jQueryUI - * dialog - */ - var button_options = {}; - // in the following function we need to use $(this) - button_options[PMA_messages['strCancel']] = function() {$(this).parent().dialog('close').remove();} - - var button_options_error = {}; - button_options_error[PMA_messages['strOK']] = function() {$(this).parent().dialog('close').remove();} + if ($("#tablestructure tbody tr").hasClass("marked")) { + /*Define the action and $url variabls for the post method*/ var $form = $("#fieldsForm"); - var $msgbox = PMA_ajaxShowMessage(); - - $.get( $form.attr('action') , $form.serialize()+"&ajax_request=true&submit_mult=change" , function(data) { - //in the case of an error, show the error message returned. - if (data.success != undefined && data.success == false) { - div - .append(data.error) - .dialog({ - title: PMA_messages['strChangeTbl'], - height: 230, - width: 900, - open: PMA_verifyTypeOfAllColumns, - buttons : button_options_error - })// end dialog options - } else { - div - .append(data) - .dialog({ - title: PMA_messages['strChangeTbl'], - height: 600, - width: 900, - open: PMA_verifyTypeOfAllColumns, - buttons : button_options - }) - //Remove the top menu container from the dialog - .find("#topmenucontainer").hide() - ; // end dialog options - $("#append_fields_form input[name=do_save_data]").addClass("ajax"); - } - PMA_ajaxRemoveMessage($msgbox); - }) // end $.get() + var action = $form.attr('action'); + var url = $form.serialize()+"&ajax_request=true&submit_mult=change"; + /*Calling for the changeColumns fucntion*/ + changeColumns(action,url); } else { PMA_ajaxShowMessage(PMA_messages['strNoRowSelected']); } }); /** - *Ajax action for submitting the column change form + *Ajax event handler for single column change **/ - $("#append_fields_form input[name=do_save_data].ajax").live('click', function(event) { + $("#fieldsForm.ajax #tablestructure tbody tr td.edit a").live('click', function(event){ event.preventDefault(); - /** - * @var the_form object referring to the export form - */ - var $form = $("#append_fields_form"); - - PMA_prepareForAjaxRequest($form); - //User wants to submit the form - $.post($form.attr('action'), $form.serialize()+"&do_save_data=Save", function(data) { - if ($("#sqlqueryresults").length != 0) { - $("#sqlqueryresults").remove(); - } else if ($(".error").length != 0) { - $(".error").remove(); - } - if (data.success == true) { - PMA_ajaxShowMessage(data.message); - $("
").insertAfter("#topmenucontainer"); - $("#sqlqueryresults").html(data.sql_query); - $("#result_query .notice").remove(); - $("#result_query").prepend((data.message)); - if ($("#change_column_dialog").length > 0) { - $("#change_column_dialog").dialog("close").remove(); - } - /*Reload the field form*/ - $.post($("#fieldsForm").attr('action'), $("#fieldsForm").serialize()+"&ajax_request=true", function(form_data) { - $("#fieldsForm").remove(); - var $temp_div = $("
").append(form_data); - if ($("#sqlqueryresults").length != 0) { - $temp_div.find("#fieldsForm").insertAfter("#sqlqueryresults"); - } else { - $temp_div.find("#fieldsForm").insertAfter(".error"); - } - /*Call the function to display the more options in table*/ - displayMoreTableOpts(); - }); - } else { - var $temp_div = $("
").append(data); - var $error = $temp_div.find(".error code").addClass("error"); - PMA_ajaxShowMessage($error); - } - }) // end $.post() - }) // end insert table button "do_save_data" + /*Define the action and $url variabls for the post method*/ + var action = "tbl_alter.php"; + var url = $(this).attr('href'); + if (url.substring(0, 13) == "tbl_alter.php") { + url = url.substring(14, url.length); + } + url = url + "&ajax_request=true"; + /*Calling for the changeColumns fucntion*/ + changeColumns(action,url); + }); /** *Ajax event handler for index edit @@ -261,7 +192,11 @@ $(document).ready(function() { } url = url + "&ajax_request=true"; - var div = $('
'); + /*Remove the hidden dialogs if there are*/ + if ($('#edit_index_dialog').length != 0) { + $('#edit_index_dialog').remove(); + } + var $div = $('
'); /** * @var button_options Object that stores the options passed to jQueryUI @@ -269,37 +204,41 @@ $(document).ready(function() { */ var button_options = {}; // in the following function we need to use $(this) - button_options[PMA_messages['strCancel']] = function() {$(this).parent().dialog('close').remove();} + button_options[PMA_messages['strCancel']] = function() {$(this).dialog('close').remove();} var button_options_error = {}; - button_options_error[PMA_messages['strOK']] = function() {$(this).parent().dialog('close').remove();} + button_options_error[PMA_messages['strOK']] = function() {$(this).dialog('close').remove();} var $msgbox = PMA_ajaxShowMessage(); $.get( "tbl_indexes.php" , url , function(data) { //in the case of an error, show the error message returned. if (data.success != undefined && data.success == false) { - div + $div .append(data.error) .dialog({ title: PMA_messages['strEdit'], height: 230, width: 900, open: PMA_verifyTypeOfAllColumns, + modal: true, buttons : button_options_error })// end dialog options } else { - div + $div .append(data) .dialog({ title: PMA_messages['strEdit'], height: 600, width: 900, open: PMA_verifyTypeOfAllColumns, + modal: true, buttons : button_options }) //Remove the top menu container from the dialog .find("#topmenucontainer").hide() ; // end dialog options + checkIndexType(); + checkIndexName("index_frm"); } PMA_ajaxRemoveMessage($msgbox); }) // end $.get() @@ -330,16 +269,22 @@ $(document).ready(function() { /*Reload the field form*/ $("#table_index").remove(); - var temp_div = $("
").append(data.index_table); - $(temp_div).find("#table_index").insertAfter("#index_header"); + var $temp_div = $("
").append(data.index_table); + $temp_div.find("#table_index").insertAfter("#index_header"); if ($("#edit_index_dialog").length > 0) { $("#edit_index_dialog").dialog("close").remove(); } } else { - var temp_div = $("
").append(data.error); - var error = $(temp_div).find(".error code").addClass("error"); - PMA_ajaxShowMessage(error); + if(data.error != undefined) { + var $temp_div = $("
").append(data.error); + if ($temp_div.find(".error code").length != 0) { + var $error = $temp_div.find(".error code").addClass("error"); + } else { + var $error = $temp_div; + } + } + PMA_ajaxShowMessage($error); } }) // end $.post() @@ -359,8 +304,8 @@ $(document).ready(function() { //User wants to submit the form $.post($form.attr('action'), $form.serialize()+"&add_fields=Go", function(data) { $("#index_columns").remove(); - var temp_div = $("
").append(data); - $(temp_div).find("#index_columns").insertAfter("#index_frm fieldset .error"); + var $temp_div = $("
").append(data); + $temp_div.find("#index_columns").appendTo("#index_edit_fields"); }) // end $.post() }) // end insert table button "Go" @@ -393,3 +338,66 @@ $(document).ready(function() { }) // end $(document).ready() + +/** + * Loads the append_fields_form to the Change dialog allowing users + * to change the columns + * @param string action Variable which parses the name of the + * destination file + * @param string $url Variable which parses the data for the + * post action + */ +function changeColumns(action,url) { + /*Remove the hidden dialogs if there are*/ + if ($('#change_column_dialog').length != 0) { + $('#change_column_dialog').remove(); + } + var $div = $('
'); + + /** + * @var button_options Object that stores the options passed to jQueryUI + * dialog + */ + var button_options = {}; + // in the following function we need to use $(this) + button_options[PMA_messages['strCancel']] = function() {$(this).dialog('close').remove();} + + var button_options_error = {}; + button_options_error[PMA_messages['strOK']] = function() {$(this).dialog('close').remove();} + var $msgbox = PMA_ajaxShowMessage(); + + $.get( action , url , function(data) { + //in the case of an error, show the error message returned. + if (data.success != undefined && data.success == false) { + $div + .append(data.error) + .dialog({ + title: PMA_messages['strChangeTbl'], + height: 230, + width: 900, + modal: true, + open: PMA_verifyTypeOfAllColumns, + buttons : button_options_error + })// end dialog options + } else { + $div + .append(data) + .dialog({ + title: PMA_messages['strChangeTbl'], + height: 600, + width: 900, + modal: true, + open: PMA_verifyTypeOfAllColumns, + buttons : button_options + }) + //Remove the top menu container from the dialog + .find("#topmenucontainer").hide() + ; // end dialog options + $("#append_fields_form input[name=do_save_data]").addClass("ajax"); + /*changed the z-index of the enum editor to allow the edit*/ + $("#enum_editor").css("z-index", "1100"); + } + PMA_ajaxRemoveMessage($msgbox); + }) // end $.get() +} + diff --git a/libraries/Index.class.php b/libraries/Index.class.php index 1800aee33d..7cc47991e3 100644 --- a/libraries/Index.class.php +++ b/libraries/Index.class.php @@ -194,9 +194,10 @@ class PMA_Index // $columns[names][] // $columns[sub_parts][] foreach ($columns['names'] as $key => $name) { + $sub_part = isset($columns['sub_parts'][$key]) ? $columns['sub_parts'][$key] : ''; $_columns[] = array( 'Column_name' => $name, - 'Sub_part' => $columns['sub_parts'][$key], + 'Sub_part' => $sub_part, ); } } else { diff --git a/libraries/Table.class.php b/libraries/Table.class.php index 37df829d74..83e67fd433 100644 --- a/libraries/Table.class.php +++ b/libraries/Table.class.php @@ -336,13 +336,11 @@ class PMA_Table $is_timestamp = strpos(strtoupper($type), 'TIMESTAMP') !== false; - /** - * @todo include db-name - */ $query = PMA_backquote($name) . ' ' . $type; if ($length != '' - && !preg_match('@^(DATE|DATETIME|TIME|TINYBLOB|TINYTEXT|BLOB|TEXT|MEDIUMBLOB|MEDIUMTEXT|LONGBLOB|LONGTEXT)$@i', $type)) { + && !preg_match('@^(DATE|DATETIME|TIME|TINYBLOB|TINYTEXT|BLOB|TEXT|MEDIUMBLOB|MEDIUMTEXT|LONGBLOB|LONGTEXT' + . '|SERIAL|BOOLEAN)$@i', $type)) { $query .= '(' . $length . ')'; } @@ -1242,8 +1240,8 @@ class PMA_Table $sql_query = " SELECT `prefs` FROM " . $pma_table . " WHERE `username` = '" . $GLOBALS['cfg']['Server']['user'] . "'" . - " AND `db_name` = '" . $this->db_name . "'" . - " AND `table_name` = '" . $this->name . "'"; + " AND `db_name` = '" . PMA_sqlAddSlashes($this->db_name) . "'" . + " AND `table_name` = '" . PMA_sqlAddSlashes($this->name) . "'"; $row = PMA_DBI_fetch_array(PMA_query_as_controluser($sql_query)); if (isset($row[0])) { @@ -1266,8 +1264,9 @@ class PMA_Table $username = $GLOBALS['cfg']['Server']['user']; $sql_query = " REPLACE INTO " . $pma_table . - " VALUES ('" . $username . "', '" . $this->db_name . "', '" . - $this->name . "', '" . PMA_sqlAddSlashes(json_encode($this->uiprefs)) . "')"; + " VALUES ('" . $username . "', '" . PMA_sqlAddSlashes($this->db_name) . "', '" . + PMA_sqlAddSlashes($this->name) . "', '" . + PMA_sqlAddSlashes(json_encode($this->uiprefs)) . "')"; $success = PMA_DBI_try_query($sql_query, $GLOBALS['controllink']); diff --git a/libraries/blobstreaming.lib.php b/libraries/blobstreaming.lib.php index d9893dd555..cd1e5d49dd 100644 --- a/libraries/blobstreaming.lib.php +++ b/libraries/blobstreaming.lib.php @@ -327,7 +327,6 @@ function PMA_BS_CreateReferenceLink($bs_reference, $db_name) return 'Error'; } - //$output = "$content_type"; $output = $content_type; // specify custom HTML for various content types diff --git a/libraries/common.inc.php b/libraries/common.inc.php index 8ccc7c0dec..1abe88544e 100644 --- a/libraries/common.inc.php +++ b/libraries/common.inc.php @@ -363,6 +363,7 @@ $goto_whitelist = array( 'db_create.php', 'db_datadict.php', 'db_sql.php', + 'db_events.php', 'db_export.php', 'db_importdocsql.php', 'db_qbe.php', diff --git a/libraries/common.lib.php b/libraries/common.lib.php index 61f3102f66..e64c75161a 100644 --- a/libraries/common.lib.php +++ b/libraries/common.lib.php @@ -140,10 +140,10 @@ function PMA_displayMaximumUploadSize($max_upload_size) * * @access public */ - function PMA_generateHiddenMaxFileSize($max_size) - { - return ''; - } +function PMA_generateHiddenMaxFileSize($max_size) +{ + return ''; +} /** * Add slashes before "'" and "\" characters so a value containing them can @@ -377,7 +377,7 @@ function PMA_showMySQLDocu($chapter, $link, $big_icon = false, $anchor = '', $ju $mysql = '5.1'; /* l10n: Language to use for MySQL 5.1 documentation, please use only languages which do exist in official documentation. */ $lang = _pgettext('MySQL 5.1 documentation language', 'en'); - } elseif (PMA_MYSQL_INT_VERSION >= 50000) { + } else { $mysql = '5.0'; /* l10n: Language to use for MySQL 5.0 documentation, please use only languages which do exist in official documentation. */ $lang = _pgettext('MySQL 5.0 documentation language', 'en'); @@ -707,7 +707,7 @@ function PMA_getTableList($db, $tables = null, $limit_offset = 0, $limit_count = $group_name_full = ''; $parts_cnt = count($parts) - 1; while ($i < $parts_cnt - && $i < $GLOBALS['cfg']['LeftFrameTableLevel']) { + && $i < $GLOBALS['cfg']['LeftFrameTableLevel']) { $group_name = $parts[$i] . $sep; $group_name_full .= $group_name; @@ -739,7 +739,7 @@ function PMA_getTableList($db, $tables = null, $limit_offset = 0, $limit_count = if ($GLOBALS['cfg']['ShowTooltipAliasTB'] - && $GLOBALS['cfg']['ShowTooltipAliasTB'] !== 'nested') { + && $GLOBALS['cfg']['ShowTooltipAliasTB'] !== 'nested') { // switch tooltip and name $table['Comment'] = $table['Name']; $table['disp_name'] = $table['Comment']; @@ -807,8 +807,6 @@ function PMA_backquote($a_name, $do_it = true) */ function PMA_whichCrlf() { - $the_crlf = "\n"; - // The 'PMA_USR_OS' constant is defined in "./libraries/Config.class.php" // Win case if (PMA_USR_OS == 'Win') { @@ -825,15 +823,12 @@ function PMA_whichCrlf() /** * Reloads navigation if needed. * - * @param $jsonly prints out pure JavaScript - * @global array configuration + * @param bool $jsonly prints out pure JavaScript * * @access public */ function PMA_reloadNavigation($jsonly=false) { - global $cfg; - // Reloads the navigation frame via JavaScript if required if (isset($GLOBALS['reload']) && $GLOBALS['reload']) { // one of the reasons for a reload is when a table is dropped @@ -869,7 +864,7 @@ if (!$jsonly) * @param string $sql_query the query to display * @param string $type the type (level) of the message * @param boolean $is_view is this a message after a VIEW operation? - * @global array the configuration array + * @return string * @access public */ function PMA_showMessage($message, $sql_query = null, $type = 'notice', $is_view = false) @@ -1218,6 +1213,7 @@ function PMA_showMessage($message, $sql_query = null, $type = 'notice', $is_view ob_end_clean(); return $buffer_contents; } + return null; } // end of the 'PMA_showMessage()' function /** @@ -1225,7 +1221,6 @@ function PMA_showMessage($message, $sql_query = null, $type = 'notice', $is_view * * @access public * @return boolean whether profiling is supported - * */ function PMA_profilingSupported() { @@ -1250,7 +1245,6 @@ function PMA_profilingSupported() * * @param string $sql_query * @access public - * */ function PMA_profilingCheckbox($sql_query) { @@ -1350,8 +1344,6 @@ function PMA_localizeNumber($value) * @return string the formatted value and its unit * * @access public - * - * @version 1.1.0 - 2005-10-27 */ function PMA_formatNumber($value, $digits_left = 3, $digits_right = 0, $only_down = false, $noTrailingZero = true) { @@ -1769,7 +1761,7 @@ function PMA_linkOrButton($url, $message, $tag_params = array(), } } // end if... else... - return $ret; + return $ret; } // end of the 'PMA_linkOrButton()' function @@ -1843,7 +1835,6 @@ function PMA_flipstring($string, $Separator = "
\n") return $format_string; } - /** * Function added to avoid path disclosures. * Called by each script that needs parameters, it displays @@ -1930,9 +1921,8 @@ function PMA_getUniqueCondition($handle, $fields_cnt, $fields_meta, $row, $force $meta->orgname = $meta->name; if (isset($GLOBALS['analyzed_sql'][0]['select_expr']) - && is_array($GLOBALS['analyzed_sql'][0]['select_expr'])) { - foreach ($GLOBALS['analyzed_sql'][0]['select_expr'] - as $select_expr) { + && is_array($GLOBALS['analyzed_sql'][0]['select_expr'])) { + foreach ($GLOBALS['analyzed_sql'][0]['select_expr'] as $select_expr) { // need (string) === (string) // '' !== 0 but '' == 0 if ((string) $select_expr['alias'] === (string) $meta->name) { @@ -1980,18 +1970,18 @@ function PMA_getUniqueCondition($handle, $fields_cnt, $fields_meta, $row, $force $condition .= '= ' . $row[$i] . ' AND'; } elseif (($meta->type == 'blob' || $meta->type == 'string') // hexify only if this is a true not empty BLOB or a BINARY - && stristr($field_flags, 'BINARY') - && !empty($row[$i])) { - // do not waste memory building a too big condition - if (strlen($row[$i]) < 1000) { - // use a CAST if possible, to avoid problems - // if the field contains wildcard characters % or _ - $condition .= '= CAST(0x' . bin2hex($row[$i]) - . ' AS BINARY) AND'; - } else { - // this blob won't be part of the final condition - $condition = ''; - } + && stristr($field_flags, 'BINARY') + && !empty($row[$i])) { + // do not waste memory building a too big condition + if (strlen($row[$i]) < 1000) { + // use a CAST if possible, to avoid problems + // if the field contains wildcard characters % or _ + $condition .= '= CAST(0x' . bin2hex($row[$i]) + . ' AS BINARY) AND'; + } else { + // this blob won't be part of the final condition + $condition = ''; + } } elseif ($meta->type == 'bit') { $condition .= "= b'" . PMA_printable_bit_value($row[$i], $meta->length) . "' AND"; } else { @@ -2167,12 +2157,12 @@ function PMA_pageselector($rows, $pageNow = 1, $nbTotalPage = 1, * Generate navigation for a list * * @todo use $pos from $_url_params - * @param integer number of elements in the list - * @param integer current position in the list - * @param array url parameters - * @param string script name for form target - * @param string target frame - * @param integer maximum number of elements to display from the list + * @param int $count number of elements in the list + * @param int $pos current position in the list + * @param array $_url_params url parameters + * @param string $script script name for form target + * @param string $frame target frame + * @param int $max_count maximum number of elements to display from the list * * @access public */ @@ -2354,10 +2344,11 @@ function PMA_display_html_radio($html_field_name, $choices, $checked_choice = '' * Generates and returns an HTML dropdown * * @param string $select_name - * @param array $choices the choices values - * @param string $active_choice the choice to select by default - * @param string $id the id of the select element; can be different in case - * the dropdown is present more than once on the page + * @param array $choices choices values + * @param string $active_choice the choice to select by default + * @param string $id id of the select element; can be different in case + * the dropdown is present more than once on the page + * @return string * @todo support titles */ function PMA_generate_html_dropdown($select_name, $choices, $active_choice, $id) @@ -2401,6 +2392,87 @@ function PMA_generate_slider_effect($id, $message) \n"; + if ($GLOBALS['cfg']['AjaxEnable']) { + $retval .= "\n"; + $retval .= "
\n"; + $retval .= "
\n"; + $retval .= "
\n"; + $retval .= " \n"; + $retval .= " \n"; + $retval .= "
 
\n"; + $retval .= " \n"; + $retval .= " $link_off\n"; + $retval .= "
"; + $retval .= str_replace(' ', ' ', $options[0]['label']) . "
\n"; + $retval .= "
\n"; + $retval .= " \n"; + $retval .= " \n"; + $retval .= " $callback\n"; + $retval .= " {$GLOBALS['text_dir']}\n"; + $retval .= "
\n"; + $retval .= "
\n"; + $retval .= "
\n"; + } + $retval .= ""; + + return $retval; +} // end PMA_toggleButton() + /** * Clears cache content which needs to be refreshed on user change. */ @@ -2411,8 +2483,8 @@ function PMA_clearUserCache() { /** * Verifies if something is cached in the session * - * @param string $var - * @param scalar $server + * @param string $var + * @param int|true $server * @return boolean */ function PMA_cacheExists($var, $server = 0) @@ -2426,8 +2498,8 @@ function PMA_cacheExists($var, $server = 0) /** * Gets cached information from the session * - * @param string $var - * @param scalar $server + * @param string $var + * @param int|true $server * @return mixed */ function PMA_cacheGet($var, $server = 0) @@ -2445,9 +2517,9 @@ function PMA_cacheGet($var, $server = 0) /** * Caches information in the session * - * @param string $var - * @param mixed $val - * @param integer $server + * @param string $var + * @param mixed $val + * @param int|true $server * @return mixed */ function PMA_cacheSet($var, $val = null, $server = 0) @@ -2461,8 +2533,8 @@ function PMA_cacheSet($var, $val = null, $server = 0) /** * Removes cached information from the session * - * @param string $var - * @param scalar $server + * @param string $var + * @param int|true $server */ function PMA_cacheUnset($var, $server = 0) { @@ -2872,7 +2944,7 @@ function PMA_getSupportedDatatypes($html = false, $selected = '') foreach ($cfg['ColumnTypes'] as $key => $value) { if (is_array($value)) { $retval .= ""; - foreach ($value as $subkey => $subvalue) { + foreach ($value as $subvalue) { if ($subvalue == $selected) { $retval .= "