createElement : (function(){
try {
var el = document.createElement(''); //MSIE memory leak according to Drip
if(el.tagName.toLowerCase() != 'div' || el.name != 'foo')
throw 'create element error';
return function(tag, attrs){
var html = '<' + tag;
for(var name in attrs)
html += ' ' + name + '="' + attrs[name] + '"';
html += '>';
if(tag.toLowerCase() != 'input')
html += ''+tag+'>';
return document.createElement(html); //'<'+tag+' name="'+name+'">'+tag+'>'
};
}
catch(err){
return function(tag, attrs){
var el = document.createElement(tag);
for(var name in attrs)
el.setAttribute(name, attrs[name]);
return el;
};
}
})(),
//Sort elements in document order (from ppk)
sortNodes : (function(){
var n = document.documentElement.firstChild;
if(n.sourceIndex){
return function (a,b){
return a.sourceIndex - b.sourceIndex;
};
}
else if(n.compareDocumentPosition){
return function (a,b){
return 3 - (a.compareDocumentPosition(b) & 6);
};
}
})(),
//Shortcut to create new list items; used by default invalid event handler in listing the errors
createLI : function(text){
var li = document.createElement('li');
li.appendChild(document.createTextNode(text));
return li;
},
//Initially inspired by Paul Sowden
ISO8601RegExp : /^(?:(\d\d\d\d)-(W(0[1-9]|[1-4]\d|5[0-2])|(0\d|1[0-2])(-(0\d|[1-2]\d|3[0-1])(T(0\d|1\d|2[0-4]):([0-5]\d)(:([0-5]\d)(\.(\d+))?)?(Z)?)?)?)|(0\d|1\d|2[0-4]):([0-5]\d)(:([0-5]\d)(\.(\d+))?)?)$/,
parseISO8601 : function (str, type) {
var d = $wf2.validateDateTimeType(str, type);
if(!d)
return null;
var date = new Date(0);
var _timePos = 8;
if(d[15]){ //Time
if(type && type != 'time') // a time date
return null;
_timePos = 15;
}
else {
date.setUTCFullYear(d[1]);
//ISO8601 Week
if(d[3]){
if(type && type != 'week')
return null;
date.setUTCDate(date.getUTCDate() + ((8 - date.getUTCDay()) % 7) + (d[3]-1)*7); //set week day and week
return date;
}
//Other date-related types
else {
date.setUTCMonth(d[4] - 1); //Month must be supplied for WF2
if(d[6])
date.setUTCDate(d[6]);
}
}
//Set time-related fields
if(d[_timePos+0]) date.setUTCHours(d[_timePos+0]);
if(d[_timePos+1]) date.setUTCMinutes(d[_timePos+1]);
if(d[_timePos+2]) date.setUTCSeconds(d[_timePos+3]);
if(d[_timePos+4]) date.setUTCMilliseconds(Math.round(Number(d[_timePos+4]) * 1000));
//Set to local time if date given, hours present and no 'Z' provided
if(d[4] && d[_timePos+0] && !d[_timePos+6])
date.setUTCMinutes(date.getUTCMinutes()+date.getTimezoneOffset());
return date;
},
validateDateTimeType : function(value, type){ //returns RegExp matches
var isValid = false;
var d = $wf2.ISO8601RegExp.exec(value); //var d = string.match(new RegExp(regexp));
if(!d || !type)
return d;
type = type.toLowerCase();
if(type == 'week') // a week date
isValid = (d[2].toString().indexOf('W') === 0); //valid if W present
else if(type == 'time') // a time date
isValid = !!d[15];
else if(type == 'month')
isValid = !d[5];
else { //a date related value
//Verify that the number of days in the month are valid
if(d[6]){
var date = new Date(d[1], d[4]-1, d[6]);
if(date.getMonth() != d[4]-1)
isValid = false;
else switch(type){
case 'date':
isValid = (d[4] && !d[7]); //valid if day of month supplied and time field not present
break;
case 'datetime':
isValid = !!d[14]; //valid if Z present
break;
case 'datetime-local':
isValid = (d[7] && !d[14]); //valid if time present and Z not provided
break;
}
}
}
return isValid ? d : null;
},
zeroPad : function(num, pad){
if(!pad)
pad = 2;
var str = num.toString();
while(str.length < pad)
str = '0' + str;
return str;
},
dateToISO8601 : function(date, type){
type = String(type).toLowerCase();
var ms = '';
if(date.getUTCMilliseconds())
ms = '.' + $wf2.zeroPad(date.getUTCMilliseconds(), 3).replace(/0+$/,'');
switch(type){
case 'date':
return date.getUTCFullYear() + '-' + $wf2.zeroPad(date.getUTCMonth()+1) + '-' + $wf2.zeroPad(date.getUTCDate());
case 'datetime-local':
return date.getFullYear() + '-' + $wf2.zeroPad(date.getMonth()+1) + '-' + $wf2.zeroPad(date.getDate()) +
'T' + $wf2.zeroPad(date.getHours()) + ':' + $wf2.zeroPad(date.getMinutes()) + ':' + $wf2.zeroPad(date.getMinutes()) + ms + 'Z';
case 'month':
return date.getUTCFullYear() + '-' + $wf2.zeroPad(date.getUTCMonth()+1);
case 'week':
var week1 = $wf2.parseISO8601(date.getUTCFullYear() + '-W01');
return date.getUTCFullYear() + '-W' + $wf2.zeroPad(((date.valueOf() - week1.valueOf()) / (7*24*60*60*1000)) + 1);
case 'time':
return $wf2.zeroPad(date.getUTCHours()) + ':' + $wf2.zeroPad(date.getUTCMinutes()) + ':' + $wf2.zeroPad(date.getUTCMinutes()) + ms;
case 'datetime':
default:
return date.getUTCFullYear() + '-' + $wf2.zeroPad(date.getUTCMonth()+1) + '-' + $wf2.zeroPad(date.getUTCDate()) +
'T' + $wf2.zeroPad(date.getUTCHours()) + ':' + $wf2.zeroPad(date.getUTCMinutes()) + ':' + $wf2.zeroPad(date.getUTCMinutes()) + ms + 'Z';
}
},
/*
* Fires an event manually.
* @author Scott Andrew - http://www.scottandrew.com/weblog/articles/cbs-events
* @author John Resig - http://ejohn.org/projects/flexible-javascript-events/
* @param {Object} obj - a javascript object.
* @param {String} evType - an event attached to the object.
* @param {Function} fn - the function that is called when the event fires.
*
*/
fireEvent: function (element, event, options){
if(!element) {
return;
}
if (document.createEventObject){
return element.fireEvent('on' + event, $wf2.globalEvent);
} else{
// dispatch for firefox + others
$wf2.globalEvent.initEvent(event, true, true); // event type,bubbling,cancelable
return !element.dispatchEvent($wf2.globalEvent);
}
},
//Emulation of DOMException
DOMException : function(code){
var message = 'DOMException: ';
switch(code){
case 1: message += 'INDEX_SIZE_ERR'; break;
case 9: message += 'NOT_SUPPORTED_ERR'; break;
case 11: message += 'INVALID_STATE_ERR'; break;
case 12: message += 'SYNTAX_ERR'; break;
case 13: message += 'INVALID_MODIFICATION_ERR'; break;
}
var err = new Error(message);
err.code = code;
err.name = 'DOMException';
//Provide error codes and messages for the exception types that are raised by WF2
err.INDEX_SIZE_ERR = 1;
err.NOT_SUPPORTED_ERR = 9;
err.INVALID_STATE_ERR = 11;
err.SYNTAX_ERR = 12;
err.INVALID_MODIFICATION_ERR = 13;
//with($wf2.DOMException.prototype){
// INDEX_SIZE_ERR = 1;
// DOMSTRING_SIZE_ERR = 2;
// HIERARCHY_REQUEST_ERR = 3;
// WRONG_DOCUMENT_ERR = 4;
// INVALID_CHARACTER_ERR = 5;
// NO_DATA_ALLOWED_ERR = 6;
// NO_MODIFICATION_ALLOWED_ERR = 7;
// NOT_FOUND_ERR = 8;
// NOT_SUPPORTED_ERR = 9;
// INUSE_ATTRIBUTE_ERR = 10;
// INVALID_STATE_ERR = 11;
// SYNTAX_ERR = 12;
// INVALID_MODIFICATION_ERR = 13;
// NAMESPACE_ERR = 14;
// INVALID_ACCESS_ERR = 15;
//};
return err;
},
css: new function () {
var me = this;
var blankRe = new RegExp('\\s');
/**
* Generates a regular expression string that can be used to detect a class name
* in a tag's class attribute. It is used by a few methods, so I
* centralized it.
*
* @param {String} className - a name of a CSS class.
*/
function getClassReString(className) {
return '\\s'+className+'\\s|^' + className + '\\s|\\s' + className + '$|' + '^' + className +'$';
}
function getClassPrefixReString(className) {
return '\\s'+className+'-[0-9a-zA-Z_]+\\s|^' + className + '[0-9a-zA-Z_]+\\s|\\s' + className + '[0-9a-zA-Z_]+$|' + '^' + className +'[0-9a-zA-Z_]+$';
}
/**
* Make an HTML object be a member of a certain class.
*
* @param {Object} obj - an HTML object
* @param {String} className - a CSS class name.
*/
me.addClass = function (obj, className) {
if (blankRe.test(className)) {
return;
}
// only add class if the object is not a member of it yet.
if (!me.isMemberOfClass(obj, className)) {
obj.className += " " + className;
}
}
/**
* Make an HTML object *not* be a member of a certain class.
*
* @param {Object} obj - an HTML object
* @param {Object} className - a CSS class name.
*/
me.removeClass = function (obj, className) {
if (blankRe.test(className)) {
return;
}
var re = new RegExp(getClassReString(className) , "g");
var oldClassName = obj.className;
if (obj.className) {
obj.className = oldClassName.replace(re, ' ');
}
}
/**
* Determines if an HTML object is a member of a specific class.
* @param {Object} obj - an HTML object.
* @param {Object} className - the CSS class name.
*/
me.isMemberOfClass = function (obj, className) {
if (blankRe.test(className))
return false;
var re = new RegExp(getClassReString(className) , "g");
return (re.test(obj.className));
}
me.getAbsoluteCoords = function(obj) {
var curleft = obj.offsetLeft;
var curtop = obj.offsetTop;
/*
* IE and Gecko
*/
if (obj.getBoundingClientRect) {
var temp = obj.getBoundingClientRect();
curleft = temp.left + me.getScrollX();
curtop = temp.top + me.getScrollY();
} else {
/* Everything else must do the quirkmode.org way */
if (obj.offsetParent) {
while (obj = obj.offsetParent) {
curleft += obj.offsetLeft - obj.scrollLeft;
curtop += obj.offsetTop - obj.scrollTop;
}
}
}
return {
x: curleft,
y: curtop
};
}
/**
* Get the the amount of pixels the window has been scrolled from the top. If there is no
* vertical scrollbar, this function return 0.
*
* @return {int} - the amount of pixels the window has been scrolled to the right, in pixels.
*/
me.getScrollX = function (myWindow)
{
var myDocument;
if (myWindow) {
myDocument = myWindow.document;
} else {
myWindow = window;
myDocument = document;
}
// All except that I know of except IE
if (myWindow.pageXOffset != null) {
return myWindow.pageXOffset;
// IE 6.x strict
} else if (myDocument.documentElement != null
&& myDocument.documentElement.scrollLeft !="0px"
&& myDocument.documentElement.scrollLeft !=0) {
return myDocument.documentElement.scrollLeft;
// all other IE
} else if (myDocument.body != null &&
myDocument.body.scrollLeft != null) {
return myDocument.body.scrollLeft;
// if for some reason none of the above work, this should.
} else if (myWindow.scrollX != null) {
return myWindow.scrollX;
} else {
return null;
}
}
/**
* Get the the amount of pixels the window has been scrolled to the right. If there is no
* horizontal scrollbar, this function return 0.
*
* @return {int} - the amount of pixels the window has been scrolled to the right, in pixels.
*/
me.getScrollY = function(myWindow)
{
var myDocument;
if (myWindow) {
myDocument = myWindow.document;
} else {
myWindow = window;
myDocument = document;
}
// All except that I know of except IE
if (myWindow.pageYOffset != null) {
return myWindow.pageYOffset;
// IE 6.x strict
} else if (myDocument.documentElement != null
&& myDocument.documentElement.scrollTop !="0px"
&& myDocument.documentElement.scrollTop !=0) {
return myDocument.documentElement.scrollTop;
// all other IE
} else if (myDocument.body && myDocument.body.scrollTop != null) {
return myDocument.body.scrollTop;
// if for some reason none of the above work, this should.
} else if (myWindow.scrollY != null) {
return myWindow.scrollY;
} else {
return null;
}
}
/**
* gets the current window's width.
*
* @author Peter-Paul Koch - http://www.quirksmode.org
* @license see http://www.quirksmode.org/about/copyright.html
* @return {int} - the window's width, in pixels.
*/
me.getWindowWidth = function (theWindow)
{
if (!theWindow) {
theWindow = window;
}
var theDocument = theWindow.document;
// all except IE
if (theWindow.innerWidth != null) {
return theWindow.innerWidth;
// IE6 Strict mode
} else if (theDocument.documentElement &&
theDocument.documentElement.clientWidth ) {
return theDocument.documentElement.clientWidth;
// IE strictly less than 6
} else if (theDocument.body != null) {
return theDocument.body.clientWidth;
} else {
return null;
}
}
/**
* gets the current window's height.
*
* @author Peter-Paul Koch - http://www.quirksmode.org
* @license see http://www.quirksmode.org/about/copyright.html
* @return {int} - the window's height in pixels.
*/
me.getWindowHeight = function (theWindow)
{
if (!theWindow) {
theWindow = window;
}
var theDocument = theWindow.document;
// all except IE
if (theWindow.innerHeight != null) {
return theWindow.innerHeight;
// IE6 Strict mode
} else if (theDocument.documentElement &&
theDocument.documentElement.clientHeight ) {
return theDocument.documentElement.clientHeight;
// IE strictly less than 6
} else if (theDocument.body != null) {
return theDocument.body.clientHeight;
} else {
return null;
}
}
me.getMouseCoords = function (e) {
if (!e) {
return;
}
// IE
if (e.clientX != null) {
return {
x: e.clientX,
y: e.clientY
}
}
// NS4
else if (e.pageX != null) {
return {
x: e.pageX,
y: e.pageY
}
// W3C
} else if (window.event != null && window.event.clientX != null
&& document.body != null &&
document.body.scrollLeft != null) {
return {
x: window.event.clientX + document.body.scrollLeft,
y: window.event.clientY + document.body.scrollTop
}
} else {
return null;
}
}
}
}; //End $wf2 = {
/*##############################################################################################
# Change the prototypes of HTML elements
##############################################################################################*/
/*##############################################################################################
# Set mutation event handlers to automatically add WF2 behaviors
##############################################################################################*/
//When a form control is inserted into a document, the UA must check to see if it has [the autofocus]
// attribute set. If it does, and the control is not disabled, and it is of a type normally
// focusable in the user's operating environment, then the UA should focus the control, as if
// the control's focus() method was invoked. UAs with a viewport should also scroll the document
// enough to make the control visible, even if it is not of a type normally focusable.
//REVISE: there should be one handler for all attr events on the page.
if(document.addEventListener){
document.addEventListener('DOMNodeInsertedIntoDocument', function(evt){ //DOMNodeInserted? DOMNodeInsertedIntoDocument
if(evt.target.nodeType == 1 && evt.target.hasAttribute('autofocus')){
$wf2.initAutofocusElement(evt.target);
}
//[[UAs may ignore this attribute if the user has indicated (for example, by starting to type in a
// form control) that he does not wish focus to be changed.]]
}, false);
//NOT CURRENTLY IMPLEMENTABLE:
// Setting the DOM attribute to true must set the content attribute to the value autofocus.
// Setting the DOM attribute to false must remove the content attribute.
document.addEventListener('DOMAttrModified', function(evt){
//The autofocus DOM attribute must return true when the content attribute is present (regardless
// of its value, even if it is the empty string), and false when it is absent.
if(evt.attrName == 'autofocus'){
if(evt.attrChange == evt.ADDITION)
//evt.relatedNode.autofocus = true;
$wf2.initAutofocusElement(evt.target);
else if(evt.attrChange == evt.REMOVAL)
evt.target.autofocus = false;
}
}, false);
}
(function(){
//Get the path to the library base directory
var match;
//For some reason, if not using documentElement, scriptaculous fails to load if reference to
// webforms2 script placed beforehand in Firefox
var scripts = document.documentElement.getElementsByTagName('script');
for(var i = 0; i < scripts.length; i++){
if(match = scripts[i].src.match(/^(.*)webforms2[^\/]+$/))
$wf2.libpath = match[1];
}
EventHelpers.addPageLoadEvent('$wf2.onDOMContentLoaded', true)
})();
} //End If(!document.implementation...
} //end if(!window.$wf2)
//if(!window.ValidityState){
//var ValidityState = {
//
//};
//if(HTMLElement.prototype)
//ValidityState interface
//node.validity = {
// typeMismatch : false,
// rangeUnderflow : false,
// rangeOverflow : false,
// stepMismatch : false,
// tooLong : false,
// patternMismatch : false,
// valueMissing : false,
// customError : false,
// valid : true
//};
//}
//if(!window.HTMLOutputElement){
//}