1 // Constants
  2 var SINGLE_TAG = /<(\w+)\s?\/?>/,
  3 	// TAG_STRIP = /\b[\.|\#\|\[].+/g, 
  4 	// TAG_STRIP = /\b(\.|\#|\[)|(\=?<!(name))(.)*/, /(?:\w+)\b((\.|\#|\[)|(\=?>!(name)))(.)*/, /(?:\w+)\b[\.|\#|\[]{1}.*/g,
  5 	FIRST_ID = /\s#/,
  6 	// ATTR_NAME_IS = /\[name\=([^\]]+)\]/,
  7 	// Is it a simple selector
  8 	COMPLEX_TAG = /^<([a-zA-Z][a-zA-Z0-9]*)([^>]*)>(.*)<\/\1>/i,
  9 	SPACE_WITH_BOUNDARY = /\b\s+/g,
 10 	COMMA_WITH_BOUNDARY = /\s?\,\s?/g,
 11 	QUERY_SELECTOR = Simples.support.useQuerySelector,
 12 	/** @private */
 13 	getElements = function(selector, context) {
 14 
 15 	    context = context || DOC;
 16 	    var tag = selector.substring(1),
 17 	    elems,
 18 	    nodes;
 19 
 20 	    if (selector.indexOf('#') === 0) {
 21 	        // Native function
 22 	        var id = (context && context.nodeType === 9 ? context: DOC).getElementById(tag);
 23 	        // test to make sure id is the own specified, because of name being read as id in some browsers
 24 	        return id && id.id === tag ? [id] : [];
 25 
 26 	    } else if (selector.indexOf('.') === 0) {
 27 	        if (typeof context.getElementsByClassName === "function" ) {
 28 	            // Native function
 29 				return Simples.makeArray( context.getElementsByClassName(tag) );
 30 	        } else {
 31 	            // For IE which doesn't support getElementsByClassName
 32 				elems = Simples.makeArray( context.getElementsByTagName('*') );
 33 				nodes = [];
 34 	            // Loop over elements to test for correct class
 35 	            for (var i = 0, l = elems.length; i < l; i++) {
 36 	                // Detect whether this element has the class specified
 37 	                if ( Simples.className( elems[i], tag ) ) {
 38 	                    nodes.push(elems[i]);
 39 	                }
 40 	            }
 41 	            return nodes;
 42 	        }
 43 	    } else if (selector.indexOf('[name=') === 0) {
 44 	        var name = selector.substring(6).replace(/\].*/, "");
 45 	        context = context && context.nodeType === 9 ? context: DOC;
 46 	        if (context.getElementsByName) {
 47 	            return Simples.makeArray( context.getElementsByName(name) );
 48 	        } else {
 49 	            // For IE which doesn't support getElementsByClassName
 50 	            elems = context.getElementsByName('*');
 51 	            nodes = [];
 52 	            // Loop over elements to test for correct class
 53 	            for (var m = 0, n = elems.length; m < n; m++) {
 54 	                // Detect whether this element has the class specified
 55 	                if ((" " + (elems[m].name || elems[m].getAttribute("name")) + " ").indexOf(name) > -1) {
 56 	                    nodes.push(elems[m]);
 57 	                }
 58 	            }
 59 	            return nodes;
 60 	        }
 61 	    } else {
 62 	        // assume that if not id or class must be tag
 63 	        return Simples.makeArray( context.getElementsByTagName(selector) );
 64 	    }
 65 	},
 66 	/** @private */
 67 	createDOM = function( selector, results ){
 68 
 69 		results.context = DOC;
 70 
 71 		if( COMPLEX_TAG.test( selector ) ){
 72             results.selector = "<"+COMPLEX_TAG.exec( selector )[1]+">";
 73 
 74 			var div = DOC.createElement('div');
 75             div.innerHTML = selector;
 76             Simples.makeArray( div.childNodes, results );
 77 
 78         } else if( SINGLE_TAG.test( selector ) ) {
 79             var tag = SINGLE_TAG.exec( selector );
 80 
 81 			results.selector = tag[0];
 82             results.push( DOC.createElement(tag[1]) );
 83 		}
 84 
 85 		return results;
 86 	};
 87 
 88 /**
 89  * @description used to create or select Elements selector based on .class #id and [name=name]
 90  * @param {String|Element} selector element is used by object and string is used to select Element(s), based on className, id and name and where the querySelector is available using querySelectorAll
 91  * @param {Element} context element used to provide context
 92  * @param {Object|Array} results optional object to return selected Elements
 93  */
 94 Simples.Selector = function(selector, context, results) {
 95     results = results || [];
 96 	results.selector = selector;
 97 	results.context = context || DOC;
 98 
 99     if (typeof(selector) === "string") {
100         // check selector if structured to create element
101 		if( selector.indexOf('<') > -1 && selector.indexOf('>') > 0 ){
102 			return createDOM( selector, results );
103         } else if ( QUERY_SELECTOR ) {
104             return Simples.makeArray( (context || DOC).querySelectorAll(selector), results );
105         } else {
106 	        // if it is a multi select split and short cut the process
107 	        if (COMMA_WITH_BOUNDARY.test(selector)) {
108 	            var get = selector.split(COMMA_WITH_BOUNDARY);
109 
110 	            for (var x = 0, y = get.length; x < y; x++) {
111 					Simples.makeArray( Simples.Selector(get[x], context), results );
112 	            }
113 	            return results;
114 	        }
115             // clean up selector
116             // selector = selector.replace(TAG_STRIP, "");
117             // get last id in selector
118             var index = selector.lastIndexOf(FIRST_ID);
119             selector = selector.substring(index > 0 ? index: 0);
120             // allow another document to be used for context where getting by id
121             results.context = context = (selector.indexOf('#') === 0 || selector.indexOf('[name=') === 0) ? (context && context.nodeType === 9 ? context: DOC) : (context || DOC);
122             var split = selector.split(SPACE_WITH_BOUNDARY);
123 
124             for (var i = 0, l = split.length; i < l; i++) {
125                 if (context.length > 0) {
126 
127                     var result = [];
128                     for (var m = 0, n = context.length; m < n; m++) {
129 
130                         result = result.concat(getElements(split[i], context[m]));
131                     }
132                     context = result;
133                 } else {
134                     context = getElements(split[i], context);
135                 }
136             }
137             results.push.apply(results, context);
138         }
139     }
140     return results;
141 };