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