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 };