2 * functions used in setup script
7 // show this window in top frame
9 window
.top
.location
.href
= location
;
12 // default values for fields
13 var defaultValues
= {};
16 var PMA_messages
= {};
21 * @param Element field
23 function getFieldType(field
) {
24 if (field
.tagName
== 'INPUT') {
25 return field
.getProperty('type');
26 } else if (field
.tagName
== 'SELECT') {
28 } else if (field
.tagName
== 'TEXTAREA') {
37 * value must be of type:
38 * o undefined (omitted) - restore default value (form default, not PMA default)
39 * o String - if type is 'text'
40 * o boolean - if type is 'checkbox'
41 * o Array of values - if type is 'select'
43 * @param Element field
44 * @param String field_type see getFieldType
47 function setFieldValue(field
, field_type
, value
) {
50 field
.value
= $defined(value
) ? value
: field
.defaultValue
;
53 field
.checked
= $defined(value
) ? value
: field
.defaultChecked
;
56 var i
, imax
= field
.options
.length
;
57 if (!$defined(value
)) {
58 for (i
= 0; i
< imax
; i
++) {
59 field
.options
[i
].selected
= field
.options
[i
].defaultSelected
;
62 for (i
= 0; i
< imax
; i
++) {
63 field
.options
[i
].selected
= (value
.indexOf(field
.options
[i
].value
) != -1);
75 * o String - if type is 'text'
76 * o boolean - if type is 'checkbox'
77 * o Array of values - if type is 'select'
79 * @param Element field
80 * @param String field_type see getFieldType
83 function getFieldValue(field
, field_type
) {
90 var i
, imax
= field
.options
.length
, items
= [];
91 for (i
= 0; i
< imax
; i
++) {
92 if (field
.options
[i
].selected
) {
93 items
.push(field
.options
[i
].value
);
101 * Returns values for all fields in fieldsets
103 function getAllValues() {
104 var elements
= $$('fieldset input, fieldset select, fieldset textarea');
107 for (var i
= 0; i
< elements
.length
; i
++) {
108 type
= getFieldType(elements
[i
]);
109 value
= getFieldValue(elements
[i
], type
);
110 if (typeof value
!= 'undefined') {
111 // we only have single selects, fatten array
112 if (type
== 'select') {
115 values
[elements
[i
].name
] = value
;
122 * Checks whether field has its default value
124 * @param Element field
128 function checkFieldDefault(field
, type
) {
129 if (!$defined(defaultValues
[field
.id
])) {
133 var currentValue
= getFieldValue(field
, type
);
134 if (type
!= 'select') {
135 isDefault
= currentValue
== defaultValues
[field
.id
];
137 // compare arrays, will work for our representation of select values
138 if (currentValue
.length
!= defaultValues
[field
.id
].length
) {
142 for (var i
= 0; i
< currentValue
.length
; i
++) {
143 if (currentValue
[i
] != defaultValues
[field
.id
][i
]) {
154 * Returns element's id prefix
155 * @param Element element
157 function getIdPrefix(element
) {
158 return element
.id
.replace(/[^-]+$/, '');
161 // ------------------------------------------------------------------
165 // stores hidden message ids
166 var hiddenMessages
= [];
168 window
.addEvent('domready', function() {
169 var hidden
= hiddenMessages
.length
;
170 for (var i
= 0; i
< hidden
; i
++) {
171 $(hiddenMessages
[i
]).style
.display
= 'none';
174 var link
= $('show_hidden_messages');
175 link
.addEvent('click', function(e
) {
177 for (var i
= 0; i
< hidden
; i
++) {
178 $(hiddenMessages
[i
]).style
.display
= '';
182 link
.set('html', link
.get('html').replace('#MSG_COUNT', hidden
));
183 link
.style
.display
= '';
189 // ------------------------------------------------------------------
191 // ------------------------------------------------------------------
192 // Form validation and field operations
195 // form validator assignments
198 // form validator list
201 * Validates positive number
203 * @param boolean isKeyUp
205 validate_positive_number: function (isKeyUp
) {
206 var result
= this.value
.test('^[0-9]*$') && this.value
!= '0';
207 return result
? true : PMA_messages
['error_nan_p'];
210 * Validates non-negative number
212 * @param boolean isKeyUp
214 validate_non_negative_number: function (isKeyUp
) {
215 var result
= this.value
.test('^[0-9]*$');
216 return result
? true : PMA_messages
['error_nan_nneg'];
219 * Validates port number
221 * @param boolean isKeyUp
223 validate_port_number: function(isKeyUp
) {
224 var result
= this.value
.test('^[0-9]*$') && this.value
!= '0';
225 if (!result
|| this.value
> 65536) {
226 result
= PMA_messages
['error_incorrect_port'];
235 * @param boolean isKeyUp
237 hide_db: function(isKeyUp
) {
238 if (!isKeyUp
&& this.value
!= '') {
240 data
[this.id
] = this.value
;
241 ajaxValidate(this, 'Servers/1/hide_db', data
);
246 * TrustedProxies field
248 * @param boolean isKeyUp
250 TrustedProxies: function(isKeyUp
) {
251 if (!isKeyUp
&& this.value
!= '') {
253 data
[this.id
] = this.value
;
254 ajaxValidate(this, 'TrustedProxies', data
);
259 // fieldset validators
262 * Validates Server fieldset
264 * @param boolean isKeyUp
266 Server: function(isKeyUp
) {
268 ajaxValidate(this, 'Server', getAllValues());
273 * Validates Server_login_options fieldset
275 * @param boolean isKeyUp
277 Server_login_options: function(isKeyUp
) {
278 return validators
._fieldset
.Server
.bind(this)(isKeyUp
);
281 * Validates Server_pmadb fieldset
283 * @param boolean isKeyUp
285 Server_pmadb: function(isKeyUp
) {
290 var prefix
= getIdPrefix(this.getElement('input'));
291 var pmadb_active
= $(prefix
+ 'pmadb').value
!= '';
293 ajaxValidate(this, 'Server_pmadb', getAllValues());
302 * Calls server-side validation procedures
304 * @param Element parent input field in <fieldset> or <fieldset>
305 * @param String id validator id
306 * @param Object values values hash (element_id: value)
308 function ajaxValidate(parent
, id
, values
) {
309 // ensure that parent is a fieldset
310 if (parent
.tagName
!= 'FIELDSET') {
311 parent
= parent
.getParent('fieldset');
316 // ensure that we have a Request object
317 if (typeof parent
.request
== 'undefined') {
319 request
: new Request
.JSON({
322 onSuccess: function(response
) {
323 if (response
== null) {
327 if ($type(response
) != 'object') {
328 error
[parent
.id
] = [response
];
329 } else if (typeof response
['error'] != 'undefined') {
330 error
[parent
.id
] = [response
['error']];
332 $each(response
, function(value
, key
) {
333 error
[key
] = $type(value
) == 'array' ? value
: [value
];
336 displayErrors(error
);
338 token
: parent
.getParent('form').token
.value
342 parent
.validate
.request
.send({
344 token
: parent
.validate
.token
,
346 values
: JSON
.encode(values
)}
353 * Registers validator for given field
355 * @param String id field id
356 * @param String type validator (key in validators object)
357 * @param boolean onKeyUp whether fire on key up
358 * @param mixed params validation function parameters
360 function validateField(id
, type
, onKeyUp
, params
) {
361 if (typeof validators
[type
] == 'undefined') {
364 if (typeof validate
[id
] == 'undefined') {
367 validate
[id
].push([type
, params
, onKeyUp
]);
371 * Returns valdiation functions associated with form field
373 * @param String field_id form field id
374 * @param boolean onKeyUpOnly see validateField
375 * @return Array array of [function, paramseters to be passed to function]
377 function getFieldValidators(field_id
, onKeyUpOnly
) {
378 // look for field bound validator
379 var name
= field_id
.match(/[^-]+$/)[0];
380 if (typeof validators
._field
[name
] != 'undefined') {
381 return [[validators
._field
[name
], null]];
384 // look for registered validators
386 if (typeof validate
[field_id
] != 'undefined') {
387 // validate[field_id]: array of [type, params, onKeyUp]
388 for (var i
= 0, imax
= validate
[field_id
].length
; i
< imax
; i
++) {
389 if (onKeyUpOnly
&& !validate
[field_id
][i
][2]) {
392 functions
.push([validators
[validate
[field_id
][i
][0]], validate
[field_id
][i
][1]]);
400 * Displays errors for given form fields
402 * WARNING: created DOM elements must be identical with the ones made by
403 * display_input() in FormDisplay.tpl.php!
405 * @param Object error list (key: field id, value: error array)
407 function displayErrors(errors
) {
408 $each(errors
, function(errors
, field_id
) {
409 var field
= $(field_id
);
410 var isFieldset
= field
.tagName
== 'FIELDSET';
411 var errorCnt
= isFieldset
412 ? field
.getElement('dl.errors')
413 : field
.getNext('.inline_errors');
415 // remove empty errors (used to clear error list)
416 errors
= errors
.filter(function(item
) {
421 // if error container doesn't exist, create it
422 if (errorCnt
=== null) {
424 errorCnt
= new Element('dl', {
427 errorCnt
.inject(field
.getElement('table'), 'before');
429 errorCnt
= new Element('dl', {
430 'class': 'inline_errors'
432 errorCnt
.inject(field
.getParent('td'), 'bottom');
437 for (var i
= 0, imax
= errors
.length
; i
< imax
; i
++) {
438 html
+= '<dd>' + errors
[i
] + '</dd>';
440 errorCnt
.set('html', html
);
441 } else if (errorCnt
!== null) {
442 // remove useless error container
449 * Validates fieldset and puts errors in 'errors' object
451 * @param Element field
452 * @param boolean isKeyUp
453 * @param Object errors
455 function validate_fieldset(fieldset
, isKeyUp
, errors
) {
456 if (fieldset
&& typeof validators
._fieldset
[fieldset
.id
] != 'undefined') {
457 var fieldset_errors
= validators
._fieldset
[fieldset
.id
].bind(fieldset
)(isKeyUp
);
458 $each(fieldset_errors
, function(field_errors
, field_id
) {
459 if (typeof errors
[field_id
] == 'undefined') {
460 errors
[field_id
] = [];
462 errors
[field_id
][$type(field_errors
) == 'array' ? 'extend' : 'push'](field_errors
);
468 * Validates form field and puts errors in 'errors' object
470 * @param Element field
471 * @param boolean isKeyUp
472 * @param Object errors
474 function validate_field(field
, isKeyUp
, errors
) {
475 errors
[field
.id
] = [];
476 var functions
= getFieldValidators(field
.id
, isKeyUp
);
477 for (var i
= 0; i
< functions
.length
; i
++) {
478 var result
= functions
[i
][0].bind(field
)(isKeyUp
, functions
[i
][1]);
479 if (result
!== true) {
480 errors
[field
.id
][$type(result
) == 'array' ? 'extend' : 'push'](result
);
486 * Validates form field and parent fieldset
488 * @param Element field
489 * @param boolean isKeyUp
491 function validate_field_and_fieldset(field
, isKeyUp
) {
493 validate_field(field
, isKeyUp
, errors
);
494 validate_fieldset(field
.getParent('fieldset'), isKeyUp
, errors
);
495 displayErrors(errors
);
499 * Marks field depending on its value (system default or custom)
501 * @param Element field
503 function markField(field
) {
504 var type
= getFieldType(field
);
505 var isDefault
= checkFieldDefault(field
, type
);
507 // checkboxes uses parent <span> for marking
508 var fieldMarker
= (type
== 'checkbox') ? field
.getParent() : field
;
509 setRestoreDefaultBtn(field
, !isDefault
);
510 fieldMarker
[isDefault
? 'removeClass' : 'addClass']('custom');
514 * Enables or disables the "restore default value" button
516 * @param Element field
517 * @param bool display
519 function setRestoreDefaultBtn(field
, display
) {
520 var td
= field
.getParent('td');
522 var el
= td
.getElement('.restore-default');
524 el
.style
.display
= (display
? '' : 'none');
527 window
.addEvent('domready', function() {
528 var elements
= $$('input[id], select[id], textarea[id]');
529 var elements_count
= elements
.length
;
531 // register validators and mark custom values
532 for (var i
= 0; i
< elements_count
; i
++) {
533 var el
= elements
[i
];
535 el
.addEvent('change', function(e
) {
536 validate_field_and_fieldset(this, false);
539 // text fields can be validated after each change
540 if (el
.tagName
== 'INPUT' && el
.type
== 'text') {
541 el
.addEvent('keyup', function(e
) {
542 validate_field_and_fieldset(this, true);
546 // disable textarea spellcheck
547 if (el
.tagName
== 'TEXTAREA') {
548 el
.setProperty('spellcheck', false)
552 // check whether we've refreshed a page and browser remembered modified
554 var check_page_refresh
= $('check_page_refresh');
555 if (!check_page_refresh
|| check_page_refresh
.value
== '1') {
556 // run all field validators
558 for (var i
= 0; i
< elements_count
; i
++) {
559 validate_field(elements
[i
], false, errors
);
561 // run all fieldset validators
562 $$('fieldset').each(function(el
){
563 validate_fieldset(el
, false, errors
);
566 displayErrors(errors
);
567 } else if (check_page_refresh
) {
568 check_page_refresh
.value
= '1';
573 // END: Form validation and field operations
574 // ------------------------------------------------------------------
576 // ------------------------------------------------------------------
583 * @param Element tab_link
585 function setTab(tab_link
) {
586 var tabs_menu
= tab_link
.getParent('.tabs');
588 var links
= tabs_menu
.getElements('a');
590 for (var i
= 0, imax
= links
.length
; i
< imax
; i
++) {
591 contents
= $(links
[i
].getProperty('href').substr(1));
592 if (links
[i
] == tab_link
) {
593 links
[i
].addClass('active');
594 contents
.style
.display
= 'block';
596 links
[i
].removeClass('active');
597 contents
.style
.display
= 'none';
600 location
.hash
= 'tab_' + tab_link
.getProperty('href').substr(1);
603 window
.addEvent('domready', function() {
604 var tabs
= $$('.tabs');
605 var url_tab
= location
.hash
.match(/^#tab_.+/)
606 ? $$('a[href$="' + location
.hash
.substr(5) + '"]') : null;
608 url_tab
= url_tab
[0];
610 // add tabs events and activate one tab (the first one or indicated by location hash)
611 for (var i
= 0, imax
= tabs
.length
; i
< imax
; i
++) {
612 var links
= tabs
[i
].getElements('a');
613 var selected_tab
= links
[0];
614 for (var j
= 0, jmax
= links
.length
; j
< jmax
; j
++) {
615 links
[j
].addEvent('click', function(e
) {
619 if (links
[j
] == url_tab
) {
620 selected_tab
= links
[j
];
623 setTab(selected_tab
);
625 // tab links handling, check each 200ms
626 // (works with history in FF, further browser support here would be an overkill)
627 var prev_hash
= location
.hash
;
629 if (location
.hash
!= prev_hash
) {
630 prev_hash
= location
.hash
;
631 var url_tab
= location
.hash
.match(/^#tab_.+/)
632 ? $$('a[href$="' + location
.hash
.substr(5) + '"]') : null;
642 // ------------------------------------------------------------------
644 // ------------------------------------------------------------------
645 // Form reset buttons
648 window
.addEvent('domready', function() {
649 var buttons
= $$('input[type=button]');
650 for (var i
= 0, imax
= buttons
.length
; i
< imax
; i
++) {
651 buttons
[i
].addEvent('click', function(e
) {
652 var fields
= this.getParent('fieldset').getElements('input, select, textarea');
653 for (var i
= 0, imax
= fields
.length
; i
< imax
; i
++) {
654 setFieldValue(fields
[i
], getFieldType(fields
[i
]));
661 // END: Form reset buttons
662 // ------------------------------------------------------------------
664 // ------------------------------------------------------------------
665 // "Restore default" and "set value" buttons
669 * Restores field's default value
671 * @param String field_id
673 function restoreField(field_id
) {
674 var field
= $(field_id
);
675 if (!field
|| !$defined(defaultValues
[field_id
])) {
678 setFieldValue(field
, getFieldType(field
), defaultValues
[field_id
]);
681 window
.addEvent('domready', function() {
682 var buttons
= $$('.restore-default, .set-value');
683 var fixIE
= Browser
.Engine
.name
== 'trident' && Browser
.Engine
.version
== 4;
684 for (var i
= 0, imax
= buttons
.length
; i
< imax
; i
++) {
685 buttons
[i
].set('opacity', 0.25);
686 if (!buttons
[i
].hasClass('restore-default')) {
687 // restore-default is handled by markField
688 buttons
[i
].style
.display
= '';
690 buttons
[i
].addEvents({
691 mouseenter: function(e
) {this.set('opacity', 1);},
692 mouseleave: function(e
) {this.set('opacity', 0.25);},
695 var href
= this.getProperty('href').substr(1);
697 if (this.hasClass('restore-default')) {
699 restoreField(field_id
);
701 field_id
= href
.match(/^[^=]+/)[0];
702 var value
= href
.match(/=(.+)$/)[1];
703 setFieldValue($(field_id
), 'text', value
);
705 $(field_id
).fireEvent('change');
708 // fix IE showing <img> alt text instead of link title
710 buttons
[i
].getChildren('img')[0].alt
= buttons
[i
].title
;
716 // END: "Restore default" and "set value" buttons
717 // ------------------------------------------------------------------