// ----------------------------------------------
// PRAjax - JavaScript code
// (C) Maarten Balliauw
// http://prajax.sf.net
// Version: PRAjaxUtil v$PRAJAXVER$
// ----------------------------------------------

// Static class
var PRAjaxUtil = new ( function () {
	// Inner EventCache object
	this.EventCache = new ( function () {
		// Event cache
		this.eventCache = new Array();
		
		// Event counter
		this.eventCounter = 0;
		
		// Get latest event
		this.getLatestCachedEvent = function () {
			// Create a self-reference
			var _this = this;
	
			// Return
			return _this.eventCache[ _this.eventCache.length - 1 ];
		}
		
		// Find cached event
		this.findCachedEvent = function (pElement, pEventType, pFunction, pUseCapture) {
			// Create a self-reference
			var _this = this;
	
			// Search event
			var iId = _this.findCachedEventId(pElement, pEventType, pFunction, pUseCapture);
			
			if (iId >= 0) {
				return _this.eventCache[iId];
			} else {
				return null;
			}
		}
		
		// Find cached event id
		this.findCachedEventId = function (pElement, pEventType, pFunction, pUseCapture) {
			// Create a self-reference
			var _this = this;
	
			// Search event
			for (var i = _this.eventCache.length - 1; i >= 0; i--) {
				if (_this.eventCache[i][0].getAttribute('PRAjaxEventCounter') == pElement.getAttribute('PRAjaxEventCounter')) {
					return i;
				}
			}
			
			return -1;
		}
		
		// Add cached event
		this.addCachedEvent = function (pElement, pEventType, pFunction, pUseCapture) {
			// Create a self-reference
			var _this = this;
			
			// Add attribute to pElement
			if (pElement.setAttribute) {
				pElement.setAttribute('PRAjaxEventCounter', _this.eventCounter++);
			}
			
			// Add event to cache
			_this.eventCache.push( [pElement, pEventType, pFunction, pUseCapture] );
		}
		
		// Remove cached event
		this.removeCachedEvent = function (idx) {
			// Create a self-reference
			var _this = this;
			
			// Remove event from cache
			var newCache = new Array();
			var cnt = _this.eventCache.length;
			for (var i = cnt; i >= 0; i--) {
				if (i != idx) {
					newCache.push(_this.eventCache[i]);
				}
			}
			_this.eventCache = newCache;
		}
	} ) ();
	
	// Delete all events
	this.deleteAllEvents = function () {
		// Create a self-reference
		var _this = this;

		// Delete all events
		if (_this.EventCache && _this.EventCache.eventCache) {
			for (var i = _this.EventCache.eventCache.length - 1; i >= 0; i--) {
				_this.deleteEvent(_this.EventCache.eventCache[i][0], _this.EventCache.eventCache[i][1], _this.EventCache.eventCache[i][2], _this.EventCache.eventCache[i][3]);
			}
		}
	}
	
	// Add event
	this.addEvent = function (pElement, pEventType, pFunction, pUseCapture) {
		// Create a self-reference
		var _this = this;
		
		// Add event to cache (for later removal)
		_this.EventCache.addCachedEvent(pElement, pEventType, pFunction, pUseCapture);
		
		// Attach event
		if (pElement.addEventListener) {
			return pElement.addEventListener(pEventType, _this.EventCache.getLatestCachedEvent()[2], pUseCapture);
		} else if (pElement.attachEvent) {
			return pElement.attachEvent('on' + pEventType, _this.EventCache.getLatestCachedEvent()[2], pUseCapture);
		} else {
			return false;
		}	
	}
	
	// Delete event
	this.deleteEvent = function (pElement, pEventType, pFunction, pUseCapture) {
		// Create a self-reference
		var _this = this;
		
		// Return value
		var returnValue = false;
		
		// Get cached event
		var eCached = _this.EventCache.findCachedEvent(pElement, pEventType, pFunction, pUseCapture);
	
		if (eCached != null) {
			// Detach event
			if (pElement.removeEventListener) {
				returnValue = pElement.removeEventListener(pEventType, eCached[2], pUseCapture);
			} else if (pElement.detachEvent) {
				returnValue = pElement.detachEvent('on' + pEventType, eCached[2], pUseCapture);
			} else {
				returnValue = false;
			}

			// Delete event from cache
			_this.EventCache.removeCachedEvent( _this.EventCache.findCachedEventId(pElement, pEventType, pFunction, pUseCapture) );
		}
		
		// Return
		return returnValue;
	}
	
	// Add slashes (PHP equivalent)
	this.addSlashes = function (pString) {
		pString = pString + "";
		pString = pString.replace(/\\/g,"\\\\");
		pString = pString.replace(/\'/g,"\\'");
		pString = pString.replace(/\"/g,"\\\"");
		return pString;
	}
	
	// Strip slashes (PHP equivalent)
	this.stripSlashes = function (pString) {
		pString = pString + "";
		return pString.replace(/(\\)([\\\'\"])/g,"$2");
	}
	
	// Get form values as an array of keys and values
	this.getFormValues = function (pForm) {
		// Return array
		var returnValue = new Array();
		
		// Loop trough form elements
		var elements = pForm.elements;
		var cnt = elements.length;
		var name = '';
		var value = '';
		for (var i = 0; i < cnt; i++) {
			if (!elements[i].name)
				continue;
			if (elements[i].type && (elements[i].type == 'radio' || elements[i].type == 'checkbox') && elements[i].checked == false)
				continue;
			if (elements[i].disabled && elements[i].disabled == true)
				continue;
						
			// If a name is set, get the value
			if (elements[i].name) {
				// If it is a select multiple then loop trough its items
				if (elements[i].type=='select-multiple') {
					for (var j = 0; j < elements[i].length; j++) {
						if (elements[i].options[j].selected == true) {
							returnValue[elements[i].name] = elements[i].options[j].value;
						}
					}
				} else {
					returnValue[elements[i].name] = elements[i].value;
				}
			}
		}
								
		// Return
		return returnValue;
	}
} ) ();


// ----------------------------------------------
// JSON Extensions
// http://www.json.org/js.html
//
// Modified by Maarten Balliauw
//
// Usage: variable.toJSONString() and variable.parseJSON()
// ----------------------------------------------
(function () {
    var m = {
            '\b': '\\b',
            '\t': '\\t',
            '\n': '\\n',
            '\f': '\\f',
            '\r': '\\r',
            '"' : '\\"',
            '\\': '\\\\'
        },
        s = {
            array: function (x) {
                var a = ['['], b, f, i, l = x.length, v;
                for (i = 0; i < l; i += 1) {
                    v = x[i];
                    f = s[typeof v];
                    if (f) {
                        v = f(v);
                        if (typeof v == 'string') {
                            if (b) {
                                a[a.length] = ',';
                            }
                            a[a.length] = v;
                            b = true;
                        }
                    }
                }
                a[a.length] = ']';
                return a.join('');
            },
            'boolean': function (x) {
                return String(x);
            },
            'null': function (x) {
                return "null";
            },
            number: function (x) {
                return isFinite(x) ? String(x) : 'null';
            },
            object: function (x) {
                if (x) {
                    if (x instanceof Array) {
                        return s.array(x);
                    }
                    var a = ['{'], b, f, i, v;
                    for (i in x) {
                        v = x[i];
                        f = s[typeof v];
                        if (f) {
                            v = f(v);
                            if (typeof v == 'string') {
                                if (b) {
                                    a[a.length] = ',';
                                }
                                a.push(s.string(i), ':', v);
                                b = true;
                            }
                        }
                    }
                    a[a.length] = '}';
                    return a.join('');
                }
                return 'null';
            },
            string: function (x) {
                if (/["\\\x00-\x1f]/.test(x)) {
                    x = x.replace(/([\x00-\x1f\\"])/g, function(a, b) {
                        var c = m[b];
                        if (c) {
                            return c;
                        }
                        c = b.charCodeAt();
                        return '\\u00' +
                            Math.floor(c / 16).toString(16) +
                            (c % 16).toString(16);
                    });
                }
                return '"' + x + '"';
            }
        };

    Boolean.prototype.toJSONString = function () {
        return s.boolean(this);
    };
    
    Number.prototype.toJSONString = function () {
        return s.number(this);
    };
    
    String.prototype.toJSONString = function () {
        return s.string(this);
    };
    
//    Object.prototype.toJSONString = function () {  
//        return s.object(this);
//    };

    Array.prototype.toJSONString = function () {
        return s.array(this);
    };
})();

String.prototype.parseJSON = function () {
    try {
        return !(/[^,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]/.test(
                this.replace(/"(\\.|[^"\\])*"/g, ''))) &&
            eval('(' + this + ')');
    } catch (e) {
        return false;
    }
};
