4 * Copyright 2009, Moxiecode Systems AB
5 * Released under LGPL License.
7 * License: http://tinymce.moxiecode.com/license
8 * Contributing: http://tinymce.moxiecode.com/contributing
14 if (!Validator.isEmail('myemail'))
15 alert('Invalid email.');
19 var f = document.forms['myform'];
21 if (!Validator.isEmail(f.myemail))
22 alert('Invalid email.');
26 isEmail : function(s
) {
27 return this.test(s
, '^[-!#$%&\'*+\\./0-9=?A-Z^_`a-z{|}~]+@[-!#$%&\'*+\\/0-9=?A-Z^_`a-z{|}~]+\.[-!#$%&\'*+\\./0-9=?A-Z^_`a-z{|}~]+$');
30 isAbsUrl : function(s
) {
31 return this.test(s
, '^(news|telnet|nttp|file|http|ftp|https)://[-A-Za-z0-9\\.]+\\/?.*$');
34 isSize : function(s
) {
35 return this.test(s
, '^[0-9.]+(%|in|cm|mm|em|ex|pt|pc|px)?$');
39 return this.test(s
, '^[A-Za-z_]([A-Za-z0-9_])*$');
42 isEmpty : function(s
) {
45 if (s
.nodeName
== 'SELECT' && s
.selectedIndex
< 1)
48 if (s
.type
== 'checkbox' && !s
.checked
)
51 if (s
.type
== 'radio') {
52 for (i
=0, nl
= s
.form
.elements
; i
<nl
.length
; i
++) {
53 if (nl
[i
].type
== "radio" && nl
[i
].name
== s
.name
&& nl
[i
].checked
)
60 return new RegExp('^\\s*$').test(s
.nodeType
== 1 ? s
.value
: s
);
63 isNumber : function(s
, d
) {
64 return !isNaN(s
.nodeType
== 1 ? s
.value
: s
) && (!d
|| !this.test(s
, '^-?[0-9]*\\.[0-9]*$'));
67 test : function(s
, p
) {
68 s
= s
.nodeType
== 1 ? s
.value
: s
;
70 return s
== '' || new RegExp(p
).test(s
);
79 number_cls
: 'number',
82 required_cls
: 'required',
83 invalid_cls
: 'invalid',
92 this.settings
[n
] = s
[n
];
95 validate : function(f
) {
96 var i
, nl
, s
= this.settings
, c
= 0;
98 nl
= this.tags(f
, 'label');
99 for (i
=0; i
<nl
.length
; i
++) {
100 this.removeClass(nl
[i
], s
.invalid_cls
);
101 nl
[i
].setAttribute('aria-invalid', false);
104 c
+= this.validateElms(f
, 'input');
105 c
+= this.validateElms(f
, 'select');
106 c
+= this.validateElms(f
, 'textarea');
111 invalidate : function(n
) {
112 this.mark(n
.form
, n
);
115 getErrorMessages : function(f
) {
116 var nl
, i
, s
= this.settings
, field
, msg
, values
, messages
= [], ed
= tinyMCEPopup
.editor
;
117 nl
= this.tags(f
, "label");
118 for (i
=0; i
<nl
.length
; i
++) {
119 if (this.hasClass(nl
[i
], s
.invalid_cls
)) {
120 field
= document
.getElementById(nl
[i
].getAttribute("for"));
121 values
= { field
: nl
[i
].textContent
};
122 if (this.hasClass(field
, s
.min_cls
, true)) {
123 message
= ed
.getLang('invalid_data_min');
124 values
.min
= this.getNum(field
, s
.min_cls
);
125 } else if (this.hasClass(field
, s
.number_cls
)) {
126 message
= ed
.getLang('invalid_data_number');
127 } else if (this.hasClass(field
, s
.size_cls
)) {
128 message
= ed
.getLang('invalid_data_size');
130 message
= ed
.getLang('invalid_data');
133 message
= message
.replace(/{\#([^}]+)\}/g, function(a
, b
) {
134 return values
[b
] || '{#' + b
+ '}';
136 messages
.push(message
);
142 reset : function(e
) {
143 var t
= ['label', 'input', 'select', 'textarea'];
144 var i
, j
, nl
, s
= this.settings
;
149 for (i
=0; i
<t
.length
; i
++) {
150 nl
= this.tags(e
.form
? e
.form
: e
, t
[i
]);
151 for (j
=0; j
<nl
.length
; j
++) {
152 this.removeClass(nl
[j
], s
.invalid_cls
);
153 nl
[j
].setAttribute('aria-invalid', false);
158 validateElms : function(f
, e
) {
159 var nl
, i
, n
, s
= this.settings
, st
= true, va
= Validator
, v
;
161 nl
= this.tags(f
, e
);
162 for (i
=0; i
<nl
.length
; i
++) {
165 this.removeClass(n
, s
.invalid_cls
);
167 if (this.hasClass(n
, s
.required_cls
) && va
.isEmpty(n
))
168 st
= this.mark(f
, n
);
170 if (this.hasClass(n
, s
.number_cls
) && !va
.isNumber(n
))
171 st
= this.mark(f
, n
);
173 if (this.hasClass(n
, s
.int_cls
) && !va
.isNumber(n
, true))
174 st
= this.mark(f
, n
);
176 if (this.hasClass(n
, s
.url_cls
) && !va
.isAbsUrl(n
))
177 st
= this.mark(f
, n
);
179 if (this.hasClass(n
, s
.email_cls
) && !va
.isEmail(n
))
180 st
= this.mark(f
, n
);
182 if (this.hasClass(n
, s
.size_cls
) && !va
.isSize(n
))
183 st
= this.mark(f
, n
);
185 if (this.hasClass(n
, s
.id_cls
) && !va
.isId(n
))
186 st
= this.mark(f
, n
);
188 if (this.hasClass(n
, s
.min_cls
, true)) {
189 v
= this.getNum(n
, s
.min_cls
);
191 if (isNaN(v
) || parseInt(n
.value
) < parseInt(v
))
192 st
= this.mark(f
, n
);
195 if (this.hasClass(n
, s
.max_cls
, true)) {
196 v
= this.getNum(n
, s
.max_cls
);
198 if (isNaN(v
) || parseInt(n
.value
) > parseInt(v
))
199 st
= this.mark(f
, n
);
206 hasClass : function(n
, c
, d
) {
207 return new RegExp('\\b' + c
+ (d
? '[0-9]+' : '') + '\\b', 'g').test(n
.className
);
210 getNum : function(n
, c
) {
211 c
= n
.className
.match(new RegExp('\\b' + c
+ '([0-9]+)\\b', 'g'))[0];
212 c
= c
.replace(/[^0-9]/g, '');
217 addClass : function(n
, c
, b
) {
218 var o
= this.removeClass(n
, c
);
219 n
.className
= b
? c
+ (o
!= '' ? (' ' + o
) : '') : (o
!= '' ? (o
+ ' ') : '') + c
;
222 removeClass : function(n
, c
) {
223 c
= n
.className
.replace(new RegExp("(^|\\s+)" + c
+ "(\\s+|$)"), ' ');
224 return n
.className
= c
!= ' ' ? c
: '';
227 tags : function(f
, s
) {
228 return f
.getElementsByTagName(s
);
231 mark : function(f
, n
) {
232 var s
= this.settings
;
234 this.addClass(n
, s
.invalid_cls
);
235 n
.setAttribute('aria-invalid', 'true');
236 this.markLabels(f
, n
, s
.invalid_cls
);
241 markLabels : function(f
, n
, ic
) {
244 nl
= this.tags(f
, "label");
245 for (i
=0; i
<nl
.length
; i
++) {
246 if (nl
[i
].getAttribute("for") == n
.id
|| nl
[i
].htmlFor
== n
.id
)
247 this.addClass(nl
[i
], ic
);