better documentation of $cfg['TempDir'] (first draft)
[phpmyadmin/last10db.git] / setup / scripts.js
blob5f0a75aaf1043aa4873c4818eeb8bd7ad1d80653
1 /**\r
2  * functions used in setup script\r
3  * \r
4  * @version $Id$\r
5  */\r
6 \r
7 // show this window in top frame\r
8 if (top != self) {\r
9     window.top.location.href = location;\r
10 }\r
12 // default values for fields\r
13 var defaultValues = {};\r
15 // language strings\r
16 var PMA_messages = {};\r
18 /**\r
19  * Returns field type\r
20  *\r
21  * @param Element field\r
22  */\r
23 function getFieldType(field) {\r
24     if (field.tagName == 'INPUT') {\r
25         return field.getProperty('type');\r
26     } else if (field.tagName == 'SELECT') {\r
27         return 'select';\r
28     } else if (field.tagName == 'TEXTAREA') {\r
29         return 'text';\r
30     }\r
31     return '';\r
32 }\r
34 /**\r
35  * Sets field value\r
36  *\r
37  * value must be of type:\r
38  * o undefined (omitted) - restore default value (form default, not PMA default)\r
39  * o String - if type is 'text'\r
40  * o boolean - if type is 'checkbox'\r
41  * o Array of values - if type is 'select'\r
42  *\r
43  * @param Element field\r
44  * @param String  field_type  see getFieldType\r
45  * @param mixed   value\r
46  */\r
47 function setFieldValue(field, field_type, value) {\r
48     switch (field_type) {\r
49         case 'text':\r
50             field.value = $defined(value) ? value : field.defaultValue;\r
51             break;\r
52         case 'checkbox':\r
53             field.checked = $defined(value) ? value : field.defaultChecked;\r
54             break;\r
55         case 'select':\r
56             var i, imax = field.options.length;\r
57             if (!$defined(value)) {\r
58                 for (i = 0; i < imax; i++) {\r
59                     field.options[i].selected = field.options[i].defaultSelected;\r
60                 }\r
61             } else {\r
62                 for (i = 0; i < imax; i++) {\r
63                     field.options[i].selected = (value.indexOf(field.options[i].value) != -1);\r
64                 }\r
65             }\r
66             break;\r
67     }\r
68     markField(field);\r
69 }\r
71 /**\r
72  * Gets field value\r
73  *\r
74  * Will return one of:\r
75  * o String - if type is 'text'\r
76  * o boolean - if type is 'checkbox'\r
77  * o Array of values - if type is 'select'\r
78  *\r
79  * @param Element field\r
80  * @param String  field_type  see getFieldType\r
81  * @return mixed\r
82  */\r
83 function getFieldValue(field, field_type) {\r
84     switch (field_type) {\r
85         case 'text':\r
86             return field.value;\r
87         case 'checkbox':\r
88             return field.checked;\r
89         case 'select':\r
90             var i, imax = field.options.length, items = [];\r
91             for (i = 0; i < imax; i++) {\r
92                 if (field.options[i].selected) {\r
93                     items.push(field.options[i].value);\r
94                 }\r
95             }\r
96             return items;\r
97     }\r
98 }\r
100 /**\r
101  * Returns values for all fields in fieldsets\r
102  */\r
103 function getAllValues() {\r
104     var elements = $$('fieldset input, fieldset select, fieldset textarea');\r
105     var values = {}\r
106     var type, value;\r
107     for (var i = 0; i < elements.length; i++) {\r
108         type = getFieldType(elements[i]);\r
109         value = getFieldValue(elements[i], type);\r
110         if (typeof value != 'undefined') {\r
111             // we only have single selects, fatten array\r
112             if (type == 'select') {\r
113                 value = value[0];\r
114             }\r
115             values[elements[i].name] = value;\r
116         }\r
117     }\r
118     return values;\r
121 /**\r
122  * Checks whether field has its default value\r
123  *\r
124  * @param Element field\r
125  * @param String  type\r
126  * @return boolean\r
127  */\r
128 function checkFieldDefault(field, type) {\r
129     if (!$defined(defaultValues[field.id])) {\r
130         return true;\r
131     }\r
132     var isDefault = true\r
133     var currentValue = getFieldValue(field, type);\r
134     if (type != 'select') {\r
135         isDefault = currentValue == defaultValues[field.id];\r
136     } else {\r
137         // compare arrays, will work for our representation of select values\r
138         if (currentValue.length != defaultValues[field.id].length) {\r
139             isDefault = false;\r
140         }\r
141         else {\r
142             for (var i = 0; i < currentValue.length; i++) {\r
143                 if (currentValue[i] != defaultValues[field.id][i]) {\r
144                     isDefault = false;\r
145                     break;\r
146                 }\r
147             }\r
148         }\r
149     }\r
150     return isDefault;\r
153 /**\r
154  * Returns element's id prefix\r
155  * @param Element element\r
156  */\r
157 function getIdPrefix(element) {\r
158     return element.id.replace(/[^-]+$/, '');\r
161 // ------------------------------------------------------------------\r
162 // Messages\r
163 //\r
165 // stores hidden message ids\r
166 var hiddenMessages = [];\r
168 window.addEvent('domready', function() {\r
169     var hidden = hiddenMessages.length;\r
170     for (var i = 0; i < hidden; i++) {\r
171         $(hiddenMessages[i]).style.display = 'none';\r
172     }\r
173     if (hidden > 0) {\r
174         var link = $('show_hidden_messages');\r
175         link.addEvent('click', function(e) {\r
176             e.stop();\r
177             for (var i = 0; i < hidden; i++) {\r
178                 $(hiddenMessages[i]).style.display = '';\r
179             }\r
180             this.dispose();\r
181         });\r
182         link.set('html', link.get('html').replace('#MSG_COUNT', hidden));\r
183         link.style.display = '';\r
184     }\r
185 });\r
187 //\r
188 // END: Messages\r
189 // ------------------------------------------------------------------\r
191 // ------------------------------------------------------------------\r
192 // Form validation and field operations\r
193 //\r
195 // form validator assignments\r
196 var validate = {};\r
198 // form validator list\r
199 var validators = {\r
200     /**\r
201      * Validates positive number\r
202      *\r
203      * @param boolean isKeyUp\r
204      */\r
205     validate_positive_number: function (isKeyUp) {\r
206         var result = this.value.test('^[0-9]*$') && this.value != '0';\r
207         return result ? true : PMA_messages['error_nan_p'];\r
208     },\r
209     /**\r
210      * Validates non-negative number\r
211      *\r
212      * @param boolean isKeyUp\r
213      */\r
214     validate_non_negative_number: function (isKeyUp) {\r
215         var result = this.value.test('^[0-9]*$');\r
216         return result ? true : PMA_messages['error_nan_nneg'];\r
217     },\r
218     /**\r
219      * Validates port number\r
220      *\r
221      * @param boolean isKeyUp\r
222      */\r
223     validate_port_number: function(isKeyUp) {\r
224         var result = this.value.test('^[0-9]*$') && this.value != '0';\r
225         if (!result || this.value > 65536) {\r
226             result = PMA_messages['error_incorrect_port'];\r
227         }\r
228         return result;\r
229     },\r
230     // field validators\r
231     _field: {\r
232         /**\r
233          * hide_db field\r
234          *\r
235          * @param boolean isKeyUp\r
236          */\r
237         hide_db: function(isKeyUp) {\r
238             if (!isKeyUp && this.value != '') {\r
239                 var data = {};\r
240                 data[this.id] = this.value;\r
241                 ajaxValidate(this, 'Servers/1/hide_db', data);\r
242             }\r
243             return true;\r
244         }\r
245     },\r
246     // fieldset validators\r
247     _fieldset: {\r
248         /**\r
249          * Validates Server fieldset\r
250          *\r
251          * @param boolean isKeyUp\r
252          */\r
253         Server: function(isKeyUp) {\r
254             if (!isKeyUp) {\r
255                 ajaxValidate(this, 'Server', getAllValues());\r
256             }\r
257             return true;\r
258         },\r
259         /**\r
260          * Validates Server_login_options fieldset\r
261          *\r
262          * @param boolean isKeyUp\r
263          */\r
264         Server_login_options: function(isKeyUp) {\r
265             return validators._fieldset.Server.bind(this)(isKeyUp);\r
266         },\r
267         /**\r
268          * Validates Server_pmadb fieldset\r
269          *\r
270          * @param boolean isKeyUp\r
271          */\r
272         Server_pmadb: function(isKeyUp) {\r
273             if (isKeyUp) {\r
274                 return true;\r
275             }\r
277             var prefix = getIdPrefix(this.getElement('input'));\r
278             var pmadb_active = $(prefix + 'pmadb').value != '';\r
279             if (pmadb_active) {\r
280                 ajaxValidate(this, 'Server_pmadb', getAllValues());\r
281             }\r
283             return true;\r
284         }\r
285     }\r
288 /**\r
289  * Calls server-side validation procedures\r
290  *\r
291  * @param Element parent  input field in <fieldset> or <fieldset>\r
292  * @param String id       validator id\r
293  * @param Object values   values hash (element_id: value)\r
294  */\r
295 function ajaxValidate(parent, id, values) {\r
296     // ensure that parent is a fieldset\r
297     if (parent.tagName != 'FIELDSET') {\r
298         parent = parent.getParent('fieldset');\r
299         if (!parent) {\r
300             return false;\r
301         }\r
302     }\r
303     // ensure that we have a Request object\r
304     if (typeof parent.request == 'undefined') {\r
305         parent.validate = {\r
306             request: new Request.JSON({\r
307                 url: 'validate.php',\r
308                 autoCancel: true,\r
309                 onSuccess: function(response) {\r
310                     if (response == null) {\r
311                         return;\r
312                     }\r
313                     var error = {};\r
314                     if ($type(response) != 'object') {\r
315                         error[parent.id] = [response];\r
316                     } else if (typeof response['error'] != 'undefined') {\r
317                         error[parent.id] = [response['error']];\r
318                     } else {\r
319                         $each(response, function(value, key) {\r
320                             error[key] = $type(value) == 'array' ? value : [value];\r
321                         });\r
322                     }\r
323                     displayErrors(error);\r
324                 }}),\r
325             token: parent.getParent('form').token.value\r
326         };\r
327     }\r
329     parent.validate.request.send({\r
330         data: {\r
331             token: parent.validate.token,\r
332             id: id,\r
333             values: JSON.encode(values)}\r
334     });\r
336     return true;\r
339 /**\r
340  * Registers validator for given field\r
341  *\r
342  * @param String  id       field id\r
343  * @param String  type     validator (key in validators object)\r
344  * @param boolean onKeyUp  whether fire on key up\r
345  * @param mixed   params   validation function parameters\r
346  */\r
347 function validateField(id, type, onKeyUp, params) {\r
348     if (typeof validators[type] == 'undefined') {\r
349         return;\r
350     }\r
351     if (typeof validate[id] == 'undefined') {\r
352         validate[id] = [];\r
353     }\r
354     validate[id].push([type, params, onKeyUp]);\r
357 /**\r
358  * Returns valdiation functions associated with form field\r
359  *\r
360  * @param  String  field_id     form field id\r
361  * @param  boolean onKeyUpOnly  see validateField\r
362  * @return Array  array of [function, paramseters to be passed to function]\r
363  */\r
364 function getFieldValidators(field_id, onKeyUpOnly) {\r
365     // look for field bound validator\r
366     var name = field_id.match(/[^-]+$/)[0];\r
367     if (typeof validators._field[name] != 'undefined') {\r
368         return [[validators._field[name], null]];\r
369     }\r
371     // look for registered validators\r
372     var functions = [];\r
373     if (typeof validate[field_id] != 'undefined') {\r
374         // validate[field_id]: array of [type, params, onKeyUp]\r
375         for (var i = 0, imax = validate[field_id].length; i < imax; i++) {\r
376             if (onKeyUpOnly && !validate[field_id][i][2]) {\r
377                 continue;\r
378             }\r
379             functions.push([validators[validate[field_id][i][0]], validate[field_id][i][1]]);\r
380         }\r
381     }\r
383     return functions;\r
386 /**\r
387  * Displays errors for given form fields\r
388  *\r
389  * WARNING: created DOM elements must be identical with the ones made by\r
390  * display_input() in FormDisplay.tpl.php!\r
391  *\r
392  * @param Object  error list (key: field id, value: error array)\r
393  */\r
394 function displayErrors(errors) {\r
395     $each(errors, function(errors, field_id) {\r
396         var field = $(field_id);\r
397         var isFieldset = field.tagName == 'FIELDSET';\r
398         var errorCnt = isFieldset\r
399             ? field.getElement('dl.errors')\r
400             : field.getNext('.inline_errors');\r
402         // remove empty errors (used to clear error list)\r
403         errors = errors.filter(function(item) {\r
404             return item != '';\r
405         });\r
407         if (errors.length) {\r
408             // if error container doesn't exist, create it\r
409             if (errorCnt === null) {\r
410                 if (isFieldset) {\r
411                     errorCnt = new Element('dl', {\r
412                         'class': 'errors'\r
413                     });\r
414                     errorCnt.inject(field.getElement('table'), 'before');\r
415                 } else {\r
416                     errorCnt = new Element('dl', {\r
417                         'class': 'inline_errors'\r
418                     });\r
419                     errorCnt.inject(field.getParent('td'), 'bottom');\r
420                 }\r
421             }\r
423             var html = '';\r
424             for (var i = 0, imax = errors.length; i < imax; i++) {\r
425                 html += '<dd>' + errors[i] + '</dd>';\r
426             }\r
427             errorCnt.set('html', html);\r
428         } else if (errorCnt !== null) {\r
429             // remove useless error container\r
430             errorCnt.dispose();\r
431         }\r
432     });\r
435 /**\r
436  * Validates fieldset and puts errors in 'errors' object\r
437  *\r
438  * @param Element field\r
439  * @param boolean isKeyUp\r
440  * @param Object  errors\r
441  */\r
442 function validate_fieldset(fieldset, isKeyUp, errors) {\r
443     if (fieldset && typeof validators._fieldset[fieldset.id] != 'undefined') {\r
444         var fieldset_errors = validators._fieldset[fieldset.id].bind(fieldset)(isKeyUp);\r
445         $each(fieldset_errors, function(field_errors, field_id) {\r
446             if (typeof errors[field_id] == 'undefined') {\r
447                 errors[field_id] = [];\r
448             }\r
449             errors[field_id][$type(field_errors) == 'array' ? 'extend' : 'push'](field_errors);\r
450         });\r
451     }\r
454 /**\r
455  * Validates form field and puts errors in 'errors' object\r
456  *\r
457  * @param Element field\r
458  * @param boolean isKeyUp\r
459  * @param Object  errors\r
460  */\r
461 function validate_field(field, isKeyUp, errors) {\r
462     errors[field.id] = [];\r
463     var functions = getFieldValidators(field.id, isKeyUp);\r
464     for (var i = 0; i < functions.length; i++) {\r
465         var result = functions[i][0].bind(field)(isKeyUp, functions[i][1]);\r
466         if (result !== true) {\r
467             errors[field.id][$type(result) == 'array' ? 'extend' : 'push'](result);\r
468         }\r
469     }\r
472 /**\r
473  * Validates form field and parent fieldset\r
474  *\r
475  * @param Element field\r
476  * @param boolean isKeyUp\r
477  */\r
478 function validate_field_and_fieldset(field, isKeyUp) {\r
479     var errors = {};\r
480     validate_field(field, isKeyUp, errors);\r
481     validate_fieldset(field.getParent('fieldset'), isKeyUp, errors);\r
482     displayErrors(errors);\r
485 /**\r
486  * Marks field depending on its value (system default or custom)\r
487  *\r
488  * @param Element field\r
489  */\r
490 function markField(field) {\r
491     var type = getFieldType(field);\r
492     var isDefault = checkFieldDefault(field, type);\r
494     // checkboxes uses parent <span> for marking\r
495     var fieldMarker = (type == 'checkbox') ? field.getParent() : field;\r
496     setRestoreDefaultBtn(field, !isDefault);\r
497     fieldMarker[isDefault ? 'removeClass' : 'addClass']('custom');\r
500 /**\r
501  * Enables or disables the "restore default value" button\r
502  *\r
503  * @param Element field\r
504  * @param bool    display\r
505  */\r
506 function setRestoreDefaultBtn(field, display) {\r
507     var td = field.getParent('td');\r
508     if (!td) return;\r
509     var el = td.getElement('.restore-default');\r
510     if (!el) return;\r
511     el.style.display = (display ? '' : 'none');\r
514 window.addEvent('domready', function() {\r
515     var elements = $$('input[id], select[id], textarea[id]');\r
516     var elements_count = elements.length;\r
518     // register validators and mark custom values\r
519     for (var i = 0; i < elements_count; i++) {\r
520         var el = elements[i];\r
521         markField(el);\r
522         el.addEvent('change', function(e) {\r
523             validate_field_and_fieldset(this, false);\r
524             markField(this);\r
525         });\r
526         // text fields can be validated after each change\r
527         if (el.tagName == 'INPUT' && el.type == 'text') {\r
528             el.addEvent('keyup', function(e) {\r
529                 validate_field_and_fieldset(this, true);\r
530                 markField(el);\r
531             });\r
532         }\r
533         // disable textarea spellcheck\r
534         if (el.tagName == 'TEXTAREA') {\r
535             el.setProperty('spellcheck', false)\r
536         }\r
537     }\r
539         // check whether we've refreshed a page and browser remembered modified\r
540         // form values\r
541         var check_page_refresh = $('check_page_refresh');\r
542         if (!check_page_refresh || check_page_refresh.value == '1') {\r
543                 // run all field validators\r
544                 var errors = {};\r
545                 for (var i = 0; i < elements_count; i++) {\r
546                         validate_field(elements[i], false, errors);\r
547                 }\r
548                 // run all fieldset validators\r
549                 $$('fieldset').each(function(el){\r
550                         validate_fieldset(el, false, errors);\r
551                 });\r
552                 \r
553                 displayErrors(errors);\r
554         } else if (check_page_refresh) {\r
555                 check_page_refresh.value = '1';\r
556         }\r
557 });\r
559 //\r
560 // END: Form validation and field operations\r
561 // ------------------------------------------------------------------\r
563 // ------------------------------------------------------------------\r
564 // Tabbed forms\r
565 //\r
567 /**\r
568  * Sets active tab\r
569  *\r
570  * @param Element tab_link\r
571  */\r
572 function setTab(tab_link) {\r
573     var tabs_menu = tab_link.getParent('.tabs');\r
575     var links = tabs_menu.getElements('a');\r
576     var contents;\r
577     for (var i = 0, imax = links.length; i < imax; i++) {\r
578         contents = $(links[i].getProperty('href').substr(1));\r
579         if (links[i] == tab_link) {\r
580             links[i].addClass('active');\r
581             contents.style.display = 'block';\r
582         } else {\r
583             links[i].removeClass('active');\r
584             contents.style.display = 'none';\r
585         }\r
586     }\r
587     location.hash = 'tab_' + tab_link.getProperty('href').substr(1);\r
590 window.addEvent('domready', function() {\r
591     var tabs = $$('.tabs');\r
592     var url_tab = location.hash.match(/^#tab_.+/)\r
593         ? $$('a[href$="' + location.hash.substr(5) + '"]') : null;\r
594     if (url_tab) {\r
595         url_tab = url_tab[0];\r
596     }\r
597     // add tabs events and activate one tab (the first one or indicated by location hash)\r
598     for (var i = 0, imax = tabs.length; i < imax; i++) {\r
599         var links = tabs[i].getElements('a');\r
600         var selected_tab = links[0];\r
601         for (var j = 0, jmax = links.length; j < jmax; j++) {\r
602             links[j].addEvent('click', function(e) {\r
603                 e.stop();\r
604                 setTab(this);\r
605             });\r
606             if (links[j] == url_tab) {\r
607                 selected_tab = links[j];\r
608             }\r
609         }\r
610         setTab(selected_tab);\r
611     }\r
612     // tab links handling, check each 200ms\r
613     // (works with history in FF, further browser support here would be an overkill)\r
614     var prev_hash = location.hash;\r
615     (function() {\r
616         if (location.hash != prev_hash) {\r
617             prev_hash = location.hash;\r
618             var url_tab = location.hash.match(/^#tab_.+/)\r
619                 ? $$('a[href$="' + location.hash.substr(5) + '"]') : null;\r
620             if (url_tab) {\r
621                 setTab(url_tab[0]);\r
622             }\r
623         }\r
624     }).periodical(200);\r
625 });\r
627 //\r
628 // END: Tabbed forms\r
629 // ------------------------------------------------------------------\r
631 // ------------------------------------------------------------------\r
632 // Form reset buttons\r
633 //\r
635 window.addEvent('domready', function() {\r
636     var buttons = $$('input[type=button]');\r
637     for (var i = 0, imax = buttons.length; i < imax; i++) {\r
638         buttons[i].addEvent('click', function(e) {\r
639             var fields = this.getParent('fieldset').getElements('input, select, textarea');\r
640             for (var i = 0, imax = fields.length; i < imax; i++) {\r
641                 setFieldValue(fields[i], getFieldType(fields[i]));\r
642             }\r
643         });\r
644     }\r
645 });\r
647 //\r
648 // END: Form reset buttons\r
649 // ------------------------------------------------------------------\r
651 // ------------------------------------------------------------------\r
652 // "Restore default" and "set value" buttons\r
653 //\r
655 /**\r
656  * Restores field's default value\r
657  *\r
658  * @param String field_id\r
659  */\r
660 function restoreField(field_id) {\r
661     var field = $(field_id);\r
662     if (!field || !$defined(defaultValues[field_id])) {\r
663         return;\r
664     }\r
665     setFieldValue(field, getFieldType(field), defaultValues[field_id]);\r
668 window.addEvent('domready', function() {\r
669     var buttons = $$('.restore-default, .set-value');\r
670     var fixIE = Browser.Engine.name == 'trident' && Browser.Engine.version == 4;\r
671     for (var i = 0, imax = buttons.length; i < imax; i++) {\r
672         buttons[i].set('opacity', 0.25);\r
673         if (!buttons[i].hasClass('restore-default')) {\r
674             // restore-default is handled by markField\r
675             buttons[i].style.display = '';\r
676         }\r
677         buttons[i].addEvents({\r
678             mouseenter: function(e) {this.set('opacity', 1);},\r
679             mouseleave: function(e) {this.set('opacity', 0.25);},\r
680             click: function(e) {\r
681                 e.stop();\r
682                 var href = this.getProperty('href').substr(1);\r
683                 var field_id;\r
684                 if (this.hasClass('restore-default')) {\r
685                     field_id = href;\r
686                     restoreField(field_id);\r
687                 } else {\r
688                     field_id = href.match(/^[^=]+/)[0];\r
689                     var value = href.match(/=(.+)$/)[1];\r
690                     setFieldValue($(field_id), 'text', value);\r
691                 }\r
692                 $(field_id).fireEvent('change');\r
693             }\r
694         });\r
695         // fix IE showing <img> alt text instead of link title\r
696         if (fixIE) {\r
697             buttons[i].getChildren('img')[0].alt = buttons[i].title;\r
698         }\r
699     }\r
700 });\r
702 //\r
703 // END: "Restore default" and "set value" buttons\r
704 // ------------------------------------------------------------------\r