/* vim: set expandtab sw=4 ts=4 sts=4: */ /** * general function, usally for data manipulation pages * */ /** * @var sql_box_locked lock for the sqlbox textarea in the querybox/querywindow */ var sql_box_locked = false; /** * @var array holds elements which content should only selected once */ var only_once_elements = new Array(); /** * @var ajax_message_init boolean boolean that stores status of * notification for PMA_ajaxShowNotification */ var ajax_message_init = false; /** * Generate a new password and copy it to the password input areas * * @param object the form that holds the password fields * * @return boolean always true */ function suggestPassword(passwd_form) { // restrict the password to just letters and numbers to avoid problems: // "editors and viewers regard the password as multiple words and // things like double click no longer work" var pwchars = "abcdefhjmnpqrstuvwxyz23456789ABCDEFGHJKLMNPQRSTUVWYXZ"; var passwordlength = 16; // do we want that to be dynamic? no, keep it simple :) var passwd = passwd_form.generated_pw; passwd.value = ''; for ( i = 0; i < passwordlength; i++ ) { passwd.value += pwchars.charAt( Math.floor( Math.random() * pwchars.length ) ) } passwd_form.text_pma_pw.value = passwd.value; passwd_form.text_pma_pw2.value = passwd.value; return true; } /** * for libraries/display_change_password.lib.php * libraries/user_password.php * */ function displayPasswordGenerateButton() { $('#tr_element_before_generate_password').parent().append('' + PMA_messages['strGeneratePassword'] + ''); $('#div_element_before_generate_password').parent().append('
'); } /** * selects the content of a given object, f.e. a textarea * * @param object element element of which the content will be selected * @param var lock variable which holds the lock for this element * or true, if no lock exists * @param boolean only_once if true this is only done once * f.e. only on first focus */ function selectContent( element, lock, only_once ) { if ( only_once && only_once_elements[element.name] ) { return; } only_once_elements[element.name] = true; if ( lock ) { return; } element.select(); } /** * Displays an confirmation box before to submit a "DROP DATABASE" query. * This function is called while clicking links * * @param object the link * @param object the sql query to submit * * @return boolean whether to run the query or not */ function confirmLinkDropDB(theLink, theSqlQuery) { // Confirmation is not required in the configuration file // or browser is Opera (crappy js implementation) if (PMA_messages['strDoYouReally'] == '' || typeof(window.opera) != 'undefined') { return true; } var is_confirmed = confirm(PMA_messages['strDropDatabaseStrongWarning'] + '\n' + PMA_messages['strDoYouReally'] + ' :\n' + theSqlQuery); if (is_confirmed) { theLink.href += '&is_js_confirmed=1'; } return is_confirmed; } // end of the 'confirmLinkDropDB()' function /** * Displays an confirmation box before to submit a "DROP/DELETE/ALTER" query. * This function is called while clicking links * * @param object the link * @param object the sql query to submit * * @return boolean whether to run the query or not */ function confirmLink(theLink, theSqlQuery) { // Confirmation is not required in the configuration file // or browser is Opera (crappy js implementation) if (PMA_messages['strDoYouReally'] == '' || typeof(window.opera) != 'undefined') { return true; } var is_confirmed = confirm(PMA_messages['strDoYouReally'] + ' :\n' + theSqlQuery); if (is_confirmed) { if ( typeof(theLink.href) != 'undefined' ) { theLink.href += '&is_js_confirmed=1'; } else if ( typeof(theLink.form) != 'undefined' ) { theLink.form.action += '?is_js_confirmed=1'; } } return is_confirmed; } // end of the 'confirmLink()' function /** * Displays an confirmation box before doing some action * * @param object the message to display * * @return boolean whether to run the query or not * * @todo used only by libraries/display_tbl.lib.php. figure out how it is used * and replace with a jQuery equivalent */ function confirmAction(theMessage) { // TODO: Confirmation is not required in the configuration file // or browser is Opera (crappy js implementation) if (typeof(window.opera) != 'undefined') { return true; } var is_confirmed = confirm(theMessage); return is_confirmed; } // end of the 'confirmAction()' function /** * Displays an error message if a "DROP DATABASE" statement is submitted * while it isn't allowed, else confirms a "DROP/DELETE/ALTER" query before * sumitting it if required. * This function is called by the 'checkSqlQuery()' js function. * * @param object the form * @param object the sql query textarea * * @return boolean whether to run the query or not * * @see checkSqlQuery() */ function confirmQuery(theForm1, sqlQuery1) { // Confirmation is not required in the configuration file if (PMA_messages['strDoYouReally'] == '') { return true; } // The replace function (js1.2) isn't supported else if (typeof(sqlQuery1.value.replace) == 'undefined') { return true; } // js1.2+ -> validation with regular expressions else { // "DROP DATABASE" statement isn't allowed if (PMA_messages['strNoDropDatabases'] != '') { var drop_re = new RegExp('(^|;)\\s*DROP\\s+(IF EXISTS\\s+)?DATABASE\\s', 'i'); if (drop_re.test(sqlQuery1.value)) { alert(PMA_messages['strNoDropDatabases']); theForm1.reset(); sqlQuery1.focus(); return false; } // end if } // end if // Confirms a "DROP/DELETE/ALTER/TRUNCATE" statement // // TODO: find a way (if possible) to use the parser-analyser // for this kind of verification // For now, I just added a ^ to check for the statement at // beginning of expression var do_confirm_re_0 = new RegExp('^\\s*DROP\\s+(IF EXISTS\\s+)?(TABLE|DATABASE|PROCEDURE)\\s', 'i'); var do_confirm_re_1 = new RegExp('^\\s*ALTER\\s+TABLE\\s+((`[^`]+`)|([A-Za-z0-9_$]+))\\s+DROP\\s', 'i'); var do_confirm_re_2 = new RegExp('^\\s*DELETE\\s+FROM\\s', 'i'); var do_confirm_re_3 = new RegExp('^\\s*TRUNCATE\\s', 'i'); if (do_confirm_re_0.test(sqlQuery1.value) || do_confirm_re_1.test(sqlQuery1.value) || do_confirm_re_2.test(sqlQuery1.value) || do_confirm_re_3.test(sqlQuery1.value)) { var message = (sqlQuery1.value.length > 100) ? sqlQuery1.value.substr(0, 100) + '\n ...' : sqlQuery1.value; var is_confirmed = confirm(PMA_messages['strDoYouReally'] + ' :\n' + message); // statement is confirmed -> update the // "is_js_confirmed" form field so the confirm test won't be // run on the server side and allows to submit the form if (is_confirmed) { theForm1.elements['is_js_confirmed'].value = 1; return true; } // statement is rejected -> do not submit the form else { window.focus(); sqlQuery1.focus(); return false; } // end if (handle confirm box result) } // end if (display confirm box) } // end confirmation stuff return true; } // end of the 'confirmQuery()' function /** * Displays a confirmation box before disabling the BLOB repository for a given database. * This function is called while clicking links * * @param object the database * * @return boolean whether to disable the repository or not */ function confirmDisableRepository(theDB) { // Confirmation is not required in the configuration file // or browser is Opera (crappy js implementation) if (PMA_messages['strDoYouReally'] == '' || typeof(window.opera) != 'undefined') { return true; } var is_confirmed = confirm(PMA_messages['strBLOBRepositoryDisableStrongWarning'] + '\n' + PMA_messages['strBLOBRepositoryDisableAreYouSure']); return is_confirmed; } // end of the 'confirmDisableBLOBRepository()' function /** * Displays an error message if the user submitted the sql query form with no * sql query, else checks for "DROP/DELETE/ALTER" statements * * @param object the form * * @return boolean always false * * @see confirmQuery() */ function checkSqlQuery(theForm) { var sqlQuery = theForm.elements['sql_query']; var isEmpty = 1; // The replace function (js1.2) isn't supported -> basic tests if (typeof(sqlQuery.value.replace) == 'undefined') { isEmpty = (sqlQuery.value == '') ? 1 : 0; if (isEmpty && typeof(theForm.elements['sql_file']) != 'undefined') { isEmpty = (theForm.elements['sql_file'].value == '') ? 1 : 0; } if (isEmpty && typeof(theForm.elements['sql_localfile']) != 'undefined') { isEmpty = (theForm.elements['sql_localfile'].value == '') ? 1 : 0; } if (isEmpty && typeof(theForm.elements['id_bookmark']) != 'undefined') { isEmpty = (theForm.elements['id_bookmark'].value == null || theForm.elements['id_bookmark'].value == ''); } } // js1.2+ -> validation with regular expressions else { var space_re = new RegExp('\\s+'); if (typeof(theForm.elements['sql_file']) != 'undefined' && theForm.elements['sql_file'].value.replace(space_re, '') != '') { return true; } if (typeof(theForm.elements['sql_localfile']) != 'undefined' && theForm.elements['sql_localfile'].value.replace(space_re, '') != '') { return true; } if (isEmpty && typeof(theForm.elements['id_bookmark']) != 'undefined' && (theForm.elements['id_bookmark'].value != null || theForm.elements['id_bookmark'].value != '') && theForm.elements['id_bookmark'].selectedIndex != 0 ) { return true; } // Checks for "DROP/DELETE/ALTER" statements if (sqlQuery.value.replace(space_re, '') != '') { if (confirmQuery(theForm, sqlQuery)) { return true; } else { return false; } } theForm.reset(); isEmpty = 1; } if (isEmpty) { sqlQuery.select(); alert(PMA_messages['strFormEmpty']); sqlQuery.focus(); return false; } return true; } // end of the 'checkSqlQuery()' function // Global variable row_class is set to even var row_class = 'even'; /** * Generates a row dynamically in the differences table displaying * the complete statistics of difference in table like number of * rows to be updated, number of rows to be inserted, number of * columns to be added, number of columns to be removed, etc. * * @param index index of matching table * @param update_size number of rows/column to be updated * @param insert_size number of rows/coulmns to be inserted * @param remove_size number of columns to be removed * @param insert_index number of indexes to be inserted * @param remove_index number of indexes to be removed * @param img_obj image object * @param table_name name of the table */ function showDetails(i, update_size, insert_size, remove_size, insert_index, remove_index, img_obj, table_name) { // The path of the image is split to facilitate comparison var relative_path = (img_obj.src).split("themes/"); // The image source is changed when the showDetails function is called. if (relative_path[1] == 'original/img/new_data_hovered.jpg') { img_obj.src = "./themes/original/img/new_data_selected_hovered.jpg"; img_obj.alt = PMA_messages['strClickToUnselect']; //only for IE browser } else if (relative_path[1] == 'original/img/new_struct_hovered.jpg') { img_obj.src = "./themes/original/img/new_struct_selected_hovered.jpg"; img_obj.alt = PMA_messages['strClickToUnselect']; } else if (relative_path[1] == 'original/img/new_struct_selected_hovered.jpg') { img_obj.src = "./themes/original/img/new_struct_hovered.jpg"; img_obj.alt = PMA_messages['strClickToSelect']; } else if (relative_path[1] == 'original/img/new_data_selected_hovered.jpg') { img_obj.src = "./themes/original/img/new_data_hovered.jpg"; img_obj.alt = PMA_messages['strClickToSelect']; } var div = document.getElementById("list"); var table = div.getElementsByTagName("table")[0]; var table_body = table.getElementsByTagName("tbody")[0]; //Global variable row_class is being used if (row_class == 'even') { row_class = 'odd'; } else { row_class = 'even'; } // If the red or green button against a table name is pressed then append a new row to show the details of differences of this table. if ((relative_path[1] != 'original/img/new_struct_selected_hovered.jpg') && (relative_path[1] != 'original/img/new_data_selected_hovered.jpg')) { var newRow = document.createElement("tr"); newRow.setAttribute("class", row_class); newRow.className = row_class; // Id assigned to this row element is same as the index of this table name in the matching_tables/source_tables_uncommon array newRow.setAttribute("id" , i); var table_name_cell = document.createElement("td"); table_name_cell.align = "center"; table_name_cell.innerHTML = table_name ; newRow.appendChild(table_name_cell); var create_table = document.createElement("td"); create_table.align = "center"; var add_cols = document.createElement("td"); add_cols.align = "center"; var remove_cols = document.createElement("td"); remove_cols.align = "center"; var alter_cols = document.createElement("td"); alter_cols.align = "center"; var add_index = document.createElement("td"); add_index.align = "center"; var delete_index = document.createElement("td"); delete_index.align = "center"; var update_rows = document.createElement("td"); update_rows.align = "center"; var insert_rows = document.createElement("td"); insert_rows.align = "center"; var tick_image = document.createElement("img"); tick_image.src = "./themes/original/img/s_success.png"; if (update_size == '' && insert_size == '' && remove_size == '') { /** This is the case when the table needs to be created in target database. */ create_table.appendChild(tick_image); add_cols.innerHTML = "--"; remove_cols.innerHTML = "--"; alter_cols.innerHTML = "--"; delete_index.innerHTML = "--"; add_index.innerHTML = "--"; update_rows.innerHTML = "--"; insert_rows.innerHTML = "--"; newRow.appendChild(create_table); newRow.appendChild(add_cols); newRow.appendChild(remove_cols); newRow.appendChild(alter_cols); newRow.appendChild(delete_index); newRow.appendChild(add_index); newRow.appendChild(update_rows); newRow.appendChild(insert_rows); } else if (update_size == '' && remove_size == '') { /** This is the case when data difference is displayed in the table which is present in source but absent from target database */ create_table.innerHTML = "--"; add_cols.innerHTML = "--"; remove_cols.innerHTML = "--"; alter_cols.innerHTML = "--"; add_index.innerHTML = "--"; delete_index.innerHTML = "--"; update_rows.innerHTML = "--"; insert_rows.innerHTML = insert_size; newRow.appendChild(create_table); newRow.appendChild(add_cols); newRow.appendChild(remove_cols); newRow.appendChild(alter_cols); newRow.appendChild(delete_index); newRow.appendChild(add_index); newRow.appendChild(update_rows); newRow.appendChild(insert_rows); } else if (remove_size == '') { /** This is the case when data difference between matching_tables is displayed. */ create_table.innerHTML = "--"; add_cols.innerHTML = "--"; remove_cols.innerHTML = "--"; alter_cols.innerHTML = "--"; add_index.innerHTML = "--"; delete_index.innerHTML = "--"; update_rows.innerHTML = update_size; insert_rows.innerHTML = insert_size; newRow.appendChild(create_table); newRow.appendChild(add_cols); newRow.appendChild(remove_cols); newRow.appendChild(alter_cols); newRow.appendChild(delete_index); newRow.appendChild(add_index); newRow.appendChild(update_rows); newRow.appendChild(insert_rows); } else { /** This is the case when structure difference between matching_tables id displayed */ create_table.innerHTML = "--"; add_cols.innerHTML = insert_size; remove_cols.innerHTML = remove_size; alter_cols.innerHTML = update_size; delete_index.innerHTML = remove_index; add_index.innerHTML = insert_index; update_rows.innerHTML = "--"; insert_rows.innerHTML = "--"; newRow.appendChild(create_table); newRow.appendChild(add_cols); newRow.appendChild(remove_cols); newRow.appendChild(alter_cols); newRow.appendChild(delete_index); newRow.appendChild(add_index); newRow.appendChild(update_rows); newRow.appendChild(insert_rows); } table_body.appendChild(newRow); } else if ((relative_path[1] != 'original/img/new_struct_hovered.jpg') && (relative_path[1] != 'original/img/new_data_hovered.jpg')) { //The case when the row showing the details need to be removed from the table i.e. the difference button is deselected now. var table_rows = table_body.getElementsByTagName("tr"); var j; var index = 0; for (j=0; j < table_rows.length; j++) { if (table_rows[j].id == i) { index = j; table_rows[j].parentNode.removeChild(table_rows[j]); } } //The table row css is being adjusted. Class "odd" for odd rows and "even" for even rows should be maintained. for(index; index < table_rows.length; index++) { row_class_element = table_rows[index].getAttribute('class'); if (row_class_element == "even") { table_rows[index].setAttribute("class","odd"); // for Mozilla firefox table_rows[index].className = "odd"; // for IE browser } else { table_rows[index].setAttribute("class","even"); // for Mozilla firefox table_rows[index].className = "even"; // for IE browser } } } } /** * Changes the image on hover effects * * @param img_obj the image object whose source needs to be changed * */ function change_Image(img_obj) { var relative_path = (img_obj.src).split("themes/"); if (relative_path[1] == 'original/img/new_data.jpg') { img_obj.src = "./themes/original/img/new_data_hovered.jpg"; } else if (relative_path[1] == 'original/img/new_struct.jpg') { img_obj.src = "./themes/original/img/new_struct_hovered.jpg"; } else if (relative_path[1] == 'original/img/new_struct_hovered.jpg') { img_obj.src = "./themes/original/img/new_struct.jpg"; } else if (relative_path[1] == 'original/img/new_data_hovered.jpg') { img_obj.src = "./themes/original/img/new_data.jpg"; } else if (relative_path[1] == 'original/img/new_data_selected.jpg') { img_obj.src = "./themes/original/img/new_data_selected_hovered.jpg"; } else if(relative_path[1] == 'original/img/new_struct_selected.jpg') { img_obj.src = "./themes/original/img/new_struct_selected_hovered.jpg"; } else if (relative_path[1] == 'original/img/new_struct_selected_hovered.jpg') { img_obj.src = "./themes/original/img/new_struct_selected.jpg"; } else if (relative_path[1] == 'original/img/new_data_selected_hovered.jpg') { img_obj.src = "./themes/original/img/new_data_selected.jpg"; } } /** * Generates the URL containing the list of selected table ids for synchronization and * a variable checked for confirmation of deleting previous rows from target tables * * @param token the token generated for each PMA form * */ function ApplySelectedChanges(token) { var div = document.getElementById("list"); var table = div.getElementsByTagName('table')[0]; var table_body = table.getElementsByTagName('tbody')[0]; // Get all the rows from the details table var table_rows = table_body.getElementsByTagName('tr'); var x = table_rows.length; var i; /** Append the token at the beginning of the query string followed by Table_ids that shows that "Apply Selected Changes" button is pressed */ var append_string = "?token="+token+"&Table_ids="+1; for(i=0; i max) { theField.select(); alert(message.replace('%d', val)); theField.focus(); return false; } // It's a valid number else { theField.value = val; } return true; } // end of the 'checkFormElementInRange()' function function checkTableEditForm(theForm, fieldsCnt) { // TODO: avoid sending a message if user just wants to add a line // on the form but has not completed at least one field name var atLeastOneField = 0; var i, elm, elm2, elm3, val, id; for (i=0; i 0 ) { unique_id = this.id; } else { return; } if ( typeof(marked_row[unique_id]) == 'undefined' || !marked_row[unique_id] ) { marked_row[unique_id] = true; } else { marked_row[unique_id] = false; } if ( marked_row[unique_id] ) { this.className += ' marked'; } else { this.className = this.className.replace(' marked', ''); } if ( checkbox && checkbox.disabled == false ) { checkbox.checked = marked_row[unique_id]; if (typeof(event) == 'object') { table = this.parentNode; parentTableLimit = 0; while (table.tagName.toLowerCase() != 'table' && parentTableLimit < 20) { parentTableLimit++; table = table.parentNode; } if (event.shiftKey == true && table.lastClicked != undefined) { if (event.preventDefault) {event.preventDefault();} else {event.returnValue = false;} i = table.lastClicked; if (i < this.rowIndex) { i++; } else { i--; } while (i != this.rowIndex) { $(table.rows[i]).mousedown(); if (i < this.rowIndex) { i++; } else { i--; } } } table.lastClicked = this.rowIndex; } } }); // ... and disable label ... var labeltag = rows[i].getElementsByTagName('label')[0]; if ( labeltag ) { labeltag.onclick = function() { return false; } } // .. and checkbox clicks var checkbox = rows[i].getElementsByTagName('input')[0]; if ( checkbox ) { checkbox.onclick = function() { // opera does not recognize return false; this.checked = ! this.checked; } } } } $(document).ready(PMA_markRowsInit); /** * marks all rows and selects its first checkbox inside the given element * the given element is usaly a table or a div containing the table or tables * * @param container DOM element */ function markAllRows( container_id ) { $("#"+container_id).find("input:checkbox:enabled").attr('checked', 'checked') .parents("tr").addClass("marked"); return true; } /** * marks all rows and selects its first checkbox inside the given element * the given element is usaly a table or a div containing the table or tables * * @param container DOM element */ function unMarkAllRows( container_id ) { $("#"+container_id).find("input:checkbox:enabled").removeAttr('checked') .parents("tr").removeClass("marked"); return true; } /** * Sets/unsets the pointer and marker in browse mode * * @param object the table row * @param integer the row number * @param string the action calling this script (over, out or click) * @param string the default background color * @param string the color to use for mouseover * @param string the color to use for marking a row * * @return boolean whether pointer is set or not */ function setPointer(theRow, theRowNum, theAction, theDefaultColor, thePointerColor, theMarkColor) { var theCells = null; // 1. Pointer and mark feature are disabled or the browser can't get the // row -> exits if ((thePointerColor == '' && theMarkColor == '') || typeof(theRow.style) == 'undefined') { return false; } // 1.1 Sets the mouse pointer to pointer on mouseover and back to normal otherwise. if (theAction == "over" || theAction == "click") { theRow.style.cursor='pointer'; } else { theRow.style.cursor='default'; } // 2. Gets the current row and exits if the browser can't get it if (typeof(document.getElementsByTagName) != 'undefined') { theCells = theRow.getElementsByTagName('td'); } else if (typeof(theRow.cells) != 'undefined') { theCells = theRow.cells; } else { return false; } // 3. Gets the current color... var rowCellsCnt = theCells.length; var domDetect = null; var currentColor = null; var newColor = null; // 3.1 ... with DOM compatible browsers except Opera that does not return // valid values with "getAttribute" if (typeof(window.opera) == 'undefined' && typeof(theCells[0].getAttribute) != 'undefined') { currentColor = theCells[0].getAttribute('bgcolor'); domDetect = true; } // 3.2 ... with other browsers else { currentColor = theCells[0].style.backgroundColor; domDetect = false; } // end 3 // 3.3 ... Opera changes colors set via HTML to rgb(r,g,b) format so fix it if (currentColor.indexOf("rgb") >= 0) { var rgbStr = currentColor.slice(currentColor.indexOf('(') + 1, currentColor.indexOf(')')); var rgbValues = rgbStr.split(","); currentColor = "#"; var hexChars = "0123456789ABCDEF"; for (var i = 0; i < 3; i++) { var v = rgbValues[i].valueOf(); currentColor += hexChars.charAt(v/16) + hexChars.charAt(v%16); } } // 4. Defines the new color // 4.1 Current color is the default one if (currentColor == '' || currentColor.toLowerCase() == theDefaultColor.toLowerCase()) { if (theAction == 'over' && thePointerColor != '') { newColor = thePointerColor; } else if (theAction == 'click' && theMarkColor != '') { newColor = theMarkColor; marked_row[theRowNum] = true; // Garvin: deactivated onclick marking of the checkbox because it's also executed // when an action (like edit/delete) on a single item is performed. Then the checkbox // would get deactived, even though we need it activated. Maybe there is a way // to detect if the row was clicked, and not an item therein... // document.getElementById('id_rows_to_delete' + theRowNum).checked = true; } } // 4.1.2 Current color is the pointer one else if (currentColor.toLowerCase() == thePointerColor.toLowerCase() && (typeof(marked_row[theRowNum]) == 'undefined' || !marked_row[theRowNum])) { if (theAction == 'out') { newColor = theDefaultColor; } else if (theAction == 'click' && theMarkColor != '') { newColor = theMarkColor; marked_row[theRowNum] = true; // document.getElementById('id_rows_to_delete' + theRowNum).checked = true; } } // 4.1.3 Current color is the marker one else if (currentColor.toLowerCase() == theMarkColor.toLowerCase()) { if (theAction == 'click') { newColor = (thePointerColor != '') ? thePointerColor : theDefaultColor; marked_row[theRowNum] = (typeof(marked_row[theRowNum]) == 'undefined' || !marked_row[theRowNum]) ? true : null; // document.getElementById('id_rows_to_delete' + theRowNum).checked = false; } } // end 4 // 5. Sets the new color... if (newColor) { var c = null; // 5.1 ... with DOM compatible browsers except Opera if (domDetect) { for (c = 0; c < rowCellsCnt; c++) { theCells[c].setAttribute('bgcolor', newColor, 0); } // end for } // 5.2 ... with other browsers else { for (c = 0; c < rowCellsCnt; c++) { theCells[c].style.backgroundColor = newColor; } } } // end 5 return true; } // end of the 'setPointer()' function /* * Sets/unsets the pointer and marker in vertical browse mode * * @param object the table row * @param integer the column number * @param string the action calling this script (over, out or click) * @param string the default background Class * @param string the Class to use for mouseover * @param string the Class to use for marking a row * * @return boolean whether pointer is set or not * */ function setVerticalPointer(theRow, theColNum, theAction, theDefaultClass1, theDefaultClass2, thePointerClass, theMarkClass) { // 1. Pointer and mark feature are disabled or the browser can't get the // row -> exits if ((thePointerClass == '' && theMarkClass == '') || typeof(theRow.style) == 'undefined') { return false; } var tagSwitch = null; // 2. Gets the current row and exits if the browser can't get it if (typeof(document.getElementsByTagName) != 'undefined') { tagSwitch = 'tag'; } else if (typeof(document.getElementById('table_results')) != 'undefined') { tagSwitch = 'cells'; } else { return false; } var theCells = null; if (tagSwitch == 'tag') { theRows = document.getElementById('table_results').getElementsByTagName('tr'); theCells = theRows[1].getElementsByTagName('td'); } else if (tagSwitch == 'cells') { theRows = document.getElementById('table_results').rows; theCells = theRows[1].cells; } // 3. Gets the current Class... var currentClass = null; var newClass = null; // 3.1 ... with DOM compatible browsers except Opera that does not return // valid values with "getAttribute" if (typeof(window.opera) == 'undefined' && typeof(theCells[theColNum].getAttribute) != 'undefined') { currentClass = theCells[theColNum].className; } // end 3 // 4. Defines the new Class // 4.1 Current Class is the default one if (currentClass == '' || currentClass.toLowerCase() == theDefaultClass1.toLowerCase() || currentClass.toLowerCase() == theDefaultClass2.toLowerCase()) { if (theAction == 'over' && thePointerClass != '') { newClass = thePointerClass; } else if (theAction == 'click' && theMarkClass != '') { newClass = theMarkClass; marked_row[theColNum] = true; } } // 4.1.2 Current Class is the pointer one else if (currentClass.toLowerCase() == thePointerClass.toLowerCase() && (typeof(marked_row[theColNum]) == 'undefined' || !marked_row[theColNum]) || marked_row[theColNum] == false) { if (theAction == 'out') { if (theColNum % 2) { newClass = theDefaultClass1; } else { newClass = theDefaultClass2; } } else if (theAction == 'click' && theMarkClass != '') { newClass = theMarkClass; marked_row[theColNum] = true; } } // 4.1.3 Current Class is the marker one else if (currentClass.toLowerCase() == theMarkClass.toLowerCase()) { if (theAction == 'click') { newClass = (thePointerClass != '') ? thePointerClass : ((theColNum % 2) ? theDefaultClass2 : theDefaultClass1); marked_row[theColNum] = false; } } // end 4 // 5 ... with DOM compatible browsers except Opera if (newClass) { var c = null; var rowCnt = theRows.length; for (c = 0; c < rowCnt; c++) { if (tagSwitch == 'tag') { Cells = theRows[c].getElementsByTagName('td'); } else if (tagSwitch == 'cells') { Cells = theRows[c].cells; } Cell = Cells[theColNum]; // 5.1 Sets the new Class... Cell.className = Cell.className.replace(currentClass, newClass); } // end for } // end 5 return true; } // end of the 'setVerticalPointer()' function /** * Checks/unchecks all checkbox in given conainer (f.e. a form, fieldset or div) * * @param string container_id the container id * @param boolean state new value for checkbox (true or false) * @return boolean always true */ function setCheckboxes( container_id, state ) { if(state) { $("#"+container_id).find("input:checkbox").attr('checked', 'checked'); } else { $("#"+container_id).find("input:checkbox").removeAttr('checked'); } return true; } // end of the 'setCheckboxes()' function // added 2004-05-08 by Michael Keck // copy the checked from left to right or from right to left // so it's easier for users to see, if $cfg['ModifyAtRight']=true, what they've checked ;) function copyCheckboxesRange(the_form, the_name, the_clicked) { if (typeof(document.forms[the_form].elements[the_name]) != 'undefined' && typeof(document.forms[the_form].elements[the_name + 'r']) != 'undefined') { if (the_clicked !== 'r') { if (document.forms[the_form].elements[the_name].checked == true) { document.forms[the_form].elements[the_name + 'r'].checked = true; }else { document.forms[the_form].elements[the_name + 'r'].checked = false; } } else if (the_clicked == 'r') { if (document.forms[the_form].elements[the_name + 'r'].checked == true) { document.forms[the_form].elements[the_name].checked = true; }else { document.forms[the_form].elements[the_name].checked = false; } } } } // added 2004-05-08 by Michael Keck // - this was directly written to each td, so why not a function ;) // setCheckboxColumn(\'id_rows_to_delete' . $row_no . ''\'); function setCheckboxColumn(theCheckbox){ if (document.getElementById(theCheckbox)) { document.getElementById(theCheckbox).checked = (document.getElementById(theCheckbox).checked ? false : true); if (document.getElementById(theCheckbox + 'r')) { document.getElementById(theCheckbox + 'r').checked = document.getElementById(theCheckbox).checked; } } else { if (document.getElementById(theCheckbox + 'r')) { document.getElementById(theCheckbox + 'r').checked = (document.getElementById(theCheckbox +'r').checked ? false : true); if (document.getElementById(theCheckbox)) { document.getElementById(theCheckbox).checked = document.getElementById(theCheckbox + 'r').checked; } } } } /** * Checks/unchecks all options of a "); return false; }); $("#btnSave").live("click",function(){ window.location.replace("import.php?db=" + db +"&table=" + table + "&sql_query=" + $("#sql_query_edit").val()+"&show_query=1&token=" + token + ""); }); $("#btnDiscard").live("click",function(){ $(".sql").html("" + oldText + ""); }); $('.sqlbutton').click(function(evt){ insertQuery(evt.target.id); return false; }); $("#export_type").change(function(){ if($("#export_type").val()=='svg'){ $("#show_grid_opt").attr("disabled","disabled"); $("#orientation_opt").attr("disabled","disabled"); $("#with_doc").attr("disabled","disabled"); $("#show_table_dim_opt").removeAttr("disabled"); $("#all_table_same_wide").removeAttr("disabled"); $("#paper_opt").removeAttr("disabled","disabled"); $("#show_color_opt").removeAttr("disabled","disabled"); //$(this).css("background-color","yellow"); }else if($("#export_type").val()=='dia'){ $("#show_grid_opt").attr("disabled","disabled"); $("#with_doc").attr("disabled","disabled"); $("#show_table_dim_opt").attr("disabled","disabled"); $("#all_table_same_wide").attr("disabled","disabled"); $("#paper_opt").removeAttr("disabled","disabled"); $("#show_color_opt").removeAttr("disabled","disabled"); $("#orientation_opt").removeAttr("disabled","disabled"); }else if($("#export_type").val()=='eps'){ $("#show_grid_opt").attr("disabled","disabled"); $("#orientation_opt").removeAttr("disabled"); $("#with_doc").attr("disabled","disabled"); $("#show_table_dim_opt").attr("disabled","disabled"); $("#all_table_same_wide").attr("disabled","disabled"); $("#paper_opt").attr("disabled","disabled"); $("#show_color_opt").attr("disabled","disabled"); }else if($("#export_type").val()=='pdf'){ $("#show_grid_opt").removeAttr("disabled"); $("#orientation_opt").removeAttr("disabled"); $("#with_doc").removeAttr("disabled","disabled"); $("#show_table_dim_opt").removeAttr("disabled","disabled"); $("#all_table_same_wide").removeAttr("disabled","disabled"); $("#paper_opt").removeAttr("disabled","disabled"); $("#show_color_opt").removeAttr("disabled","disabled"); }else{ // nothing } }); $('#sqlquery').focus(); if ($('#input_username')) { if ($('#input_username').val() == '') { $('#input_username').focus(); } else { $('#input_password').focus(); } } }); /** * Function to process the plain HTML response from an Ajax request. Inserts * the various HTML divisions from the response at the proper locations. The * array relates the divisions to be inserted to their placeholders. * * @param var divisions_map an associative array of id names * * * PMA_ajaxInsertResponse({'resultsTable':'resultsTable_response', * 'profilingData':'profilingData_response'}); * * */ function PMA_ajaxInsertResponse(divisions_map) { $.each(divisions_map, function(key, value) { var content_div = '#'+value; var target_div = '#'+key; var content = $(content_div).html(); //replace content of target_div with that from the response $(target_div).html(content); }); }; /** * Show a message on the top of the page for an Ajax request * * @param var message string containing the message to be shown. * optional, defaults to 'Loading...' * @param var timeout number of milliseconds for the message to be visible * optional, defaults to 5000 */ function PMA_ajaxShowMessage(message, timeout) { //Handle the case when a empty data.message is passed. We don't want the empty message if(message == '') { return true; } /** * @var msg String containing the message that has to be displayed * @default PMA_messages['strLoading'] */ if(!message) { var msg = PMA_messages['strLoading']; } else { var msg = message; } /** * @var timeout Number of milliseconds for which {@link msg} will be visible * @default 5000 ms */ if(!timeout) { var to = 5000; } else { var to = timeout; } if( !ajax_message_init) { //For the first time this function is called, append a new div $(function(){ $('
') .insertBefore("#serverinfo"); $('') .appendTo("#loading_parent") .html(msg) .slideDown('medium') .delay(to) .slideUp('medium', function(){ $(this) .html("") //Clear the message .hide(); }); }, 'top.frame_content'); ajax_message_init = true; } else { //Otherwise, just show the div again after inserting the message $("#loading") .clearQueue() .html(msg) .slideDown('medium') .delay(to) .slideUp('medium', function() { $(this) .html("") .hide(); }) } } /** * Hides/shows the "Open in ENUM/SET editor" message, depending on the data type of the column currently selected */ function toggle_enum_notice(selectElement) { var enum_notice_id = selectElement.attr("id").split("_")[1]; enum_notice_id += "_" + (parseInt(selectElement.attr("id").split("_")[2]) + 1); var selectedType = selectElement.attr("value"); if(selectedType == "ENUM" || selectedType == "SET") { $("p[id='enum_notice_" + enum_notice_id + "']").show(); } else { $("p[id='enum_notice_" + enum_notice_id + "']").hide(); } } /** * jQuery function that uses jQueryUI's dialogs to confirm with user. Does not * return a jQuery object yet and hence cannot be chained * * @param string question * @param string url URL to be passed to the callbackFn to make * an Ajax call to * @param function callbackFn callback to execute after user clicks on OK */ jQuery.fn.PMA_confirm = function(question, url, callbackFn) { if (PMA_messages['strDoYouReally'] == '') { return true; } /** * @var button_options Object that stores the options passed to jQueryUI * dialog */ var button_options = {}; button_options[PMA_messages['strOK']] = function(){ $(this).dialog("close").remove(); if($.isFunction(callbackFn)) { callbackFn.call(this, url); } }; button_options[PMA_messages['strCancel']] = function() {$(this).dialog("close").remove();} $('
') .prepend(question) .dialog({buttons: button_options}); }; /** * jQuery function to sort a table's body after a new row has been appended to it. * Also fixes the even/odd classes of the table rows at the end. * * @param string text_selector string to select the sortKey's text * * @return jQuery Object for chaining purposes */ jQuery.fn.PMA_sort_table = function(text_selector) { return this.each(function() { /** * @var table_body Object referring to the table's element */ var table_body = $(this); /** * @var rows Object referring to the collection of rows in {@link table_body} */ var rows = $(this).find('tr').get(); //get the text of the field that we will sort by $.each(rows, function(index, row) { row.sortKey = $.trim($(row).find(text_selector).text().toLowerCase()); }) //get the sorted order rows.sort(function(a,b) { if(a.sortKey < b.sortKey) { return -1; } if(a.sortKey > b.sortKey) { return 1; } return 0; }) //pull out each row from the table and then append it according to it's order $.each(rows, function(index, row) { $(table_body).append(row); row.sortKey = null; }) //Re-check the classes of each row $(this).find('tr:odd') .removeClass('even').addClass('odd') .end() .find('tr:even') .removeClass('odd').addClass('even'); }) } /** * jQuery coding for 'Create Table'. Used on db_operations.php, * db_structure.php and db_tracking.php (i.e., wherever * libraries/display_create_table.lib.php is used) * * Attach Ajax Event handlers for Create Table */ $(document).ready(function() { /** * Attach event handler to the submit action of the create table minimal form * and retrieve the full table form and display it in a dialog * * @uses PMA_ajaxShowMessage() */ $("#create_table_form_minimal").live('submit', function(event) { event.preventDefault(); /* @todo Validate this form! */ /** * @var button_options Object that stores the options passed to jQueryUI * dialog */ var button_options = {}; button_options[PMA_messages['strCancel']] = function() {$(this).dialog('close').remove();} PMA_ajaxShowMessage(); $(this).append(''); $.get($(this).attr('action'), $(this).serialize(), function(data) { $('
') .append(data) .dialog({ title: top.frame_content.PMA_messages['strCreateTable'], width: 900, buttons : button_options }); // end dialog options }) // end $.get() // empty table name and number of columns from the minimal form $(this).find('input[name=table],input[name=num_fields]').val(''); }); /** * Attach event handler for submission of create table form (save) * * @uses PMA_ajaxShowMessage() * @uses $.PMA_sort_table() * @uses window.parent.refreshNavigation() * */ // .live() must be called after a selector, see http://api.jquery.com/live $("#create_table_form input[name=do_save_data]").live('click', function(event) { event.preventDefault(); /** * @var the_form object referring to the create table form */ var the_form = $("#create_table_form"); PMA_ajaxShowMessage(PMA_messages['strProcessingRequest']); $(the_form).append(''); //User wants to submit the form $.post($(the_form).attr('action'), $(the_form).serialize() + "&do_save_data=" + $(this).val(), function(data) { if(data.success == true) { PMA_ajaxShowMessage(data.message); $("#create_table_dialog").dialog("close").remove(); /** * @var tables_table Object referring to the element that holds the list of tables */ var tables_table = $("#tablesForm").find("tbody").not("#tbl_summary_row"); /** * @var curr_last_row Object referring to the last element in {@link tables_table} */ var curr_last_row = $(tables_table).find('tr:last'); /** * @var curr_last_row_index_string String containing the index of {@link curr_last_row} */ var curr_last_row_index_string = $(curr_last_row).find('input:checkbox').attr('id').match(/\d+/)[0]; /** * @var curr_last_row_index Index of {@link curr_last_row} */ var curr_last_row_index = parseFloat(curr_last_row_index_string); /** * @var new_last_row_index Index of the new row to be appended to {@link tables_table} */ var new_last_row_index = curr_last_row_index + 1; /** * @var new_last_row_id String containing the id of the row to be appended to {@link tables_table} */ var new_last_row_id = 'checkbox_tbl_' + new_last_row_index; //append to table $(data.new_table_string) .find('input:checkbox') .val(new_last_row_id) .end() .appendTo(tables_table); //Sort the table $(tables_table).PMA_sort_table('th'); //Refresh navigation frame as a new table has been added window.parent.refreshNavigation(); } else { PMA_ajaxShowMessage(data.error); } }) // end $.post() }) // end create table form (save) /** * Attach event handler for create table form (add fields) * * @uses PMA_ajaxShowMessage() * @uses $.PMA_sort_table() * @uses window.parent.refreshNavigation() * */ // .live() must be called after a selector, see http://api.jquery.com/live $("#create_table_form input[name=submit_num_fields]").live('click', function(event) { event.preventDefault(); /** * @var the_form object referring to the create table form */ var the_form = $("#create_table_form"); PMA_ajaxShowMessage(PMA_messages['strProcessingRequest']); $(the_form).append(''); //User wants to add more fields to the table $.post($(the_form).attr('action'), $(the_form).serialize() + "&submit_num_fields=" + $(this).val(), function(data) { $("#create_table_dialog").html(data); }) //end $.post() }) // end create table form (add fields) }, 'top.frame_content'); //end $(document).ready for 'Create Table' /** * Attach event handlers for Empty Table and Drop Table. Used wherever libraries/ * tbl_links.inc.php is used. */ $(document).ready(function() { /** * Attach Ajax event handlers for Empty Table * * @uses PMA_ajaxShowMessage() * @uses $.PMA_confirm() */ $("#empty_table_anchor").live('click', function(event) { event.preventDefault(); /** * @var question String containing the question to be asked for confirmation */ var question = 'TRUNCATE TABLE ' + window.parent.table; $(this).PMA_confirm(question, $(this).attr('href'), function(url) { PMA_ajaxShowMessage(PMA_messages['strProcessingRequest']); $.get(url, {'is_js_confirmed': 1, 'ajax_request': true}, function(data) { if(data.success == true) { PMA_ajaxShowMessage(data.message); $("#topmenucontainer") .next('div') .remove() .end() .after(data.sql_query); } else { PMA_ajaxShowMessage(data.error); } }) // end $.get }) // end $.PMA_confirm() }) // end Empty Table /** * Attach Ajax event handler for Drop Table * * @uses PMA_ajaxShowMessage() * @uses $.PMA_confirm() * @uses window.parent.refreshNavigation() */ $("#drop_table_anchor").live('click', function(event) { event.preventDefault(); /** * @var question String containing the question to be asked for confirmation */ var question = 'DROP TABLE/VIEW ' + window.parent.table; $(this).PMA_confirm(question, $(this).attr('href'), function(url) { PMA_ajaxShowMessage(PMA_messages['strProcessingRequest']); $.get(url, {'is_js_confirmed': 1, 'ajax_request': true}, function(data) { if(data.success == true) { PMA_ajaxShowMessage(data.message); $("#topmenucontainer") .next('div') .remove() .end() .after(data.sql_query); window.parent.table = ''; window.parent.refreshNavigation(); } else { PMA_ajaxShowMessage(data.error); } }) // end $.get }) // end $.PMA_confirm() }) // end $().live() }, 'top.frame_content'); //end $(document).ready() for libraries/tbl_links.inc.php /** * Attach Ajax event handlers for Drop Trigger. Used on tbl_structure.php */ $(document).ready(function() { $(".drop_trigger_anchor").live('click', function(event) { event.preventDefault(); /** * @var curr_row Object reference to the current trigger's */ var curr_row = $(this).parents('tr'); /** * @var question String containing the question to be asked for confirmation */ var question = 'DROP TRIGGER IF EXISTS `' + $(curr_row).children('td:first').text() + '`'; $(this).PMA_confirm(question, $(this).attr('href'), function(url) { PMA_ajaxShowMessage(PMA_messages['strProcessingRequest']); $.get(url, {'is_js_confirmed': 1, 'ajax_request': true}, function(data) { if(data.success == true) { PMA_ajaxShowMessage(data.message); $("#topmenucontainer") .next('div') .remove() .end() .after(data.sql_query); $(curr_row).hide("medium").remove(); } else { PMA_ajaxShowMessage(data.error); } }) // end $.get() }) // end $.PMA_confirm() }) // end $().live() }, 'top.frame_content'); //end $(document).ready() for Drop Trigger /** * Attach Ajax event handlers for Drop Database. Moved here from db_structure.js * as it was also required on db_create.php * * @uses $.PMA_confirm() * @uses PMA_ajaxShowMessage() * @uses window.parent.refreshNavigation() * @uses window.parent.refreshMain() */ $(document).ready(function() { $("#drop_db_anchor").live('click', function(event) { event.preventDefault(); //context is top.frame_content, so we need to use window.parent.db to access the db var /** * @var question String containing the question to be asked for confirmation */ var question = PMA_messages['strDropDatabaseStrongWarning'] + '\n' + PMA_messages['strDoYouReally'] + ' :\n' + 'DROP DATABASE ' + window.parent.db; $(this).PMA_confirm(question, $(this).attr('href') ,function(url) { PMA_ajaxShowMessage(PMA_messages['strProcessingRequest']); $.get(url, {'is_js_confirmed': '1', 'ajax_request': true}, function(data) { //Database deleted successfully, refresh both the frames window.parent.refreshNavigation(); window.parent.refreshMain(); }) // end $.get() }); // end $.PMA_confirm() }); //end of Drop Database Ajax action }) // end of $(document).ready() for Drop Database /** * Attach Ajax event handlers for 'Create Database'. Used wherever libraries/ * display_create_database.lib.php is used, ie main.php and server_databases.php * * @uses PMA_ajaxShowMessage() */ $(document).ready(function() { $('#create_database_form').live('submit', function(event) { event.preventDefault(); PMA_ajaxShowMessage(PMA_messages['strProcessingRequest']); $(this).append(''); $.post($(this).attr('action'), $(this).serialize(), function(data) { if(data.success == true) { PMA_ajaxShowMessage(data.message); //Append database's row to table $("#tabledatabases") .find('tbody') .append(data.new_db_string) .PMA_sort_table('.name') .find('#db_summary_row') .appendTo('#tabledatabases tbody') .removeClass('odd even'); } else { PMA_ajaxShowMessage(data.error); } }) // end $.post() }) // end $().live() }) // end $(document).ready() for Create Database /** * Attach Ajax event handlers for 'Change Password' on main.php */ $(document).ready(function() { /** * Attach Ajax event handler on the change password anchor */ $('#change_password_anchor').live('click', function(event) { event.preventDefault(); /** * @var button_options Object containing options to be passed to jQueryUI's dialog */ var button_options = {}; button_options[PMA_messages['strCancel']] = function() {$(this).dialog('close').remove();} $.get($(this).attr('href'), {'ajax_request': true}, function(data) { $('
'); $.post($(the_form).attr('action'), $(the_form).serialize() + '&change_pw='+ this_value, function(data) { if(data.success == true) { PMA_ajaxShowMessage(data.message); $("#topmenucontainer").after(data.sql_query); $("#change_password_dialog").hide().remove(); $("#edit_user_dialog").dialog("close").remove(); } else { PMA_ajaxShowMessage(data.error); } }) // end $.post() }) // end handler for Change Password form submission }) // end $(document).ready() for Change Password /** * Toggle the hiding/showing of the "Open in ENUM/SET editor" message when * the page loads and when the selected data type changes */ $(document).ready(function() { $.each($("select[class='column_type']"), function() { toggle_enum_notice($(this)); }); $("select[class='column_type']").change(function() { toggle_enum_notice($(this)); }); }); /** * Closes the ENUM/SET editor and removes the data in it */ function disable_popup() { $("#popup_background").fadeOut("fast"); $("#enum_editor").fadeOut("fast"); // clear the data from the text boxes $("#enum_editor #values input").remove(); $("#enum_editor input[type='hidden']").remove(); } /** * Opens the ENUM/SET editor and controls its functions */ $(document).ready(function() { $("a[class='open_enum_editor']").click(function() { // Center the popup var windowWidth = document.documentElement.clientWidth; var windowHeight = document.documentElement.clientHeight; var popupWidth = windowWidth/2; var popupHeight = windowHeight*0.8; var popupOffsetTop = windowHeight/2 - popupHeight/2; var popupOffsetLeft = windowWidth/2 - popupWidth/2; $("#enum_editor").css({"position":"absolute", "top": popupOffsetTop, "left": popupOffsetLeft, "width": popupWidth, "height": popupHeight}); // Make it appear $("#popup_background").css({"opacity":"0.7"}); $("#popup_background").fadeIn("fast"); $("#enum_editor").fadeIn("fast"); // Get the values var values = $(this).parent().prev("input").attr("value").split(","); $.each(values, function(index, val) { if(jQuery.trim(val) != "") { // enclose the string in single quotes if it's not already if(val.substr(0, 1) != "'") { val = "'" + val; } if(val.substr(val.length-1, val.length) != "'") { val = val + "'"; } // escape the single quotes, except the mandatory ones enclosing the entire string val = val.substr(1, val.length-2).replace(/''/g, "'").replace(/\\\\/g, '\\').replace(/\\'/g, "'").replace(/'/g, "'"); // escape the greater-than symbol val = val.replace(/>/g, ">"); $("#enum_editor #values").append(""); } }); // So we know which column's data is being edited $("#enum_editor").append(""); return false; }); // If the "close" link is clicked, close the enum editor $("a[class='close_enum_editor']").click(function() { disable_popup(); }); // If the "cancel" link is clicked, close the enum editor $("a[class='cancel_enum_editor']").click(function() { disable_popup(); }); // When "add a new value" is clicked, append an empty text field $("a[class='add_value']").click(function() { $("#enum_editor #values").append(""); }); // When the submit button is clicked, put the data back into the original form $("#enum_editor input[type='submit']").click(function() { var value_array = new Array(); $.each($("#enum_editor #values input"), function(index, input_element) { val = jQuery.trim(input_element.value); if(val != "") { value_array.push("'" + val.replace(/\\/g, '\\\\').replace(/'/g, "''") + "'"); } }); // get the Length/Values text field where this value belongs var values_id = $("#enum_editor input[type='hidden']").attr("value"); $("input[id='" + values_id + "']").attr("value", value_array.join(",")); disable_popup(); }); /** * Hides certain table structure actions, replacing them with the word "More". They are displayed * in a dropdown menu when the user hovers over the word "More." */ // Remove the actions from the table cells (they are available by default for JavaScript-disabled browsers) // if the table is not a view or information_schema (otherwise there is only one action to hide and there's no point) if($("input[type='hidden'][name='table_type']").attr("value") == "table") { $("table[id='tablestructure'] td[class='browse']").remove(); $("table[id='tablestructure'] td[class='primary']").remove(); $("table[id='tablestructure'] td[class='unique']").remove(); $("table[id='tablestructure'] td[class='index']").remove(); $("table[id='tablestructure'] td[class='fulltext']").remove(); $("table[id='tablestructure'] th[class='action']").attr("colspan", 3); // Display the "more" text $("table[id='tablestructure'] td[class='more_opts']").show() // Position the dropdown $.each($(".structure_actions_dropdown"), function() { // The top offset must be set for IE even if it didn't change var cell_right_edge_offset = $(this).parent().offset().left + $(this).parent().innerWidth(); var left_offset = cell_right_edge_offset - $(this).innerWidth(); var top_offset = $(this).parent().offset().top + $(this).parent().innerHeight(); $(this).offset({ top: top_offset, left: left_offset }); }); // A hack for IE6 to prevent the after_field select element from being displayed on top of the dropdown by // positioning an iframe directly on top of it $("iframe[class='IE_hack']").width($("select[name='after_field']").width()); $("iframe[class='IE_hack']").height($("select[name='after_field']").height()); $("iframe[class='IE_hack']").offset({ top: $("select[name='after_field']").offset().top, left: $("select[name='after_field']").offset().left }); // When "more" is hovered over, show the hidden actions $("table[id='tablestructure'] td[class='more_opts']").mouseenter( function() { if($.browser.msie && $.browser.version == "6.0") { $("iframe[class='IE_hack']").show(); $("iframe[class='IE_hack']").width($("select[name='after_field']").width()+4); $("iframe[class='IE_hack']").height($("select[name='after_field']").height()+4); $("iframe[class='IE_hack']").offset({ top: $("select[name='after_field']").offset().top, left: $("select[name='after_field']").offset().left}); } $(".structure_actions_dropdown").hide(); // Hide all the other ones that may be open $(this).children(".structure_actions_dropdown").show(); // Need to do this again for IE otherwise the offset is wrong if($.browser.msie) { var left_offset_IE = $(this).offset().left + $(this).innerWidth() - $(this).children(".structure_actions_dropdown").innerWidth(); var top_offset_IE = $(this).offset().top + $(this).innerHeight(); $(this).children(".structure_actions_dropdown").offset({ top: top_offset_IE, left: left_offset_IE }); } }); $(".structure_actions_dropdown").mouseleave(function() { $(this).hide(); if($.browser.msie && $.browser.version == "6.0") { $("iframe[class='IE_hack']").hide(); } }); } }); /* Displays tooltips */ $(document).ready(function() { // Hide the footnotes from the footer (which are displayed for // JavaScript-disabled browsers) since the tooltip is sufficient $(".footnotes").hide(); $(".footnotes span").each(function() { $(this).children("sup").remove(); }); // The border and padding must be removed otherwise a thin yellow box remains visible $(".footnotes").css("border", "none"); $(".footnotes").css("padding", "0px"); // Replace the superscripts with the help icon $("sup[class='footnotemarker']").hide(); $("img[class='footnotemarker']").show(); $("img[class='footnotemarker']").each(function() { var span_id = $(this).attr("id"); span_id = span_id.split("_")[1]; var tooltip_text = $(".footnotes span[id='footnote_" + span_id + "']").html(); $(this).qtip({ content: tooltip_text, show: { delay: 0 }, hide: { when: 'unfocus', delay: 0 }, style: { background: '#ffffcc' } }); }); }); function menuResize() { var cnt = $('#topmenu'); var wmax = cnt.width() - 5; // 5 px margin for jumping menu in Chrome var submenu = cnt.find('.submenu'); var submenu_w = submenu.outerWidth(true); var submenu_ul = submenu.find('ul'); var li = cnt.find('> li'); var li2 = submenu_ul.find('li'); var more_shown = li2.length > 0; var w = more_shown ? submenu_w : 0; // hide menu items var hide_start = 0; for (var i = 0; i < li.length-1; i++) { // li.length-1: skip .submenu element var el = $(li[i]); var el_width = el.outerWidth(true); el.data('width', el_width); w += el_width; if (w > wmax) { w -= el_width; if (w + submenu_w < wmax) { hide_start = i; } else { hide_start = i-1; w -= $(li[i-1]).data('width'); } break; } } if (hide_start > 0) { for (var i = hide_start; i < li.length-1; i++) { $(li[i])[more_shown ? 'prependTo' : 'appendTo'](submenu_ul); } submenu.show(); } else if (more_shown) { w -= submenu_w; // nothing hidden, maybe something can be restored for (var i = 0; i < li2.length; i++) { //console.log(li2[i], submenu_w); w += $(li2[i]).data('width'); // item fits or (it is the last item and it would fit if More got removed) if (w+submenu_w < wmax || (i == li2.length-1 && w < wmax)) { $(li2[i]).insertBefore(submenu); if (i == li2.length-1) { submenu.hide(); } continue; } break; } } if (submenu.find('.tabactive').length) { submenu.addClass('active').find('> a').removeClass('tab').addClass('tabactive'); } else { submenu.removeClass('active').find('> a').addClass('tab').removeClass('tabactive'); } } $(function() { var topmenu = $('#topmenu'); if (topmenu.length == 0) { return; } // create submenu container var link = $('', {href: '#', 'class': 'tab'}) .text(PMA_messages['strMore']) .click(function(e) { e.preventDefault(); }); var img = topmenu.find('li:first-child img'); if (img.length) { img.clone().attr('src', img.attr('src').replace(/\/[^\/]+$/, '/b_more.png')).prependTo(link); } var submenu = $('
  • ', {'class': 'submenu'}) .append(link) .append($('
      ')) .mouseenter(function() { if ($(this).find('ul .tabactive').length == 0) { $(this).addClass('submenuhover').find('> a').addClass('tabactive'); } }) .mouseleave(function() { if ($(this).find('ul .tabactive').length == 0) { $(this).removeClass('submenuhover').find('> a').removeClass('tabactive'); } }) .hide(); topmenu.append(submenu); // populate submenu and register resize event $(window).resize(menuResize); menuResize(); });