summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorwei <>2006-01-13 04:55:22 +0000
committerwei <>2006-01-13 04:55:22 +0000
commit8da0f8dd4a0347f15df6e71ac2b0f4b3c27e8475 (patch)
treef4b75568da1fd702bcb3320259bb1642f3cc53b8
parentd202492e4ad31c4127b4b459b300de7cd1976c1b (diff)
Focus added to client validators
-rw-r--r--.gitattributes3
-rw-r--r--framework/Web/Javascripts/base/ajax.js76
-rw-r--r--framework/Web/Javascripts/base/date.js147
-rw-r--r--framework/Web/Javascripts/base/datepicker.js274
-rw-r--r--framework/Web/Javascripts/base/prado.js3
-rw-r--r--framework/Web/Javascripts/base/rico.js175
-rw-r--r--framework/Web/Javascripts/base/util.js92
-rw-r--r--framework/Web/Javascripts/base/validation.js80
-rw-r--r--framework/Web/Javascripts/base/validators.js18
-rw-r--r--framework/Web/Javascripts/extended/dom.js11
-rw-r--r--framework/Web/Javascripts/js/dom.js273
-rw-r--r--framework/Web/Javascripts/js/validator.js65
-rw-r--r--tests/FunctionalTests/protected/pages/Validation/RequiredFieldValidator.page8
-rw-r--r--tools/jsbuilder/build.php4
14 files changed, 820 insertions, 409 deletions
diff --git a/.gitattributes b/.gitattributes
index f3a53ef0..91595e98 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -439,13 +439,16 @@ framework/TComponent.php -text
framework/TODO.txt -text
framework/Web/Javascripts/base/ajax.js -text
framework/Web/Javascripts/base/controls.js -text
+framework/Web/Javascripts/base/date.js -text
framework/Web/Javascripts/base/datepicker.js -text
framework/Web/Javascripts/base/effects.js -text
framework/Web/Javascripts/base/focus.js -text
framework/Web/Javascripts/base/json.js -text
framework/Web/Javascripts/base/postback.js -text
framework/Web/Javascripts/base/prado.js -text
+framework/Web/Javascripts/base/rico.js -text
framework/Web/Javascripts/base/scroll.js -text
+framework/Web/Javascripts/base/util.js -text
framework/Web/Javascripts/base/validation.js -text
framework/Web/Javascripts/base/validators.js -text
framework/Web/Javascripts/effects/CHANGELOG -text
diff --git a/framework/Web/Javascripts/base/ajax.js b/framework/Web/Javascripts/base/ajax.js
index ccfb085d..06c3d741 100644
--- a/framework/Web/Javascripts/base/ajax.js
+++ b/framework/Web/Javascripts/base/ajax.js
@@ -386,86 +386,16 @@ Prado.AJAX.Validate = function(options)
if(options.CausesValidation)
{
if(options.ValidatorGroup)
- return Prado.AJAX.ValidateGroup1(options.ValidatorGroup);
+ return Prado.Validation.ValidateValidatorGroup(options.ValidatorGroup);
else if(options.ValidationGroup)
- return Prado.AJAX.ValidateGroup2(options.ValidationGroup);
+ return Prado.Validation.ValidateValidationGroup(options.ValidationGroup);
else
- return Prado.AJAX.ValidateOthers(options.ValidationForm);
+ return Prado.Validation.ValidateNonGroup(options.ValidationForm);
}
else
return true;
};
-/**
- * Validate Validator Groups.
- * @param string ValidatorGroup
- * @return boolean true if valid, false otherwise
- */
-Prado.AJAX.ValidateGroup1 = function(groupId)
-{
- var groups = Prado.Validation.groups;
- var group = null;
- for(var i = 0; i < groups.length; i++)
- {
- if(groups[i].id == groupId)
- {
- group = groups[i];
- Prado.Validation.groups[i].active = true;
- Prado.Validation.CurrentTargetGroup = null;
- Prado.Validation.IsGroupValidation = true;
- }
- else
- {
- Prado.Validation.groups[i].active = false;
- }
- }
- if(group)
- {
- return Prado.Validation.IsValid(group.target.form);
- }
- return true;
-};
-
-/**
- * Validate ValidationGroup
- * @param string ValidationGroup
- * @return boolean true if valid, false otherwise.
- */
-Prado.AJAX.ValidateGroup2 = function(groupId)
-{
- var groups = Prado.Validation.TargetGroups;
- for(var id in groups)
- {
- if(groups[id] == groupId)
- {
- var target = $(id);
- Prado.Validation.ActiveTarget = target;
- Prado.Validation.CurrentTargetGroup = groupId;
- Prado.Validation.IsGroupValidation = false;
- return Prado.Validation.IsValid(target.form);
- }
- }
- return true;
-};
-
-/**
- * Validate the page
- * @return boolean true if valid, false otherwise.
- */
-Prado.AJAX.ValidateOthers = function(formId)
-{
- if(Prado.Validation)
- {
- var form = $(formId);
- form = form || document.forms[0];
- Prado.Validation.ActiveTarget = form;
- Prado.Validation.CurrentTargetGroup = null;
- Prado.Validation.IsGroupValidation = false;
- return Prado.Validation.IsValid(form);
- }
- return true;
-};
-
//Available callback service
Prado.AJAX.Callback.Server = '';
diff --git a/framework/Web/Javascripts/base/date.js b/framework/Web/Javascripts/base/date.js
new file mode 100644
index 00000000..375c59df
--- /dev/null
+++ b/framework/Web/Javascripts/base/date.js
@@ -0,0 +1,147 @@
+
+Object.extend(Date.prototype,
+{
+ SimpleFormat: function(format)
+ {
+ var bits = new Array();
+ bits['d'] = this.getDate();
+ bits['dd'] = Prado.Util.pad(this.getDate(),2);
+
+ bits['M'] = this.getMonth()+1;
+ bits['MM'] = Prado.Util.pad(this.getMonth()+1,2);
+
+ var yearStr = "" + this.getFullYear();
+ yearStr = (yearStr.length == 2) ? '19' + yearStr: yearStr;
+ bits['yyyy'] = yearStr;
+ bits['yy'] = bits['yyyy'].toString().substr(2,2);
+
+ // do some funky regexs to replace the format string
+ // with the real values
+ var frm = new String(format);
+ for (var sect in bits)
+ {
+ var reg = new RegExp("\\b"+sect+"\\b" ,"g");
+ frm = frm.replace(reg, bits[sect]);
+ }
+ return frm;
+ },
+
+ toISODate : function()
+ {
+ var y = this.getFullYear();
+ var m = Prado.Util.pad(this.getMonth() + 1);
+ var d = Prado.Util.pad(this.getDate());
+ return String(y) + String(m) + String(d);
+ }
+});
+
+Object.extend(Date,
+{
+ SimpleParse: function(value, format)
+ {
+ val=String(value);
+ format=String(format);
+
+ if(val.length <= 0) return null;
+
+ if(format.length <= 0) return new Date(value);
+
+ var isInteger = function (val)
+ {
+ var digits="1234567890";
+ for (var i=0; i < val.length; i++)
+ {
+ if (digits.indexOf(val.charAt(i))==-1) { return false; }
+ }
+ return true;
+ };
+
+ var getInt = function(str,i,minlength,maxlength)
+ {
+ for (var x=maxlength; x>=minlength; x--)
+ {
+ var token=str.substring(i,i+x);
+ if (token.length < minlength) { return null; }
+ if (isInteger(token)) { return token; }
+ }
+ return null;
+ };
+
+ var i_val=0;
+ var i_format=0;
+ var c="";
+ var token="";
+ var token2="";
+ var x,y;
+ var now=new Date();
+ var year=now.getFullYear();
+ var month=now.getMonth()+1;
+ var date=1;
+
+ while (i_format < format.length)
+ {
+ // Get next token from format string
+ c=format.charAt(i_format);
+ token="";
+ while ((format.charAt(i_format)==c) && (i_format < format.length))
+ {
+ token += format.charAt(i_format++);
+ }
+
+ // Extract contents of value based on format token
+ if (token=="yyyy" || token=="yy" || token=="y")
+ {
+ if (token=="yyyy") { x=4;y=4; }
+ if (token=="yy") { x=2;y=2; }
+ if (token=="y") { x=2;y=4; }
+ year=getInt(val,i_val,x,y);
+ if (year==null) { return null; }
+ i_val += year.length;
+ if (year.length==2)
+ {
+ if (year > 70) { year=1900+(year-0); }
+ else { year=2000+(year-0); }
+ }
+ }
+
+ else if (token=="MM"||token=="M")
+ {
+ month=getInt(val,i_val,token.length,2);
+ if(month==null||(month<1)||(month>12)){return null;}
+ i_val+=month.length;
+ }
+ else if (token=="dd"||token=="d")
+ {
+ date=getInt(val,i_val,token.length,2);
+ if(date==null||(date<1)||(date>31)){return null;}
+ i_val+=date.length;
+ }
+ else
+ {
+ if (val.substring(i_val,i_val+token.length)!=token) {return null;}
+ else {i_val+=token.length;}
+ }
+ }
+
+ // If there are any trailing characters left in the value, it doesn't match
+ if (i_val != val.length) { return null; }
+
+ // Is date valid for month?
+ if (month==2)
+ {
+ // Check for leap year
+ if ( ( (year%4==0)&&(year%100 != 0) ) || (year%400==0) ) { // leap year
+ if (date > 29){ return null; }
+ }
+ else { if (date > 28) { return null; } }
+ }
+
+ if ((month==4)||(month==6)||(month==9)||(month==11))
+ {
+ if (date > 30) { return null; }
+ }
+
+ var newdate=new Date(year,month-1,date, 0, 0, 0);
+ return newdate;
+ }
+}); \ No newline at end of file
diff --git a/framework/Web/Javascripts/base/datepicker.js b/framework/Web/Javascripts/base/datepicker.js
index 046a0a4b..68e63168 100644
--- a/framework/Web/Javascripts/base/datepicker.js
+++ b/framework/Web/Javascripts/base/datepicker.js
@@ -3,272 +3,7 @@ Prado.Calendar = Class.create();
Prado.Calendar.Util = Class.create();
Object.extend(Prado.Calendar.Util,
-{
- // utility function to pad a number to a given width
- pad : function(number, X)
- {
- X = (!X ? 2 : X);
- number = ""+number;
- while (number.length < X)
- number = "0" + number;
- return number;
- },
-
- //allow for deprecated formats
- FormatDate : function(date, format)
- {
- if(!isObject(date)) return "";
- if(format.indexOf("%") > -1)
- {
- alert('Please use the new SimpleDateFormat pattern, e.g. yyyy-MM-dd');
- return this.FormatDateDepr(date,format);
- }
- else
- {
- return this.SimpleFormatDate(date, format);
- }
- },
-
- //allow for deprecated format
- ParseDate : function(value, format)
- {
- val=String(value);
- format=String(format);
-
- if(val.length <= 0) return null;
-
- if(format.length <= 0) return new Date(value);
-
- if(format.indexOf("%") > -1)
- return this.ParseDateDepr(value, format);
- else
- return this.SimpleParseDate(value, format);
- },
-
- //deprecated format
- FormatDateDepr : function(date, str)
- {
- var m = date.getMonth();
- var d = date.getDate();
- var y = date.getFullYear();
-
- var s = {};
-
- s["%d"] = this.pad(d); // the day of the month (range 01 to 31)
- s["%e"] = d; // the day of the month (range 1 to 31)
- s["%m"] = this.pad(m+1);
- s["%y"] = ('' + y).substr(2, 2); // year without the century (range 00 to 99)
- s["%Y"] = y; // year with the century
-
- var re = /%./g;
-
- var a = str.match(re);
- for (var i = 0; i < a.length; i++)
- {
- var tmp = s[a[i]];
- if (tmp)
- {
- re = new RegExp(a[i], 'g');
- str = str.replace(re, tmp);
- }
- }
-
- return str;
- },
-
- //deprecated format parser
- ParseDateDepr : function(value, format)
- {
- var y = 0;
- var m = -1;
- var d = 0;
- var a = value.split(/\W+/);
- var b = format.match(/%./g);
- var i = 0, j = 0;
- var hr = 0;
- var min = 0;
- for (i = 0; i < a.length; ++i) {
- if (!a[i])
- continue;
- switch (b[i]) {
- case "%d":
- case "%e":
- d = parseInt(a[i], 10);
- break;
-
- case "%m":
- m = parseInt(a[i], 10) - 1;
- break;
-
- case "%Y":
- case "%y":
- y = parseInt(a[i], 10);
- (y < 100) && (y += (y > 29) ? 1900 : 2000);
- break;
-
- case "%H":
- case "%I":
- case "%k":
- case "%l":
- hr = parseInt(a[i], 10);
- break;
-
- case "%P":
- case "%p":
- if (/pm/i.test(a[i]) && hr < 12)
- hr += 12;
- break;
-
- case "%M":
- min = parseInt(a[i], 10);
- break;
- }
- }
- if (y != 0 && m != -1 && d != 0)
- {
- var date = new Date(y, m, d, hr, min, 0);
- return (isObject(date)
- && y == date.getFullYear()
- && m == date.getMonth()
- && d == date.getDate()) ? date : null;
- }
- return null;
- },
-
- SimpleFormatDate : function(date, format)
- {
- if(!isObject(date)) return "";
- var bits = new Array();
- bits['d'] = date.getDate();
- bits['dd'] = this.pad(date.getDate(),2);
-
- bits['M'] = date.getMonth()+1;
- bits['MM'] = this.pad(date.getMonth()+1,2);
-
- var yearStr = "" + date.getFullYear();
- yearStr = (yearStr.length == 2) ? '19' + yearStr: yearStr;
- bits['yyyy'] = yearStr;
- bits['yy'] = bits['yyyy'].toString().substr(2,2);
-
- // do some funky regexs to replace the format string
- // with the real values
- var frm = new String(format);
- for (var sect in bits)
- {
- var reg = new RegExp("\\b"+sect+"\\b" ,"g");
- frm = frm.replace(reg, bits[sect]);
- }
- return frm;
- },
-
- SimpleParseDate : function(value, format)
- {
- val=String(value);
- format=String(format);
-
- if(val.length <= 0) return null;
-
- if(format.length <= 0) return new Date(value);
-
- var isInteger = function (val)
- {
- var digits="1234567890";
- for (var i=0; i < val.length; i++)
- {
- if (digits.indexOf(val.charAt(i))==-1) { return false; }
- }
- return true;
- };
-
- var getInt = function(str,i,minlength,maxlength)
- {
- for (var x=maxlength; x>=minlength; x--)
- {
- var token=str.substring(i,i+x);
- if (token.length < minlength) { return null; }
- if (isInteger(token)) { return token; }
- }
- return null;
- };
-
- var i_val=0;
- var i_format=0;
- var c="";
- var token="";
- var token2="";
- var x,y;
- var now=new Date();
- var year=now.getFullYear();
- var month=now.getMonth()+1;
- var date=1;
-
- while (i_format < format.length)
- {
- // Get next token from format string
- c=format.charAt(i_format);
- token="";
- while ((format.charAt(i_format)==c) && (i_format < format.length))
- {
- token += format.charAt(i_format++);
- }
-
- // Extract contents of value based on format token
- if (token=="yyyy" || token=="yy" || token=="y")
- {
- if (token=="yyyy") { x=4;y=4; }
- if (token=="yy") { x=2;y=2; }
- if (token=="y") { x=2;y=4; }
- year=getInt(val,i_val,x,y);
- if (year==null) { return null; }
- i_val += year.length;
- if (year.length==2)
- {
- if (year > 70) { year=1900+(year-0); }
- else { year=2000+(year-0); }
- }
- }
-
- else if (token=="MM"||token=="M")
- {
- month=getInt(val,i_val,token.length,2);
- if(month==null||(month<1)||(month>12)){return null;}
- i_val+=month.length;
- }
- else if (token=="dd"||token=="d")
- {
- date=getInt(val,i_val,token.length,2);
- if(date==null||(date<1)||(date>31)){return null;}
- i_val+=date.length;
- }
- else
- {
- if (val.substring(i_val,i_val+token.length)!=token) {return null;}
- else {i_val+=token.length;}
- }
- }
-
- // If there are any trailing characters left in the value, it doesn't match
- if (i_val != val.length) { return null; }
-
- // Is date valid for month?
- if (month==2)
- {
- // Check for leap year
- if ( ( (year%4==0)&&(year%100 != 0) ) || (year%400==0) ) { // leap year
- if (date > 29){ return null; }
- }
- else { if (date > 28) { return null; } }
- }
-
- if ((month==4)||(month==6)||(month==9)||(month==11))
- {
- if (date > 30) { return null; }
- }
-
- var newdate=new Date(year,month-1,date, 0, 0, 0);
- return newdate;
- },
-
+{
IsLeapYear : function (year)
{
return ((year%4 == 0) && ((year%100 != 0) || (year%400 == 0)));
@@ -288,13 +23,6 @@ Object.extend(Prado.Calendar.Util,
Calendar.LEAP_NUM_DAYS : Calendar.NUM_DAYS;
return a[date.getMonth()] + date.getDate();
},
- ISODate : function(date)
- {
- var y = date.getFullYear();
- var m = this.pad(date.getMonth() + 1);
- var d = this.pad(date.getDate());
- return String(y) + String(m) + String(d);
- },
browser : function()
{
diff --git a/framework/Web/Javascripts/base/prado.js b/framework/Web/Javascripts/base/prado.js
index 7dd14e19..95600f09 100644
--- a/framework/Web/Javascripts/base/prado.js
+++ b/framework/Web/Javascripts/base/prado.js
@@ -1 +1,2 @@
-var Prado = { Version: 2.0 }; \ No newline at end of file
+var Prado = { Version: 2.0 };
+
diff --git a/framework/Web/Javascripts/base/rico.js b/framework/Web/Javascripts/base/rico.js
new file mode 100644
index 00000000..d3df3a9b
--- /dev/null
+++ b/framework/Web/Javascripts/base/rico.js
@@ -0,0 +1,175 @@
+Prado.RicoLiveGrid = Class.create();
+Prado.RicoLiveGrid.prototype = Object.extend(Rico.LiveGrid.prototype,
+{
+ initialize : function(tableId, options)
+ {
+ this.options = {
+ tableClass: $(tableId).className || '',
+ loadingClass: $(tableId).className || '',
+ scrollerBorderRight: '1px solid #ababab',
+ bufferTimeout: 20000,
+ sortAscendImg: 'images/sort_asc.gif',
+ sortDescendImg: 'images/sort_desc.gif',
+ sortImageWidth: 9,
+ sortImageHeight: 5,
+ ajaxSortURLParms: [],
+ onRefreshComplete: null,
+ requestParameters: null,
+ inlineStyles: true,
+ visibleRows: 10,
+ totalRows: 0,
+ initialOffset: 0
+ };
+ Object.extend(this.options, options || {});
+
+ //this.ajaxOptions = {parameters: null};
+ //Object.extend(this.ajaxOptions, ajaxOptions || {});
+
+ this.tableId = tableId;
+ this.table = $(tableId);
+
+ this.addLiveGridHtml();
+
+ var columnCount = this.table.rows[0].cells.length;
+ this.metaData = new Rico.LiveGridMetaData(this.options.visibleRows, this.options.totalRows, columnCount, options);
+ this.buffer = new Rico.LiveGridBuffer(this.metaData);
+
+ var rowCount = this.table.rows.length;
+ this.viewPort = new Rico.GridViewPort(this.table,
+ this.table.offsetHeight/rowCount,
+ this.options.visibleRows,
+ this.buffer, this);
+ this.scroller = new Rico.LiveGridScroller(this,this.viewPort);
+ this.options.sortHandler = this.sortHandler.bind(this);
+
+ if ( $(tableId + '_header') )
+ this.sort = new Rico.LiveGridSort(tableId + '_header', this.options)
+
+ this.processingRequest = null;
+ this.unprocessedRequest = null;
+
+ //this.initAjax(url);
+ if (this.options.initialOffset >= 0)
+ {
+ var offset = this.options.initialOffset;
+ this.scroller.moveScroll(offset);
+ this.viewPort.scrollTo(this.scroller.rowToPixel(offset));
+ if (this.options.sortCol) {
+ this.sortCol = options.sortCol;
+ this.sortDir = options.sortDir;
+ }
+ var grid = this;
+ setTimeout(function(){
+ grid.requestContentRefresh(offset);
+ },100);
+ }
+ },
+
+ fetchBuffer: function(offset)
+ {
+ if ( this.buffer.isInRange(offset) &&
+ !this.buffer.isNearingLimit(offset)) {
+ return;
+ }
+ if (this.processingRequest) {
+ this.unprocessedRequest = new Rico.LiveGridRequest(offset);
+ return;
+ }
+ var bufferStartPos = this.buffer.getFetchOffset(offset);
+ this.processingRequest = new Rico.LiveGridRequest(offset);
+ this.processingRequest.bufferOffset = bufferStartPos;
+ var fetchSize = this.buffer.getFetchSize(offset);
+ var partialLoaded = false;
+
+ // var queryString
+ // if (this.options.requestParameters)
+ // queryString = this._createQueryString(this.options.requestParameters, 0);
+ var param =
+ {
+ 'page_size' : fetchSize,
+ 'offset' : bufferStartPos
+ };
+ if(this.sortCol)
+ {
+ Object.extend(param,
+ {
+ 'sort_col': this.sortCol,
+ 'sort_dir': this.sortDir
+ });
+ }
+ /*queryString = (queryString == null) ? '' : queryString+'&';
+ queryString = queryString+'id='+this.tableId+'&page_size='+fetchSize+'&offset='+bufferStartPos;
+ if (this.sortCol)
+ queryString = queryString+'&sort_col='+escape(this.sortCol)+'&sort_dir='+this.sortDir;
+
+ this.ajaxOptions.parameters = queryString;
+
+ ajaxEngine.sendRequest( this.tableId + '_request', this.ajaxOptions );
+ */
+ Prado.Callback(this.tableId, param, this.ajaxUpdate.bind(this), this.options);
+ this.timeoutHandler = setTimeout( this.handleTimedOut.bind(this), this.options.bufferTimeout);
+
+ },
+
+ ajaxUpdate: function(result, output)
+ {
+ try {
+ clearTimeout( this.timeoutHandler );
+ this.buffer.update(result,this.processingRequest.bufferOffset);
+ this.viewPort.bufferChanged();
+ }
+ catch(err) {}
+ finally {this.processingRequest = null; }
+ this.processQueuedRequest();
+ }
+});
+
+Object.extend(Rico.LiveGridBuffer.prototype,
+{
+ update: function(newRows, start)
+ {
+ if (this.rows.length == 0) { // initial load
+ this.rows = newRows;
+ this.size = this.rows.length;
+ this.startPos = start;
+ return;
+ }
+ if (start > this.startPos) { //appending
+ if (this.startPos + this.rows.length < start) {
+ this.rows = newRows;
+ this.startPos = start;//
+ } else {
+ this.rows = this.rows.concat( newRows.slice(0, newRows.length));
+ if (this.rows.length > this.maxBufferSize) {
+ var fullSize = this.rows.length;
+ this.rows = this.rows.slice(this.rows.length - this.maxBufferSize, this.rows.length)
+ this.startPos = this.startPos + (fullSize - this.rows.length);
+ }
+ }
+ } else { //prepending
+ if (start + newRows.length < this.startPos) {
+ this.rows = newRows;
+ } else {
+ this.rows = newRows.slice(0, this.startPos).concat(this.rows);
+ if (this.rows.length > this.maxBufferSize)
+ this.rows = this.rows.slice(0, this.maxBufferSize)
+ }
+ this.startPos = start;
+ }
+ this.size = this.rows.length;
+ }
+});
+
+
+Object.extend(Rico.GridViewPort.prototype,
+{
+ populateRow: function(htmlRow, row)
+ {
+ if(isdef(htmlRow))
+ {
+ for (var j=0; j < row.length; j++) {
+ htmlRow.cells[j].innerHTML = row[j]
+ }
+ }
+ }
+}); \ No newline at end of file
diff --git a/framework/Web/Javascripts/base/util.js b/framework/Web/Javascripts/base/util.js
new file mode 100644
index 00000000..61b7d646
--- /dev/null
+++ b/framework/Web/Javascripts/base/util.js
@@ -0,0 +1,92 @@
+Prado.Util = {}
+
+/**
+ * Pad a number with zeros from the left.
+ * @param integer number
+ * @param integer total string length
+ * @return string zero padded number
+ */
+Prado.Util.pad = function(number, X)
+{
+ X = (!X ? 2 : X);
+ number = ""+number;
+ while (number.length < X)
+ number = "0" + number;
+ return number;
+}
+
+/**
+ * Convert a string into integer, returns null if not integer.
+ * @param {string} the string to convert to integer
+ * @type {integer|null} null if string does not represent an integer.
+ */
+Prado.Util.toInteger = function(value)
+{
+ var exp = /^\s*[-\+]?\d+\s*$/;
+ if (value.match(exp) == null)
+ return null;
+ var num = parseInt(value, 10);
+ return (isNaN(num) ? null : num);
+}
+
+/**
+ * Convert a string into a double/float value. <b>Internationalization
+ * is not supported</b>
+ * @param {string} the string to convert to double/float
+ * @param {string} the decimal character
+ * @return {float|null} null if string does not represent a float value
+ */
+Prado.Util.toDouble = function(value, decimalchar)
+{
+ decimalchar = undef(decimalchar) ? "." : decimalchar;
+ var exp = new RegExp("^\\s*([-\\+])?(\\d+)?(\\" + decimalchar + "(\\d+))?\\s*$");
+ var m = value.match(exp);
+ if (m == null)
+ return null;
+ var cleanInput = m[1] + (m[2].length>0 ? m[2] : "0") + "." + m[4];
+ var num = parseFloat(cleanInput);
+ return (isNaN(num) ? null : num);
+}
+
+/**
+ * Convert strings that represent a currency value (e.g. a float with grouping
+ * characters) to float. E.g. "10,000.50" will become "10000.50". The number
+ * of dicimal digits, grouping and decimal characters can be specified.
+ * <i>The currency input format is <b>very</b> strict, null will be returned if
+ * the pattern does not match</i>.
+ * @param {string} the currency value
+ * @param {string} the grouping character, default is ","
+ * @param {int} number of decimal digits
+ * @param {string} the decimal character, default is "."
+ * @type {float|null} the currency value as float.
+ */
+Prado.Util.toCurrency = function(value, groupchar, digits, decimalchar)
+{
+ groupchar = undef(groupchar) ? "," : groupchar;
+ decimalchar = undef(decimalchar) ? "." : decimalchar;
+ digits = undef(digits) ? 2 : digits;
+
+ var exp = new RegExp("^\\s*([-\\+])?(((\\d+)\\" + groupchar + ")*)(\\d+)"
+ + ((digits > 0) ? "(\\" + decimalchar + "(\\d{1," + digits + "}))?" : "")
+ + "\\s*$");
+ var m = value.match(exp);
+ if (m == null)
+ return null;
+ var intermed = m[2] + m[5] ;
+ var cleanInput = m[1] + intermed.replace(
+ new RegExp("(\\" + groupchar + ")", "g"), "")
+ + ((digits > 0) ? "." + m[7] : "");
+ var num = parseFloat(cleanInput);
+ return (isNaN(num) ? null : num);
+}
+
+/**
+ * Trim the value, if the value is undefined, empty string is return.
+ * @param {string} string to be trimmed.
+ * @type {string} trimmed string.
+ */
+Prado.Util.trim = function(value)
+{
+ if(!isString(value)) return "";
+ return value.replace(/^\s+|\s+$/g, "");
+} \ No newline at end of file
diff --git a/framework/Web/Javascripts/base/validation.js b/framework/Web/Javascripts/base/validation.js
index e7fa9203..78694ca4 100644
--- a/framework/Web/Javascripts/base/validation.js
+++ b/framework/Web/Javascripts/base/validation.js
@@ -152,7 +152,7 @@ Prado.Validation.Util.toDate = function(value, format)
*/
Prado.Validation.Util.trim = function(value)
{
- if(!isString(value)) return "";
+ if(undef(value)) return "";
return value.replace(/^\s+|\s+$/g, "");
}
@@ -367,8 +367,6 @@ Prado.Validation.prototype =
*/
update : function()
{
- Logger.info("isvalid ? " + this.isValid);
-
if(this.attr.display == "Dynamic")
this.isValid ? Element.hide(this.message) : Element.show(this.message);
@@ -380,6 +378,9 @@ Prado.Validation.prototype =
if(this.control && isString(className) && className.length>0)
Element.condClassName(this.control, className, !this.isValid);
Prado.Validation.ShowSummary();
+
+ if(this.attr.focusonerror)
+ Prado.Element.focus(this.attr.focuselementid);
},
/**
@@ -671,6 +672,79 @@ Prado.Validation.OnLoad = function()
Event.observe(Prado.Validation.forms,"submit", Prado.Validation.OnSubmit);
}
+
+/**
+ * Validate Validator Groups.
+ * @param string ValidatorGroup
+ * @return boolean true if valid, false otherwise
+ */
+Prado.Validation.ValidateValidatorGroup = function(groupId)
+{
+ var groups = Prado.Validation.groups;
+ var group = null;
+ for(var i = 0; i < groups.length; i++)
+ {
+ if(groups[i].id == groupId)
+ {
+ group = groups[i];
+ Prado.Validation.groups[i].active = true;
+ Prado.Validation.CurrentTargetGroup = null;
+ Prado.Validation.IsGroupValidation = true;
+ }
+ else
+ {
+ Prado.Validation.groups[i].active = false;
+ }
+ }
+ if(group)
+ {
+ return Prado.Validation.IsValid(group.target.form);
+ }
+ return true;
+};
+
+/**
+ * Validate ValidationGroup
+ * @param string ValidationGroup
+ * @return boolean true if valid, false otherwise.
+ */
+Prado.Validation.ValidateValidationGroup= function(groupId)
+{
+ var groups = Prado.Validation.TargetGroups;
+ for(var id in groups)
+ {
+ if(groups[id] == groupId)
+ {
+ var target = $(id);
+ Prado.Validation.ActiveTarget = target;
+ Prado.Validation.CurrentTargetGroup = groupId;
+ Prado.Validation.IsGroupValidation = false;
+ return Prado.Validation.IsValid(target.form);
+ }
+ }
+ return true;
+};
+
+/**
+ * Validate the page
+ * @return boolean true if valid, false otherwise.
+ */
+Prado.Validation.ValidateNonGroup= function(formId)
+{
+ if(Prado.Validation)
+ {
+ var form = $(formId);
+ form = form || document.forms[0];
+ Prado.Validation.ActiveTarget = form;
+ Prado.Validation.CurrentTargetGroup = null;
+ Prado.Validation.IsGroupValidation = false;
+ return Prado.Validation.IsValid(form);
+ }
+ return true;
+};
+
+
+
/**
* Register Prado.Validation.Onload() for window.onload event.
*/
diff --git a/framework/Web/Javascripts/base/validators.js b/framework/Web/Javascripts/base/validators.js
index 2f49eb12..427b46fc 100644
--- a/framework/Web/Javascripts/base/validators.js
+++ b/framework/Web/Javascripts/base/validators.js
@@ -5,8 +5,8 @@ Prado.Validation.TRequiredFieldValidator=function(){
return true;
}
else{
- var trim=Prado.Validation.Util.trim;
- var a=trim($F(this.control));
+ var trim=Prado.Util.trim;
+ var a=trim(Form.Element.getValue(this.control));
var b=trim(this.attr.initialvalue);
return(a!=b);
}
@@ -15,8 +15,8 @@ Prado.Validation.TRequiredFieldValidator=function(){
Prado.Validation.TRegularExpressionValidator = function()
{
- var trim = Prado.Validation.Util.trim;
- var value = trim($F(this.control));
+ var trim = Prado.Util.trim;
+ var value = trim(Form.Element.getValue(this.control));
if (value == "") return true;
var rx = new RegExp(this.attr.validationexpression);
var matches = rx.exec(value);
@@ -35,8 +35,8 @@ Prado.Validation.TCustomValidator = function()
Prado.Validation.TRangeValidator = function()
{
- var trim = Prado.Validation.Util.trim;
- var value = trim($F(this.control));
+ var trim = Prado.Util.trim;
+ var value = trim(Form.Element.getValue(this.control));
if (value == "") return true;
var minval = this.attr.minimumvalue;
@@ -62,8 +62,8 @@ Prado.Validation.TRangeValidator = function()
Prado.Validation.TCompareValidator = function()
{
- var trim = Prado.Validation.Util.trim;
- var value = trim($F(this.control));
+ var trim = Prado.Util.trim;
+ var value = trim(Form.Element.getValue(this.control));
if (value.length == 0) return true;
var compareTo;
@@ -71,7 +71,7 @@ Prado.Validation.TCompareValidator = function()
var comparee = $(this.attr.controlhookup);;
if(comparee)
- compareTo = trim($F(comparee));
+ compareTo = trim(Form.Element.getValue(comparee));
else
{
compareTo = isString(this.attr.valuetocompare) ? this.attr.valuetocompare : "";
diff --git a/framework/Web/Javascripts/extended/dom.js b/framework/Web/Javascripts/extended/dom.js
index de5ae056..f29cf37d 100644
--- a/framework/Web/Javascripts/extended/dom.js
+++ b/framework/Web/Javascripts/extended/dom.js
@@ -69,6 +69,17 @@ Prado.Element =
for(var i = 0; i<options.length; i++)
el.options[el.options.length] = new Option(options[i][0],options[i][1]);
}
+ },
+/**
+ * A delayed focus on a particular element
+ * @param {element} element to apply focus()
+ */
+ focus : function(element)
+ {
+ var obj = $(element);
+ if(isObject(obj) && isdef(obj.focus))
+ setTimeout(function(){ obj.focus(); }, 100);
+ return false;
}
}
diff --git a/framework/Web/Javascripts/js/dom.js b/framework/Web/Javascripts/js/dom.js
index b93a6c63..4a4904ad 100644
--- a/framework/Web/Javascripts/js/dom.js
+++ b/framework/Web/Javascripts/js/dom.js
@@ -292,23 +292,31 @@ for(var i=0;i<_18.length;i++){
el.options[el.options.length]=new Option(_18[i][0],_18[i][1]);
}
}
+},focus:function(_20){
+var obj=$(_20);
+if(isObject(obj)&&isdef(obj.focus)){
+setTimeout(function(){
+obj.focus();
+},100);
+}
+return false;
}};
-Prado.Element.Selection={inputValue:function(el,_20){
+Prado.Element.Selection={inputValue:function(el,_22){
switch(el.type.toLowerCase()){
case "checkbox":
case "radio":
-return el.checked=_20;
+return el.checked=_22;
}
-},selectValue:function(el,_21){
-$A(el.options).each(function(_22){
-_22.selected=_22.value==_21;
+},selectValue:function(el,_23){
+$A(el.options).each(function(_24){
+_24.selected=_24.value==_23;
});
-},selectIndex:function(el,_23){
+},selectIndex:function(el,_25){
if(el.type=="select-one"){
-el.selectedIndex=_23;
+el.selectedIndex=_25;
}else{
for(var i=0;i<el.length;i++){
-if(i==_23){
+if(i==_25){
el.options[i].selected=true;
}
}
@@ -316,49 +324,49 @@ el.options[i].selected=true;
},selectClear:function(el){
el.selectedIndex=-1;
},selectAll:function(el){
-$A(el.options).each(function(_24){
-_24.selected=true;
-Logger.warn(_24.value);
+$A(el.options).each(function(_26){
+_26.selected=true;
+Logger.warn(_26.value);
});
},selectInvert:function(el){
-$A(el.options).each(function(_25){
-_25.selected=!_25.selected;
+$A(el.options).each(function(_27){
+_27.selected=!_27.selected;
});
-},checkValue:function(_26,_27){
-$A(document.getElementsByName(_26)).each(function(el){
-el.checked=el.value==_27;
+},checkValue:function(_28,_29){
+$A(document.getElementsByName(_28)).each(function(el){
+el.checked=el.value==_29;
});
-},checkIndex:function(_28,_29){
-var _30=$A(document.getElementsByName(_28));
-for(var i=0;i<_30.length;i++){
-if(i==_29){
-_30[i].checked=true;
+},checkIndex:function(_30,_31){
+var _32=$A(document.getElementsByName(_30));
+for(var i=0;i<_32.length;i++){
+if(i==_31){
+_32[i].checked=true;
}
}
-},checkClear:function(_31){
-$A(document.getElementsByName(_31)).each(function(el){
+},checkClear:function(_33){
+$A(document.getElementsByName(_33)).each(function(el){
el.checked=false;
});
-},checkAll:function(_32){
-$A(document.getElementsByName(_32)).each(function(el){
+},checkAll:function(_34){
+$A(document.getElementsByName(_34)).each(function(el){
el.checked=true;
});
-},checkInvert:function(_33){
-$A(document.getElementsByName(_33)).each(function(el){
+},checkInvert:function(_35){
+$A(document.getElementsByName(_35)).each(function(el){
el.checked=!el.checked;
});
}};
-Object.extend(Prado.Element,{Insert:{After:function(_34,_35){
-new Insertion.After(_34,_35);
-},Before:function(_36,_37){
-new Insertion.Before(_36.innerHTML);
-},Below:function(_38,_39){
-new Insertion.Bottom(_38,_39);
-},Above:function(_40,_41){
-new Insertion.Top(_40,_41);
-}},CssClass:{set:function(_42,_43){
-_42=new Element.ClassNames(_42);
-_42.set(_43);
+Object.extend(Prado.Element,{Insert:{After:function(_36,_37){
+new Insertion.After(_36,_37);
+},Before:function(_38,_39){
+new Insertion.Before(_38.innerHTML);
+},Below:function(_40,_41){
+new Insertion.Bottom(_40,_41);
+},Above:function(_42,_43){
+new Insertion.Top(_42,_43);
+}},CssClass:{set:function(_44,_45){
+_44=new Element.ClassNames(_44);
+_44.set(_45);
}}});
var Field={clear:function(){
@@ -1477,3 +1485,192 @@ _89.push(_88[i]);
return _89;
}};
+Object.extend(Date.prototype,{SimpleFormat:function(_1){
+var _2=new Array();
+_2["d"]=this.getDate();
+_2["dd"]=Prado.Util.pad(this.getDate(),2);
+_2["M"]=this.getMonth()+1;
+_2["MM"]=Prado.Util.pad(this.getMonth()+1,2);
+var _3=""+this.getFullYear();
+_3=(_3.length==2)?"19"+_3:_3;
+_2["yyyy"]=_3;
+_2["yy"]=_2["yyyy"].toString().substr(2,2);
+var _4=new String(_1);
+for(var _5 in _2){
+var _6=new RegExp("\\b"+_5+"\\b","g");
+_4=_4.replace(_6,_2[_5]);
+}
+return _4;
+},toISODate:function(){
+var y=this.getFullYear();
+var m=Prado.Util.pad(this.getMonth()+1);
+var d=Prado.Util.pad(this.getDate());
+return String(y)+String(m)+String(d);
+}});
+Object.extend(Date,{SimpleParse:function(_10,_11){
+val=String(_10);
+_11=String(_11);
+if(val.length<=0){
+return null;
+}
+if(_11.length<=0){
+return new Date(_10);
+}
+var _12=function(val){
+var _14="1234567890";
+for(var i=0;i<val.length;i++){
+if(_14.indexOf(val.charAt(i))==-1){
+return false;
+}
+}
+return true;
+};
+var _16=function(str,i,_18,_19){
+for(var x=_19;x>=_18;x--){
+var _21=str.substring(i,i+x);
+if(_21.length<_18){
+return null;
+}
+if(_12(_21)){
+return _21;
+}
+}
+return null;
+};
+var _22=0;
+var _23=0;
+var c="";
+var _25="";
+var _26="";
+var x,y;
+var now=new Date();
+var _28=now.getFullYear();
+var _29=now.getMonth()+1;
+var _30=1;
+while(_23<_11.length){
+c=_11.charAt(_23);
+_25="";
+while((_11.charAt(_23)==c)&&(_23<_11.length)){
+_25+=_11.charAt(_23++);
+}
+if(_25=="yyyy"||_25=="yy"||_25=="y"){
+if(_25=="yyyy"){
+x=4;
+y=4;
+}
+if(_25=="yy"){
+x=2;
+y=2;
+}
+if(_25=="y"){
+x=2;
+y=4;
+}
+_28=_16(val,_22,x,y);
+if(_28==null){
+return null;
+}
+_22+=_28.length;
+if(_28.length==2){
+if(_28>70){
+_28=1900+(_28-0);
+}else{
+_28=2000+(_28-0);
+}
+}
+}else{
+if(_25=="MM"||_25=="M"){
+_29=_16(val,_22,_25.length,2);
+if(_29==null||(_29<1)||(_29>12)){
+return null;
+}
+_22+=_29.length;
+}else{
+if(_25=="dd"||_25=="d"){
+_30=_16(val,_22,_25.length,2);
+if(_30==null||(_30<1)||(_30>31)){
+return null;
+}
+_22+=_30.length;
+}else{
+if(val.substring(_22,_22+_25.length)!=_25){
+return null;
+}else{
+_22+=_25.length;
+}
+}
+}
+}
+}
+if(_22!=val.length){
+return null;
+}
+if(_29==2){
+if(((_28%4==0)&&(_28%100!=0))||(_28%400==0)){
+if(_30>29){
+return null;
+}
+}else{
+if(_30>28){
+return null;
+}
+}
+}
+if((_29==4)||(_29==6)||(_29==9)||(_29==11)){
+if(_30>30){
+return null;
+}
+}
+var _31=new Date(_28,_29-1,_30,0,0,0);
+return _31;
+}});
+
+Prado.Util={};
+Prado.Util.pad=function(_1,X){
+X=(!X?2:X);
+_1=""+_1;
+while(_1.length<X){
+_1="0"+_1;
+}
+return _1;
+};
+Prado.Util.toInteger=function(_3){
+var _4=/^\s*[-\+]?\d+\s*$/;
+if(_3.match(_4)==null){
+return null;
+}
+var _5=parseInt(_3,10);
+return (isNaN(_5)?null:_5);
+};
+Prado.Util.toDouble=function(_6,_7){
+_7=undef(_7)?".":_7;
+var _8=new RegExp("^\\s*([-\\+])?(\\d+)?(\\"+_7+"(\\d+))?\\s*$");
+var m=_6.match(_8);
+if(m==null){
+return null;
+}
+var _10=m[1]+(m[2].length>0?m[2]:"0")+"."+m[4];
+var num=parseFloat(_10);
+return (isNaN(num)?null:num);
+};
+Prado.Util.toCurrency=function(_12,_13,_14,_15){
+_13=undef(_13)?",":_13;
+_15=undef(_15)?".":_15;
+_14=undef(_14)?2:_14;
+var exp=new RegExp("^\\s*([-\\+])?(((\\d+)\\"+_13+")*)(\\d+)"+((_14>0)?"(\\"+_15+"(\\d{1,"+_14+"}))?":"")+"\\s*$");
+var m=_12.match(exp);
+if(m==null){
+return null;
+}
+var _17=m[2]+m[5];
+var _18=m[1]+_17.replace(new RegExp("(\\"+_13+")","g"),"")+((_14>0)?"."+m[7]:"");
+var num=parseFloat(_18);
+return (isNaN(num)?null:num);
+};
+Prado.Util.trim=function(_19){
+if(!isString(_19)){
+return "";
+}
+return _19.replace(/^\s+|\s+$/g,"");
+};
+
diff --git a/framework/Web/Javascripts/js/validator.js b/framework/Web/Javascripts/js/validator.js
index 6f347756..14808d73 100644
--- a/framework/Web/Javascripts/js/validator.js
+++ b/framework/Web/Javascripts/js/validator.js
@@ -83,7 +83,7 @@ return (isObject(_27)&&y==_27.getFullYear()&&m==_27.getMonth()&&d==_27.getDate()
return null;
};
Prado.Validation.Util.trim=function(_28){
-if(!isString(_28)){
+if(undef(_28)){
return "";
}
return _28.replace(/^\s+|\s+$/g,"");
@@ -185,6 +185,9 @@ if(this.control&&isString(_43)&&_43.length>0){
Element.condClassName(this.control,_43,!this.isValid);
}
Prado.Validation.ShowSummary();
+if(this.attr.focusonerror){
+Prado.Element.focus(this.attr.focuselementid);
+}
},setValid:function(_44){
this.isValid=_44;
this.update();
@@ -346,6 +349,48 @@ return _64;
Prado.Validation.OnLoad=function(){
Event.observe(Prado.Validation.forms,"submit",Prado.Validation.OnSubmit);
};
+Prado.Validation.ValidateValidatorGroup=function(_65){
+var _66=Prado.Validation.groups;
+var _67=null;
+for(var i=0;i<_66.length;i++){
+if(_66[i].id==_65){
+_67=_66[i];
+Prado.Validation.groups[i].active=true;
+Prado.Validation.CurrentTargetGroup=null;
+Prado.Validation.IsGroupValidation=true;
+}else{
+Prado.Validation.groups[i].active=false;
+}
+}
+if(_67){
+return Prado.Validation.IsValid(_67.target.form);
+}
+return true;
+};
+Prado.Validation.ValidateValidationGroup=function(_68){
+var _69=Prado.Validation.TargetGroups;
+for(var id in _69){
+if(_69[id]==_68){
+var _70=$(id);
+Prado.Validation.ActiveTarget=_70;
+Prado.Validation.CurrentTargetGroup=_68;
+Prado.Validation.IsGroupValidation=false;
+return Prado.Validation.IsValid(_70.form);
+}
+}
+return true;
+};
+Prado.Validation.ValidateNonGroup=function(_71){
+if(Prado.Validation){
+var _72=$(_71);
+_72=_72||document.forms[0];
+Prado.Validation.ActiveTarget=_72;
+Prado.Validation.CurrentTargetGroup=null;
+Prado.Validation.IsGroupValidation=false;
+return Prado.Validation.IsValid(_72);
+}
+return true;
+};
Event.OnLoad(Prado.Validation.OnLoad);
Prado.Validation.TRequiredFieldValidator=function(){
@@ -353,15 +398,15 @@ var _1=this.control.getAttribute("type");
if(_1=="file"){
return true;
}else{
-var _2=Prado.Validation.Util.trim;
-var a=_2($F(this.control));
+var _2=Prado.Util.trim;
+var a=_2(Form.Element.getValue(this.control));
var b=_2(this.attr.initialvalue);
return (a!=b);
}
};
Prado.Validation.TRegularExpressionValidator=function(){
-var _5=Prado.Validation.Util.trim;
-var _6=_5($F(this.control));
+var _5=Prado.Util.trim;
+var _6=_5(Form.Element.getValue(this.control));
if(_6==""){
return true;
}
@@ -377,8 +422,8 @@ eval("var validate = "+_10);
return validate&&isFunction(validate)?validate(this,_9):true;
};
Prado.Validation.TRangeValidator=function(){
-var _11=Prado.Validation.Util.trim;
-var _12=_11($F(this.control));
+var _11=Prado.Util.trim;
+var _12=_11(Form.Element.getValue(this.control));
if(_12==""){
return true;
}
@@ -403,15 +448,15 @@ _12=this.convert(_15,_12);
return _12>=min&&_12<=max;
};
Prado.Validation.TCompareValidator=function(){
-var _18=Prado.Validation.Util.trim;
-var _19=_18($F(this.control));
+var _18=Prado.Util.trim;
+var _19=_18(Form.Element.getValue(this.control));
if(_19.length==0){
return true;
}
var _20;
var _21=$(this.attr.controlhookup);
if(_21){
-_20=_18($F(_21));
+_20=_18(Form.Element.getValue(_21));
}else{
_20=isString(this.attr.valuetocompare)?this.attr.valuetocompare:"";
}
diff --git a/tests/FunctionalTests/protected/pages/Validation/RequiredFieldValidator.page b/tests/FunctionalTests/protected/pages/Validation/RequiredFieldValidator.page
index 4c9a8cd3..56ef07bd 100644
--- a/tests/FunctionalTests/protected/pages/Validation/RequiredFieldValidator.page
+++ b/tests/FunctionalTests/protected/pages/Validation/RequiredFieldValidator.page
@@ -1,7 +1,13 @@
<com:TForm>
<h1>Basic TRequiredFieldValidator Test1</h1>
<com:TTextBox ID="text1" />
- <com:TRequiredFieldValidator ID="validator1" ControlToValidate="text1" ErrorMessage="*" />
+ <com:TRequiredFieldValidator
+ ID="validator1"
+ FocusOnError="true"
+ FocusElementID="text2"
+ ControlToValidate="text1"
+ ErrorMessage="*" />
<com:TButton ID="button1" Text="Click" />
+ <com:TTextBox ID="text2" />
<com:TJavascriptLogger />
</com:TForm> \ No newline at end of file
diff --git a/tools/jsbuilder/build.php b/tools/jsbuilder/build.php
index 28d809c1..86135619 100644
--- a/tools/jsbuilder/build.php
+++ b/tools/jsbuilder/build.php
@@ -74,7 +74,9 @@ $libraries = array(
'prototype/position.js',
'extra/getElementsBySelector.js',
'extra/behaviour.js',
- 'effects/util.js'
+ 'effects/util.js',
+ 'base/date.js',
+ 'base/util.js'
),
//effects
'effects.js' => array(