1 /** 
  2  * @description
  3  * Package: jet.mini
  4  *
  5  * Need package:
  6  * jet.core.js
  7  * 
  8  */
  9  
 10 Jx().$package(function(J){
 11 
 12     
 13 /**
 14  * "mini" Selector Engine
 15  * Copyright (c) 2009 James Padolsey
 16  * -------------------------------------------------------
 17  * Dual licensed under the MIT and GPL licenses.
 18  *    - http://www.opensource.org/licenses/mit-license.php
 19  *    - http://www.gnu.org/copyleft/gpl.html
 20  * -------------------------------------------------------
 21  * Version: 0.01 (BETA)
 22  */
 23 
 24 
 25 var mini = (function(){
 26     
 27     var snack = /(?:[\w\-\\.#]+)+(?:\[\w+?=([\'"])?(?:\\\1|.)+?\1\])?|\*|>/ig,
 28         exprClassName = /^(?:[\w\-_]+)?\.([\w\-_]+)/,
 29         exprId = /^(?:[\w\-_]+)?#([\w\-_]+)/,
 30         exprNodeName = /^([\w\*\-_]+)/,
 31         na = [null,null];
 32     
 33     function _find(selector, context) {
 34         
 35         /*
 36          * This is what you call via x()
 37          * Starts everything off...
 38          */
 39         
 40         context = context || document;
 41         
 42         var simple = /^[\w\-_#]+$/.test(selector);
 43         
 44         if (!simple && context.querySelectorAll) {
 45             return realArray(context.querySelectorAll(selector));
 46         }
 47         
 48         if (selector.indexOf(',') > -1) {
 49             var split = selector.split(/,/g), ret = [], sIndex = 0, len = split.length;
 50             for(; sIndex < len; ++sIndex) {
 51                 ret = ret.concat( _find(split[sIndex], context) );
 52             }
 53             return unique(ret);
 54         }
 55         
 56         var parts = selector.match(snack),
 57             part = parts.pop(),
 58             id = (part.match(exprId) || na)[1],
 59             className = !id && (part.match(exprClassName) || na)[1],
 60             nodeName = !id && (part.match(exprNodeName) || na)[1],
 61             collection;
 62             
 63         if (className && !nodeName && context.getElementsByClassName) {
 64             
 65             collection = realArray(context.getElementsByClassName(className));
 66             
 67         } else {
 68             
 69             collection = !id && realArray(context.getElementsByTagName(nodeName || '*'));
 70             
 71             if (className) {
 72                 collection = filterByAttr(collection, 'className', RegExp('(^|\\s)' + className + '(\\s|$)'));
 73             }
 74             
 75             if (id) {
 76                 var byId = context.getElementById(id);
 77                 return byId?[byId]:[];
 78             }
 79         }
 80         
 81         return parts[0] && collection[0] ? filterParents(parts, collection) : collection;
 82         
 83     }
 84     
 85     function realArray(c) {
 86         
 87         /**
 88          * Transforms a node collection into
 89          * a real array
 90          */
 91         
 92         try {
 93             return Array.prototype.slice.call(c);
 94         } catch(e) {
 95             var ret = [], i = 0, len = c.length;
 96             for (; i < len; ++i) {
 97                 ret[i] = c[i];
 98             }
 99             return ret;
100         }
101         
102     }
103     
104     function filterParents(selectorParts, collection, direct) {
105         
106         /**
107          * This is where the magic happens.
108          * Parents are stepped through (upwards) to
109          * see if they comply with the selector.
110          */
111         
112         var parentSelector = selectorParts.pop();
113         
114         if (parentSelector === '>') {
115             return filterParents(selectorParts, collection, true);
116         }
117         
118         var ret = [],
119             r = -1,
120             id = (parentSelector.match(exprId) || na)[1],
121             className = !id && (parentSelector.match(exprClassName) || na)[1],
122             nodeName = !id && (parentSelector.match(exprNodeName) || na)[1],
123             cIndex = -1,
124             node, parent,
125             matches;
126             
127         nodeName = nodeName && nodeName.toLowerCase();
128             
129         while ( (node = collection[++cIndex]) ) {
130             
131             parent = node.parentNode;
132             
133             do {
134                 
135                 matches = !nodeName || nodeName === '*' || nodeName === parent.nodeName.toLowerCase();
136                 matches = matches && (!id || parent.id === id);
137                 matches = matches && (!className || RegExp('(^|\\s)' + className + '(\\s|$)').test(parent.className));
138                 
139                 if (direct || matches) { break; }
140                 
141             } while ( (parent = parent.parentNode) );
142             
143             if (matches) {
144                 ret[++r] = node;
145             }
146         }
147         
148         return selectorParts[0] && ret[0] ? filterParents(selectorParts, ret) : ret;
149         
150     }
151     
152     
153     var unique = (function(){
154         
155         var uid = +new Date();
156                 
157         var data = (function(){
158          
159             var n = 1;
160          
161             return function(elem) {
162          
163                 var cacheIndex = elem[uid],
164                     nextCacheIndex = n++;
165          
166                 if(!cacheIndex) {
167                     elem[uid] = nextCacheIndex;
168                     return true;
169                 }
170          
171                 return false;
172          
173             };
174          
175         })();
176         
177         return function(arr) {
178         
179             /**
180              * Returns a unique array
181              */
182             
183             var length = arr.length,
184                 ret = [],
185                 r = -1,
186                 i = 0,
187                 item;
188                 
189             for (; i < length; ++i) {
190                 item = arr[i];
191                 if (data(item)) {
192                     ret[++r] = item;
193                 }
194             }
195             
196             uid += 1;
197             
198             return ret;
199     
200         };
201     
202     })();
203     
204     function filterByAttr(collection, attr, regex) {
205         
206         /**
207          * Filters a collection by an attribute.
208          */
209         
210         var i = -1, node, r = -1, ret = [];
211         
212         while ( (node = collection[++i]) ) {
213             if (regex.test(node[attr])) {
214                 ret[++r] = node;
215             }
216         }
217         
218         return ret;
219     }
220     
221     return _find;
222     
223 })();
224 
225 
226 
227 
228     /*
229      * ////////////////////////////////////////////////////////////////
230      * 
231      * Adapter to JET
232      * 
233      * ////////////////////////////////////////////////////////////////
234      */
235     /**
236      * 一个据说比jq还快的筛选器,可以满足日常99%的筛选需要
237      * @function
238      * @memberOf dom
239      * @name mini
240      * 
241      * @param {String} query string 筛选器语法
242      * @returns {Element} 返回筛选出的dom元素
243      * 
244      * @example
245      * //创建一个匿名package包:
246      * Jx().$package(function(J){
247      *  //这时上下文对象this指向全局window对象
248      *  var lists = J.dom.mini(".list");
249      * };
250      * 
251      */
252     J.dom.mini = mini;
253 
254 
255 
256 });
257