var attr, prop, hasAttr, removeAttr, badReflections, attributesBad, numericAttributesBad, encTypeAttributeBad;

(function() {
	var doc = window.document;
	var html = doc.documentElement;
	attributesBad = (function() {

		// Detect broken MSHTML features

		var div, bad = !!(typeof html.getAttribute != 'undefined' && html.getAttribute('style') && typeof html.getAttribute('style') != 'string');
		
		if (bad && typeof doc.createElement != 'undefined') {
			div = doc.createElement('div');
			div.setAttribute('className', 'test');
			bad = div.className == 'test';
		}
		return bad;
	})();

	// These can be safely skipped for broken MSHTML implementations

	if (!attributesBad && typeof doc.createElement != 'undefined') {
		numericAttributesBad = (function() {
			var el = doc.createElement('td');
			return el.getAttribute('colspan') !== null;
		})();

		encTypeAttributeBad = (function() {
			var el = doc.createElement('form');
			el.setAttribute('enctype', 'application/x-www-form-urlencoded');
			el.removeAttribute('enctype');
			return el.getAttribute('enctype') !== null;
		})();
	}
	
	var attributeAliases = {'for':'htmlFor', accesskey:'accessKey', codebase:'codeBase', frameborder:'frameBorder', framespacing:'frameSpacing', nowrap:'noWrap', maxlength:'maxLength', 'class':'className', readonly:'readOnly', longdesc:'longDesc', tabindex:'tabIndex', rowspan:'rowSpan', colspan:'colSpan', ismap:'isMap', usemap:'useMap', cellpadding:'cellPadding', cellspacing:'cellSpacing'};

	// Used by attr to fix broken attributes

	var reEvent, reNewLine, reFunction;

	if (attributesBad) {
		reEvent = new RegExp('^on');
		reNewLine = new RegExp('[\\n\\r]', 'g');
		reFunction = new RegExp('^function [^\\(]*\\(\\) *{(.*)} *$');
	}
	var reUserBoolean = /^(checked|selected)$/;
        var reURI = new RegExp('^(href|src|data|usemap|longdesc|codebase|classid|profile|cite)$');
	var reSpan = new RegExp('^(row|col)?span$');
	var reCamel = new RegExp('([^-]*)-(.)(.*)');

	var camelize = function(name) {
		if (reCamel.test(name)) {
			var m = name.match(reCamel);
			return (m)?([m[1], m[2].toUpperCase(), m[3]].join('')):name;
		}
		return name;
	};

	hasAttr = (function() {
		var alias, attributeSpecified, nameLower, re, value, valueType;

		if (typeof html.hasAttribute != 'undefined') {
			return function(el, name) {
				nameLower = name.toLowerCase();
				alias = attributeAliases[nameLower];
				valueType = typeof el[alias];
				if (numericAttributesBad) {
					if (reSpan.test(nameLower)) {

						// Some agents (e.g. Blackberry browser) return '' for missing span attributes

						if (!el.getAttribute(nameLower)) {
							return false;
						}

						// Check outer HTML as last resort (IE8 standards mode known to take this fork)

						if (typeof el.outerHTML == 'string') {
							re = new RegExp('^[^>]*\\s+' + name + '=([\'"])?\\w+\\1?', 'i');
							return re.test(el.outerHTML);
						}
					} else if (valueType == 'number' && !el.getAttribute(nameLower)) {						
						return false;
					}
				}
				if (encTypeAttributeBad && nameLower == 'enctype') {
					// *** Consolidate
					if (typeof el.outerHTML == 'string') {
						re = new RegExp('^[^>]*\\s+' + name + '=([\'"])?\\w+\\1?', 'i');
						return re.test(el.outerHTML);
					}
					return !!(el.attributes.enctype && el.attributes.enctype.specified);
				}
				return el.hasAttribute(name);
			};
		}
		if (typeof html.attributes != 'undefined') {
			attributeSpecified = function(el, name) {				
				value = el.attributes[name];

				return !!(value && value.specified);
			};
			if (attributesBad) {
				return function(el, name) {

					// MSXML document

					if (el.ownerDocument && typeof el.ownerDocument.selectNodes != 'undefined') {
						return attributeSpecified(el, name);
					}

					nameLower = name.toLowerCase();

					// NOTE: encType is a non-standard alias found only in broken MSHTML DOM's (only applies to attributes collection)

					alias = nameLower == 'enctype' ? 'encType' : attributeAliases[nameLower];
					
					if (alias && alias.toLowerCase() == nameLower) {
						name = alias;
					}

					// NOTE: Broken MSHTML DOM is case-sensitive here with custom attributes

					if (el.attributes) {
						value = el.attributes[name] || el.attributes[nameLower];
					}

					if (value) {

						// NOTE: enctype and value attributes never specified

						if (value.specified) {
							return true;
						}

						if (typeof el[name] == 'boolean') {
							return el[name];
						}

						if (nameLower == 'value' && typeof el.defaultValue == 'string') {
							return !!(el.defaultValue || el.defaultValue != el.value);
						}

						if (/^(enctype|value)$/.test(nameLower) && typeof el.outerHTML == 'string') {
							re = new RegExp('^[^>]*\\s+' + name + '=([\'"])?\\w+\\1?', 'i');
							return re.test(el.outerHTML);
						}
					}
					return false;
				};
			}
			return attributeSpecified;
		}
	})();

	removeAttr = function(/*DomNode|String*/node, /*String*/name){

		// summary: Removes an attribute from an HTML element.
		//
		// node: id or reference to the element to remove the attribute from
		//
		// name: the name of the attribute to remove

		var nameLower = name.toLowerCase();
		var alias = attributeAliases[nameLower];

		if (attributesBad) {

			// NOTE: encType alias does not apply here

			if (alias && alias.toLowerCase() == nameLower) {
				name = alias;
			} else {
				name = camelize(name);
			}
		}
		alias = alias || nameLower;
		if (typeof node[alias] == 'boolean') {
			node[alias] = false;
		} else {
			node.removeAttribute(name);
		}
	};

	attr = (function() {
		var alias, doc, hasAttribute, key, nameLower, nn, val;

		if (attributesBad) {
			hasAttribute = hasAttr;
			return function(node, name, value) {

				// Find owner document

				doc = node.ownerDocument;

				// Convert name to lower

				nameLower = name.toLowerCase();

				// Find alias

				alias = attributeAliases[nameLower];

				// Camelize if necessary
				// Aliases are never hyphenated

				key = alias || (nameLower.indexOf('-') == -1 && nameLower) || camelize(nameLower);

				// Get node name for special cases

				nn = node.tagName.toLowerCase();

				if (arguments.length == 2) {

					// Getter

					// MSXML document

					if (doc && typeof doc.selectNodes != 'undefined') {
						return node.getAttribute(name);
					}

					if (hasAttribute(node, name)) {
						if (name == 'style') {
							return node.style.cssText;
						}

						// NOTE: In case of form elements named with standard property names (e.g. action.)

						if (nn == 'form' && typeof node.getAttributeNode != 'undefined') {
							if (nameLower == 'enctype' && typeof node.enctype == 'string') {
								return node.enctype;
							}
							val = node.getAttributeNode(name) || node.getAttributeNode(nameLower);
							return val ? val.nodeValue : null;
						}
						val = node[key];
						switch(typeof val) {
						case 'boolean':
							if (reUserBoolean.test(nameLower)) {
								return node['default' + nameLower.substring(0, 1).toUpperCase() + nameLower.substring(1)] ? '' : null;
							}
							return val ? '' : null;
						case 'undefined':

							// Custom attribute (case sensitive)

							val = node.getAttribute(name);
							return typeof val == 'string' ? val : null;
						case 'string':
							if (reURI.test(nameLower)) {
								return node.getAttribute(nameLower, 2);
							}
							if (nameLower == 'value' && typeof node.defaultValue == 'string') {
								return node.defaultValue;
							}						
							return val;
						case 'function':
							if (reEvent.test(nameLower)) {
								val = node[nameLower].toString();
								if (val) {
									val = val.replace(reNewLine, '');
									if (reFunction.test(val)) {
										return val.replace(reFunction, '$1');
									}
								}
							}
							return null;
						default:
							return val === null ? null : String(val);
						}
					}
					return null;
				}

				// Setter

				if (doc && typeof doc.selectNodes != 'undefined') {

					// MSXML document

					node.setAttribute(name, value);
				} else {

					// Broken by design MSHTML DOM (IE < 8 and compatibility modes)

				        nn = node.tagName.toLowerCase();

					// HTML attributes are case insensitive

					var b = value.toLowerCase() == nameLower || !value;
					switch(nameLower) {
					case 'style':
						node.style.cssText = value;
						break;
					case 'checked':
					case 'selected':
						node['default' + nameLower.substring(0, 1).toUpperCase() + nameLower.substring(1)] = b;
						break;
					case 'disabled':
					case 'multiple':
					case 'readonly':
					case 'defer':
					case 'ismap':						
						node[key] = b;
						break;
					case 'type':
						if (nn != 'select') {

							// No such attribute, but there is a property

							node.type = value;
						}
						break;
					default:
						if (reEvent.test(nameLower)) {
							node[nameLower] = new Function(value);
						} else if (typeof node[key] == 'undefined') {

							// No defined property
							// Custom attribute (case sensitive)

							node.setAttribute(name, value);
						} else {

							if (nameLower == 'value') {
								node.defaultValue = value;
							} else {
								node[key] = value;
							}
						}
					}
				}
			};
		}

		return function(node, name, value) {
			var nameLower = name.toLowerCase();
			var alias = attributeAliases[nameLower] || nameLower;
			if (arguments.length == 2) {

				// Getter

				if (typeof node[alias] == 'boolean') {
					// *** consolidate

					if (reUserBoolean.test(nameLower)) {
						return node['default' + nameLower.substring(0, 1).toUpperCase() + nameLower.substring(1)] ? '' : null;
					}
					return node[alias] ? '' : null;
				}

				if (numericAttributesBad) {

					// NOTE: May only need this workaround for numbers

					return hasAttr(node, name) ? node.getAttribute(name) : null;
				}

				return node.getAttribute(name); // String or null
			}

			// Setter

			if (typeof node[alias] == 'boolean') {
				var b = !value || nameLower == value.toLowerCase();
				if (reUserBoolean.test(nameLower)) {
					if (b) {
						node.setAttribute(nameLower, nameLower);
					} else {
						node.removeAttribute(nameLower);
					}
				} else {
					node[alias] = b;
				}
			} else {
				node.setAttribute(name, value);
			}
		};
	})();


// For use with HTML DOM's.
// Expando properties must be strings and are handled as custom attributes.

var anchorHrefResolves = (function() {
	var el = doc.createElement('a');
	el.setAttribute('href', 'images/cinsoft.gif');
	return el.href != 'images/cinsoft.gif';
})();


prop = (function() {


if (typeof doc.createElement != 'undefined') {
	if (anchorHrefResolves) {
		badReflections = (function() {
			var result = {}, path = 'images/cinsoft.gif';
			var el = doc.createElement('form');

			// *** Consolidate

			el.setAttribute('action', path);
			result.action = el.action == path;
			el = doc.createElement('img');
			el.setAttribute('usemap', path);
			result.usemap = el.useMap == path;
			el.setAttribute('src', path);
			result.src = el.src == path;
			el.setAttribute('longdesc', path);
			result.longdesc = el.longDesc == path;
			el = doc.createElement('link');
			el.setAttribute('href', path);
			result.href = el.href == path;
			el = doc.createElement('head');
			el.setAttribute('profile', path);
			result.profile = el.profile == path;
			el = doc.createElement('object');
			el.setAttribute('codebase', path);
			result.codebase = el.codeBase == path;
			el.setAttribute('classid', path);
			result.classid = el.classid == path;
			el.setAttribute('data', path);
			result.data = el.data == path;
			el = doc.createElement('blockquote');
			el.setAttribute('cite', path);
			result.cite = el.cite == path;
			el = doc.createElement('area');
			el.setAttribute('href', path);
			result.href = result.href || el.href == path;
			return result;
		})();
	}
}



	// TODO: Get element document

	var elA = window.document.createElement('a');
	
	return function(el, name, value) {
		var nameLower = name.toLowerCase();
		var alias = camelize(attributeAliases[nameLower] || nameLower);

		// Getter

		if (arguments.length == 2) {
			switch (typeof el[alias]) {
			case 'boolean':				
				return reUserBoolean.test(nameLower) ? el['default' + nameLower.substring(0, 1).toUpperCase() + nameLower.substring(1)] : el[alias];
			case 'undefined':
				if (nameLower == 'tabindex') {
					return null;
				}

				if (nameLower == 'classid') {
					if (anchorHrefResolves) {
						var href = el.getAttribute('classid');
						if (href) {
							elA.setAttribute('href', href);
							return elA.href;
						}
						return null;
					}
				}

				// Missing expando or event handlers in some browsers (e.g. FF)

				return attr(el, nameLower);
			default:
				if (hasAttr(el, name)) {
					if (anchorHrefResolves && (reURI.test(nameLower) || nameLower == 'action') && badReflections[nameLower] && !(/^a$/i).test(el.tagName)) {
						elA.setAttribute('href', attr(el, nameLower));
						return elA.href;
					}
					return nameLower == 'value' ? attr(el, nameLower) : el[alias];
				}
				return null;
			}
		}

		// Setter

		if (typeof value == 'string' && typeof el[alias] == 'undefined' && alias == nameLower) {

			// Expando (implemented as a custom attribute)

			el.setAttribute(nameLower, value);
		} else {
			if (nameLower == 'value') {
				attr(el, 'value', value);
			} else if (numericAttributesBad && typeof el[alias] == 'number') {
				attr(el, nameLower, value + '');
			} else if (reUserBoolean.test(nameLower)) {
				if (value) {
					attr(el, nameLower, '');
				} else {
					removeAttr(el, nameLower);
				}
			} else {
				el[alias] = value;
			}
		}
	};
})();

html = doc = null;


})();
