(function() {

	var Ext = {};
	
	Ext.fly = function (element) {
		return {
			getStyle : function (style) {
				return window.getComputedStyle (element, null).getPropertyValue (style);
			}
		};
	}
	
	/*
	 * Ext - JS Library 1.0 Alpha 3 - Rev 4
	 * Copyright(c) 2006-2007, Jack Slocum.
	 * 
	 * http://www.extjs.com/license.txt
	 */
	
	/*
	 * This is code is also distributed under MIT license for use
	 * with jQuery and prototype JavaScript libraries.
	 */
	/**
	 * @class Ext.DomQuery
	 * Provides high performance selector/xpath processing by compiling queries into reusable functions.
	 * New pseudo classes and matchers can be plugged. It works on HTML and XML documents (if a content node is passed in).
	 * @singleton
	 */
	Ext.DomQuery = function(){
	    var cache = {}, simpleCache = {}, valueCache = {};
	    var nonSpace = /\S/;
	    var trimRe = /^\s*(.*?)\s*$/;
	    var tplRe = /\{(\d+)\}/g;
	    var modeRe = /^(\s?[\/>]\s?|\s|$)/;
	    var tagTokenRe = /^(#)?([\w-\*]+)/;
	    
	    function child(p, index){
	        var i = 0;
	        var n = p.firstChild;
	        while(n){
	            if(n.nodeType == 1){
	               if(++i == index){
	                   return n;
	               }
	            }
	            n = n.nextSibling;
	        }
	        return null;
	    };
	    
	    function next(n){
	        while((n = n.nextSibling) && n.nodeType != 1);
	        return n;
	    };
	    
	    function prev(n){
	        while((n = n.previousSibling) && n.nodeType != 1);
	        return n;
	    };
	    
	    function clean(d){
	        var n = d.firstChild, ni = -1;
	 	    while(n){
	 	        var nx = n.nextSibling;
	 	        if(n.nodeType == 3 && !nonSpace.test(n.nodeValue)){
	 	            d.removeChild(n);
	 	        }else{
	 	            n.nodeIndex = ++ni;
	 	        }
	 	        n = nx;
	 	    }
	 	    return this;
	 	};
	
	    function byClassName(c, a, v, re, cn){
	        if(!v){
	            return c;
	        }
	        var r = [];
	        for(var i = 0, ci; ci = c[i]; i++){
	            cn = ci.className;
	            if(cn && (' '+cn+' ').indexOf(v) != -1){
	                r[r.length] = ci;
	            }
	        }
	        return r;
	    };
	
	    function attrValue(n, attr){
	        if(!n.tagName && typeof n.length != "undefined"){
	            n = n[0];
	        }
	        if(!n){
	            return null;
	        }
	        if(attr == "for"){
	            return n.htmlFor;
	        }
	        if(attr == "class" || attr == "className"){
	            return n.className;
	        }
	        return n.getAttribute(attr) || n[attr];
	          
	    };
	    
	    function getNodes(ns, mode, tagName){
	        var result = [], cs;
	        if(!ns){
	            return result;
	        }
	        mode = mode ? mode.replace(trimRe, "$1") : "";
	        tagName = tagName || "*";
	        if(typeof ns.getElementsByTagName != "undefined"){
	            ns = [ns];   
	        }
	        if(mode != "/" && mode != ">"){
	            for(var i = 0, ni; ni = ns[i]; i++){
	                cs = ni.getElementsByTagName(tagName);
	                for(var j = 0, ci; ci = cs[j]; j++){
	                    result[result.length] = ci;
	                }
	            }
	        }else{
	            for(var i = 0, ni; ni = ns[i]; i++){
	                var cn = ni.getElementsByTagName(tagName);
	                for(var j = 0, cj; cj = cn[j]; j++){
	                    if(cj.parentNode == ni){
	                        result[result.length] = cj;
	                    }
	                }
	            }
	        }
	        return result;
	    };
	    
	    function concat(a, b){
	        if(b.slice){
	            return a.concat(b);
	        }
	        for(var i = 0, l = b.length; i < l; i++){
	            a[a.length] = b[i];
	        }
	        return a;
	    }
	    
	    function byTag(cs, tagName){
	        if(cs.tagName || cs == document){
	            cs = [cs];
	        }
	        if(!tagName){
	            return cs;
	        }
	        var r = []; tagName = tagName.toLowerCase();
	        for(var i = 0, ci; ci = cs[i]; i++){
	            if(ci.nodeType == 1 && ci.tagName.toLowerCase()==tagName){
	                r[r.length] = ci;
	            }
	        }
	        return r; 
	    };
	    
	    function byId(cs, attr, id){
	        if(cs.tagName || cs == document){
	            cs = [cs];
	        }
	        if(!id){
	            return cs;
	        }
	        var r = [];
	        for(var i = 0,ci; ci = cs[i]; i++){
	            if(ci && ci.id == id){
	                r[r.length] = ci;
	                return r;
	            }
	        }
	        return r; 
	    };
	    
	    function byAttribute(cs, attr, value, op, custom){
	        var r = [], st = custom=="{";
	        var f = Ext.DomQuery.operators[op];
	        for(var i = 0; ci = cs[i]; i++){
	            var a;
	            if(st){
	                a = Ext.DomQuery.getStyle(ci, attr);
	            }
	            else if(attr == "class" || attr == "className"){
	                a = ci.className;
	            }else if(attr == "for"){
	                a = ci.htmlFor;
	            }else if(attr == "href"){
	                a = ci.getAttribute("href", 2);
	            }else{
	                a = ci.getAttribute(attr);
	            }
	            if((f && f(a, value)) || (!f && a)){
	                r[r.length] = ci;
	            }
	        }
	        return r;
	    };
	    
	    function byPseudo(cs, name, value){
	        return Ext.DomQuery.pseudos[name](cs, value);
	    };
	    
	    // This is for IE MSXML which does not support expandos.
	    // IE runs the same speed using setAttribute, however FF slows way down
	    // and Safari completely fails so they need to continue to use expandos.
	    var isIE = window.ActiveXObject ? true : false;
	
	    var key = 30803;
	
	    function nodupIEXml(cs){
	        var d = ++key;
	        cs[0].setAttribute("_nodup", d);
	        var r = [cs[0]];
	        for(var i = 1, len = cs.length; i < len; i++){
	            var c = cs[i];
	            if(!c.getAttribute("_nodup") != d){
	                c.setAttribute("_nodup", d);
	                r[r.length] = c;
	            }
	        }
	        for(var i = 0, len = cs.length; i < len; i++){
	            cs[i].removeAttribute("_nodup");
	        }
	        return r;
	    }
	
	    function nodup(cs){
	        var len = cs.length, c, i, r = cs, cj;
	        if(!len || typeof cs.nodeType != "undefined" || len == 1){
	            return cs;
	        }
	        if(isIE && typeof cs[0].selectSingleNode != "undefined"){
	            return nodupIEXml(cs);
	        }
	        var d = ++key;
	        cs[0]._nodup = d;
	        for(i = 1; c = cs[i]; i++){
	            if(c._nodup != d){
	                c._nodup = d;
	            }else{
	                r = [];
	                for(var j = 0; j < i; j++){
	                    r[r.length] = cs[j];
	                }
	                for(j = i+1; cj = cs[j]; j++){
	                    if(cj._nodup != d){
	                        cj._nodup = d;
	                        r[r.length] = cj;
	                    }
	                }
	                return r;
	            }
	        }
	        return r;
	    }
	
	    function quickDiffIEXml(c1, c2){
	        var d = ++key;
	        for(var i = 0, len = c1.length; i < len; i++){
	            c1[i].setAttribute("_qdiff", d);
	        }
	        var r = [];
	        for(var i = 0, len = c2.length; i < len; i++){
	            if(c2[i].getAttribute("_qdiff") != d){
	                r[r.length] = c2[i];
	            }
	        }
	        for(var i = 0, len = c1.length; i < len; i++){
	           c1[i].removeAttribute("_qdiff");
	        }
	        return r;
	    }
	
	    function quickDiff(c1, c2){
	        var len1 = c1.length;
	        if(!len1){
	            return c2;
	        }
	        if(isIE && c1[0].selectSingleNode){
	            return quickDiffIEXml(c1, c2);
	        }
	        var d = ++key;
	        for(var i = 0; i < len1; i++){
	            c1[i]._qdiff = d;
	        }
	        var r = [];
	        for(var i = 0, len = c2.length; i < len; i++){
	            if(c2[i]._qdiff != d){
	                r[r.length] = c2[i];
	            }
	        }
	        return r;
	    }
	    
	    function quickId(ns, mode, root, id){
	        if(ns == root){
	           var d = root.ownerDocument || root;
	           return d.getElementById(id);
	        }
	        ns = getNodes(ns, mode, "*");
	        return byId(ns, null, id);
	    }
	    
	    return {
	        getStyle : function(el, name){
	            return Ext.fly(el).getStyle(name);
	        },
	        /**
	         * Compiles a selector/xpath query into a reusable function. The returned function
	         * takes one parameter "root" (optional), which is the context node from where the query should start. 
	         * @param {String} selector The selector/xpath query
	         * @param {String} type (optional) Either "select" (the default) or "simple" for a simple selector match
	         * @return {Function}
	         */
	        compile : function(path, type){
	            // strip leading slashes
	            while(path.substr(0, 1)=="/"){
	                path = path.substr(1);
	            }
	            type = type || "select";
	            
	            var fn = ["var f = function(root){\n var mode; var n = root || document;\n"];
	            var q = path, mode, lq;
	            var tk = Ext.DomQuery.matchers;
	            var tklen = tk.length;
	            var mm;
	            while(q && lq != q){
	                lq = q;
	                var tm = q.match(tagTokenRe);
	                if(type == "select"){
	                    if(tm){
	                        if(tm[1] == "#"){
	                            fn[fn.length] = 'n = quickId(n, mode, root, "'+tm[2]+'");';
	                        }else{
	                            fn[fn.length] = 'n = getNodes(n, mode, "'+tm[2]+'");';
	                        }
	                        q = q.replace(tm[0], "");
	                    }else if(q.substr(0, 1) != '@'){
	                        fn[fn.length] = 'n = getNodes(n, mode, "*");';
	                    }
	                }else{
	                    if(tm){
	                        if(tm[1] == "#"){
	                            fn[fn.length] = 'n = byId(n, null, "'+tm[2]+'");';
	                        }else{
	                            fn[fn.length] = 'n = byTag(n, "'+tm[2]+'");';
	                        }
	                        q = q.replace(tm[0], "");
	                    }
	                }
	                while(!(mm = q.match(modeRe))){
	                    var matched = false;
	                    for(var j = 0; j < tklen; j++){
	                        var t = tk[j];
	                        var m = q.match(t.re);
	                        if(m){
	                            fn[fn.length] = t.select.replace(tplRe, function(x, i){
	                                                    return m[i];
	                                                });
	                            q = q.replace(m[0], "");
	                            matched = true;
	                            break;
	                        }
	                    }
	                    // prevent infinite loop on bad selector
	                    if(!matched){
	                        throw 'Error parsing selector, parsing failed at "' + q + '"';
	                    }
	                }
	                if(mm[1]){
	                    fn[fn.length] = 'mode="'+mm[1]+'";';
	                    q = q.replace(mm[1], "");
	                }
	            }
	            fn[fn.length] = "return nodup(n);\n}";
	            eval(fn.join(""));
	            return f;
	        },
	        
	        /**
	         * Selects a group of elements.
	         * @param {String} selector The selector/xpath query
	         * @param {Node} root (optional) The start of the query (defaults to document).
	         * @return {Array}
	         */
	        select : function(path, root, type){
	            if(!root || root == document){
	                root = document;
	            }
	            if(typeof root == "string"){
	                root = document.getElementById(root);
	            }
	            var paths = path.split(",");
	            var results = [];
	            for(var i = 0, len = paths.length; i < len; i++){
	                var p = paths[i].replace(trimRe, "$1");
	                if(!cache[p]){
	                    cache[p] = Ext.DomQuery.compile(p);
	                    if(!cache[p]){
	                        throw p + " is not a valid selector";
	                    }
	                }
	                var result = cache[p](root);
	                if(result && result != document){
	                    results = results.concat(result);
	                }
	            }
	            return results;
	        },
	        
	        /**
	         * Selects a single element.
	         * @param {String} selector The selector/xpath query
	         * @param {Node} root (optional) The start of the query (defaults to document).
	         * @return {Element}
	         */
	        selectNode : function(path, root){
	            return Ext.DomQuery.select(path, root)[0];
	        },
	        
	        /**
	         * Selects the value of a node, optionally replacing null with the defaultValue.
	         * @param {String} selector The selector/xpath query
	         * @param {Node} root (optional) The start of the query (defaults to document).
	         * @param {String} defaultValue
	         */
	        selectValue : function(path, root, defaultValue){
	            path = path.replace(trimRe, "$1");
	            if(!valueCache[path]){
	                valueCache[path] = Ext.DomQuery.compile(path, "select");
	            }
	            var n = valueCache[path](root);
	            n = n[0] ? n[0] : n;
	            var v = (n && n.firstChild ? n.firstChild.nodeValue : null);
	            return (v === null ? defaultValue : v);
	        },
	        
	        /**
	         * Selects the value of a node, parsing integers and floats.
	         * @param {String} selector The selector/xpath query
	         * @param {Node} root (optional) The start of the query (defaults to document).
	         * @param {Number} defaultValue
	         * @return {Number}
	         */
	        selectNumber : function(path, root, defaultValue){
	            var v = Ext.DomQuery.selectValue(path, root, defaultValue || 0);
	            return parseFloat(v);
	        },
	        
	        /**
	         * Returns true if the passed element(s) match the passed simple selector (e.g. div.some-class or span:first-child)
	         * @param {String/HTMLElement/Array} el An element id, element or array of elements
	         * @param {String} selector The simple selector to test
	         * @return {Boolean}
	         */
	        is : function(el, ss){
	            if(typeof el == "string"){
	                el = document.getElementById(el);
	            }
	            var isArray = (el instanceof Array);
	            var result = Ext.DomQuery.filter(isArray ? el : [el], ss);
	            return isArray ? (result.length == el.length) : (result.length > 0);
	        },
	        
	        /**
	         * Filters an array of elements to only include matches of a simple selector (e.g. div.some-class or span:first-child)
	         * @param {Array} el An array of elements to filter
	         * @param {String} selector The simple selector to test
	         * @param {Boolean} nonMatches If true, it returns the elements that DON'T match 
	         * the selector instead of the ones that match
	         * @return {Array}
	         */
	        filter : function(els, ss, nonMatches){
	            ss = ss.replace(trimRe, "$1");
	            if(!simpleCache[ss]){
	                simpleCache[ss] = Ext.DomQuery.compile(ss, "simple");
	            }
	            var result = simpleCache[ss](els);
	            return nonMatches ? quickDiff(result, els) : result;
	        },
	        
	        /**
	         * Collection of matching regular expressions and code snippets. 
	         */
	        matchers : [{
	                re: /^\.([\w-]+)/,
	                select: 'n = byClassName(n, null, " {1} ");'
	            }, {
	                re: /^\:([\w-]+)(?:\(((?:[^\s>\/]*|.*?))\))?/,
	                select: 'n = byPseudo(n, "{1}", "{2}");'
	            },{
	                re: /^(?:([\[\{])(?:@)?([\w-]+)\s?(?:(=|.=)\s?['"]?(.*?)["']?)?[\]\}])/,
	                select: 'n = byAttribute(n, "{2}", "{4}", "{3}", "{1}");'
	            }, {
	                re: /^#([\w-]+)/,
	                select: 'n = byId(n, null, "{1}");'
	            },{
	                re: /^@([\w-]+)/,
	                select: 'return {firstChild:{nodeValue:attrValue(n, "{1}")}};'
	            }
	        ],
	        
	        /**
	         * Collection of operator comparison functions. The default operators are =, !=, ^=, $=, *= and %=.
	         * New operators can be added as long as the match the format <i>c</i>= where <i>c<i> is any character other than space, &gt; &lt;.
	         */
	        operators : {
	            "=" : function(a, v){
	                return a == v;
	            },
	            "!=" : function(a, v){
	                return a != v;
	            },
	            "^=" : function(a, v){
	                return a && a.substr(0, v.length) == v;
	            },
	            "$=" : function(a, v){
	                return a && a.substr(a.length-v.length) == v;
	            },
	            "*=" : function(a, v){
	                return a && a.indexOf(v) !== -1;
	            },
	            "%=" : function(a, v){
	                return (a % v) == 0;
	            }
	        },
	        
	        /**
	         * Collection of "pseudo class" processors. Each processor is passed the current nodeset (array)
	         * and the argument (if any) supplied in the selector.
	         */
	        pseudos : {
	            "first-child" : function(c){
	                var r = [], n;
	                for(var i = 0, ci; ci = n = c[i]; i++){
	                    while((n = n.previousSibling) && n.nodeType != 1);
	                    if(!n){
	                        r[r.length] = ci;
	                    }
	                }
	                return r;
	            },
	            
	            "last-child" : function(c){
	                var r = [];
	                for(var i = 0, ci; ci = n = c[i]; i++){
	                    while((n = n.nextSibling) && n.nodeType != 1);
	                    if(!n){
	                        r[r.length] = ci;
	                    }
	                }
	                return r;
	            },
	            
	            "nth-child" : function(c, a){
	                var r = [];
	                if(a != "odd" && a != "even"){
	                    for(var i = 0, ci; ci = c[i]; i++){
	                        var m = child(ci.parentNode, a);
	                        if(m == ci){
	                            r[r.length] = m;
	                        }
	                    }
	                    return r;
	                }
	                var p;
	                // first let's clean up the parent nodes
	                for(var i = 0, l = c.length; i < l; i++){
	                    var cp = c[i].parentNode;
	                    if(cp != p){
	                        clean(cp);
	                        p = cp;
	                    }
	                }
	                // then lets see if we match
	                for(var i = 0, ci; ci = c[i]; i++){
	                    var m = false;
	                    if(a == "odd"){
	                        m = ((ci.nodeIndex+1) % 2 == 1);
	                    }else if(a == "even"){
	                        m = ((ci.nodeIndex+1) % 2 == 0);
	                    }
	                    if(m){
	                        r[r.length] = ci;
	                    }
	                }
	                return r;
	            },
	            
	            "only-child" : function(c){
	                var r = [];
	                for(var i = 0, ci; ci = c[i]; i++){
	                    if(!prev(ci) && !next(ci)){
	                        r[r.length] = ci;
	                    }
	                }
	                return r;
	            },
	            
	            "empty" : function(c){
	                var r = [];
	                for(var i = 0, ci; ci = c[i]; i++){
	                    var cns = ci.childNodes, j = 0, cn, empty = true;
	                    while(cn = cns[j]){
	                        ++j;
	                        if(cn.nodeType == 1 || cn.nodeType == 3){
	                            empty = false;
	                            break;
	                        }
	                    }
	                    if(empty){
	                        r[r.length] = ci;
	                    }
	                }
	                return r;
	            },
	            
	            "contains" : function(c, v){
	                var r = [];
	                for(var i = 0, ci; ci = c[i]; i++){
	                    if(ci.innerHTML.indexOf(v) !== -1){
	                        r[r.length] = ci;
	                    }
	                }
	                return r;
	            },
	
	            "nodeValue" : function(c, v){
	                var r = [];
	                for(var i = 0, ci; ci = c[i]; i++){
	                    if(ci.firstChild && ci.firstChild.nodeValue == v){
	                        r[r.length] = ci;
	                    }
	                }
	                return r;
	            },
	
	            "checked" : function(c){
	                var r = [];
	                for(var i = 0, ci; ci = c[i]; i++){
	                    if(ci.checked == true){
	                        r[r.length] = ci;
	                    }
	                }
	                return r;
	            },
	            
	            "not" : function(c, ss){
	                return Ext.DomQuery.filter(c, ss, true);
	            },
	            
	            "odd" : function(c){
	                return this["nth-child"](c, "odd");
	            },
	            
	            "even" : function(c){
	                return this["nth-child"](c, "even");
	            },
	            
	            "nth" : function(c, a){
	                return c[a-1];
	            },
	            
	            "first" : function(c){
	                return c[0];
	            },
	            
	            "last" : function(c){
	                return c[c.length-1];
	            },
	            
	            "has" : function(c, ss){
	                var s = Ext.DomQuery.select;
	                var r = [];
	                for(var i = 0, ci; ci = c[i]; i++){
	                    if(s(ss, ci).length > 0){
	                        r[r.length] = ci;
	                    }
	                }
	                return r;
	            },
	            
	            "next" : function(c, ss){
	                var is = Ext.DomQuery.is;
	                var r = [];
	                for(var i = 0, ci; ci = c[i]; i++){
	                    var n = next(ci);
	                    if(n && is(n, ss)){
	                        r[r.length] = ci;
	                    }
	                }
	                return r;
	            },
	            
	            "prev" : function(c, ss){
	                var is = Ext.DomQuery.is;
	                var r = [];
	                for(var i = 0, ci; ci = c[i]; i++){
	                    var n = prev(ci);
	                    if(n && is(n, ss)){
	                        r[r.length] = ci;
	                    }
	                }
	                return r;
	            }
	        }
	    };
	}();
	
	LSF.DOM.CSS.query = Ext.DomQuery.select;
	
	LSF.DOM.CSS.queryEach = function (callback, path, root, type) {
		LSF.each (LSF.DOM.CSS.query (path, root, type), callback);
	}
	
})();

LSF.quickAccess ('css_query', LSF.DOM.CSS.query);
LSF.quickAccess ('css_query_iterate', LSF.DOM.CSS.queryEach);