// repeat a string
if (!String.repeat)  {
	String.prototype.repeat = function(l)  {
		return new Array (l + 1).join(this);
	}
}
// remove trailing and leading white spaces
if (!String.trim)  {
	String.prototype.trim = function()  {
		return this.replace(/^\s+|\s+$/g,'');
	}
}
// FTP namespace
(function()  {
if (!window['FTP'])  {
	window['FTP'] = {};
}
// convert word-word to wordWord
function camelize(s) {
    return s.replace(/-(\w)/g, function (strMatch, p1){
        return p1.toUpperCase();
    });
}
window['FTP']['camelize'] = camelize;
function walkElementsLinear(func, node)  {
	var root = node || window.document;
	var nodes = root.getelementsByTagName('*');
	for (var i = 0; i < nodes.length; i++)  {
		func.call(nodes[i]);
	}
}
function walkTheDOMRecursive(func, node, depth, returnedFromParent)  {
	var root = node || window.document;
	var returnedFromParent = func.call(root, depth++, returnedFromParent);
	var node = root.firstChild;
	while (node)  {
		walkTheDOMERecursive(func, root.childNode[i], depth, retrunedFromParent);
		node = node.nextSibling;
	}
};
function walkTheDOMWithAttributes(node, func, depth, returnedFromParent)  {
	var root = node || window.document;
	var returnedFromParent = func (root, depth++, prefix);
	if (root.attributes)  {
			for (var i = 0; i < root.attributes.length; i++)  {
				walkTheDOMWithAttributes(root.attributes[i], func, depth - 1, returnedFromParent);
			}
	}
	if (root.nodeType != Node.ATTRIBUTE_NODE)  {
		var node = root.firstChild;
		while (node)  {
			walkTheDOMWithAttributes (node, func, depth, returnedFromParent);
			node = node.nextSibling;
		}
	}
}
window['FTP']['node'] =  {
	ELEMENT_NODE : 1,
	ATTRIBUTE_NODE: 2,
	TEXT_NODE: 3,
	CDATA_SECTION_NODE: 4,
	ENTITY_REFERENCE_NODE: 5,
	ENTITY_NODE: 6,
	PROCESSING_INSTRUCTION_NODE: 7,
	COMMENT_NODE: 8,
	DOCUMENT_NODE: 9,
	DOCUMENT_TYPE_NODE: 10,
	DOCUMENT_FRAGMENT_NODE: 11,
	NOTATION_NODE: 12
};
function getBrowserWindowSize()  {
	var de = document.documentElement;
	return  {
		'width': (
			window.innerWidth
			|| (de && de.clientWidth)
			|| document.body.clientWidth),
		'height': (
			window.innerHeight
			|| (de && de.clientHeight)
			|| document.body.clientHeight)
	}
};
window['FTP']['getBrowserWindowSize'] = getBrowserWindowSize;
function bindFunction(obj, func)  {
	return function()  {
		func.apply(obj, arguments);
	};
};
window['FTP']['bindFunction'] = bindFunction;

function isCompatible(other) {
	// use capability detection to check requirements
	if (other == false
				|| !Array.push
				|| !Object.hasOwnProperty
				||!document.createElement
				|| !document.getElementsByTagName
				)  {
				return false;
	}
	return true;
}
window['FTP']['isCompatible'] = isCompatible;

function $()  {
	var elements = new Array();
	
	//find all the elements supplied as arguments
	for (var i = 0; i < arguments.length; i++)  {
		var element = arguments[i];
		
		// if the argument is a string assume it's an id
		if (typeof element == 'string')  {
			element = document.getElementById(element);
		}
		
		//if only one argument was supplied, return the element immediately
		if(arguments.length ==1)  {
			return element;
		}
		
		//otherwise add it to the array
		elements.push(element);
	}
	//return the array of multiple requested elements
	return elements;
};
window['FTP']['$'] = $;

function addEvent( node, type, listener ) {
    // Check compatibility using the earlier method
    // to ensure graceful degradation
    if(!isCompatible()) { return false }
    if(!(node = $(node))) return false;
    
    if (node.addEventListener) {
        // W3C method
        node.addEventListener( type, listener, false );
        return true;
    } else if(node.attachEvent) {
        // MSIE method
        node['e'+type+listener] = listener;
        node[type+listener] = function(){node['e'+type+listener]( window.event );}
        node.attachEvent( 'on'+type, node[type+listener] );
        return true;
    }
    
    // Didn't have either so return false
    return false;
};
window['FTP']['addEvent'] = addEvent;

function removeEvent(node, type, listener ) {
    if(!(node = $(node))) return false;
    if (node.removeEventListener) {
        node.removeEventListener( type, listener, false );
        return true;
    } else if (node.detachEvent) {
        // MSIE method
        node.detachEvent( 'on'+type, node[type+listener] );
        node[type+listener] = null;
        return true;
    }
    // Didn't have either so return false
    return false;
};
window['FTP']['removeEvent'] = removeEvent;

function getElementByClassName(className, tag, parent) {
	parent = parent || document;
	if (!(parent = $ (parent)))  { return false; }
	
	// locate all the matching tags
	var allTags = (tag == "*" && parent.all) ? parent.all : parent.getElementsByTagName(tag);
	var matchingElements = new Array();
	
	// create a regular expression to determine whehter the class name is correct
	className = className.replace(/\-/g, "\\-");
	var regex = new RegExp("(^|\\s)" + className + "(\\s|$)");
	
	var element;
	// check each element
	for (var i = 0; i < allTags.length; i++)  {
		element = allTags[i];
		if (regex.test(element.className))  {
			matchingElements.push(element);
		}
	}
	// return matching elements
	return matchingElements;
};
window['FTP']['getElementByClassName'] = getElementByClassName;

function toggleDisplay(node, value) {
	if (!(node = $(node)))  return false;
	if (node.style.display != 'none')  {
		node.display.style = 'none';
	}else  {
		node.style.display = value || '';
	}
	return true;
};
window['FTP']['toggleDisplay'] = toggleDisplay;

function insertAfter(node, referenceNode) {
	if (!(node = $(node))) return false;
	if (!(referenceNode = $(referenceNode))) return false;
	return referenceNode.parentNode.insertBefore(
		node, referenceNode, nextSibling
		);
};
window['FTP']['insertAfter'] = insertAfter;

function removeChildren(parent) {
	if (!(parent = $(parent)))  { return false };
	
	// while there is a child remove it
	while (parent.firstChild)  {
		parent.firstChild.parentNode.removeChild(parent.firstChild);
	}
	// return the parent again so you can chain the methods
	return parent;
};
window['FTP']['removeChildren'] = removeChildren;

function prependChild(parent, newChild) {
	if (!(parent = $(parent))) return false;
	if (!(newChild = $(newChild))) return false;
	
	if (parent.firstChild)  {
		//there is alreqady a child so insert before the first one
		parent.insertBefore(newChild.parent.firstChild);
	} else  {
		//no children so append
		parent.appendChild(newChild);
	}
	// return the parent again so you can chain the methods
	return parent;
}
window['FTP']['prependChild'] = prependChild;

})();
