(function() {
    var singleFile = (typeof ML == "object" && ML.singleFile);
    var scriptLocation;
    window.ML = {a:'aaa',
        _scriptName: (!singleFile) ? "firefly.js" : "firefly.js",
        _getScriptLocation: function () {
            if (scriptLocation != undefined) {
                return scriptLocation;
            }
            scriptLocation = "";            
            var isOL = new RegExp("(^|(.*?\\/))(" + ML._scriptName + ")(\\?|$)");
         
            var scripts = document.getElementsByTagName('script');
            for (var i=0, len=scripts.length; i<len; i++) {
                var src = scripts[i].getAttribute('src');
                if (src) {
                    var match = src.match(isOL);
                    if(match) {
                        scriptLocation = match[1];
                        break;
                    }
                }
            }
            return scriptLocation;
        }
    };
    if (!singleFile) {
        var jsfiles = new Array(
            "firefly.Url.js",
            "firefly.String.js"
        ); // etc.

        var agent = navigator.userAgent;
        var docWrite = (agent.match("MSIE") || agent.match("Safari"));
        if (docWrite) {
            var allScriptTags = new Array(jsfiles.length);
        }
        var host = ML._getScriptLocation();    
        for (var i = 0, len = jsfiles.length; i < len; i++) {
            if (docWrite) {
                allScriptTags[i] = "<script src='" + host + jsfiles[i] + "'></script>"; 
            } else {
                var s = document.createElement("script");
                s.src = host + jsfiles[i];
                var h = document.getElementsByTagName("head").length ? 
                           document.getElementsByTagName("head")[0] : 
                           document.body;
                h.appendChild(s);
            }
        }
        if (docWrite) {
            document.write(allScriptTags.join(""));
        }
    }
})();

ML.VERSION_NUMBER="$Revision: 1 $";

var url = function(qs) {
	Firefly('Url.setParam')(qs);
}

function Firefly(name) {
	var self = arguments.callee;
	var a = name.split('.');
	var head = document.getElementsByTagName('head')[0];
	
	var func = self;
	var context = context || './';
	var c = context + 'js/firefly';
	for (var i = 0, b; b = a[i]; i++)
	{
		c += '.' + b;
		if ('undefined' == typeof func[b])
		{
			var ajax = self.Ajax()
			ajax.onreadystatechange = function()
			{
				if (ajax.readyState == 4 && ajax.status == 200)
				{//alert(ajax.responseText)
					eval(ajax.responseText);
				}
			};

			//ajax.open('GET', 'http://www.firefly.bj.cn/firefly.php?action=Firefly:Proxy&url=' + c + '.js', false)
			ajax.open('GET', c + '.js', false)
			ajax.send(null); // null is for firefox
			
			if ('undefined' == typeof func[b])
			{
				throw Error('Could not load ' + c + '.js');
			}
		}

		func = func[b];
	}
	
	return func;
}

ML.$ = function(id) {
	return typeof id == 'string' ? document.getElementById(id) : id;
}

/**
 * 浏览器信息
 * Firefox 举例
appName:		Netscape
appVersion:		5.0 (Windows; zh-CN)
userAgent:		Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9.2.10) Gecko/20100914 Firefox/3.6.10
appCodeName:	Mozilla
platform:		Win32
 *
 * IE6 举例, znwb 居然都有了
appName:		Microsoft Internet Explorer
appVersion:		4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; znwb6500)
userAgent:		Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; znwb6500)
appCodeName:	Mozilla
platform:		Win32
 *
 * Chrome 举例
appName:		Netscape
appVersion:		5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/534.3 (KHTML, like Gecko) Chrome/6.0.472.59 Safari/534.3
userAgent:		Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/534.3 (KHTML, like Gecko) Chrome/6.0.472.59 Safari/534.3
appCodeName:	Mozilla
platform:		Win32
 *
 * Opera 举例，从菜单"关于Opera"中看到的版本不是9.80，而是10.62
appName:		Opera
appVersion:		9.80 (Windows NT 5.1; U; zh-cn)
userAgent:		Opera/9.80 (Windows NT 5.1; U; zh-cn) Presto/2.6.30 Version/10.62
appCodeName:	Mozilla
platform:		Win32
 *
 * Safari 举例
appName:		Netscape
appVersion:		5.0 (Windows; U; Windows NT 5.1; zh-CN) AppleWebKit/533.18.1 (KHTML, like Gecko) Version/5.0.2 Safari/533.18.5
userAgent:		Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN) AppleWebKit/533.18.1 (KHTML, like Gecko) Version/5.0.2 Safari/533.18.5
appCodeName:	Mozilla
platform:		Win32
 */
ML.browser = (function( ua ) {
	ua = ua.toLowerCase();
	
	var match = /(firefox)\/((\d+\.?)+)/.exec(ua) ||
		/(chrome)\/((\d+\.?)+)/.exec(ua) ||
		/(?:.*version)?[ \/]([\w.]+) (safari)/.exec(ua) ||
		/(webkit)[ \/]([\w.]+)/.exec( ua ) ||
		/(opera)(?:.*version)?[ \/]([\w.]+)/.exec(ua) ||
		/(msie) ([\w.]+)/.exec( ua ) ||
		!/compatible/.test( ua ) && /(mozilla)(?:.*? rv:([\w.]+))?/.exec( ua ) ||
	  	[];
	
	return match[2] == 'safari'
		? { name: match[2] || "", version: match[1] || "0" }
		: { name: match[1] || "", version: match[2] || "0" };
})(navigator.userAgent);

ML.navigatorInfo = function() {
	var msg = "浏览器信息如下\n";
	msg += "appName:\t\t" + navigator["appName"] + "\n";
	msg += "appVersion:\t\t" + navigator["appVersion"] + "\n";
	msg += "userAgent:\t\t" + navigator["userAgent"] + "\n";
	msg += "appCodeName:\t" + navigator["appCodeName"] + "\n";
	msg += "platform:\t\t" + navigator["platform"] + "\n";
	
	//window.open();
	//window.open().document.write(msg);
//	window.onload = function() {alert('x')
//		document.body.innerHTML = '<pre>' + msg + '</pre>';
//	}
	alert(msg);
}
//ML.navigatorInfo()

ML.Ajax = Firefly.Ajax = function() {
	var ajax = null;
	
	if (typeof XMLHttpRequest != "undefined") {
		ajax = new XMLHttpRequest();
	} else {
		if (typeof ActiveXObject != "undefined") {
			if (ML.Ajax.XMLHTTP) {
				ajax = new ActiveXObject(xmlhttps[i]);
			} else {
				var xmlhttps = ["MSXML2.XMLHTTP.6.0", "MSXML2.XMLHTTP.3.0", "MSXML2.XMLHTTP", "Microsoft.XMLHTTP"];
				for (var i = 0; i < xmlhttps.length; i++) {
					try {
						ajax = new ActiveXObject(xmlhttps[i]);
						ML.Ajax.XMLHTTP = xmlhttps[i];
						break;
					} catch(e) {}
				}
				if (!ajax) {
					throw Error("Could not create ActiveXObject. MSXML might not be installed");
				}
			}
		} else {
			throw Error("Could not create ActiveXObject. ActiveX might be disabled");
		}
	}
	
	ajax.onreadystatechange = function() {
		ML.Ajax.onreadystatechange(ajax);
	}
	
	return ajax;
}

ML.Ajax.XMLHTTP = Firefly.Ajax.XMLHTTP = null;

ML.Ajax.onreadystatechange = function(ajax) {
	if (ajax.readyState == 4 && ajax.status == 200 && ajax.onready) {
		try {
			var json = eval('(' + ajax.responseText + ')');
		} catch (e) {
			alert(e + '\n\n' + ajax.responseText);
			return
		}
		
		ajax.onready(json);
	}
}

//setRequestHeader("Content-Type","application/x-www-form-urlencoded");  

/**
 * 方便查看变量内容的函数
 */
function pre(v, depth, level) {
	var silent = level === true || depth === true;
	
	(typeof depth == 'number') || (depth = 5);
	level || (level = 0);
	level++;
	
	var str = '';
	var pad = (new Array(level + 1)).join('    ');
	
	try {
		var t = typeof v;
		// note: typeof null = object
		if (v == null) {
			str += '[null]\n';
		} else if (t == 'number') {
			str += '[number]: ' + v + '\n';
		} else if (t == 'string') {
			str += '[string]: ' + v + '\n';
		} else if (t == 'boolean') {
			str += '[boolean]: ' + v + '\n';
		} else if (t == 'function') {
			str += '[function]: ' + v + '\n';
		} else if (t == 'object') {
			// if it is HTML element
			if (v.nodeType) {
				var tmp = '';
				var keys = [];//['tagName', 'id', 'className', 'href'];
				for (var i = 0, len = keys.length; i < len; i++) {
					var key = keys[i];
					if (typeof v[key] == 'undefined' || v[key] === '') {
						continue;
					} else if (typeof v[key] != 'object') {
						tmp += pad + key + ' => ' + v[key] + '\n';
					} else {
						tmp += pad + key + ' => ' + (level >= depth ? '...' + '\n' : arguments.callee(v[key], depth, level));
					}
				}
				
				str += '[object] ' + v.constructor + ' nodeType:' + v.nodeType + '\n' + tmp + '\n';
			} else {
				var cnt = 0;
				var tmp = '';
				for (var key in v) {
					if (typeof v[key] == 'function') continue;
					//if (key != 'text' && key != 'name' && key != 'children' && !key.match(/\d+/)) {
					//	continue
					//}
					cnt++
					if (typeof v[key] != 'object') {
						tmp += pad + key + ' => ' + v[key] + '\n';
					} else {
						tmp += pad + key + ' => ' + (level >= depth ? '...' + '\n' : arguments.callee(v[key], depth, level));
					}
					//if (cnt > 10) break;
				}
				
				if (v.constructor) {
					var constructor = v.constructor.toString();
					if (constructor.indexOf('\n') != -1) {
						constructor = constructor.substr(0, constructor.indexOf('\n'));
					}
				} else {
					constructor = 'none';
				}
				str += cnt ? '[object] constructor:' + constructor + '\n' + tmp + '\n' : '{}\n';
			}
		} else {
			str += '[' + t + ']\n';
//		} else if (v.length && !(v instanceof Firefly.Collection)) {
//			str += '[' + typeof v + ':' + typeof v.constructor + ':length:' + v.length + ']\n';
//			var key, val;
//			for (var i = 0, len = v.length; i < len; i++) {
//				if (v instanceof Firefly.Collection) {
//					key = i + ': ' + v.keyAt(i)
//					val = v.valueAt(i)
//				} else if (typeof v.constructor == 'function') {
//					key = i
//					val = v[i]
//				} else {
//					try {
//						key = v.item(i).tagName
//						val = v.item(i).childNodes(0) && v.item(i).childNodes(0).tagName ? v.item(i).childNodes : v.item(i).text
//					} catch (e) {
//						throw e
//					}
//				}
//				if ((typeof val) == 'function') continue;
//				
//				if (config.level > config.depth) {
//					str += pad + key + ' => ' + '...' + '\n';
//				} else {
//					str += pad + key + ' => ' + arguments.callee(val, config);
//					str += typeof val == 'object' ? '\n' : '';
//				}
//			}
//			str += '\n'
		}
	} catch (e) {
		str += t + ':' + typeof v.constructor + ', error: ' + e.message
	}
	
	if (--level == 0 && silent == false) alert(str)
	return str;
}

ML.createRecords = function(rows) {
	var fields	= rows.shift();
	if (fields == null) {
		return rows;
	}
	var num		= fields.length;
	var len		= rows.length;
	var key		= '';
	
	for (var j = 0; j < num; j++) {
		if (fields[j] == 'id') key = 'id';
	}
	
	var records = key == 'id' ? {} : [];
	for (var i = 0; i < len; i++) {
		var row = rows[i], record = {};
		for (var j = 0; j < num; j++) {
			record[fields[j]] = row[j];
		}
		records[key == 'id' ? record[key] : i] = record;
	}
	
	return records;
}

ML.getSize = function(el) {
	if (!el || el.navigator) {// window
		var win = el || window;
		return {
			width: win.innerWidth	// Firefox, Opera
				|| win.document.documentElement.offsetWidth,	// IE6
			height: win.innerHeight
				|| win.document.documentElement.offsetHeight
		}
	} else {
		return {width: el.offsetWidth, height: el.offsetHeight};
	}
}
ML.getClientSize = function(el) {
	if (!el || el.navigator) {// window
		var win = el || window;
		return {
			width: win.document.html.clientWidth,
			height: win.document.html.clientHeight
		}
	} else {
		return {
			width: el.tagName == 'HTML'
				? el.offsetWidth - parseInt(el.style.borderLeftWidth) - parseInt(el.style.borderRightWidth)	// Firefox, Opera
				: el.clientWidth,	// IE6
			height: el.tagName == 'HTML'
				? el.offsetHeight - parseInt(el.style.borderTopWidth) - parseInt(el.style.borderBottomWidth)	// Firefox, Opera
				: el.clientHeight	// IE6
		}
	}
}
ML.getOffset = function(el) {
	if (el.getBoundingClientRect) {
		var bound	= el.getBoundingClientRect();
		var html	= document.documentElement;
		
		return {
			left: Math.round(bound.left) - html.clientLeft,
			top: Math.round(bound.top)  - html.clientTop
		};
	} else {
		throw Error('getBoundingClientRect is not supported')
	}
}
ML.getPosition = function(el) {
	if (el.getBoundingClientRect) {
		var bound	= ML.getOffset(el);
		var scrolls	= ML.getScrolls(el);
		
		return {
			x: bound.left + scrolls.x,
			y: bound.top  + scrolls.y
		};
	} else {
		throw Error('getBoundingClientRect is not supported')
	}
}
ML.getScroll = function(el) {
	return {
		x: el.scrollLeft,
		y: el.scrollTop
	}
}
ML.getScrolls = function(el) {
	var position = {x: 0, y: 0};
	while (el.nodeType == 1) {// Element
		position.x += el.scrollLeft;
		position.y += el.scrollTop;
		el = el.parentNode;
	}
	return position;
}

ML.contains = function(haystack, needle, separator){
	return separator ? (separator + haystack + separator).indexOf(separator + needle + separator) > -1 : haystack.indexOf(needle) > -1;
}
ML.camelCase = function(string) {
	return string.replace(/-\D/g, function(match) {
		return match.charAt(1).toUpperCase();
	});
}

ML.hasClass = function(el, className) {
	return this.contains(el.className, className, ' ');
}
ML.addClass = function(el, className){
	if (!this.hasClass(el, className)) {
		el.className = el.className + ' ' + className;
	}
}
ML.removeClass = function(el, className) {
	el.className = el.className.replace(new RegExp('(^|\\s)' + className + '(?:\\s|$)'), '$1');
}
ML.toggleClass = function(el, className){
	this.hasClass(el, className) ? this.removeClass(el, className) : this.addClass(el, className);
}


ML.click = function(el) {
	if (el.click) {
		el.click();
	} else {
		var evt = document.createEvent("MouseEvents");
		evt.initEvent("click", true, true);
		el.dispatchEvent(evt);
	}
}
ML.eventElement = function(e) {
	e = e || window.event;
	return e.target || e.fromElement;
}

ML.radioValue = function(elements) {
	if (typeof elements == 'string') {
		elements = document.getElementsByName(elements);
	}
	
	for (var i = 0, len = elements.length; i < len; i++) {
		if (elements[i].checked) {
			return elements[i].value;
		}
	}
}
ML.checkboxValues = function(elements) {
	if (typeof elements == 'string') {
		elements = document.getElementsByName(elements);
	}
	
	var values = [];
	for (var i = 0, len = elements.length; i < len; i++) {
		if (elements[i].checked) {
			values.push(elements[i].value);
		}
	}
	
	return values;
}

ML.disabledOptionNotWork = function() {
	var browser = ML.browser.name + ML.browser.version;
	return browser == "msie5.5" || browser == "msie6.0" || browser == "msie7.0" || browser == "msie8.0";
}
ML.fixDisabledOption = function(select) {
	select = ML.$(select);
	if (!ML.disabledOptionNotWork() || typeof select._selectedIndex != 'undefined') {
		return;
	}
	
	ML.observe(select, 'focus', function() {
		select._selectedIndex = select.selectedIndex;
	});
	ML.observe(select, 'change', function() {
		if (select.options[select.selectedIndex]._disabled) {
			select.selectedIndex = select._selectedIndex;
			if (select._selectedIndex != -1 && !select.options[select._selectedIndex]._disabled) {
				ML.fireEvent(select, 'onchange');
			}
		} else {
			select._selectedIndex = select.selectedIndex;
		}
	});
}
ML.disableOption = function(option, select) {
	if (this.disabledOptionNotWork()) {
		option._disabled = true;
		option.style.color = 'graytext';
	} else {
		option.disabled = true;
	}
}
ML.enableOption = function(option) {
	if (this.disabledOptionNotWork()) {
		option._disabled = false;
		option.style.color = 'menutext';
	} else {
		option.disabled = false;
	}
}

ML.observe = function(el, name, observer, useCapture) {
	el			= ML.$(el);
    useCapture	= useCapture || false;

    if (name == 'keypress' && (navigator.appVersion.match(/Konqueror|Safari|KHTML/) || el.attachEvent)) {
        name = 'keydown';
    }
    
    //add the actual browser event listener
    if (el.addEventListener) {
        el.addEventListener(name, observer, useCapture);
    } else if (el.attachEvent) {
        el.attachEvent('on' + name, observer);
    }
}
ML.fireEvent = function(el, eventName) {
	if (el.fireEvent) {
		el.fireEvent(eventName);  
	} else {
		var evt = document.createEvent('HTMLEvents');
		evt.initEvent(eventName, true, true);
		el.dispatchEvent(evt);
	}
}

ML.copyToClipboard = function(txt) {
	if (window.clipboardData) {
		window.clipboardData.clearData();
		window.clipboardData.setData("Text", txt);
	} else if(navigator.userAgent.indexOf("Opera") != -1) {
		window.location = txt;
	} else if (window.netscape) {
		try {
			netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
		} catch (e) {
			alert("Copy operation is refused by web browser, please try Ctrl+C instead")
			//alert("\n请在浏览器地址栏输入'about:config'并回车\n然后将'signed.applets.codebase_principal_support'设置为'true'");
			return
		}
		var clip = Components.classes['@mozilla.org/widget/clipboard;1'].createInstance(Components.interfaces.nsIClipboard);
		if (!clip) {
			return;
		}
		var trans = Components.classes['@mozilla.org/widget/transferable;1'].createInstance(Components.interfaces.nsITransferable);
		if (!trans) {
			return;
		}
  		trans.addDataFlavor('text/unicode');
		var str = new Object();
		var len = new Object();
		var str = Components.classes["@mozilla.org/supports-string;1"].createInstance(Components.interfaces.nsISupportsString);
		var copytext = txt;
		str.data = copytext;
		trans.setTransferData("text/unicode", str, copytext.length * 2);
		var clipid = Components.interfaces.nsIClipboard;
		if (!clip) {
			return false;
		}
		clip.setData(trans, null, clipid.kGlobalClipboard);
		alert("Copy success: " + txt)
	} else {// chrome
		alert("Copy operation is not supported by Chrome, please try Ctrl+C instead")
	}
}
