bug #3058102 AJAX and adding a column
[phpmyadmin/crack.git] / js / functions.js
blob292e544068bed5c362b65b5eade3a91d72ff6a10
1 /* vim: set expandtab sw=4 ts=4 sts=4: */
2 /**
3  * general function, usally for data manipulation pages
4  *
5  */
7 /**
8  * @var sql_box_locked lock for the sqlbox textarea in the querybox/querywindow
9  */
10 var sql_box_locked = false;
12 /**
13  * @var array holds elements which content should only selected once
14  */
15 var only_once_elements = new Array();
17 /**
18  * @var ajax_message_init   boolean boolean that stores status of
19  *      notification for PMA_ajaxShowNotification
20  */
21 var ajax_message_init = false;
23 /**
24  * Generate a new password and copy it to the password input areas
25  *
26  * @param   object   the form that holds the password fields
27  *
28  * @return  boolean  always true
29  */
30 function suggestPassword(passwd_form) {
31     // restrict the password to just letters and numbers to avoid problems:
32     // "editors and viewers regard the password as multiple words and
33     // things like double click no longer work"
34     var pwchars = "abcdefhjmnpqrstuvwxyz23456789ABCDEFGHJKLMNPQRSTUVWYXZ";
35     var passwordlength = 16;    // do we want that to be dynamic?  no, keep it simple :)
36     var passwd = passwd_form.generated_pw;
37     passwd.value = '';
39     for ( i = 0; i < passwordlength; i++ ) {
40         passwd.value += pwchars.charAt( Math.floor( Math.random() * pwchars.length ) )
41     }
42     passwd_form.text_pma_pw.value = passwd.value;
43     passwd_form.text_pma_pw2.value = passwd.value;
44     return true;
47 /**
48  * for libraries/display_change_password.lib.php 
49  *     libraries/user_password.php
50  *
51  */
53 function displayPasswordGenerateButton() {
54     $('#tr_element_before_generate_password').parent().append('<tr><td>' + PMA_messages['strGeneratePassword'] + '</td><td><input type="button" id="button_generate_password" value="' + PMA_messages['strGenerate'] + '" onclick="suggestPassword(this.form)" /><input type="text" name="generated_pw" id="generated_pw" /></td></tr>');
55     $('#div_element_before_generate_password').parent().append('<div class="item"><label for="button_generate_password">' + PMA_messages['strGeneratePassword'] + ':</label><span class="options"><input type="button" id="button_generate_password" value="' + PMA_messages['strGenerate'] + '" onclick="suggestPassword(this.form)" /></span><input type="text" name="generated_pw" id="generated_pw" /></div>');
59 /**
60  * selects the content of a given object, f.e. a textarea
61  *
62  * @param   object  element     element of which the content will be selected
63  * @param   var     lock        variable which holds the lock for this element
64  *                              or true, if no lock exists
65  * @param   boolean only_once   if true this is only done once
66  *                              f.e. only on first focus
67  */
68 function selectContent( element, lock, only_once ) {
69     if ( only_once && only_once_elements[element.name] ) {
70         return;
71     }
73     only_once_elements[element.name] = true;
75     if ( lock  ) {
76         return;
77     }
79     element.select();
82 /**
83  * Displays an confirmation box before to submit a "DROP DATABASE" query.
84  * This function is called while clicking links
85  *
86  * @param   object   the link
87  * @param   object   the sql query to submit
88  *
89  * @return  boolean  whether to run the query or not
90  */
91 function confirmLinkDropDB(theLink, theSqlQuery)
93     // Confirmation is not required in the configuration file
94     // or browser is Opera (crappy js implementation)
95     if (PMA_messages['strDoYouReally'] == '' || typeof(window.opera) != 'undefined') {
96         return true;
97     }
99     var is_confirmed = confirm(PMA_messages['strDropDatabaseStrongWarning'] + '\n' + PMA_messages['strDoYouReally'] + ' :\n' + theSqlQuery);
100     if (is_confirmed) {
101         theLink.href += '&is_js_confirmed=1';
102     }
104     return is_confirmed;
105 } // end of the 'confirmLinkDropDB()' function
108  * Displays an confirmation box before to submit a "DROP/DELETE/ALTER" query.
109  * This function is called while clicking links
111  * @param   object   the link
112  * @param   object   the sql query to submit
114  * @return  boolean  whether to run the query or not
115  */
116 function confirmLink(theLink, theSqlQuery)
118     // Confirmation is not required in the configuration file
119     // or browser is Opera (crappy js implementation)
120     if (PMA_messages['strDoYouReally'] == '' || typeof(window.opera) != 'undefined') {
121         return true;
122     }
124     var is_confirmed = confirm(PMA_messages['strDoYouReally'] + ' :\n' + theSqlQuery);
125     if (is_confirmed) {
126         if ( typeof(theLink.href) != 'undefined' ) {
127             theLink.href += '&is_js_confirmed=1';
128         } else if ( typeof(theLink.form) != 'undefined' ) {
129             theLink.form.action += '?is_js_confirmed=1';
130         }
131     }
133     return is_confirmed;
134 } // end of the 'confirmLink()' function
138  * Displays an confirmation box before doing some action
140  * @param   object   the message to display
142  * @return  boolean  whether to run the query or not
144  * @todo used only by libraries/display_tbl.lib.php. figure out how it is used
145  *       and replace with a jQuery equivalent
146  */
147 function confirmAction(theMessage)
149     // TODO: Confirmation is not required in the configuration file
150     // or browser is Opera (crappy js implementation)
151     if (typeof(window.opera) != 'undefined') {
152         return true;
153     }
155     var is_confirmed = confirm(theMessage);
157     return is_confirmed;
158 } // end of the 'confirmAction()' function
162  * Displays an error message if a "DROP DATABASE" statement is submitted
163  * while it isn't allowed, else confirms a "DROP/DELETE/ALTER" query before
164  * sumitting it if required.
165  * This function is called by the 'checkSqlQuery()' js function.
167  * @param   object   the form
168  * @param   object   the sql query textarea
170  * @return  boolean  whether to run the query or not
172  * @see     checkSqlQuery()
173  */
174 function confirmQuery(theForm1, sqlQuery1)
176     // Confirmation is not required in the configuration file
177     if (PMA_messages['strDoYouReally'] == '') {
178         return true;
179     }
181     // The replace function (js1.2) isn't supported
182     else if (typeof(sqlQuery1.value.replace) == 'undefined') {
183         return true;
184     }
186     // js1.2+ -> validation with regular expressions
187     else {
188         // "DROP DATABASE" statement isn't allowed
189         if (PMA_messages['strNoDropDatabases'] != '') {
190             var drop_re = new RegExp('(^|;)\\s*DROP\\s+(IF EXISTS\\s+)?DATABASE\\s', 'i');
191             if (drop_re.test(sqlQuery1.value)) {
192                 alert(PMA_messages['strNoDropDatabases']);
193                 theForm1.reset();
194                 sqlQuery1.focus();
195                 return false;
196             } // end if
197         } // end if
199         // Confirms a "DROP/DELETE/ALTER/TRUNCATE" statement
200         //
201         // TODO: find a way (if possible) to use the parser-analyser
202         // for this kind of verification
203         // For now, I just added a ^ to check for the statement at
204         // beginning of expression
206         var do_confirm_re_0 = new RegExp('^\\s*DROP\\s+(IF EXISTS\\s+)?(TABLE|DATABASE|PROCEDURE)\\s', 'i');
207         var do_confirm_re_1 = new RegExp('^\\s*ALTER\\s+TABLE\\s+((`[^`]+`)|([A-Za-z0-9_$]+))\\s+DROP\\s', 'i');
208         var do_confirm_re_2 = new RegExp('^\\s*DELETE\\s+FROM\\s', 'i');
209         var do_confirm_re_3 = new RegExp('^\\s*TRUNCATE\\s', 'i');
211         if (do_confirm_re_0.test(sqlQuery1.value)
212             || do_confirm_re_1.test(sqlQuery1.value)
213             || do_confirm_re_2.test(sqlQuery1.value)
214             || do_confirm_re_3.test(sqlQuery1.value)) {
215             var message      = (sqlQuery1.value.length > 100)
216                              ? sqlQuery1.value.substr(0, 100) + '\n    ...'
217                              : sqlQuery1.value;
218             var is_confirmed = confirm(PMA_messages['strDoYouReally'] + ' :\n' + message);
219             // statement is confirmed -> update the
220             // "is_js_confirmed" form field so the confirm test won't be
221             // run on the server side and allows to submit the form
222             if (is_confirmed) {
223                 theForm1.elements['is_js_confirmed'].value = 1;
224                 return true;
225             }
226             // statement is rejected -> do not submit the form
227             else {
228                 window.focus();
229                 sqlQuery1.focus();
230                 return false;
231             } // end if (handle confirm box result)
232         } // end if (display confirm box)
233     } // end confirmation stuff
235     return true;
236 } // end of the 'confirmQuery()' function
240  * Displays a confirmation box before disabling the BLOB repository for a given database.
241  * This function is called while clicking links
243  * @param   object   the database
245  * @return  boolean  whether to disable the repository or not
246  */
247 function confirmDisableRepository(theDB)
249     // Confirmation is not required in the configuration file
250     // or browser is Opera (crappy js implementation)
251     if (PMA_messages['strDoYouReally'] == '' || typeof(window.opera) != 'undefined') {
252         return true;
253     }
255     var is_confirmed = confirm(PMA_messages['strBLOBRepositoryDisableStrongWarning'] + '\n' + PMA_messages['strBLOBRepositoryDisableAreYouSure']);
257     return is_confirmed;
258 } // end of the 'confirmDisableBLOBRepository()' function
262  * Displays an error message if the user submitted the sql query form with no
263  * sql query, else checks for "DROP/DELETE/ALTER" statements
265  * @param   object   the form
267  * @return  boolean  always false
269  * @see     confirmQuery()
270  */
271 function checkSqlQuery(theForm)
273     var sqlQuery = theForm.elements['sql_query'];
274     var isEmpty  = 1;
276     // The replace function (js1.2) isn't supported -> basic tests
277     if (typeof(sqlQuery.value.replace) == 'undefined') {
278         isEmpty      = (sqlQuery.value == '') ? 1 : 0;
279         if (isEmpty && typeof(theForm.elements['sql_file']) != 'undefined') {
280             isEmpty  = (theForm.elements['sql_file'].value == '') ? 1 : 0;
281         }
282         if (isEmpty && typeof(theForm.elements['sql_localfile']) != 'undefined') {
283             isEmpty  = (theForm.elements['sql_localfile'].value == '') ? 1 : 0;
284         }
285         if (isEmpty && typeof(theForm.elements['id_bookmark']) != 'undefined') {
286             isEmpty  = (theForm.elements['id_bookmark'].value == null || theForm.elements['id_bookmark'].value == '');
287         }
288     }
289     // js1.2+ -> validation with regular expressions
290     else {
291         var space_re = new RegExp('\\s+');
292         if (typeof(theForm.elements['sql_file']) != 'undefined' &&
293                 theForm.elements['sql_file'].value.replace(space_re, '') != '') {
294             return true;
295         }
296         if (typeof(theForm.elements['sql_localfile']) != 'undefined' &&
297                 theForm.elements['sql_localfile'].value.replace(space_re, '') != '') {
298             return true;
299         }
300         if (isEmpty && typeof(theForm.elements['id_bookmark']) != 'undefined' &&
301                 (theForm.elements['id_bookmark'].value != null || theForm.elements['id_bookmark'].value != '') &&
302                 theForm.elements['id_bookmark'].selectedIndex != 0
303                 ) {
304             return true;
305         }
306         // Checks for "DROP/DELETE/ALTER" statements
307         if (sqlQuery.value.replace(space_re, '') != '') {
308             if (confirmQuery(theForm, sqlQuery)) {
309                 return true;
310             } else {
311                 return false;
312             }
313         }
314         theForm.reset();
315         isEmpty = 1;
316     }
318     if (isEmpty) {
319         sqlQuery.select();
320         alert(PMA_messages['strFormEmpty']);
321         sqlQuery.focus();
322         return false;
323     }
325     return true;
326 } // end of the 'checkSqlQuery()' function
328 // Global variable row_class is set to even
329 var row_class = 'even';
332 * Generates a row dynamically in the differences table displaying
333 * the complete statistics of difference in  table like number of
334 * rows to be updated, number of rows to be inserted, number of
335 * columns to be added, number of columns to be removed, etc.
337 * @param  index         index of matching table
338 * @param  update_size   number of rows/column to be updated
339 * @param  insert_size   number of rows/coulmns to be inserted
340 * @param  remove_size   number of columns to be removed
341 * @param  insert_index  number of indexes to be inserted
342 * @param  remove_index  number of indexes to be removed
343 * @param  img_obj       image object
344 * @param  table_name    name of the table
347 function showDetails(i, update_size, insert_size, remove_size, insert_index, remove_index, img_obj, table_name)
349     // The path of the image is split to facilitate comparison
350     var relative_path = (img_obj.src).split("themes/");
352     // The image source is changed when the showDetails function is called.
353     if (relative_path[1] == 'original/img/new_data_hovered.jpg') {
354         img_obj.src = "./themes/original/img/new_data_selected_hovered.jpg";
355         img_obj.alt = PMA_messages['strClickToUnselect'];  //only for IE browser
356     } else if (relative_path[1] == 'original/img/new_struct_hovered.jpg') {
357         img_obj.src = "./themes/original/img/new_struct_selected_hovered.jpg";
358         img_obj.alt = PMA_messages['strClickToUnselect'];
359     } else if (relative_path[1] == 'original/img/new_struct_selected_hovered.jpg') {
360         img_obj.src = "./themes/original/img/new_struct_hovered.jpg";
361         img_obj.alt = PMA_messages['strClickToSelect'];
362     } else if (relative_path[1] == 'original/img/new_data_selected_hovered.jpg') {
363         img_obj.src = "./themes/original/img/new_data_hovered.jpg";
364         img_obj.alt = PMA_messages['strClickToSelect'];
365     }
367     var div = document.getElementById("list");
368     var table = div.getElementsByTagName("table")[0];
369     var table_body = table.getElementsByTagName("tbody")[0];
371     //Global variable row_class is being used
372     if (row_class == 'even') {
373         row_class = 'odd';
374     } else {
375         row_class = 'even';
376     }
377     // 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.
378     if ((relative_path[1] != 'original/img/new_struct_selected_hovered.jpg') && (relative_path[1] != 'original/img/new_data_selected_hovered.jpg')) {
380         var newRow = document.createElement("tr");
381         newRow.setAttribute("class", row_class);
382         newRow.className = row_class;
383         // Id assigned to this row element is same as the index of this table name in the  matching_tables/source_tables_uncommon array
384         newRow.setAttribute("id" , i);
386         var table_name_cell = document.createElement("td");
387         table_name_cell.align = "center";
388         table_name_cell.innerHTML = table_name ;
390         newRow.appendChild(table_name_cell);
392         var create_table = document.createElement("td");
393         create_table.align = "center";
395         var add_cols = document.createElement("td");
396         add_cols.align = "center";
398         var remove_cols = document.createElement("td");
399         remove_cols.align = "center";
401         var alter_cols = document.createElement("td");
402         alter_cols.align = "center";
404         var add_index = document.createElement("td");
405         add_index.align = "center";
407         var delete_index = document.createElement("td");
408         delete_index.align = "center";
410         var update_rows = document.createElement("td");
411         update_rows.align = "center";
413         var insert_rows = document.createElement("td");
414         insert_rows.align = "center";
416         var tick_image = document.createElement("img");
417         tick_image.src = "./themes/original/img/s_success.png";
419         if (update_size == '' && insert_size == '' && remove_size == '') {
420           /**
421           This is the case when the table needs to be created in target database.
422           */
423             create_table.appendChild(tick_image);
424             add_cols.innerHTML = "--";
425             remove_cols.innerHTML = "--";
426             alter_cols.innerHTML = "--";
427             delete_index.innerHTML = "--";
428             add_index.innerHTML = "--";
429             update_rows.innerHTML = "--";
430             insert_rows.innerHTML = "--";
432             newRow.appendChild(create_table);
433             newRow.appendChild(add_cols);
434             newRow.appendChild(remove_cols);
435             newRow.appendChild(alter_cols);
436             newRow.appendChild(delete_index);
437             newRow.appendChild(add_index);
438             newRow.appendChild(update_rows);
439             newRow.appendChild(insert_rows);
441         } else if (update_size == '' && remove_size == '') {
442            /**
443            This is the case when data difference is displayed in the
444            table which is present in source but absent from target database
445           */
446             create_table.innerHTML = "--";
447             add_cols.innerHTML = "--";
448             remove_cols.innerHTML = "--";
449             alter_cols.innerHTML = "--";
450             add_index.innerHTML = "--";
451             delete_index.innerHTML = "--";
452             update_rows.innerHTML = "--";
453             insert_rows.innerHTML = insert_size;
455             newRow.appendChild(create_table);
456             newRow.appendChild(add_cols);
457             newRow.appendChild(remove_cols);
458             newRow.appendChild(alter_cols);
459             newRow.appendChild(delete_index);
460             newRow.appendChild(add_index);
461             newRow.appendChild(update_rows);
462             newRow.appendChild(insert_rows);
464         } else if (remove_size == '') {
465             /**
466              This is the case when data difference between matching_tables is displayed.
467             */
468             create_table.innerHTML = "--";
469             add_cols.innerHTML = "--";
470             remove_cols.innerHTML = "--";
471             alter_cols.innerHTML = "--";
472             add_index.innerHTML = "--";
473             delete_index.innerHTML = "--";
474             update_rows.innerHTML = update_size;
475             insert_rows.innerHTML = insert_size;
477             newRow.appendChild(create_table);
478             newRow.appendChild(add_cols);
479             newRow.appendChild(remove_cols);
480             newRow.appendChild(alter_cols);
481             newRow.appendChild(delete_index);
482             newRow.appendChild(add_index);
483             newRow.appendChild(update_rows);
484             newRow.appendChild(insert_rows);
486         } else {
487             /**
488             This is the case when structure difference between matching_tables id displayed
489             */
490             create_table.innerHTML = "--";
491             add_cols.innerHTML = insert_size;
492             remove_cols.innerHTML = remove_size;
493             alter_cols.innerHTML = update_size;
494             delete_index.innerHTML = remove_index;
495             add_index.innerHTML = insert_index;
496             update_rows.innerHTML = "--";
497             insert_rows.innerHTML = "--";
499             newRow.appendChild(create_table);
500             newRow.appendChild(add_cols);
501             newRow.appendChild(remove_cols);
502             newRow.appendChild(alter_cols);
503             newRow.appendChild(delete_index);
504             newRow.appendChild(add_index);
505             newRow.appendChild(update_rows);
506             newRow.appendChild(insert_rows);
507         }
508         table_body.appendChild(newRow);
510     } else if ((relative_path[1] != 'original/img/new_struct_hovered.jpg') && (relative_path[1] != 'original/img/new_data_hovered.jpg')) {
511       //The case when the row showing the details need to be removed from the table i.e. the difference button is deselected now.
512         var table_rows = table_body.getElementsByTagName("tr");
513         var j;
514         var index = 0;
515         for (j=0; j < table_rows.length; j++)
516         {
517             if (table_rows[j].id == i) {
518                 index = j;
519                 table_rows[j].parentNode.removeChild(table_rows[j]);
520             }
521         }
522         //The table row css is being adjusted. Class "odd" for odd rows and "even" for even rows should be maintained.
523         for(index; index < table_rows.length; index++)
524         {
525             row_class_element = table_rows[index].getAttribute('class');
526             if (row_class_element == "even") {
527                 table_rows[index].setAttribute("class","odd");  // for Mozilla firefox
528                 table_rows[index].className = "odd";            // for IE browser
529             } else {
530                 table_rows[index].setAttribute("class","even"); // for Mozilla firefox
531                 table_rows[index].className = "even";           // for IE browser
532             }
533         }
534     }
538  * Changes the image on hover effects
540  * @param   img_obj   the image object whose source needs to be changed
542  */
544 function change_Image(img_obj)
546      var relative_path = (img_obj.src).split("themes/");
548     if (relative_path[1] == 'original/img/new_data.jpg') {
549         img_obj.src = "./themes/original/img/new_data_hovered.jpg";
550     } else if (relative_path[1] == 'original/img/new_struct.jpg') {
551         img_obj.src = "./themes/original/img/new_struct_hovered.jpg";
552     } else if (relative_path[1] == 'original/img/new_struct_hovered.jpg') {
553         img_obj.src = "./themes/original/img/new_struct.jpg";
554     } else if (relative_path[1] == 'original/img/new_data_hovered.jpg') {
555         img_obj.src = "./themes/original/img/new_data.jpg";
556     } else if (relative_path[1] == 'original/img/new_data_selected.jpg') {
557         img_obj.src = "./themes/original/img/new_data_selected_hovered.jpg";
558     } else if(relative_path[1] == 'original/img/new_struct_selected.jpg') {
559         img_obj.src = "./themes/original/img/new_struct_selected_hovered.jpg";
560     } else if (relative_path[1] == 'original/img/new_struct_selected_hovered.jpg') {
561         img_obj.src = "./themes/original/img/new_struct_selected.jpg";
562     } else if (relative_path[1] == 'original/img/new_data_selected_hovered.jpg') {
563         img_obj.src = "./themes/original/img/new_data_selected.jpg";
564     }
568  * Generates the URL containing the list of selected table ids for synchronization and
569  * a variable checked for confirmation of deleting previous rows from target tables
571  * @param   token   the token generated for each PMA form
573  */
575 function ApplySelectedChanges(token)
577     var div =  document.getElementById("list");
578     var table = div.getElementsByTagName('table')[0];
579     var table_body = table.getElementsByTagName('tbody')[0];
580     // Get all the rows from the details table
581     var table_rows = table_body.getElementsByTagName('tr');
582     var x = table_rows.length;
583     var i;
584     /**
585      Append the token at the beginning of the query string followed by
586     Table_ids that shows that "Apply Selected Changes" button is pressed
587     */
588     var append_string = "?token="+token+"&Table_ids="+1;
589     for(i=0; i<x; i++){
590            append_string += "&";
591            append_string += i+"="+table_rows[i].id;
592     }
594     // Getting the value of checkbox delete_rows
595     var checkbox = document.getElementById("delete_rows");
596     if (checkbox.checked){
597         append_string += "&checked=true";
598     } else {
599          append_string += "&checked=false";
600     }
601     //Appending the token and list of table ids in the URL
602     location.href += token;
603     location.href += append_string;
607 * Displays error message if any text field
608 * is left empty other than port field.
610 * @param  string   the form name
611 * @param  object   the form
613 * @return  boolean  whether the form field is empty or not
615 function validateConnection(form_name, form_obj)
617     var check = true;
618     var src_hostfilled = true;
619     var trg_hostfilled = true;
621     for (var i=1; i<form_name.elements.length; i++)
622     {
623         // All the text fields are checked excluding the port field because the default port can be used.
624         if ((form_name.elements[i].type == 'text') && (form_name.elements[i].name != 'src_port') && (form_name.elements[i].name != 'trg_port')) {
625             check = emptyFormElements(form_obj, form_name.elements[i].name);
626             if (check==false) {
627                 element = form_name.elements[i].name;
628                 if (form_name.elements[i].name == 'src_host') {
629                     src_hostfilled = false;
630                     continue;
631                 }
632                 if (form_name.elements[i].name == 'trg_host') {
633                     trg_hostfilled = false;
634                     continue;
635                 }
636                 if ((form_name.elements[i].name == 'src_socket' && src_hostfilled==false) || (form_name.elements[i].name == 'trg_socket' && trg_hostfilled==false))
637                     break;
638                 else
639                     continue;
640             }
641         }
642     }
643     if (!check) {
644         form_obj.reset();
645         element.select();
646         alert(PMA_messages['strFormEmpty']);
647         element.focus();
648     }
649     return check;
653  * Check if a form's element is empty
654  * should be
656  * @param   object   the form
657  * @param   string   the name of the form field to put the focus on
659  * @return  boolean  whether the form field is empty or not
660  */
661 function emptyCheckTheField(theForm, theFieldName)
663     var isEmpty  = 1;
664     var theField = theForm.elements[theFieldName];
665     // Whether the replace function (js1.2) is supported or not
666     var isRegExp = (typeof(theField.value.replace) != 'undefined');
668     if (!isRegExp) {
669         isEmpty      = (theField.value == '') ? 1 : 0;
670     } else {
671         var space_re = new RegExp('\\s+');
672         isEmpty      = (theField.value.replace(space_re, '') == '') ? 1 : 0;
673     }
675     return isEmpty;
676 } // end of the 'emptyCheckTheField()' function
681  * @param   object   the form
682  * @param   string   the name of the form field to put the focus on
684  * @return  boolean  whether the form field is empty or not
685  */
686 function emptyFormElements(theForm, theFieldName)
688     var theField = theForm.elements[theFieldName];
689     var isEmpty = emptyCheckTheField(theForm, theFieldName);
692     return isEmpty;
693 } // end of the 'emptyFormElements()' function
697  * Ensures a value submitted in a form is numeric and is in a range
699  * @param   object   the form
700  * @param   string   the name of the form field to check
701  * @param   integer  the minimum authorized value
702  * @param   integer  the maximum authorized value
704  * @return  boolean  whether a valid number has been submitted or not
705  */
706 function checkFormElementInRange(theForm, theFieldName, message, min, max)
708     var theField         = theForm.elements[theFieldName];
709     var val              = parseInt(theField.value);
711     if (typeof(min) == 'undefined') {
712         min = 0;
713     }
714     if (typeof(max) == 'undefined') {
715         max = Number.MAX_VALUE;
716     }
718     // It's not a number
719     if (isNaN(val)) {
720         theField.select();
721         alert(PMA_messages['strNotNumber']);
722         theField.focus();
723         return false;
724     }
725     // It's a number but it is not between min and max
726     else if (val < min || val > max) {
727         theField.select();
728         alert(message.replace('%d', val));
729         theField.focus();
730         return false;
731     }
732     // It's a valid number
733     else {
734         theField.value = val;
735     }
736     return true;
738 } // end of the 'checkFormElementInRange()' function
741 function checkTableEditForm(theForm, fieldsCnt)
743     // TODO: avoid sending a message if user just wants to add a line
744     // on the form but has not completed at least one field name
746     var atLeastOneField = 0;
747     var i, elm, elm2, elm3, val, id;
749     for (i=0; i<fieldsCnt; i++)
750     {
751         id = "#field_" + i + "_2";
752         elm = $(id);
753         val = elm.val()
754         if (val == 'VARCHAR' || val == 'CHAR' || val == 'BIT' || val == 'VARBINARY' || val == 'BINARY') {
755             elm2 = $("#field_" + i + "_3");
756             val = parseInt(elm2.val());
757             elm3 = $("#field_" + i + "_1");
758             if (isNaN(val) && elm3.val() != "") {
759                 elm2.select();
760                 alert(PMA_messages['strNotNumber']);
761                 elm2.focus();
762                 return false;
763             }
764         }
766         if (atLeastOneField == 0) {
767             id = "field_" + i + "_1";
768             if (!emptyCheckTheField(theForm, id)) {
769                 atLeastOneField = 1;
770             }
771         }
772     }
773     if (atLeastOneField == 0) {
774         var theField = theForm.elements["field_0_1"];
775         alert(PMA_messages['strFormEmpty']);
776         theField.focus();
777         return false;
778     }
780     return true;
781 } // enf of the 'checkTableEditForm()' function
785  * Ensures the choice between 'transmit', 'zipped', 'gzipped' and 'bzipped'
786  * checkboxes is consistant
788  * @param   object   the form
789  * @param   string   a code for the action that causes this function to be run
791  * @return  boolean  always true
792  */
793 function checkTransmitDump(theForm, theAction)
795     var formElts = theForm.elements;
797     // 'zipped' option has been checked
798     if (theAction == 'zip' && formElts['zip'].checked) {
799         if (!formElts['asfile'].checked) {
800             theForm.elements['asfile'].checked = true;
801         }
802         if (typeof(formElts['gzip']) != 'undefined' && formElts['gzip'].checked) {
803             theForm.elements['gzip'].checked = false;
804         }
805         if (typeof(formElts['bzip']) != 'undefined' && formElts['bzip'].checked) {
806             theForm.elements['bzip'].checked = false;
807         }
808     }
809     // 'gzipped' option has been checked
810     else if (theAction == 'gzip' && formElts['gzip'].checked) {
811         if (!formElts['asfile'].checked) {
812             theForm.elements['asfile'].checked = true;
813         }
814         if (typeof(formElts['zip']) != 'undefined' && formElts['zip'].checked) {
815             theForm.elements['zip'].checked = false;
816         }
817         if (typeof(formElts['bzip']) != 'undefined' && formElts['bzip'].checked) {
818             theForm.elements['bzip'].checked = false;
819         }
820     }
821     // 'bzipped' option has been checked
822     else if (theAction == 'bzip' && formElts['bzip'].checked) {
823         if (!formElts['asfile'].checked) {
824             theForm.elements['asfile'].checked = true;
825         }
826         if (typeof(formElts['zip']) != 'undefined' && formElts['zip'].checked) {
827             theForm.elements['zip'].checked = false;
828         }
829         if (typeof(formElts['gzip']) != 'undefined' && formElts['gzip'].checked) {
830             theForm.elements['gzip'].checked = false;
831         }
832     }
833     // 'transmit' option has been unchecked
834     else if (theAction == 'transmit' && !formElts['asfile'].checked) {
835         if (typeof(formElts['zip']) != 'undefined' && formElts['zip'].checked) {
836             theForm.elements['zip'].checked = false;
837         }
838         if ((typeof(formElts['gzip']) != 'undefined' && formElts['gzip'].checked)) {
839             theForm.elements['gzip'].checked = false;
840         }
841         if ((typeof(formElts['bzip']) != 'undefined' && formElts['bzip'].checked)) {
842             theForm.elements['bzip'].checked = false;
843         }
844     }
846     return true;
847 } // end of the 'checkTransmitDump()' function
851  * This array is used to remember mark status of rows in browse mode
852  */
853 var marked_row = new Array;
856  * enables highlight and marking of rows in data tables
858  */
859 function PMA_markRowsInit() {
860     // for every table row ...
861     var rows = document.getElementsByTagName('tr');
862     for ( var i = 0; i < rows.length; i++ ) {
863         // ... with the class 'odd' or 'even' ...
864         if ( 'odd' != rows[i].className.substr(0,3) && 'even' != rows[i].className.substr(0,4) ) {
865             continue;
866         }
867         // ... add event listeners ...
868         // ... to highlight the row on mouseover ...
869         if ( navigator.appName == 'Microsoft Internet Explorer' ) {
870             // but only for IE, other browsers are handled by :hover in css
871             rows[i].onmouseover = function() {
872                 this.className += ' hover';
873             }
874             rows[i].onmouseout = function() {
875                 this.className = this.className.replace( ' hover', '' );
876             }
877         }
878         // Do not set click events if not wanted
879         if (rows[i].className.search(/noclick/) != -1) {
880             continue;
881         }
882         // ... and to mark the row on click ...
883         $(rows[i]).bind('mousedown', function(event) {
884             var unique_id;
885             var checkbox;
886             var table;
888             // Somehow IE8 has this not set
889             if (!event) var event = window.event
891             checkbox = this.getElementsByTagName( 'input' )[0];
892             if ( checkbox && checkbox.type == 'checkbox' ) {
893                 unique_id = checkbox.name + checkbox.value;
894             } else if ( this.id.length > 0 ) {
895                 unique_id = this.id;
896             } else {
897                 return;
898             }
900             if ( typeof(marked_row[unique_id]) == 'undefined' || !marked_row[unique_id] ) {
901                 marked_row[unique_id] = true;
902             } else {
903                 marked_row[unique_id] = false;
904             }
906             if ( marked_row[unique_id] ) {
907                 this.className += ' marked';
908             } else {
909                 this.className = this.className.replace(' marked', '');
910             }
912             if ( checkbox && checkbox.disabled == false ) {
913                 checkbox.checked = marked_row[unique_id];
914                 if (typeof(event) == 'object') {
915                     table = this.parentNode;
916                     parentTableLimit = 0;
917                     while (table.tagName.toLowerCase() != 'table' && parentTableLimit < 20) {
918                         parentTableLimit++;
919                         table = table.parentNode;
920                     }
922                     if (event.shiftKey == true && table.lastClicked != undefined) {
923                         if (event.preventDefault) {event.preventDefault();} else {event.returnValue = false;}
924                         i = table.lastClicked;
926                         if (i < this.rowIndex) {
927                             i++;
928                         } else {
929                             i--;
930                         }
932                         while (i != this.rowIndex) {
933                             $(table.rows[i]).mousedown();
934                             if (i < this.rowIndex) {
935                                 i++;
936                             } else {
937                                 i--;
938                             }
939                         }
940                     }
942                     table.lastClicked = this.rowIndex;
943                 }
944             }
945         });
947         // ... and disable label ...
948         var labeltag = rows[i].getElementsByTagName('label')[0];
949         if ( labeltag ) {
950             labeltag.onclick = function() {
951                 return false;
952             }
953         }
954         // .. and checkbox clicks
955         var checkbox = rows[i].getElementsByTagName('input')[0];
956         if ( checkbox ) {
957             checkbox.onclick = function() {
958                 // opera does not recognize return false;
959                 this.checked = ! this.checked;
960             }
961         }
962     }
964 $(document).ready(PMA_markRowsInit);
967  * marks all rows and selects its first checkbox inside the given element
968  * the given element is usaly a table or a div containing the table or tables
970  * @param    container    DOM element
971  */
972 function markAllRows( container_id ) {
974     $("#"+container_id).find("input:checkbox:enabled").attr('checked', 'checked')
975     .parents("tr").addClass("marked");
976     return true;
980  * marks all rows and selects its first checkbox inside the given element
981  * the given element is usaly a table or a div containing the table or tables
983  * @param    container    DOM element
984  */
985 function unMarkAllRows( container_id ) {
987     $("#"+container_id).find("input:checkbox:enabled").removeAttr('checked')
988     .parents("tr").removeClass("marked");
989     return true;
993  * Sets/unsets the pointer and marker in browse mode
995  * @param   object    the table row
996  * @param   integer  the row number
997  * @param   string    the action calling this script (over, out or click)
998  * @param   string    the default background color
999  * @param   string    the color to use for mouseover
1000  * @param   string    the color to use for marking a row
1002  * @return  boolean  whether pointer is set or not
1003  */
1004 function setPointer(theRow, theRowNum, theAction, theDefaultColor, thePointerColor, theMarkColor)
1006     var theCells = null;
1008     // 1. Pointer and mark feature are disabled or the browser can't get the
1009     //    row -> exits
1010     if ((thePointerColor == '' && theMarkColor == '')
1011         || typeof(theRow.style) == 'undefined') {
1012         return false;
1013     }
1015     // 1.1 Sets the mouse pointer to pointer on mouseover and back to normal otherwise.
1016     if (theAction == "over" || theAction == "click") {
1017         theRow.style.cursor='pointer';
1018     } else {
1019         theRow.style.cursor='default';
1020     }
1022     // 2. Gets the current row and exits if the browser can't get it
1023     if (typeof(document.getElementsByTagName) != 'undefined') {
1024         theCells = theRow.getElementsByTagName('td');
1025     }
1026     else if (typeof(theRow.cells) != 'undefined') {
1027         theCells = theRow.cells;
1028     }
1029     else {
1030         return false;
1031     }
1033     // 3. Gets the current color...
1034     var rowCellsCnt  = theCells.length;
1035     var domDetect    = null;
1036     var currentColor = null;
1037     var newColor     = null;
1038     // 3.1 ... with DOM compatible browsers except Opera that does not return
1039     //         valid values with "getAttribute"
1040     if (typeof(window.opera) == 'undefined'
1041         && typeof(theCells[0].getAttribute) != 'undefined') {
1042         currentColor = theCells[0].getAttribute('bgcolor');
1043         domDetect    = true;
1044     }
1045     // 3.2 ... with other browsers
1046     else {
1047         currentColor = theCells[0].style.backgroundColor;
1048         domDetect    = false;
1049     } // end 3
1051     // 3.3 ... Opera changes colors set via HTML to rgb(r,g,b) format so fix it
1052     if (currentColor.indexOf("rgb") >= 0)
1053     {
1054         var rgbStr = currentColor.slice(currentColor.indexOf('(') + 1,
1055                                      currentColor.indexOf(')'));
1056         var rgbValues = rgbStr.split(",");
1057         currentColor = "#";
1058         var hexChars = "0123456789ABCDEF";
1059         for (var i = 0; i < 3; i++)
1060         {
1061             var v = rgbValues[i].valueOf();
1062             currentColor += hexChars.charAt(v/16) + hexChars.charAt(v%16);
1063         }
1064     }
1066     // 4. Defines the new color
1067     // 4.1 Current color is the default one
1068     if (currentColor == ''
1069         || currentColor.toLowerCase() == theDefaultColor.toLowerCase()) {
1070         if (theAction == 'over' && thePointerColor != '') {
1071             newColor              = thePointerColor;
1072         }
1073         else if (theAction == 'click' && theMarkColor != '') {
1074             newColor              = theMarkColor;
1075             marked_row[theRowNum] = true;
1076             // Garvin: deactivated onclick marking of the checkbox because it's also executed
1077             // when an action (like edit/delete) on a single item is performed. Then the checkbox
1078             // would get deactived, even though we need it activated. Maybe there is a way
1079             // to detect if the row was clicked, and not an item therein...
1080             // document.getElementById('id_rows_to_delete' + theRowNum).checked = true;
1081         }
1082     }
1083     // 4.1.2 Current color is the pointer one
1084     else if (currentColor.toLowerCase() == thePointerColor.toLowerCase()
1085              && (typeof(marked_row[theRowNum]) == 'undefined' || !marked_row[theRowNum])) {
1086         if (theAction == 'out') {
1087             newColor              = theDefaultColor;
1088         }
1089         else if (theAction == 'click' && theMarkColor != '') {
1090             newColor              = theMarkColor;
1091             marked_row[theRowNum] = true;
1092             // document.getElementById('id_rows_to_delete' + theRowNum).checked = true;
1093         }
1094     }
1095     // 4.1.3 Current color is the marker one
1096     else if (currentColor.toLowerCase() == theMarkColor.toLowerCase()) {
1097         if (theAction == 'click') {
1098             newColor              = (thePointerColor != '')
1099                                   ? thePointerColor
1100                                   : theDefaultColor;
1101             marked_row[theRowNum] = (typeof(marked_row[theRowNum]) == 'undefined' || !marked_row[theRowNum])
1102                                   ? true
1103                                   : null;
1104             // document.getElementById('id_rows_to_delete' + theRowNum).checked = false;
1105         }
1106     } // end 4
1108     // 5. Sets the new color...
1109     if (newColor) {
1110         var c = null;
1111         // 5.1 ... with DOM compatible browsers except Opera
1112         if (domDetect) {
1113             for (c = 0; c < rowCellsCnt; c++) {
1114                 theCells[c].setAttribute('bgcolor', newColor, 0);
1115             } // end for
1116         }
1117         // 5.2 ... with other browsers
1118         else {
1119             for (c = 0; c < rowCellsCnt; c++) {
1120                 theCells[c].style.backgroundColor = newColor;
1121             }
1122         }
1123     } // end 5
1125     return true;
1126 } // end of the 'setPointer()' function
1129  * Sets/unsets the pointer and marker in vertical browse mode
1131  * @param   object    the table row
1132  * @param   integer   the column number
1133  * @param   string    the action calling this script (over, out or click)
1134  * @param   string    the default background Class
1135  * @param   string    the Class to use for mouseover
1136  * @param   string    the Class to use for marking a row
1138  * @return  boolean  whether pointer is set or not
1140  */
1141 function setVerticalPointer(theRow, theColNum, theAction, theDefaultClass1, theDefaultClass2, thePointerClass, theMarkClass) {
1142     // 1. Pointer and mark feature are disabled or the browser can't get the
1143     //    row -> exits
1144     if ((thePointerClass == '' && theMarkClass == '')
1145         || typeof(theRow.style) == 'undefined') {
1146         return false;
1147     }
1149     var tagSwitch = null;
1151     // 2. Gets the current row and exits if the browser can't get it
1152     if (typeof(document.getElementsByTagName) != 'undefined') {
1153         tagSwitch = 'tag';
1154     } else if (typeof(document.getElementById('table_results')) != 'undefined') {
1155         tagSwitch = 'cells';
1156     } else {
1157         return false;
1158     }
1160     var theCells = null;
1162     if (tagSwitch == 'tag') {
1163         theRows     = document.getElementById('table_results').getElementsByTagName('tr');
1164         theCells    = theRows[1].getElementsByTagName('td');
1165     } else if (tagSwitch == 'cells') {
1166         theRows     = document.getElementById('table_results').rows;
1167         theCells    = theRows[1].cells;
1168     }
1170     // 3. Gets the current Class...
1171     var currentClass   = null;
1172     var newClass       = null;
1174     // 3.1 ... with DOM compatible browsers except Opera that does not return
1175     //         valid values with "getAttribute"
1176     if (typeof(window.opera) == 'undefined'
1177         && typeof(theCells[theColNum].getAttribute) != 'undefined') {
1178         currentClass = theCells[theColNum].className;
1179     } // end 3
1181     // 4. Defines the new Class
1182     // 4.1 Current Class is the default one
1183     if (currentClass == ''
1184         || currentClass.toLowerCase() == theDefaultClass1.toLowerCase()
1185         || currentClass.toLowerCase() == theDefaultClass2.toLowerCase()) {
1186         if (theAction == 'over' && thePointerClass != '') {
1187             newClass              = thePointerClass;
1188         } else if (theAction == 'click' && theMarkClass != '') {
1189             newClass              = theMarkClass;
1190             marked_row[theColNum] = true;
1191         }
1192     }
1193     // 4.1.2 Current Class is the pointer one
1194     else if (currentClass.toLowerCase() == thePointerClass.toLowerCase() &&
1195              (typeof(marked_row[theColNum]) == 'undefined' || !marked_row[theColNum]) || marked_row[theColNum] == false) {
1196             if (theAction == 'out') {
1197                 if (theColNum % 2) {
1198                     newClass              = theDefaultClass1;
1199                 } else {
1200                     newClass              = theDefaultClass2;
1201                 }
1202             }
1203             else if (theAction == 'click' && theMarkClass != '') {
1204                 newClass              = theMarkClass;
1205                 marked_row[theColNum] = true;
1206             }
1207     }
1208     // 4.1.3 Current Class is the marker one
1209     else if (currentClass.toLowerCase() == theMarkClass.toLowerCase()) {
1210         if (theAction == 'click') {
1211             newClass              = (thePointerClass != '')
1212                                   ? thePointerClass
1213                                   : ((theColNum % 2) ? theDefaultClass2 : theDefaultClass1);
1214             marked_row[theColNum] = false;
1215         }
1216     } // end 4
1218     // 5 ... with DOM compatible browsers except Opera
1220     if (newClass) {
1221         var c = null;
1222         var rowCnt = theRows.length;
1223         for (c = 0; c < rowCnt; c++) {
1224             if (tagSwitch == 'tag') {
1225                 Cells = theRows[c].getElementsByTagName('td');
1226             } else if (tagSwitch == 'cells') {
1227                 Cells = theRows[c].cells;
1228             }
1230             Cell  = Cells[theColNum];
1232             // 5.1 Sets the new Class...
1233             Cell.className = Cell.className.replace(currentClass, newClass);
1234         } // end for
1235     } // end 5
1237      return true;
1238  } // end of the 'setVerticalPointer()' function
1241  * Checks/unchecks all checkbox in given conainer (f.e. a form, fieldset or div)
1243  * @param   string   container_id  the container id
1244  * @param   boolean  state         new value for checkbox (true or false)
1245  * @return  boolean  always true
1246  */
1247 function setCheckboxes( container_id, state ) {
1249     if(state) {
1250         $("#"+container_id).find("input:checkbox").attr('checked', 'checked');
1251     }
1252     else {
1253         $("#"+container_id).find("input:checkbox").removeAttr('checked');
1254     }
1256     return true;
1257 } // end of the 'setCheckboxes()' function
1260 // added 2004-05-08 by Michael Keck <mail_at_michaelkeck_dot_de>
1261 //   copy the checked from left to right or from right to left
1262 //   so it's easier for users to see, if $cfg['ModifyAtRight']=true, what they've checked ;)
1263 function copyCheckboxesRange(the_form, the_name, the_clicked)
1265     if (typeof(document.forms[the_form].elements[the_name]) != 'undefined' && typeof(document.forms[the_form].elements[the_name + 'r']) != 'undefined') {
1266         if (the_clicked !== 'r') {
1267             if (document.forms[the_form].elements[the_name].checked == true) {
1268                 document.forms[the_form].elements[the_name + 'r'].checked = true;
1269             }else {
1270                 document.forms[the_form].elements[the_name + 'r'].checked = false;
1271             }
1272         } else if (the_clicked == 'r') {
1273             if (document.forms[the_form].elements[the_name + 'r'].checked == true) {
1274                 document.forms[the_form].elements[the_name].checked = true;
1275             }else {
1276                 document.forms[the_form].elements[the_name].checked = false;
1277             }
1278        }
1279     }
1283 // added 2004-05-08 by Michael Keck <mail_at_michaelkeck_dot_de>
1284 //  - this was directly written to each td, so why not a function ;)
1285 //  setCheckboxColumn(\'id_rows_to_delete' . $row_no . ''\');
1286 function setCheckboxColumn(theCheckbox){
1287     if (document.getElementById(theCheckbox)) {
1288         document.getElementById(theCheckbox).checked = (document.getElementById(theCheckbox).checked ? false : true);
1289         if (document.getElementById(theCheckbox + 'r')) {
1290             document.getElementById(theCheckbox + 'r').checked = document.getElementById(theCheckbox).checked;
1291         }
1292     } else {
1293         if (document.getElementById(theCheckbox + 'r')) {
1294             document.getElementById(theCheckbox + 'r').checked = (document.getElementById(theCheckbox +'r').checked ? false : true);
1295             if (document.getElementById(theCheckbox)) {
1296                 document.getElementById(theCheckbox).checked = document.getElementById(theCheckbox + 'r').checked;
1297             }
1298         }
1299     }
1304   * Checks/unchecks all options of a <select> element
1305   *
1306   * @param   string   the form name
1307   * @param   string   the element name
1308   * @param   boolean  whether to check or to uncheck the element
1309   *
1310   * @return  boolean  always true
1311   */
1312 function setSelectOptions(the_form, the_select, do_check)
1315     if( do_check ) {
1316         $("form[name='"+ the_form +"']").find("select[name='"+the_select+"']").find("option").attr('selected', 'selected');
1317     }
1318     else {
1319         $("form[name='"+ the_form +"']").find("select[name="+the_select+"]").find("option").removeAttr('selected');
1320     }
1321     return true;
1322 } // end of the 'setSelectOptions()' function
1326   * Create quick sql statements.
1327   *
1328   */
1329 function insertQuery(queryType) {
1330     var myQuery = document.sqlform.sql_query;
1331     var myListBox = document.sqlform.dummy;
1332     var query = "";
1333     var table = document.sqlform.table.value;
1335     if (myListBox.options.length > 0) {
1336         sql_box_locked = true;
1337         var chaineAj = "";
1338         var valDis = "";
1339         var editDis = "";
1340         var NbSelect = 0;
1341         for (var i=0; i < myListBox.options.length; i++) {
1342             NbSelect++;
1343             if (NbSelect > 1) {
1344                 chaineAj += ", ";
1345                 valDis += ",";
1346                 editDis += ",";
1347             }
1348             chaineAj += myListBox.options[i].value;
1349             valDis += "[value-" + NbSelect + "]";
1350             editDis += myListBox.options[i].value + "=[value-" + NbSelect + "]";
1351         }
1352     if (queryType == "selectall") {
1353         query = "SELECT * FROM `" + table + "` WHERE 1";
1354     } else if (queryType == "select") {
1355         query = "SELECT " + chaineAj + " FROM `" + table + "` WHERE 1";
1356     } else if (queryType == "insert") {
1357            query = "INSERT INTO `" + table + "`(" + chaineAj + ") VALUES (" + valDis + ")";
1358     } else if (queryType == "update") {
1359         query = "UPDATE `" + table + "` SET " + editDis + " WHERE 1";
1360     } else if(queryType == "delete") {
1361         query = "DELETE FROM `" + table + "` WHERE 1";
1362     }
1363     document.sqlform.sql_query.value = query;
1364     sql_box_locked = false;
1365     }
1370   * Inserts multiple fields.
1371   *
1372   */
1373 function insertValueQuery() {
1374     var myQuery = document.sqlform.sql_query;
1375     var myListBox = document.sqlform.dummy;
1377     if(myListBox.options.length > 0) {
1378         sql_box_locked = true;
1379         var chaineAj = "";
1380         var NbSelect = 0;
1381         for(var i=0; i<myListBox.options.length; i++) {
1382             if (myListBox.options[i].selected){
1383                 NbSelect++;
1384                 if (NbSelect > 1)
1385                     chaineAj += ", ";
1386                 chaineAj += myListBox.options[i].value;
1387             }
1388         }
1390         //IE support
1391         if (document.selection) {
1392             myQuery.focus();
1393             sel = document.selection.createRange();
1394             sel.text = chaineAj;
1395             document.sqlform.insert.focus();
1396         }
1397         //MOZILLA/NETSCAPE support
1398         else if (document.sqlform.sql_query.selectionStart || document.sqlform.sql_query.selectionStart == "0") {
1399             var startPos = document.sqlform.sql_query.selectionStart;
1400             var endPos = document.sqlform.sql_query.selectionEnd;
1401             var chaineSql = document.sqlform.sql_query.value;
1403             myQuery.value = chaineSql.substring(0, startPos) + chaineAj + chaineSql.substring(endPos, chaineSql.length);
1404         } else {
1405             myQuery.value += chaineAj;
1406         }
1407         sql_box_locked = false;
1408     }
1412   * listbox redirection
1413   */
1414 function goToUrl(selObj, goToLocation) {
1415     eval("document.location.href = '" + goToLocation + "pos=" + selObj.options[selObj.selectedIndex].value + "'");
1419  * getElement
1420  */
1421 function getElement(e,f){
1422     if(document.layers){
1423         f=(f)?f:self;
1424         if(f.document.layers[e]) {
1425             return f.document.layers[e];
1426         }
1427         for(W=0;W<f.document.layers.length;W++) {
1428             return(getElement(e,f.document.layers[W]));
1429         }
1430     }
1431     if(document.all) {
1432         return document.all[e];
1433     }
1434     return document.getElementById(e);
1438   * Refresh the WYSIWYG scratchboard after changes have been made
1439   */
1440 function refreshDragOption(e) {
1441     var elm = $('#' + e);
1442     if (elm.css('visibility') == 'visible') {
1443         refreshLayout();
1444         TableDragInit();
1445     }
1449   * Refresh/resize the WYSIWYG scratchboard
1450   */
1451 function refreshLayout() {
1452     var elm = $('#pdflayout')
1453     var orientation = $('#orientation_opt').val();
1454     if($('#paper_opt').length==1){
1455         var paper = $('#paper_opt').val();
1456     }else{
1457         var paper = 'A4';
1458     }
1459     if (orientation == 'P') {
1460         posa = 'x';
1461         posb = 'y';
1462     } else {
1463         posa = 'y';
1464         posb = 'x';
1465     }
1466     elm.css('width', pdfPaperSize(paper, posa) + 'px');
1467     elm.css('height', pdfPaperSize(paper, posb) + 'px');
1471   * Show/hide the WYSIWYG scratchboard
1472   */
1473 function ToggleDragDrop(e) {
1474     var elm = $('#' + e);
1475     if (elm.css('visibility') == 'hidden') {
1476         PDFinit(); /* Defined in pdf_pages.php */
1477         elm.css('visibility', 'visible');
1478         elm.css('display', 'block');
1479         $('#showwysiwyg').val('1')
1480     } else {
1481         elm.css('visibility', 'hidden');
1482         elm.css('display', 'none');
1483         $('#showwysiwyg').val('0')
1484     }
1488   * PDF scratchboard: When a position is entered manually, update
1489   * the fields inside the scratchboard.
1490   */
1491 function dragPlace(no, axis, value) {
1492     var elm = $('#table_' + no);
1493     if (axis == 'x') {
1494         elm.css('left', value + 'px');
1495     } else {
1496         elm.css('top', value + 'px');
1497     }
1501  * Returns paper sizes for a given format
1502  */
1503 function pdfPaperSize(format, axis) {
1504     switch (format.toUpperCase()) {
1505         case '4A0':
1506             if (axis == 'x') return 4767.87; else return 6740.79;
1507             break;
1508         case '2A0':
1509             if (axis == 'x') return 3370.39; else return 4767.87;
1510             break;
1511         case 'A0':
1512             if (axis == 'x') return 2383.94; else return 3370.39;
1513             break;
1514         case 'A1':
1515             if (axis == 'x') return 1683.78; else return 2383.94;
1516             break;
1517         case 'A2':
1518             if (axis == 'x') return 1190.55; else return 1683.78;
1519             break;
1520         case 'A3':
1521             if (axis == 'x') return 841.89; else return 1190.55;
1522             break;
1523         case 'A4':
1524             if (axis == 'x') return 595.28; else return 841.89;
1525             break;
1526         case 'A5':
1527             if (axis == 'x') return 419.53; else return 595.28;
1528             break;
1529         case 'A6':
1530             if (axis == 'x') return 297.64; else return 419.53;
1531             break;
1532         case 'A7':
1533             if (axis == 'x') return 209.76; else return 297.64;
1534             break;
1535         case 'A8':
1536             if (axis == 'x') return 147.40; else return 209.76;
1537             break;
1538         case 'A9':
1539             if (axis == 'x') return 104.88; else return 147.40;
1540             break;
1541         case 'A10':
1542             if (axis == 'x') return 73.70; else return 104.88;
1543             break;
1544         case 'B0':
1545             if (axis == 'x') return 2834.65; else return 4008.19;
1546             break;
1547         case 'B1':
1548             if (axis == 'x') return 2004.09; else return 2834.65;
1549             break;
1550         case 'B2':
1551             if (axis == 'x') return 1417.32; else return 2004.09;
1552             break;
1553         case 'B3':
1554             if (axis == 'x') return 1000.63; else return 1417.32;
1555             break;
1556         case 'B4':
1557             if (axis == 'x') return 708.66; else return 1000.63;
1558             break;
1559         case 'B5':
1560             if (axis == 'x') return 498.90; else return 708.66;
1561             break;
1562         case 'B6':
1563             if (axis == 'x') return 354.33; else return 498.90;
1564             break;
1565         case 'B7':
1566             if (axis == 'x') return 249.45; else return 354.33;
1567             break;
1568         case 'B8':
1569             if (axis == 'x') return 175.75; else return 249.45;
1570             break;
1571         case 'B9':
1572             if (axis == 'x') return 124.72; else return 175.75;
1573             break;
1574         case 'B10':
1575             if (axis == 'x') return 87.87; else return 124.72;
1576             break;
1577         case 'C0':
1578             if (axis == 'x') return 2599.37; else return 3676.54;
1579             break;
1580         case 'C1':
1581             if (axis == 'x') return 1836.85; else return 2599.37;
1582             break;
1583         case 'C2':
1584             if (axis == 'x') return 1298.27; else return 1836.85;
1585             break;
1586         case 'C3':
1587             if (axis == 'x') return 918.43; else return 1298.27;
1588             break;
1589         case 'C4':
1590             if (axis == 'x') return 649.13; else return 918.43;
1591             break;
1592         case 'C5':
1593             if (axis == 'x') return 459.21; else return 649.13;
1594             break;
1595         case 'C6':
1596             if (axis == 'x') return 323.15; else return 459.21;
1597             break;
1598         case 'C7':
1599             if (axis == 'x') return 229.61; else return 323.15;
1600             break;
1601         case 'C8':
1602             if (axis == 'x') return 161.57; else return 229.61;
1603             break;
1604         case 'C9':
1605             if (axis == 'x') return 113.39; else return 161.57;
1606             break;
1607         case 'C10':
1608             if (axis == 'x') return 79.37; else return 113.39;
1609             break;
1610         case 'RA0':
1611             if (axis == 'x') return 2437.80; else return 3458.27;
1612             break;
1613         case 'RA1':
1614             if (axis == 'x') return 1729.13; else return 2437.80;
1615             break;
1616         case 'RA2':
1617             if (axis == 'x') return 1218.90; else return 1729.13;
1618             break;
1619         case 'RA3':
1620             if (axis == 'x') return 864.57; else return 1218.90;
1621             break;
1622         case 'RA4':
1623             if (axis == 'x') return 609.45; else return 864.57;
1624             break;
1625         case 'SRA0':
1626             if (axis == 'x') return 2551.18; else return 3628.35;
1627             break;
1628         case 'SRA1':
1629             if (axis == 'x') return 1814.17; else return 2551.18;
1630             break;
1631         case 'SRA2':
1632             if (axis == 'x') return 1275.59; else return 1814.17;
1633             break;
1634         case 'SRA3':
1635             if (axis == 'x') return 907.09; else return 1275.59;
1636             break;
1637         case 'SRA4':
1638             if (axis == 'x') return 637.80; else return 907.09;
1639             break;
1640         case 'LETTER':
1641             if (axis == 'x') return 612.00; else return 792.00;
1642             break;
1643         case 'LEGAL':
1644             if (axis == 'x') return 612.00; else return 1008.00;
1645             break;
1646         case 'EXECUTIVE':
1647             if (axis == 'x') return 521.86; else return 756.00;
1648             break;
1649         case 'FOLIO':
1650             if (axis == 'x') return 612.00; else return 936.00;
1651             break;
1652     } // end switch
1654     return 0;
1658  * for playing media from the BLOB repository
1660  * @param   var
1661  * @param   var     url_params  main purpose is to pass the token
1662  * @param   var     bs_ref      BLOB repository reference
1663  * @param   var     m_type      type of BLOB repository media
1664  * @param   var     w_width     width of popup window
1665  * @param   var     w_height    height of popup window
1666  */
1667 function popupBSMedia(url_params, bs_ref, m_type, is_cust_type, w_width, w_height)
1669     // if width not specified, use default
1670     if (w_width == undefined)
1671         w_width = 640;
1673     // if height not specified, use default
1674     if (w_height == undefined)
1675         w_height = 480;
1677     // open popup window (for displaying video/playing audio)
1678     var mediaWin = window.open('bs_play_media.php?' + url_params + '&bs_reference=' + bs_ref + '&media_type=' + m_type + '&custom_type=' + is_cust_type, 'viewBSMedia', 'width=' + w_width + ', height=' + w_height + ', resizable=1, scrollbars=1, status=0');
1682  * popups a request for changing MIME types for files in the BLOB repository
1684  * @param   var     db                      database name
1685  * @param   var     table                   table name
1686  * @param   var     reference               BLOB repository reference
1687  * @param   var     current_mime_type       current MIME type associated with BLOB repository reference
1688  */
1689 function requestMIMETypeChange(db, table, reference, current_mime_type)
1691     // no mime type specified, set to default (nothing)
1692     if (undefined == current_mime_type)
1693         current_mime_type = "";
1695     // prompt user for new mime type
1696     var new_mime_type = prompt("Enter custom MIME type", current_mime_type);
1698     // if new mime_type is specified and is not the same as the previous type, request for mime type change
1699     if (new_mime_type && new_mime_type != current_mime_type)
1700         changeMIMEType(db, table, reference, new_mime_type);
1704  * changes MIME types for files in the BLOB repository
1706  * @param   var     db              database name
1707  * @param   var     table           table name
1708  * @param   var     reference       BLOB repository reference
1709  * @param   var     mime_type       new MIME type to be associated with BLOB repository reference
1710  */
1711 function changeMIMEType(db, table, reference, mime_type)
1713     // specify url and parameters for jQuery POST
1714     var mime_chg_url = 'bs_change_mime_type.php';
1715     var params = {bs_db: db, bs_table: table, bs_reference: reference, bs_new_mime_type: mime_type};
1717     // jQuery POST
1718     jQuery.post(mime_chg_url, params);
1722  * Jquery Coding for inline editing SQL_QUERY
1723  */
1724 $(document).ready(function(){
1725     var $oldText,$db,$table,$token,$sql_query;
1726     $oldText=$(".inner_sql").html();
1727     $("#inline_edit").click(function(){
1728         $db=$("input[name='db']").val();
1729         $table=$("input[name='table']").val();
1730         $token=$("input[name='token']").val();
1731         $sql_query=$("input[name='sql_query']").val();
1732         $(".inner_sql").replaceWith("<textarea name=\"sql_query_edit\" id=\"sql_query_edit\">"+ $sql_query +"</textarea><input type=\"button\" id=\"btnSave\" value=\"" + PMA_messages['strGo'] + "\"><input type=\"button\" id=\"btnDiscard\" value=\"" + PMA_messages['strCancel'] + "\">");
1733         return false;
1734     });
1736     $("#btnSave").live("click",function(){
1737         window.location.replace("import.php?db="+$db+"&table="+$table+"&sql_query="+$("#sql_query_edit").val()+"&show_query=1&token="+$token+"");
1738     });
1740     $("#btnDiscard").live("click",function(){
1741         $(".sql").html("<span class=\"syntax\"><span class=\"inner_sql\">"+$oldText+"</span></span>");
1742     });
1744     $('.sqlbutton').click(function(evt){
1745         insertQuery(evt.target.id);
1746         return false;
1747     });
1749     $("#export_type").change(function(){
1750         if($("#export_type").val()=='svg'){
1751             $("#show_grid_opt").attr("disabled","disabled");
1752             $("#orientation_opt").attr("disabled","disabled");
1753             $("#with_doc").attr("disabled","disabled");
1754             $("#show_table_dim_opt").removeAttr("disabled");
1755             $("#all_table_same_wide").removeAttr("disabled");
1756             $("#paper_opt").removeAttr("disabled","disabled");
1757             $("#show_color_opt").removeAttr("disabled","disabled");
1758             //$(this).css("background-color","yellow");
1759         }else if($("#export_type").val()=='dia'){
1760             $("#show_grid_opt").attr("disabled","disabled");
1761             $("#with_doc").attr("disabled","disabled");
1762             $("#show_table_dim_opt").attr("disabled","disabled");
1763             $("#all_table_same_wide").attr("disabled","disabled");
1764             $("#paper_opt").removeAttr("disabled","disabled");
1765             $("#show_color_opt").removeAttr("disabled","disabled");
1766             $("#orientation_opt").removeAttr("disabled","disabled");
1767         }else if($("#export_type").val()=='eps'){
1768             $("#show_grid_opt").attr("disabled","disabled");
1769             $("#orientation_opt").removeAttr("disabled");
1770             $("#with_doc").attr("disabled","disabled");
1771             $("#show_table_dim_opt").attr("disabled","disabled");
1772             $("#all_table_same_wide").attr("disabled","disabled");
1773             $("#paper_opt").attr("disabled","disabled");
1774             $("#show_color_opt").attr("disabled","disabled");
1776         }else if($("#export_type").val()=='pdf'){
1777             $("#show_grid_opt").removeAttr("disabled");
1778             $("#orientation_opt").removeAttr("disabled");
1779             $("#with_doc").removeAttr("disabled","disabled");
1780             $("#show_table_dim_opt").removeAttr("disabled","disabled");
1781             $("#all_table_same_wide").removeAttr("disabled","disabled");
1782             $("#paper_opt").removeAttr("disabled","disabled");
1783             $("#show_color_opt").removeAttr("disabled","disabled");
1784         }else{
1785             // nothing
1786         }
1787     });
1789     $('#sqlquery').focus();
1790     if ($('#input_username')) {
1791         if ($('#input_username').val() == '') {
1792             $('#input_username').focus();
1793         } else {
1794             $('#input_password').focus();
1795         }
1796     }
1800  * Function to process the plain HTML response from an Ajax request.  Inserts
1801  * the various HTML divisions from the response at the proper locations.  The
1802  * array relates the divisions to be inserted to their placeholders.
1804  * @param   var divisions_map   an associative array of id names
1806  * <code>
1807  * PMA_ajaxInsertResponse({'resultsTable':'resultsTable_response',
1808  *                         'profilingData':'profilingData_response'});
1809  * </code>
1811  */
1813 function PMA_ajaxInsertResponse(divisions_map) {
1814     $.each(divisions_map, function(key, value) {
1815         var content_div = '#'+value;
1816         var target_div = '#'+key;
1817         var content = $(content_div).html();
1819         //replace content of target_div with that from the response
1820         $(target_div).html(content);
1821     });
1825  * Show a message on the top of the page for an Ajax request
1827  * @param   var     message     string containing the message to be shown.
1828  *                              optional, defaults to 'Loading...'
1829  * @param   var     timeout     number of milliseconds for the message to be visible
1830  *                              optional, defaults to 5000
1831  */
1833 function PMA_ajaxShowMessage(message, timeout) {
1835     //Handle the case when a empty data.message is passed.  We don't want the empty message
1836     if(message == '') {
1837         return true;
1838     }
1840     /**
1841      * @var msg String containing the message that has to be displayed
1842      * @default PMA_messages['strLoading']
1843      */
1844     if(!message) {
1845         var msg = PMA_messages['strLoading'];
1846     }
1847     else {
1848         var msg = message;
1849     }
1851     /**
1852      * @var timeout Number of milliseconds for which {@link msg} will be visible
1853      * @default 5000 ms
1854      */
1855     if(!timeout) {
1856         var to = 5000;
1857     }
1858     else {
1859         var to = timeout;
1860     }
1862     if( !ajax_message_init) {
1863         //For the first time this function is called, append a new div
1864         $(function(){
1865             $('<div id="loading_parent"></div>')
1866             .insertBefore("#serverinfo");
1868             $('<span id="loading" class="ajax_notification"></span>')
1869             .appendTo("#loading_parent")
1870             .html(msg)
1871             .slideDown('medium')
1872             .delay(to)
1873             .slideUp('medium', function(){
1874                 $(this)
1875                 .html("") //Clear the message
1876                 .hide();
1877             });
1878         }, 'top.frame_content');
1879         ajax_message_init = true;
1880     }
1881     else {
1882         //Otherwise, just show the div again after inserting the message
1883         $("#loading")
1884         .clearQueue()
1885         .html(msg)
1886         .slideDown('medium')
1887         .delay(to)
1888         .slideUp('medium', function() {
1889             $(this)
1890             .html("")
1891             .hide();
1892         })
1893     }
1897  * Hides/shows the "Open in ENUM/SET editor" message, depending on the data type of the column currently selected
1898  */
1899 function toggle_enum_notice(selectElement) {
1900     var enum_notice_id = selectElement.attr("id").split("_")[1];
1901     enum_notice_id += "_" + (parseInt(selectElement.attr("id").split("_")[2]) + 1);
1902     var selectedType = selectElement.attr("value");
1903     if(selectedType == "ENUM" || selectedType == "SET") {
1904         $("p[id='enum_notice_" + enum_notice_id + "']").show();
1905     } else {
1906           $("p[id='enum_notice_" + enum_notice_id + "']").hide();
1907     }
1911  * jQuery function that uses jQueryUI's dialogs to confirm with user. Does not
1912  *  return a jQuery object yet and hence cannot be chained
1914  * @param   string      question
1915  * @param   string      url         URL to be passed to the callbackFn to make
1916  *                                  an Ajax call to
1917  * @param   function    callbackFn  callback to execute after user clicks on OK
1918  */
1920 jQuery.fn.PMA_confirm = function(question, url, callbackFn) {
1921     if (PMA_messages['strDoYouReally'] == '') {
1922         return true;
1923     }
1925     /**
1926      *  @var    button_options  Object that stores the options passed to jQueryUI
1927      *                          dialog
1928      */
1929     var button_options = {};
1930     button_options[PMA_messages['strOK']] = function(){
1931                                                 $(this).dialog("close").remove();
1933                                                 if($.isFunction(callbackFn)) {
1934                                                     callbackFn.call(this, url);
1935                                                 }
1936                                             };
1937     button_options[PMA_messages['strCancel']] = function() {$(this).dialog("close").remove();}
1939     $('<div id="confirm_dialog"></div>')
1940     .prepend(question)
1941     .dialog({buttons: button_options});
1945  * jQuery function to sort a table's body after a new row has been appended to it.
1946  * Also fixes the even/odd classes of the table rows at the end.
1948  * @param   string      text_selector   string to select the sortKey's text
1950  * @return  jQuery Object for chaining purposes
1951  */
1952 jQuery.fn.PMA_sort_table = function(text_selector) {
1953     return this.each(function() {
1955         /**
1956          * @var table_body  Object referring to the table's <tbody> element
1957          */
1958         var table_body = $(this);
1959         /**
1960          * @var rows    Object referring to the collection of rows in {@link table_body}
1961          */
1962         var rows = $(this).find('tr').get();
1964         //get the text of the field that we will sort by
1965         $.each(rows, function(index, row) {
1966             row.sortKey = $.trim($(row).find(text_selector).text().toLowerCase());
1967         })
1969         //get the sorted order
1970         rows.sort(function(a,b) {
1971             if(a.sortKey < b.sortKey) {
1972                 return -1;
1973             }
1974             if(a.sortKey > b.sortKey) {
1975                 return 1;
1976             }
1977             return 0;
1978         })
1980         //pull out each row from the table and then append it according to it's order
1981         $.each(rows, function(index, row) {
1982             $(table_body).append(row);
1983             row.sortKey = null;
1984         })
1986         //Re-check the classes of each row
1987         $(this).find('tr:odd')
1988         .removeClass('even').addClass('odd')
1989         .end()
1990         .find('tr:even')
1991         .removeClass('odd').addClass('even');
1992     })
1996  * jQuery coding for 'Create Table'.  Used on db_operations.php,
1997  * db_structure.php and db_tracking.php (i.e., wherever
1998  * libraries/display_create_table.lib.php is used)
2000  * Attach Ajax Event handlers for Create Table
2001  */
2002 $(document).ready(function() {
2004     /**
2005      * Attach event handler to the submit action of the create table minimal form
2006      * and retrieve the full table form and display it in a dialog
2007      *
2008      * @uses    PMA_ajaxShowMessage()
2009      */
2010     $("#create_table_form_minimal").live('submit', function(event) {
2011         event.preventDefault();
2013         /* @todo Validate this form! */
2015         /**
2016          *  @var    button_options  Object that stores the options passed to jQueryUI
2017          *                          dialog
2018          */
2019         var button_options = {};
2020         button_options[PMA_messages['strCancel']] = function() {$(this).dialog('close').remove();}
2022         PMA_ajaxShowMessage();
2023         $(this).append('<input type="hidden" name="ajax_request" value="true" />');
2025         $.get($(this).attr('action'), $(this).serialize(), function(data) {
2026             $('<div id="create_table_dialog"></div>')
2027             .append(data)
2028             .dialog({
2029                 title: top.frame_content.PMA_messages['strCreateTable'],
2030                 width: 900,
2031                 buttons : button_options
2032             }); // end dialog options
2033         }) // end $.get()
2035     });
2037     /**
2038      * Attach event handler for submission of create table form
2039      *
2040      * @uses    PMA_ajaxShowMessage()
2041      * @uses    $.PMA_sort_table()
2042      * @uses    window.parent.refreshNavigation()
2043      *
2044      * The create_table_form whose action is tbl_create.php is the
2045      * one which is ajaxified; in this form the action could be 
2046      * tbl_addfield.php but it's not ajaxified yet.
2047      */
2048     $("#create_table_form").attr('action').is('tbl_create.php').find("input[name=submit_num_fields], input[name=do_save_data]").live('click', function(event) {
2049         event.preventDefault();
2051         /**
2052          *  @var    the_form    object referring to the create table form
2053          */
2054         var the_form = $("#create_table_form");
2056         PMA_ajaxShowMessage(PMA_messages['strProcessingRequest']);
2057         $(the_form).append('<input type="hidden" name="ajax_request" value="true" />');
2059         if($(this).attr('name') == 'submit_num_fields') {
2060             //User wants to add more fields to the table
2061             $.post($(the_form).attr('action'), $(the_form).serialize() + "&submit_num_fields=" + $(this).val(), function(data) {
2062                 $("#create_table_dialog").html(data);
2063             }) //end $.post()
2064         }
2065         else if($(this).attr('name') == 'do_save_data') {
2066             //User wants to submit the form
2067             $.post($(the_form).attr('action'), $(the_form).serialize() + "&do_save_data=" + $(this).val(), function(data) {
2068                 if(data.success == true) {
2069                     PMA_ajaxShowMessage(data.message);
2070                     $("#create_table_dialog").dialog("close").remove();
2072                     /**
2073                      * @var tables_table    Object referring to the <tbody> element that holds the list of tables
2074                      */
2075                     var tables_table = $("#tablesForm").find("tbody").not("#tbl_summary_row");
2077                     /**
2078                      * @var curr_last_row   Object referring to the last <tr> element in {@link tables_table}
2079                      */
2080                     var curr_last_row = $(tables_table).find('tr:last');
2081                     /**
2082                      * @var curr_last_row_index_string   String containing the index of {@link curr_last_row}
2083                      */
2084                     var curr_last_row_index_string = $(curr_last_row).find('input:checkbox').attr('id').match(/\d+/)[0];
2085                     /**
2086                      * @var curr_last_row_index Index of {@link curr_last_row}
2087                      */
2088                     var curr_last_row_index = parseFloat(curr_last_row_index_string);
2089                     /**
2090                      * @var new_last_row_index   Index of the new row to be appended to {@link tables_table}
2091                      */
2092                     var new_last_row_index = curr_last_row_index + 1;
2093                     /**
2094                      * @var new_last_row_id String containing the id of the row to be appended to {@link tables_table}
2095                      */
2096                     var new_last_row_id = 'checkbox_tbl_' + new_last_row_index;
2098                     //append to table
2099                     $(data.new_table_string)
2100                     .find('input:checkbox')
2101                     .val(new_last_row_id)
2102                     .end()
2103                     .appendTo(tables_table);
2105                     //Sort the table
2106                     $(tables_table).PMA_sort_table('th');
2108                     //Refresh navigation frame as a new table has been added
2109                     window.parent.refreshNavigation();
2110                 }
2111                 else {
2112                     PMA_ajaxShowMessage(data.error);
2113                 }
2114             }) // end $.post()
2115         } // end elseif()
2116     }) // end create table form submit button actions
2118 }, 'top.frame_content'); //end $(document).ready for 'Create Table'
2121  * Attach event handlers for Empty Table and Drop Table.  Used wherever libraries/
2122  * tbl_links.inc.php is used.
2123  */
2124 $(document).ready(function() {
2126     /**
2127      * Attach Ajax event handlers for Empty Table
2128      *
2129      * @uses    PMA_ajaxShowMessage()
2130      * @uses    $.PMA_confirm()
2131      */
2132     $("#empty_table_anchor").live('click', function(event) {
2133         event.preventDefault();
2135         /**
2136          * @var question    String containing the question to be asked for confirmation
2137          */
2138         var question = 'TRUNCATE TABLE ' + window.parent.table;
2140         $(this).PMA_confirm(question, $(this).attr('href'), function(url) {
2142             PMA_ajaxShowMessage(PMA_messages['strProcessingRequest']);
2143             $.get(url, {'is_js_confirmed': 1, 'ajax_request': true}, function(data) {
2144                 if(data.success == true) {
2145                     PMA_ajaxShowMessage(data.message);
2146                     $("#topmenucontainer")
2147                     .next('div')
2148                     .remove()
2149                     .end()
2150                     .after(data.sql_query);
2151                 }
2152                 else {
2153                     PMA_ajaxShowMessage(data.error);
2154                 }
2155             }) // end $.get
2156         }) // end $.PMA_confirm()
2157     }) // end Empty Table
2159     /**
2160      * Attach Ajax event handler for Drop Table
2161      *
2162      * @uses    PMA_ajaxShowMessage()
2163      * @uses    $.PMA_confirm()
2164      * @uses    window.parent.refreshNavigation()
2165      */
2166     $("#drop_table_anchor").live('click', function(event) {
2167         event.preventDefault();
2169         /**
2170          * @var question    String containing the question to be asked for confirmation
2171          */
2172         var question = 'DROP TABLE/VIEW ' + window.parent.table;
2173         $(this).PMA_confirm(question, $(this).attr('href'), function(url) {
2175             PMA_ajaxShowMessage(PMA_messages['strProcessingRequest']);
2176             $.get(url, {'is_js_confirmed': 1, 'ajax_request': true}, function(data) {
2177                 if(data.success == true) {
2178                     PMA_ajaxShowMessage(data.message);
2179                     $("#topmenucontainer")
2180                     .next('div')
2181                     .remove()
2182                     .end()
2183                     .after(data.sql_query);
2184                     window.parent.table = '';
2185                     window.parent.refreshNavigation();
2186                 }
2187                 else {
2188                     PMA_ajaxShowMessage(data.error);
2189                 }
2190             }) // end $.get
2191         }) // end $.PMA_confirm()
2192     }) // end $().live()
2193 }, 'top.frame_content'); //end $(document).ready() for libraries/tbl_links.inc.php
2196  * Attach Ajax event handlers for Drop Trigger.  Used on tbl_structure.php
2197  */
2198 $(document).ready(function() {
2200     $(".drop_trigger_anchor").live('click', function(event) {
2201         event.preventDefault();
2203         /**
2204          * @var curr_row    Object reference to the current trigger's <tr>
2205          */
2206         var curr_row = $(this).parents('tr');
2207         /**
2208          * @var question    String containing the question to be asked for confirmation
2209          */
2210         var question = 'DROP TRIGGER IF EXISTS `' + $(curr_row).children('td:first').text() + '`';
2212         $(this).PMA_confirm(question, $(this).attr('href'), function(url) {
2214             PMA_ajaxShowMessage(PMA_messages['strProcessingRequest']);
2215             $.get(url, {'is_js_confirmed': 1, 'ajax_request': true}, function(data) {
2216                 if(data.success == true) {
2217                     PMA_ajaxShowMessage(data.message);
2218                     $("#topmenucontainer")
2219                     .next('div')
2220                     .remove()
2221                     .end()
2222                     .after(data.sql_query);
2223                     $(curr_row).hide("medium").remove();
2224                 }
2225                 else {
2226                     PMA_ajaxShowMessage(data.error);
2227                 }
2228             }) // end $.get()
2229         }) // end $.PMA_confirm()
2230     }) // end $().live()
2231 }, 'top.frame_content'); //end $(document).ready() for Drop Trigger
2234  * Attach Ajax event handlers for Drop Database. Moved here from db_structure.js
2235  * as it was also required on db_create.php
2237  * @uses    $.PMA_confirm()
2238  * @uses    PMA_ajaxShowMessage()
2239  * @uses    window.parent.refreshNavigation()
2240  * @uses    window.parent.refreshMain()
2241  */
2242 $(document).ready(function() {
2243     $("#drop_db_anchor").live('click', function(event) {
2244         event.preventDefault();
2246         //context is top.frame_content, so we need to use window.parent.db to access the db var
2247         /**
2248          * @var question    String containing the question to be asked for confirmation
2249          */
2250         var question = PMA_messages['strDropDatabaseStrongWarning'] + '\n' + PMA_messages['strDoYouReally'] + ' :\n' + 'DROP DATABASE ' + window.parent.db;
2252         $(this).PMA_confirm(question, $(this).attr('href') ,function(url) {
2254             PMA_ajaxShowMessage(PMA_messages['strProcessingRequest']);
2255             $.get(url, {'is_js_confirmed': '1', 'ajax_request': true}, function(data) {
2256                 //Database deleted successfully, refresh both the frames
2257                 window.parent.refreshNavigation();
2258                 window.parent.refreshMain();
2259             }) // end $.get()
2260         }); // end $.PMA_confirm()
2261     }); //end of Drop Database Ajax action
2262 }) // end of $(document).ready() for Drop Database
2265  * Attach Ajax event handlers for 'Create Database'.  Used wherever libraries/
2266  * display_create_database.lib.php is used, ie main.php and server_databases.php
2268  * @uses    PMA_ajaxShowMessage()
2269  */
2270 $(document).ready(function() {
2272     $('#create_database_form').live('submit', function(event) {
2273         event.preventDefault();
2275         PMA_ajaxShowMessage(PMA_messages['strProcessingRequest']);
2276         $(this).append('<input type="hidden" name="ajax_request" value="true" />');
2278         $.post($(this).attr('action'), $(this).serialize(), function(data) {
2279             if(data.success == true) {
2280                 PMA_ajaxShowMessage(data.message);
2282                 //Append database's row to table
2283                 $("#tabledatabases")
2284                 .find('tbody')
2285                 .append(data.new_db_string)
2286                 .PMA_sort_table('.name')
2287                 .find('#db_summary_row')
2288                 .appendTo('#tabledatabases tbody')
2289                 .removeClass('odd even');
2290             }
2291             else {
2292                 PMA_ajaxShowMessage(data.error);
2293             }
2294         }) // end $.post()
2295     }) // end $().live()
2296 })  // end $(document).ready() for Create Database
2299  * Attach Ajax event handlers for 'Change Password' on main.php
2300  */
2301 $(document).ready(function() {
2303     /**
2304      * Attach Ajax event handler on the change password anchor
2305      */
2306     $('#change_password_anchor').live('click', function(event) {
2307         event.preventDefault();
2309         /**
2310          * @var button_options  Object containing options to be passed to jQueryUI's dialog
2311          */
2312         var button_options = {};
2314         button_options[PMA_messages['strCancel']] = function() {$(this).dialog('close').remove();}
2316         $.get($(this).attr('href'), {'ajax_request': true}, function(data) {
2317             $('<div id="change_password_dialog></div>')
2318             .dialog({
2319                 title: top.frame_content.PMA_messages['strChangePassword'],
2320                 width: 600,
2321                 buttons : button_options
2322             })
2323             .append(data);
2324             displayPasswordGenerateButton();
2325         }) // end $.get()
2326     }) // end handler for change password anchor
2328     /**
2329      * Attach Ajax event handler for Change Password form submission
2330      *
2331      * @uses    PMA_ajaxShowMessage()
2332      */
2333     $("#change_password_form").find('input[name=change_pw]').live('click', function(event) {
2334         event.preventDefault();
2336         /**
2337          * @var the_form    Object referring to the change password form
2338          */
2339         var the_form = $("#change_password_form");
2341         /**
2342          * @var this_value  String containing the value of the submit button.
2343          * Need to append this for the change password form on Server Privileges
2344          * page to work
2345          */
2346         var this_value = $(this).val();
2348         PMA_ajaxShowMessage(PMA_messages['strProcessingRequest']);
2349         $(the_form).append('<input type="hidden" name="ajax_request" value="true" />');
2351         $.post($(the_form).attr('action'), $(the_form).serialize() + '&change_pw='+ this_value, function(data) {
2352             if(data.success == true) {
2354                 PMA_ajaxShowMessage(data.message);
2356                 $("#topmenucontainer").after(data.sql_query);
2358                 $("#change_password_dialog").hide().remove();
2359                 $("#edit_user_dialog").dialog("close").remove();
2360             }
2361             else {
2362                 PMA_ajaxShowMessage(data.error);
2363             }
2364         }) // end $.post()
2365     }) // end handler for Change Password form submission
2366 }) // end $(document).ready() for Change Password
2369  * Toggle the hiding/showing of the "Open in ENUM/SET editor" message when
2370  * the page loads and when the selected data type changes
2371  */
2372 $(document).ready(function() {
2373     $.each($("select[class='column_type']"), function() {
2374         toggle_enum_notice($(this));
2375     });
2376     $("select[class='column_type']").change(function() {
2377         toggle_enum_notice($(this));
2378     });
2382  * Closes the ENUM/SET editor and removes the data in it
2383  */
2384 function disable_popup() {
2385     $("#popup_background").fadeOut("fast");
2386     $("#enum_editor").fadeOut("fast");
2387     // clear the data from the text boxes
2388     $("#enum_editor #values input").remove();
2389     $("#enum_editor input[type='hidden']").remove();
2393  * Opens the ENUM/SET editor and controls its functions
2394  */
2395 $(document).ready(function() {
2396     $("a[class='open_enum_editor']").click(function() {
2397         // Center the popup
2398         var windowWidth = document.documentElement.clientWidth;
2399         var windowHeight = document.documentElement.clientHeight;
2400         var popupWidth = windowWidth/2;
2401         var popupHeight = windowHeight*0.8;
2402         var popupOffsetTop = windowHeight/2 - popupHeight/2;
2403         var popupOffsetLeft = windowWidth/2 - popupWidth/2;
2404         $("#enum_editor").css({"position":"absolute", "top": popupOffsetTop, "left": popupOffsetLeft, "width": popupWidth, "height": popupHeight});
2406         // Make it appear
2407         $("#popup_background").css({"opacity":"0.7"});
2408         $("#popup_background").fadeIn("fast");
2409         $("#enum_editor").fadeIn("fast");
2411         // Get the values
2412         var values = $(this).parent().prev("input").attr("value").split(",");
2413         $.each(values, function(index, val) {
2414             if(jQuery.trim(val) != "") {
2415                  // enclose the string in single quotes if it's not already
2416                  if(val.substr(0, 1) != "'") {
2417                       val = "'" + val;
2418                  }
2419                  if(val.substr(val.length-1, val.length) != "'") {
2420                       val = val + "'";
2421                  }
2422                 // escape the single quotes, except the mandatory ones enclosing the entire string
2423                 val = val.substr(1, val.length-2).replace(/''/g, "'").replace(/\\\\/g, '\\').replace(/\\'/g, "'").replace(/'/g, "&#039;");
2424                 // escape the greater-than symbol
2425                 val = val.replace(/>/g, "&gt;");
2426                 $("#enum_editor #values").append("<input type='text' value=" + val + " />");
2427             }
2428         });
2429         // So we know which column's data is being edited
2430         $("#enum_editor").append("<input type='hidden' value='" + $(this).parent().prev("input").attr("id") + "' />");
2431         return false;
2432     });
2434     // If the "close" link is clicked, close the enum editor
2435     $("a[class='close_enum_editor']").click(function() {
2436         disable_popup();
2437     });
2439     // If the "cancel" link is clicked, close the enum editor
2440     $("a[class='cancel_enum_editor']").click(function() {
2441         disable_popup();
2442     });
2444     // When "add a new value" is clicked, append an empty text field
2445     $("a[class='add_value']").click(function() {
2446         $("#enum_editor #values").append("<input type='text' />");
2447     });
2449     // When the submit button is clicked, put the data back into the original form
2450     $("#enum_editor input[type='submit']").click(function() {
2451         var value_array = new Array();
2452         $.each($("#enum_editor #values input"), function(index, input_element) {
2453             val = jQuery.trim(input_element.value);
2454             if(val != "") {
2455                 value_array.push("'" + val.replace(/\\/g, '\\\\').replace(/'/g, "''") + "'");
2456             }
2457         });
2458         // get the Length/Values text field where this value belongs
2459         var values_id = $("#enum_editor input[type='hidden']").attr("value");
2460         $("input[id='" + values_id + "']").attr("value", value_array.join(","));
2461         disable_popup();
2462      });
2464     /**
2465      * Hides certain table structure actions, replacing them with the word "More". They are displayed
2466      * in a dropdown menu when the user hovers over the word "More."
2467      */
2468     // Remove the actions from the table cells (they are available by default for JavaScript-disabled browsers)
2469     // if the table is not a view or information_schema (otherwise there is only one action to hide and there's no point)
2470     if($("input[type='hidden'][name='table_type']").attr("value") == "table") {
2471          $("table[id='tablestructure'] td[class='browse']").remove();
2472          $("table[id='tablestructure'] td[class='primary']").remove();
2473          $("table[id='tablestructure'] td[class='unique']").remove();
2474          $("table[id='tablestructure'] td[class='index']").remove();
2475          $("table[id='tablestructure'] td[class='fulltext']").remove();
2476          $("table[id='tablestructure'] th[class='action']").attr("colspan", 3);
2478          // Display the "more" text
2479          $("table[id='tablestructure'] td[class='more_opts']").show()
2481          // Position the dropdown
2482          $.each($(".structure_actions_dropdown"), function() {
2483               // The top offset must be set for IE even if it didn't change
2484              var cell_right_edge_offset = $(this).parent().offset().left + $(this).parent().innerWidth();
2485              var left_offset = cell_right_edge_offset - $(this).innerWidth();
2486              var top_offset = $(this).parent().offset().top + $(this).parent().innerHeight();
2487              $(this).offset({ top: top_offset, left: left_offset });
2488          });
2490          // A hack for IE6 to prevent the after_field select element from being displayed on top of the dropdown by
2491          // positioning an iframe directly on top of it
2492          $("iframe[class='IE_hack']").width($("select[name='after_field']").width());
2493          $("iframe[class='IE_hack']").height($("select[name='after_field']").height());
2494          $("iframe[class='IE_hack']").offset({ top: $("select[name='after_field']").offset().top, left: $("select[name='after_field']").offset().left });
2496          // When "more" is hovered over, show the hidden actions
2497          $("table[id='tablestructure'] td[class='more_opts']").mouseenter(
2498              function() {
2499                 if($.browser.msie && $.browser.version == "6.0") {
2500                     $("iframe[class='IE_hack']").show();
2501                     $("iframe[class='IE_hack']").width($("select[name='after_field']").width()+4);
2502                     $("iframe[class='IE_hack']").height($("select[name='after_field']").height()+4);
2503                     $("iframe[class='IE_hack']").offset({ top: $("select[name='after_field']").offset().top, left: $("select[name='after_field']").offset().left});
2504                 }
2505                 $(".structure_actions_dropdown").hide(); // Hide all the other ones that may be open
2506                 $(this).children(".structure_actions_dropdown").show();
2507                 // Need to do this again for IE otherwise the offset is wrong
2508                 if($.browser.msie) {
2509                     var left_offset_IE = $(this).offset().left + $(this).innerWidth() - $(this).children(".structure_actions_dropdown").innerWidth();
2510                     var top_offset_IE = $(this).offset().top + $(this).innerHeight();
2511                     $(this).children(".structure_actions_dropdown").offset({ top: top_offset_IE, left: left_offset_IE });
2512                 }
2513          });
2514          $(".structure_actions_dropdown").mouseleave(function() {
2515               $(this).hide();
2516               if($.browser.msie && $.browser.version == "6.0") {
2517                   $("iframe[class='IE_hack']").hide();
2518               }
2519          });
2520     }
2523 /* Displays tooltips */
2524 $(document).ready(function() {
2525     // Hide the footnotes from the footer (which are displayed for
2526     // JavaScript-disabled browsers) since the tooltip is sufficient
2527     $(".footnotes").hide();
2528     $(".footnotes span").each(function() {
2529         $(this).children("sup").remove();
2530     });
2531     // The border and padding must be removed otherwise a thin yellow box remains visible
2532     $(".footnotes").css("border", "none");
2533     $(".footnotes").css("padding", "0px");
2535     // Replace the superscripts with the help icon
2536     $("sup[class='footnotemarker']").hide();
2537     $("img[class='footnotemarker']").show();
2539     $("img[class='footnotemarker']").each(function() {
2540         var span_id = $(this).attr("id");
2541         span_id = span_id.split("_")[1];
2542         var tooltip_text = $(".footnotes span[id='footnote_" + span_id + "']").html();
2543         $(this).qtip({
2544             content: tooltip_text,
2545             show: { delay: 0 },
2546             hide: { when: 'unfocus', delay: 0 },
2547             style: { background: '#ffffcc' }
2548         });
2549     });
2552 function menuResize()
2554     var cnt = $('#topmenu');
2555     var wmax = cnt.width() - 5; // 5 px margin for jumping menu in Chrome
2556     var submenu = cnt.find('.submenu');
2557     var submenu_w = submenu.outerWidth(true);
2558     var submenu_ul = submenu.find('ul');
2559     var li = cnt.find('> li');
2560     var li2 = submenu_ul.find('li');
2561     var more_shown = li2.length > 0;
2562     var w = more_shown ? submenu_w : 0;
2564     // hide menu items
2565     var hide_start = 0;
2566     for (var i = 0; i < li.length-1; i++) { // li.length-1: skip .submenu element
2567         var el = $(li[i]);
2568         var el_width = el.outerWidth(true);
2569         el.data('width', el_width);
2570         w += el_width;
2571         if (w > wmax) {
2572             w -= el_width;
2573             if (w + submenu_w < wmax) {
2574                 hide_start = i;
2575             } else {
2576                 hide_start = i-1;
2577                 w -= $(li[i-1]).data('width');
2578             }
2579             break;
2580         }
2581     }
2583     if (hide_start > 0) {
2584         for (var i = hide_start; i < li.length-1; i++) {
2585             $(li[i])[more_shown ? 'prependTo' : 'appendTo'](submenu_ul);
2586         }
2587         submenu.show();
2588     } else if (more_shown) {
2589         w -= submenu_w;
2590         // nothing hidden, maybe something can be restored
2591         for (var i = 0; i < li2.length; i++) {
2592             //console.log(li2[i], submenu_w);
2593             w += $(li2[i]).data('width');
2594             // item fits or (it is the last item and it would fit if More got removed)
2595             if (w+submenu_w < wmax || (i == li2.length-1 && w < wmax)) {
2596                 $(li2[i]).insertBefore(submenu);
2597                 if (i == li2.length-1) {
2598                     submenu.hide();
2599                 }
2600                 continue;
2601             }
2602             break;
2603         }
2604     }
2605     if (submenu.find('.tabactive').length) {
2606         submenu.addClass('active').find('> a').removeClass('tab').addClass('tabactive');
2607     } else {
2608         submenu.removeClass('active').find('> a').addClass('tab').removeClass('tabactive');
2609     }
2612 $(function() {
2613     var topmenu = $('#topmenu');
2614     if (topmenu.length == 0) {
2615         return;
2616     }
2617     // create submenu container
2618     var link = $('<a />', {href: '#', 'class': 'tab'})
2619         .text(PMA_messages['strMore'])
2620         .click(function(e) {
2621             e.preventDefault();
2622         });
2623     var img = topmenu.find('li:first-child img');
2624     if (img.length) {
2625         img.clone().attr('src', img.attr('src').replace(/\/[^\/]+$/, '/b_more.png')).prependTo(link);
2626     }
2627     var submenu = $('<li />', {'class': 'submenu'})
2628         .append(link)
2629         .append($('<ul />'))
2630         .mouseenter(function() {
2631             if ($(this).find('ul .tabactive').length == 0) {
2632                 $(this).addClass('submenuhover').find('> a').addClass('tabactive');
2633             }
2634         })
2635         .mouseleave(function() {
2636             if ($(this).find('ul .tabactive').length == 0) {
2637                 $(this).removeClass('submenuhover').find('> a').removeClass('tabactive');
2638             }
2639         })
2640         .hide();
2641     topmenu.append(submenu);
2643     // populate submenu and register resize event
2644     $(window).resize(menuResize);
2645     menuResize();