1 /**
  2  * 4.[Browser part]: dom 扩展包
  3  */
  4 Jx().$package(function(J){
  5     var $D,
  6         $B,
  7         id,
  8         name,
  9         tagName,
 10         getText,
 11         getAttributeByParent,
 12         node,
 13         setClass,
 14         getClass,
 15         hasClass,
 16         addClass,
 17         removeClass,
 18         toggleClass,
 19         replaceClass,
 20         createStyleNode,
 21         setStyle,
 22         getStyle,
 23         setCssText,
 24         getCssText,
 25         addCssText,
 26         show,
 27         isShow,
 28         recover,
 29         hide,
 30         
 31         setTransform,
 32         getTransform,
 33         
 34         getScrollHeight,
 35         getScrollWidth,
 36         getClientHeight,
 37         getClientWidth,
 38         getOffsetHeight,
 39         getOffsetWidth,
 40         
 41         getScrollLeft,
 42         getScrollTop,
 43         getClientXY,
 44         setClientXY,
 45         getXY,
 46         setXY,
 47         getRelativeXY,
 48         getPosX,
 49         getPosY,
 50         getWidth,
 51         getHeight,
 52         
 53         getSelection,
 54         getSelectionText,
 55         getTextFieldSelection,
 56         
 57         contains,
 58         getHref,
 59     
 60         getDoc,
 61         _getDoc=null,
 62         getWin,
 63         w,
 64         getDocumentElement,
 65         DocumentElement,
 66         getDocHead,
 67         HeadElement;
 68     /**
 69      * dom 名字空间
 70      * 
 71      * @namespace
 72      * @name dom
 73      * @type Object
 74      */
 75     J.dom = J.dom || {};
 76     $D = J.dom;
 77     $B = J.browser;
 78     
 79         
 80 
 81     // find targeted window and @TODO create facades
 82     w = ($D.win) ? ($D.win.contentWindow) : $D.win  || window;
 83     $D.win = w;
 84     $D.doc = w.document;
 85     
 86     // feature detection 必须对已创建的对象检测
 87     var hasClassListProperty = document && Object.prototype.hasOwnProperty.call(document.documentElement,'classList');
 88 
 89     /**
 90      * 获取DocumentElement
 91      * 
 92      * @memberOf dom
 93      * 
 94      * @return {HTMLElement} documentElement
 95      * 
 96      */
 97     getDocumentElement = function(){
 98         if(DocumentElement) {
 99             return DocumentElement;
100         }
101         if(document.compatMode === 'CSS1Compat'){
102             DocumentElement= document.documentElement;
103         }else{
104             DocumentElement= document.body;
105         }
106         return DocumentElement;
107         
108     };
109     
110     /**
111      * 获取元素所属的根文档
112      * 
113      * @memberOf dom
114      * @return {HTMLElement} document
115      * 
116      */
117     getDoc = function(element) {
118         if(element) {
119             element = element || window.document;
120             _getDoc= (element["nodeType"] === 9) ? element : element["ownerDocument"]
121                 || $D.doc;
122             return _getDoc;        
123         }else {
124             if(_getDoc) {
125                 return _getDoc;
126             }
127             else {
128                 element = element || window.document;
129                 _getDoc= (element["nodeType"] === 9) ? element : element["ownerDocument"]
130                     || $D.doc;
131                 return _getDoc;
132             }            
133         }
134 
135     };
136     
137     /**
138      * 获取元素所属的 window 对象
139      * returns the appropriate window.
140      * 
141      * @memberOf dom
142      * @private
143      * @param {HTMLElement} element optional Target element.
144      * @return {Object} The window for the given element or the default window. 
145      */
146     getWin = function(element) {
147         var doc = getDoc(element);
148         return (element.document) ? element : doc["defaultView"] ||
149             doc["parentWindow"] || $D.win;
150     };
151     
152     /**
153      * 获取文档的头节点
154      * returns the head of the doc
155      * 
156      * @memberOf dom
157      * @private
158      * @param {HTMLElement} element optional Target element.
159      * @return {Object} The window for the given element or the default window. 
160      */
161     getDocHead = function() {
162         if(!HeadElement){        
163            var doc = getDoc();
164            HeadElement = doc.getElementsByTagName('head') ? doc.getElementsByTagName('head')[0] : doc.documentElement;
165         }
166         return HeadElement;
167     };
168     
169     /**
170      * 
171      * 根据 id 获取元素
172      * 
173      * @method id
174      * @memberOf dom
175      * 
176      * @param {String} id 元素的 id 名称
177      * @param {Element} doc 元素所属的文档对象,默认为当前文档
178      * @return {Element} 返回元素
179      * 
180      * @example
181      * 
182      * 
183      */
184     id = function(id, doc) {
185         return getDoc(doc).getElementById(id);
186     };
187     
188     /**
189      * 
190      * 根据 name 属性获取元素
191      * 
192      * @memberOf dom
193      * 
194      * @param {String} name 元素的 name 属性
195      * @param {Element} doc 元素所属的文档对象,默认为当前文档
196      * @return {Element} 返回元素
197      */
198     name = function(name, doc) {
199         var el = doc;
200         return getDoc(doc).getElementsByName(name);
201     };
202     
203     /**
204      * 
205      * 根据 tagName 获取元素
206      * 
207      * @memberOf dom
208      * 
209      * @param {String} tagName 元素的 tagName 标签名
210      * @param {Element} doc 元素所属的文档对象,默认为当前文档
211      * @return {Element} 返回元素
212      */
213     tagName = function(tagName, el) {
214         var el = el || getDoc();
215         return el.getElementsByTagName(tagName);
216     };
217     
218     /**
219      * 获取元素中的文本内容
220      * Returns the text content of the HTMLElement. 
221      * 
222      * @memberOf dom
223      * @param {HTMLElement} element The html element. 
224      * @return {String} The text content of the element (includes text of any descending elements).
225      */
226     getText = function(element) {
227         var text = element ? element[TEXT_CONTENT] : '';
228         if (text === UNDEFINED && INNER_TEXT in element) {
229             text = element[INNER_TEXT];
230         } 
231         return text || '';
232     };
233     
234     
235     /**
236      * 从起始元素查找某个属性,直到找到,或者到达顶层元素位置
237      * Returns the text content of the HTMLElement. 
238      * 
239      * @memberOf dom
240      * @param {HTMLElement} element The html element. 
241      * @return {String} The text content of the element (includes text of any descending elements).
242      */
243     getAttributeByParent = function(attribute, startNode,  topNode){
244         var jumpOut = false;
245         var el = startNode;
246         var result;
247         do{
248             result = el.getAttribute(attribute);
249             // 如果本次循环未找到result
250             if(J.isUndefined(result) || J.isNull(result)){
251                 // 如果本次循环已经到了监听的dom
252                 if(el === topNode){
253                     jumpOut = true;
254                 }
255                 // 如果本次循环还未到监听的dom,则继续向上查找
256                 else {
257                     el = el.parentNode;
258                 }
259             }
260             // 如果找到了result
261             else{
262                 jumpOut = true;
263             }
264         }
265         while(!jumpOut);
266         
267         return result;
268     };
269     
270     
271     /** 
272      * 生成一个 DOM 节点
273      * Generates an HTML element, this is not appended to a document
274      * 
275      * @memberOf dom
276      * 
277      * @param type {string} the type of element
278      * @param attr {string} the attributes
279      * @param win {Window} optional window to create the element in
280      * @return {HTMLElement} the generated node
281      */
282     node = function(type, attrObj, win){
283         var p,
284             w = win || $D.win,
285             d = document,
286             n = d.createElement(type);
287         var mapObj = {
288             "class":function(){
289                 n.className = attrObj["class"];
290             },
291             "style":function(){
292                 setCssText(n, attrObj["style"]);
293             }
294         }
295         for (p in attrObj) {
296             if(mapObj[p]){
297                 mapObj[p]();
298             }else{
299                 n.setAttribute(p, attrObj[p]);
300             }
301         }
302 
303         return n;
304     };
305     
306     
307 
308 
309     /**
310      * 获取文档的 scroll 高度,即文档的实际高度
311      * Returns the height of the document.
312      * 
313      * @method getDocumentHeight
314      * @memberOf dom
315      * 
316      * @param {HTMLElement} element The html element. 
317      * @return {Number} The height of the actual document (which includes the body and its margin).
318      */
319     getScrollHeight = function(el) {
320         var scrollHeight;
321         if(el){
322             scrollHeight = el.scrollHeight;
323         }else{
324             scrollHeight = Math.max(document.documentElement.scrollHeight, document.body.scrollHeight);
325         }
326         return scrollHeight || 0;
327     };
328     
329     /**
330      * 获取文档的 scroll 宽度,即文档的实际宽度
331      * Returns the width of the document.
332      * 
333      * @method getDocumentWidth
334      * @memberOf dom
335      * 
336      * @param {HTMLElement} element The html element. 
337      * @return {Number} The width of the actual document (which includes the body and its margin).
338      */
339     getScrollWidth = function(el) {
340         var scrollWidth;
341         if(el){
342             scrollWidth = el.scrollWidth;
343         }else{
344             scrollWidth = Math.max(document.documentElement.scrollWidth, document.body.scrollWidth);
345         }
346         return scrollWidth || 0;
347     };
348 
349     /**
350      * 获取当前视窗的高度
351      * Returns the current height of the viewport.
352      * 
353      * @method getClientHeight
354      * @memberOf dom
355      * @return {Number} The height of the viewable area of the page (excludes scrollbars).
356      */
357     getClientHeight = function(el) {
358         //var name = J.browser.engine.name;
359         el = el || getDocumentElement();
360         return el.clientHeight; // IE, Gecko
361     };
362     
363     /**
364      * 获取元素的client宽度
365      * Returns the current width of the viewport.
366      * @method getClientWidth
367      * @memberOf dom
368      * @param {Element} el 要获取client宽度的元素
369      * @return {Number} 宽度值.
370      */
371     
372     getClientWidth = function(el) {
373         //var name = J.browser.engine.name;
374         el = el || getDocumentElement();
375         return el.clientWidth; // IE, Gecko
376     };
377     
378     
379     /**
380      * 获取当前视窗的高度
381      * Returns the current height of the viewport.
382      * 
383      * @method getOffsetHeight
384      * @memberOf dom
385      * @return {Number} The height of the viewable area of the page (excludes scrollbars).
386      */
387     getOffsetHeight = function(el) {
388         var name = J.browser.engine.name;
389         el = el || getDocumentElement();
390         return el.offsetHeight; 
391     };
392     
393     /**
394      * 获取元素的client宽度
395      * Returns the current width of the viewport.
396      * @method getOffsetWidth
397      * @memberOf dom
398      * @param {Element} el 要获取client宽度的元素
399      * @return {Number} 宽度值.
400      */
401     getOffsetWidth = function(el) {
402         var name = J.browser.engine.name;
403         el = el || getDocumentElement();
404         return el.offsetWidth;
405     };
406     
407     /**
408      * 获取当前文档的左边已卷动的宽度
409      * Returns the left scroll value of the document 
410      * @method getDocumentScrollLeft
411      * @memberOf dom
412      * @param {HTMLDocument} document (optional) The document to get the scroll value of
413      * @return {Number}  The amount that the document is scrolled to the left
414      */
415     getScrollLeft = function(el) {
416         var scrollLeft;
417         if(el){
418             scrollLeft = el.scrollLeft;
419         }else{
420             scrollLeft = Math.max(document.documentElement.scrollLeft, document.body.scrollLeft);
421         }
422         return scrollLeft || 0;
423     };
424 
425     /**
426      * 获取当前文档的上边已卷动的宽度
427      * Returns the top scroll value of the document 
428      * @method getDocumentScrollTop
429      * @memberOf dom
430      * @param {HTMLDocument} document (optional) The document to get the scroll value of
431      * @return {Number}  The amount that the document is scrolled to the top
432      */
433     getScrollTop = function(el) {
434         var scrollTop;
435         if(el){
436             scrollTop = el.scrollTop;
437         }else{
438             scrollTop = Math.max(document.documentElement.scrollTop, document.body.scrollTop);
439         }
440         return scrollTop || 0;
441     };
442 
443     
444     /**
445      * 
446      * 设置元素的class属性
447      * 
448      * @method setClass
449      * @memberOf dom
450      * 
451      * @param {Element} el 元素
452      * @param {String} className class 名称
453      */
454     setClass = function(el, className){
455         el.className = className;
456     };
457     
458     /**
459      * 
460      * 获取元素的class属性
461      * 
462      * @method getClass
463      * @memberOf dom
464      * 
465      * @param {Element} el 元素
466      * @param {String} className class 名称
467      */
468     getClass = function(el){
469         return el.className;
470     };
471 
472     /**
473      * 
474      * 判断元素是否含有 class
475      * @function
476      * @method hasClass
477      * @memberOf dom
478      * 
479      * @param {Element} el 元素
480      * @param {String} className class 名称
481      */
482     hasClass = function(){
483         if (hasClassListProperty) {
484             return function (el, className) {
485                 if (!el || !className) {
486                     return false;
487                 }
488                 return el.classList.contains(className);
489             };
490         } else {
491             return function (el, className) {
492                 if (!el || !className) {
493                     return false;
494                 }
495                 return -1 < (' ' + el.className + ' ').indexOf(' ' + className + ' ');
496             };
497         }
498     }();
499 
500     /**
501      * 
502      * 给元素添加 class
503      * @function
504      * @method addClass
505      * @memberOf dom
506      * 
507      * @param {Element} el 元素
508      * @param {String} className class 名称
509      */
510     addClass = function(){
511         if (hasClassListProperty) {
512             return function (el, className) {
513                 if (!el || !className || hasClass(el, className)) {
514                     return;
515                 }
516                 el.classList.add(className);
517             };
518         } else {
519             return function (el, className) {
520                 if (!el || !className || hasClass(el, className)) {
521                     return;
522                 }
523                 el.className += ' ' + className;
524             };
525         }
526     }();
527 
528     /**
529      * 
530      * 给元素移除 class
531      * @function
532      * @method addClass
533      * @memberOf dom
534      * 
535      * @param {Element} el 元素
536      * @param {String} className class 名称
537      */
538     removeClass = function(){
539         if (hasClassListProperty) {
540             return function (el, className) {
541                 if (!el || !className || !hasClass(el, className)) {
542                     return;
543                 }
544                 el.classList.remove(className);
545             };
546         } else {
547             return function (el, className) {
548                 if (!el || !className || !hasClass(el, className)) {
549                     return;
550                 }
551                 el.className = el.className.replace(new RegExp('(?:^|\\s)' + className + '(?:\\s|$)'), ' ');
552             };
553         }
554     }();
555     
556     /*
557     removeClass2 = function(el, className){
558         replaceClass(el, className, "");
559     };
560     */
561     
562     
563     /**
564      * 
565      * 对元素 class 的切换方法,即:如果元素用此class则移除此class,如果没有此class则添加此class
566      * 
567      * @function
568      * @method toggleClass
569      * @memberOf dom
570      * 
571      * @param {Element} el 元素
572      * @param {String} className class 名称
573      */
574     toggleClass = function(){
575         if (hasClassListProperty) {
576             return function (el, className) {
577                 if (!el || !className) {
578                     return;
579                 }
580                 el.classList.toggle(className);
581             };
582         } else {
583             return function (el, className) {
584                 if (!el || !className) {
585                     return;
586                 }
587                 hasClass(el, className) ? removeClass(el, className) : addClass(el, className);
588             };
589         }
590     }();
591 
592     /**
593      * 
594      * 替换元素 oldClassName 为 newClassName
595      * 
596      * @method toggleClass
597      * @memberOf dom
598      * 
599      * @param {Element} el 元素
600      * @param {String} oldClassName 被替换的 class 名称
601      * @param {String} newClassName 要替换成的 class 名称
602      */
603     replaceClass = function(el, oldClassName, newClassName){
604         removeClass(el, oldClassName);
605         addClass(el, newClassName);
606         //el.className = (" "+el.className+" ").replace(" "+oldClassName+" "," "+newClassName+" ");
607     };
608     /*
609     replaceClass2 = function(el, oldClassName, newClassName){
610         var i,
611             tempClassNames = el.className.split(" ");
612             
613         for(i=0; i<tempClassNames.length; i++){
614             if(tempClassNames[i] === oldClassName){
615                 tempClassNames[i] = newClassName;
616             }
617         }
618         //J.out(tempClassNames);
619 
620         el.className = tempClassNames.join(" ");
621     };
622     */
623     
624     /**
625      * 
626      * 创建 style 标签
627      * 
628      * @method setStyle
629      * @memberOf dom
630      * 
631      * @param 样式内容,支持string和object
632      * @param {String} id 样式标签的 id
633      */
634     createStyleNode = function(styles, id){
635         var styleNode = $D.node('style', {
636             'id': id || '',
637             'type': 'text/css'
638         });
639 
640         $D.getDocHead().appendChild(styleNode);
641 
642         var stylesType = typeof(styles);
643         if(stylesType == "string"){     //参数是文本
644             if(styleNode.styleSheet){    //IE
645                 styleNode.styleSheet.cssText = styles;
646             }else{
647                 var tn = document.createTextNode(styles);
648                 styleNode.appendChild(tn);
649             }
650         }else if(stylesType == "object"){   //参数是对象
651             var i = 0,
652                 styleSheet = document.styleSheets[document.styleSheets.length-1];
653             for(selector in styles){
654                 if(styleSheet.insertRule){
655                     var rule = selector + "{" + styles[selector] + "}";
656                     styleSheet.insertRule(rule, i++);
657                 }else {                  //IE
658                     styleSheet.addRule(selector, styles[selector], i++);
659                 }
660             }
661         }
662 
663         return styleNode;
664     };
665     
666     /**
667      * 
668      * 设置元素的样式,css 属性需要用驼峰式写法,如:fontFamily
669      * 
670      * @method setStyle
671      * @memberOf dom
672      * 
673      * @param {Element} el 元素
674      * @param {String} styleName css 属性名称
675      * @param {String} value css 属性值
676      */
677     setStyle = function(el, styleName, value){
678         if(!el){
679             return;
680         }
681         
682         var name = J.browser.name;
683         if(styleName === "float" || styleName === "cssFloat"){
684             if(name === "ie"){
685                 styleName = "styleFloat";
686             }else{
687                 styleName = "cssFloat";
688             }
689         }
690         
691         //J.out(styleName);
692         
693         if(styleName === "opacity" && name === "ie" && J.browser.ie<9){
694             var opacity = value*100;
695             
696             /*
697             if(el.style.filter.alpha){
698                 
699                 el.style.filter.alpha.opacity = opacity;
700                 J.debug("filter alpha!")
701             }else{
702                 addCssText(el,'filter:alpha(opacity="' + opacity + '")');
703             }*/
704             //addCssText(el,'filter:alpha(opacity="' + opacity + '")');
705             //J.out(">>>el.style.filter.alpha.opacity: "+el.style.filter.alpha.opacity);
706             el.style.filter = 'alpha(opacity="' + opacity + '")';
707 
708             if(!el.style.zoom){
709                 el.style.zoom = 1;
710             }
711 
712             return;
713         }
714         el.style[styleName] = value;
715     };
716     
717     
718 
719     
720     /**
721      * 
722      * 获取元素的当前实际样式,css 属性需要用驼峰式写法,如:fontFamily
723      * 
724      * @method getStyle
725      * @memberOf dom
726      * 
727      * @param {Element} el 元素
728      * @param {String} styleName css 属性名称
729      * @return {String} 返回元素样式
730      */
731     getStyle = function(el, styleName){
732         if(!el){
733             return;
734         }
735         
736         var win = getWin(el);
737         var name = J.browser.name;
738         //J.out(name);
739         if(styleName === "float" || styleName === "cssFloat"){
740             if(name === "ie"){
741                 styleName = "styleFloat";
742             }else{
743                 styleName = "cssFloat";
744             }
745         }
746         if(styleName === "opacity" && name === "ie" && J.browser.ie<9){
747             var opacity = 1,
748                 result = el.style.filter.match(/opacity=(\d+)/);
749             if(result && result[1]){
750                 opacity = result[1]/100;
751             }
752             return opacity;
753         }
754         
755         if(el.style[styleName]){
756             return el.style[styleName];
757         }else if(el.currentStyle){
758             //alert(el.currentStyle[styleName]);
759             return el.currentStyle[styleName];
760         }else if(win.getComputedStyle){
761             //J.out(win.getComputedStyle(el, null));
762             return win.getComputedStyle(el, null)[styleName];
763         }else if(document.defaultView && document.defaultView.getComputedStyle){
764             styleName = styleName.replace(/([/A-Z])/g, "-$1");
765             styleName = styleName.toLowerCase();
766             var style = document.defaultView.getComputedStyle(el, "");
767             return style && style.getPropertyValue(styleName);
768         }
769 
770     };
771 
772     /**
773      * 
774      * 给元素添加cssText
775      *  
776      * @method addCssText
777      * @memberOf dom
778      * 
779      * @param {Element} el 元素
780      * @param {String} cssText css 属性
781      */
782     addCssText = function(el, cssText){
783         el.style.cssText += ';' + cssText;
784     };
785     
786     /**
787      * 
788      * 给元素设置cssText
789      *  
790      * @method setCssText
791      * @memberOf dom
792      * 
793      * @param {Element} el 元素
794      * @param {String} cssText css 属性
795      */
796     setCssText = function(el, cssText){
797         el.style.cssText = cssText;
798     };
799     /**
800      * 
801      * 获取元素的cssText
802      *  
803      * @method getCssText
804      * @memberOf dom
805      * 
806      * @param {Element} el 元素
807      */
808     getCssText = function(el){
809         return el.style.cssText;
810     };
811     
812     /**
813      * 
814      * 显示元素
815      * 
816      * @method show
817      * @memberOf dom
818      * 
819      * @param {Element} el 元素
820      * @param {String} displayStyle 强制指定以何种方式显示,如:block,inline,inline-block等等
821      */
822     show = function(el, displayStyle){
823         var display;
824         var _oldDisplay = el.getAttribute("_oldDisplay");
825         
826         if(_oldDisplay){
827             display = _oldDisplay;
828         }else{
829             display = getStyle(el, "display");
830         }
831 
832         if(displayStyle){
833             setStyle(el, "display", displayStyle);
834         }else{
835             if(display === "none"){
836                 setStyle(el, "display", "block");
837             }else{
838                 setStyle(el, "display", display);
839             }
840         }
841     };
842     
843     /**
844      * 
845      * 判断元素是否是显示状态
846      * 
847      * @method isShow
848      * @memberOf dom
849      * 
850      * @param {Element} el 元素
851      */
852     isShow = function(el){
853         var display = getStyle(el, "display");
854         if(display === "none"){
855             return false;
856         }else{
857             return true;
858         }
859     };
860     
861     /**
862      * 
863      * 还原元素原来的display属性
864      * 
865      * @method recover
866      * @memberOf dom
867      * 
868      * @param {Element} el 元素
869      */
870     recover = function(el){
871         var display;
872         var _oldDisplay = el.getAttribute("_oldDisplay");
873         
874         if(_oldDisplay){
875             display = _oldDisplay;
876         }else{
877             display = getStyle(el, "display");
878         }
879         if(display === "none"){
880             setStyle(el, "display", "");
881         }else{
882             setStyle(el, "display", display);
883         }
884     };
885     
886     /**
887      * 
888      * 隐藏元素
889      * 
890      * @method hide
891      * @memberOf dom
892      * 
893      * @param {Element} el 元素
894      */
895     hide = function(el){
896         var display = getStyle(el, "display");
897         var _oldDisplay = el.getAttribute("_oldDisplay");
898         
899         if(!_oldDisplay){
900             if(display === "none"){
901                 el.setAttribute("_oldDisplay", "");
902             }else{
903                 el.setAttribute("_oldDisplay", display);
904             }
905         }
906         setStyle(el, "display", "none");
907     };
908     
909 
910     //获取当前浏览器支持的transform属性
911     var transform = function() {
912         var styles = document.createElement('a').style,
913             props = ['webkitTransform', 'MozTransform', 'OTransform', 'msTransform', 'Transform'];
914 
915         for (var i = props.length; i--;) {
916             if (props[i] in styles) return props[i];
917         }
918     } ();
919     /**
920      *
921      * 设置元素的transform属性
922      * 
923      * @method setTransform
924      * @memberOf dom
925      * 
926      * @param {element} target  要设置属性的元素
927      * @param {mixed}   value   属性值,类型视具体属性而定
928      * @param {string}  style   要设置的属性,如果不指定则默认为transform
929      */
930     setTransform = function(target, value, style){
931         var v = target.style[transform] || '';
932         
933         switch(style) {
934             case 'translate3d'  :
935             case 'translate3d-x':
936             case 'translate3d-y':
937             case 'translate3d-z':
938                 if(!/translate3d\([^)]*\)/.test(v)) v += ' translate3d(0px,0px,0px)';
939                 if (style != 'translate3d') {
940                     var temp = {x : '$1', y : '$2', z : '$3'};
941                     var map = {'translate3d-x':'x', 'translate3d-y':'y', 'translate3d-z':'z'};
942                     temp[map[style]] = value;
943                     value = temp;
944                 }
945                 v = v.replace(/translate3d\(([^,]*)px,([^,]*)px,([^,]*)px\)/,
946                     'translate3d(' + value.x + 'px,' + value.y + 'px,' + value.z + 'px)');
947                 break;
948             case 'translate'    :
949             case 'translate-x':
950             case 'translate-y':
951                 if(!/translate\([^)]*\)/.test(v)) v += ' translate(0px,0px)';
952                 if (style != 'translate') {
953                     var temp = {x : '$1', y : '$2'};
954                     var map = {'translate3d-x':'x', 'translate3d-y':'y'};
955                     temp[map[style]] = value;
956                     value = temp;
957                 }
958                 v = v.replace(/translate\(([^,]*)px,([^,]*)px\)/,
959                     'translate(' + value.x + 'px,' + value.y + 'px)');
960                 break;
961             case 'scale':
962                 v = (/scale\([^)]*\)/.test(v)?
963                     v.replace(/scale\([^)]*\)/, 'scale(' + value + ')'):
964                     v + ' scale(' + value + ')'
965                 );
966                 break;
967             case 'rotate':
968                 v = (/rotate\([^)]*\)/.test(v)?
969                     v.replace(/rotate\([^)]*\)/, 'rotate(' + value + 'deg)'):
970                     v + ' rotate(' + value + 'deg)'
971                 );
972                 break;
973             default:
974                 //没有设置style的话,直接修改transform属性
975                 v = value;
976         }
977         
978         target.style[transform] = v;
979     };
980     
981     /**
982      *
983      * 获取CSS3 transform属性的值,或具体的scale等的值
984      * 
985      * @method getTransform
986      * @memberOf dom
987      * 
988      * @param {element} target  要获取属性的元素
989      * @param {string}  style   要获取的属性,如果不指定则默认为transform
990      */
991     getTransform = function(target, style){
992         //获取属性。就算设置的时候写的是0,读取的时候还是会读到 0px
993         var v = target.style[transform] || 'scale(1) translate(0px, 0px) translate3d(0px, 0px, 0px) rotate(0deg)';
994         
995         switch(style){
996             case 'scale':
997                 v = /scale\(([^)]*)\)/.exec(v);
998                 v = v? Number(v[1]): 1;
999                 break;
1000             case 'translate3d':
1001             case 'translate3d-x':
1002             case 'translate3d-y':
1003             case 'translate3d-z':
1004                 v = /translate3d\(([^,]*)px,([^,]*)px,([^,]*)px\)/.exec(v) || [0,0,0,0];
1005                 if(style != 'translate3d') {
1006                     var map = {'translate3d-x':1, 'translate3d-y':2, 'translate3d-z':3};
1007                     v = Number(v[map[style]]);
1008                 }
1009                 else {
1010                     v = {x : Number(v[1]), y : Number(v[2]), z : Number(v[3])};
1011                 }
1012                 break;
1013             case 'translate':
1014             case 'translate-x':
1015             case 'translate-y':
1016                 v = /translate\(([^,]*)px,([^,]*)px\)/.exec(v) || [0,0,0];
1017                 if(style != 'translate') {
1018                     var map = {'translate-x':1, 'translate-y':2};
1019                     v = Number(v[map[style]]);
1020                 }
1021                 else {
1022                     v = {x : Number(v[1]), y : Number(v[2])};
1023                 }
1024                 break;
1025             case 'rotate':
1026                 v = /rotate\(([^)]*)deg\)/.exec(v);
1027                 v = v? Number(v[1]): 0;
1028                 break;
1029             default:
1030         }
1031         
1032         return v;
1033     };
1034     
1035     
1036     /**
1037      * 获取对象坐标
1038      *
1039      * @method getClientXY
1040      * @memberOf dom
1041      * 
1042      * @param {HTMLElement} el
1043      * @return Array [left,top]
1044      */
1045     getClientXY = function(el) {
1046         var _t = 0,
1047             _l = 0;
1048 
1049         if (el) {
1050             //这里只检查document不够严谨, 在el被侵染置换(jQuery做了这么恶心的事情)
1051             //的情况下, el.getBoundingClientRect() 调用回挂掉
1052             if (document.documentElement.getBoundingClientRect && el.getBoundingClientRect) { // 顶IE的这个属性,获取对象到可视范围的距离。
1053                 //现在firefox3,chrome2,opera9.63都支持这个属性。
1054                 var box = {left:0,top:0,right:0,bottom:0};//
1055                 try{
1056                     box=el.getBoundingClientRect();
1057                 }catch(ex){
1058                     return [0,0];
1059                 }
1060                 var oDoc = el.ownerDocument;
1061                 
1062                 var _fix = J.browser.ie ? 2 : 0; //修正ie和firefox之间的2像素差异
1063                 
1064                 _t = box.top - _fix + getScrollTop(oDoc);
1065                 _l = box.left - _fix + getScrollLeft(oDoc);
1066             } else {//这里只有safari执行。
1067                 while (el.offsetParent) {
1068                     _t += el.offsetTop;
1069                     _l += el.offsetLeft;
1070                     el = el.offsetParent;
1071                 }
1072             }
1073         }
1074         return [_l, _t];
1075     };
1076     
1077     /**
1078      * 设置dom坐标
1079      * 
1080      * @method setClientXY
1081      * @memberOf dom
1082      
1083      * @param {HTMLElement} el
1084      * @param {string|number} x 横坐标
1085      * @param {string|number} y 纵坐标
1086      */
1087     setClientXY = function(el, x, y) {
1088         x = parseInt(x) + getScrollLeft();
1089         y = parseInt(y) + getScrollTop();
1090         setXY(el, x, y);
1091     };
1092 
1093     /**
1094      * 获取对象坐标
1095      * 
1096      * @method getXY
1097      * @memberOf dom
1098      *
1099      * @param {HTMLElement} el
1100      * @return Array [top,left]
1101      */
1102     getXY = function(el) {
1103         var xy = getClientXY(el);
1104 
1105         xy[0] = xy[0] + getScrollLeft();
1106         xy[1] = xy[1] + getScrollTop();
1107         return xy;
1108     }
1109 
1110     /**
1111      * 设置dom坐标
1112      * @method setXY
1113      * @memberOf dom
1114      * 
1115      * @param {HTMLElement} el
1116      * @param {string|number} x 横坐标
1117      * @param {string|number} y 纵坐标
1118      */
1119     setXY = function(el, x, y) {
1120         var _ml = parseInt(getStyle(el, "marginLeft")) || 0;
1121         var _mt = parseInt(getStyle(el, "marginTop")) || 0;
1122 
1123         setStyle(el, "left", parseInt(x) - _ml + "px");
1124         setStyle(el, "top", parseInt(y) - _mt + "px");
1125     };
1126     
1127     /**
1128      * 获取对象相对一个节点的坐标
1129      *
1130      * @method getRelativeXY
1131      * @memberOf dom
1132      * 
1133      * @param {HTMLElement} el
1134      * @param {HTMLElement} relativeEl 
1135      * @return Array [top,left]
1136      * 
1137      */
1138     getRelativeXY = function(el, relativeEl) {
1139         var xyEl = getXY(el);
1140         var xyRelativeEl = getXY(relativeEl);
1141         var xy=[];
1142         
1143         xy[0] = xyEl[0] - xyRelativeEl[0];
1144         xy[1] = xyEl[1] - xyRelativeEl[1];
1145         return xy;
1146     }
1147     
1148     var parseCssPx = function(value){
1149         if(!value || value == 'auto') return 0;
1150         else return parseInt(value.substr(0, value.length-2));
1151     }
1152     /**
1153      * 获取x坐标的简便方法
1154      *
1155      * @method getPosX
1156      * @memberOf dom
1157      * 
1158      * @param {HTMLElement} el
1159      * @return {String}
1160      * 
1161      */
1162     getPosX = function(el){
1163         return parseCssPx($D.getStyle(el, 'left'));
1164     }
1165     /**
1166      * 获取y坐标的简便方法
1167      *
1168      * @method getPosY
1169      * @memberOf dom
1170      * 
1171      * @param {HTMLElement} el
1172      * @return {String}
1173      * 
1174      */
1175     getPosY = function(el){
1176         return parseCssPx($D.getStyle(el, 'top'));
1177     }
1178     /**
1179      * 获取宽度的简便方法
1180      *
1181      * @method getWidth
1182      * @memberOf dom
1183      * 
1184      * @param {HTMLElement} el
1185      * @return {String}
1186      * 
1187      */
1188     getWidth = function(el){
1189         return parseCssPx($D.getStyle(el, 'width'));
1190     }
1191     /**
1192      * 获取高度的简便方法
1193      *
1194      * @method getHeight
1195      * @memberOf dom
1196      * 
1197      * @param {HTMLElement} el
1198      * @return {String}
1199      * 
1200      */
1201     getHeight = function(el){
1202         return parseCssPx($D.getStyle(el, 'height'));
1203     }
1204     
1205     /**
1206      * 获取选择的文本
1207      *
1208      * @method getSelectionText
1209      * @memberOf dom
1210      * 
1211      * @param {Window} win
1212      * @return {String} 返回选择的文本
1213      */
1214     getSelectionText = function(win) {
1215         win = win || window;
1216         var doc = win.document;
1217         if (win.getSelection) {
1218             // This technique is the most likely to be standardized.
1219             // getSelection() returns a Selection object, which we do not document.
1220             return win.getSelection().toString();
1221         }else if (doc.getSelection) {
1222             // This is an older, simpler technique that returns a string
1223             return doc.getSelection();
1224         }else if (doc.selection) {
1225             // This is the IE-specific technique.
1226             // We do not document the IE selection property or TextRange objects.
1227             return doc.selection.createRange().text;
1228         }
1229     
1230     };
1231 
1232 
1233     /**
1234      * FireFox 下获取 input 或者 textarea 中选中的文字
1235      *
1236      * @method getTextFieldSelection
1237      * @memberOf dom
1238      * 
1239      * @param {HTMLElement} el
1240      * @return {String} 返回选择的文本
1241      */
1242     getTextFieldSelection = function(el) {
1243         if (el.selectionStart != undefined && el.selectionEnd != undefined) {
1244             var start = el.selectionStart;
1245             var end = el.selectionEnd;
1246             return el.value.substring(start, end);
1247         }else{
1248             return ""; // Not supported on this browser
1249         }
1250     
1251     };
1252     
1253     /**
1254      * 判断一个节点是否是某个父节点的子节点, 
1255      * 默认不包含parent === child的情况
1256      * @memberOf dom
1257      * @name contains
1258      * @function
1259      * @param {HTMLElement} parent
1260      * @param {HTMLElement} child
1261      * @param {Boolean} containSelf 指示是否包括parent等于child的情况
1262      * @return {Boolean} 包含则返回true
1263      */
1264     contains = function(parent, child, containSelf){
1265         if(!containSelf && parent === child){
1266             return false;
1267         }
1268         if(parent.compareDocumentPosition){//w3c
1269             var res = parent.compareDocumentPosition(child);
1270             if(res == 20 || res == 0){
1271                 return true;
1272             }
1273         }else{
1274             if(parent.contains(child)){//ie
1275                 return true;
1276             }
1277         }
1278         return false;
1279     };
1280     
1281     /**
1282      * 取一个a标签的href的绝对路径
1283      * @method getFullHref
1284      * @memberOf dom
1285      * 
1286      * @param {HTMLElement} el
1287      * @return {String} 返回一个完整的url
1288      */
1289     getHref = function(el){
1290         var result;
1291         if($B.ie && $B.ie<=7){
1292             result=el.getAttribute('href',4);
1293         }else{
1294             result=el.href;
1295         }
1296         return result || null;
1297     };
1298     
1299     
1300     
1301     var scripts = tagName("script");
1302     for(var i=0; i<scripts.length; i++){
1303         
1304         if(scripts[i].getAttribute("hasJx")=="true"){
1305             //J.out("hasJx: "+(scripts[i].getAttribute("hasJx")=="true"));
1306             J.src = scripts[i].src;
1307         }
1308     }
1309     if(!J.src){
1310         J.src = scripts[scripts.length-1].src;
1311     }
1312     
1313     J.filename = J.src.replace(/(.*\/){0,}([^\\]+).*/ig,"$2");
1314     //J.out(J.src+" _ "+J.filename)
1315     J.path = J.src.split(J.filename)[0];
1316     
1317     
1318     $D.getDoc = getDoc;
1319     
1320     $D.id = id;
1321     $D.name = name;
1322     $D.tagName = tagName;
1323     $D.getText = getText;
1324     $D.getAttributeByParent = getAttributeByParent;
1325     $D.node = node;
1326     $D.setClass = setClass;
1327     $D.getClass = getClass;
1328     $D.hasClass = hasClass;
1329     
1330     $D.addClass = addClass;
1331     $D.removeClass = removeClass;
1332     $D.toggleClass = toggleClass;
1333     $D.replaceClass = replaceClass;
1334     
1335     $D.createStyleNode = createStyleNode;
1336     $D.setStyle = setStyle;
1337     $D.getStyle = getStyle;
1338     
1339     $D.setCssText = setCssText;
1340     $D.getCssText = getCssText;
1341     $D.addCssText = addCssText;
1342     
1343     $D.show = show;
1344     $D.isShow = isShow;
1345     $D.recover = recover;
1346     $D.hide = hide;
1347     
1348     
1349     $D.getScrollLeft = getScrollLeft;
1350     $D.getScrollTop = getScrollTop;
1351     $D.getScrollHeight = getScrollHeight;
1352     $D.getScrollWidth = getScrollWidth;
1353     
1354     $D.getClientHeight = getClientHeight;
1355     $D.getClientWidth = getClientWidth;
1356     
1357     $D.getOffsetHeight = getOffsetHeight;
1358     $D.getOffsetWidth = getOffsetWidth;
1359     
1360     $D.getClientXY = getClientXY;
1361     $D.setClientXY = setClientXY;
1362     
1363     $D.getXY = getXY;
1364     $D.setXY = setXY;
1365     $D.getRelativeXY = getRelativeXY;
1366     $D.getPosX = getPosX;
1367     $D.getPosY = getPosY;
1368     $D.getWidth = getWidth;
1369     $D.getHeight = getHeight;
1370     $D.getSelection = getSelection;
1371     $D.getSelectionText = getSelectionText;
1372     
1373     $D.getTextFieldSelection = getTextFieldSelection;
1374     
1375     $D.getDocumentElement = getDocumentElement;
1376     $D.getDocHead = getDocHead;
1377     
1378     $D.contains = contains;
1379     $D.getHref = getHref;
1380     
1381 });
1382