css.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426
  1. define( [
  2. "./core",
  3. "./var/pnum",
  4. "./core/access",
  5. "./css/var/rmargin",
  6. "./var/document",
  7. "./var/rcssNum",
  8. "./css/var/rnumnonpx",
  9. "./css/var/cssExpand",
  10. "./css/var/getStyles",
  11. "./css/var/swap",
  12. "./css/curCSS",
  13. "./css/adjustCSS",
  14. "./css/addGetHookIf",
  15. "./css/support",
  16. "./core/init",
  17. "./core/ready",
  18. "./selector" // contains
  19. ], function( jQuery, pnum, access, rmargin, document, rcssNum, rnumnonpx, cssExpand,
  20. getStyles, swap, curCSS, adjustCSS, addGetHookIf, support ) {
  21. "use strict";
  22. var
  23. // Swappable if display is none or starts with table
  24. // except "table", "table-cell", or "table-caption"
  25. // See here for display values: https://developer.mozilla.org/en-US/docs/CSS/display
  26. rdisplayswap = /^(none|table(?!-c[ea]).+)/,
  27. cssShow = { position: "absolute", visibility: "hidden", display: "block" },
  28. cssNormalTransform = {
  29. letterSpacing: "0",
  30. fontWeight: "400"
  31. },
  32. cssPrefixes = [ "Webkit", "Moz", "ms" ],
  33. emptyStyle = document.createElement( "div" ).style;
  34. // Return a css property mapped to a potentially vendor prefixed property
  35. function vendorPropName( name ) {
  36. // Shortcut for names that are not vendor prefixed
  37. if ( name in emptyStyle ) {
  38. return name;
  39. }
  40. // Check for vendor prefixed names
  41. var capName = name[ 0 ].toUpperCase() + name.slice( 1 ),
  42. i = cssPrefixes.length;
  43. while ( i-- ) {
  44. name = cssPrefixes[ i ] + capName;
  45. if ( name in emptyStyle ) {
  46. return name;
  47. }
  48. }
  49. }
  50. function setPositiveNumber( elem, value, subtract ) {
  51. // Any relative (+/-) values have already been
  52. // normalized at this point
  53. var matches = rcssNum.exec( value );
  54. return matches ?
  55. // Guard against undefined "subtract", e.g., when used as in cssHooks
  56. Math.max( 0, matches[ 2 ] - ( subtract || 0 ) ) + ( matches[ 3 ] || "px" ) :
  57. value;
  58. }
  59. function augmentWidthOrHeight( elem, name, extra, isBorderBox, styles ) {
  60. var i,
  61. val = 0;
  62. // If we already have the right measurement, avoid augmentation
  63. if ( extra === ( isBorderBox ? "border" : "content" ) ) {
  64. i = 4;
  65. // Otherwise initialize for horizontal or vertical properties
  66. } else {
  67. i = name === "width" ? 1 : 0;
  68. }
  69. for ( ; i < 4; i += 2 ) {
  70. // Both box models exclude margin, so add it if we want it
  71. if ( extra === "margin" ) {
  72. val += jQuery.css( elem, extra + cssExpand[ i ], true, styles );
  73. }
  74. if ( isBorderBox ) {
  75. // border-box includes padding, so remove it if we want content
  76. if ( extra === "content" ) {
  77. val -= jQuery.css( elem, "padding" + cssExpand[ i ], true, styles );
  78. }
  79. // At this point, extra isn't border nor margin, so remove border
  80. if ( extra !== "margin" ) {
  81. val -= jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles );
  82. }
  83. } else {
  84. // At this point, extra isn't content, so add padding
  85. val += jQuery.css( elem, "padding" + cssExpand[ i ], true, styles );
  86. // At this point, extra isn't content nor padding, so add border
  87. if ( extra !== "padding" ) {
  88. val += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles );
  89. }
  90. }
  91. }
  92. return val;
  93. }
  94. function getWidthOrHeight( elem, name, extra ) {
  95. // Start with offset property, which is equivalent to the border-box value
  96. var val,
  97. valueIsBorderBox = true,
  98. styles = getStyles( elem ),
  99. isBorderBox = jQuery.css( elem, "boxSizing", false, styles ) === "border-box";
  100. // Support: IE <=11 only
  101. // Running getBoundingClientRect on a disconnected node
  102. // in IE throws an error.
  103. if ( elem.getClientRects().length ) {
  104. val = elem.getBoundingClientRect()[ name ];
  105. }
  106. // Some non-html elements return undefined for offsetWidth, so check for null/undefined
  107. // svg - https://bugzilla.mozilla.org/show_bug.cgi?id=649285
  108. // MathML - https://bugzilla.mozilla.org/show_bug.cgi?id=491668
  109. if ( val <= 0 || val == null ) {
  110. // Fall back to computed then uncomputed css if necessary
  111. val = curCSS( elem, name, styles );
  112. if ( val < 0 || val == null ) {
  113. val = elem.style[ name ];
  114. }
  115. // Computed unit is not pixels. Stop here and return.
  116. if ( rnumnonpx.test( val ) ) {
  117. return val;
  118. }
  119. // Check for style in case a browser which returns unreliable values
  120. // for getComputedStyle silently falls back to the reliable elem.style
  121. valueIsBorderBox = isBorderBox &&
  122. ( support.boxSizingReliable() || val === elem.style[ name ] );
  123. // Normalize "", auto, and prepare for extra
  124. val = parseFloat( val ) || 0;
  125. }
  126. // Use the active box-sizing model to add/subtract irrelevant styles
  127. return ( val +
  128. augmentWidthOrHeight(
  129. elem,
  130. name,
  131. extra || ( isBorderBox ? "border" : "content" ),
  132. valueIsBorderBox,
  133. styles
  134. )
  135. ) + "px";
  136. }
  137. jQuery.extend( {
  138. // Add in style property hooks for overriding the default
  139. // behavior of getting and setting a style property
  140. cssHooks: {
  141. opacity: {
  142. get: function( elem, computed ) {
  143. if ( computed ) {
  144. // We should always get a number back from opacity
  145. var ret = curCSS( elem, "opacity" );
  146. return ret === "" ? "1" : ret;
  147. }
  148. }
  149. }
  150. },
  151. // Don't automatically add "px" to these possibly-unitless properties
  152. cssNumber: {
  153. "animationIterationCount": true,
  154. "columnCount": true,
  155. "fillOpacity": true,
  156. "flexGrow": true,
  157. "flexShrink": true,
  158. "fontWeight": true,
  159. "lineHeight": true,
  160. "opacity": true,
  161. "order": true,
  162. "orphans": true,
  163. "widows": true,
  164. "zIndex": true,
  165. "zoom": true
  166. },
  167. // Add in properties whose names you wish to fix before
  168. // setting or getting the value
  169. cssProps: {
  170. "float": "cssFloat"
  171. },
  172. // Get and set the style property on a DOM Node
  173. style: function( elem, name, value, extra ) {
  174. // Don't set styles on text and comment nodes
  175. if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) {
  176. return;
  177. }
  178. // Make sure that we're working with the right name
  179. var ret, type, hooks,
  180. origName = jQuery.camelCase( name ),
  181. style = elem.style;
  182. name = jQuery.cssProps[ origName ] ||
  183. ( jQuery.cssProps[ origName ] = vendorPropName( origName ) || origName );
  184. // Gets hook for the prefixed version, then unprefixed version
  185. hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];
  186. // Check if we're setting a value
  187. if ( value !== undefined ) {
  188. type = typeof value;
  189. // Convert "+=" or "-=" to relative numbers (#7345)
  190. if ( type === "string" && ( ret = rcssNum.exec( value ) ) && ret[ 1 ] ) {
  191. value = adjustCSS( elem, name, ret );
  192. // Fixes bug #9237
  193. type = "number";
  194. }
  195. // Make sure that null and NaN values aren't set (#7116)
  196. if ( value == null || value !== value ) {
  197. return;
  198. }
  199. // If a number was passed in, add the unit (except for certain CSS properties)
  200. if ( type === "number" ) {
  201. value += ret && ret[ 3 ] || ( jQuery.cssNumber[ origName ] ? "" : "px" );
  202. }
  203. // background-* props affect original clone's values
  204. if ( !support.clearCloneStyle && value === "" && name.indexOf( "background" ) === 0 ) {
  205. style[ name ] = "inherit";
  206. }
  207. // If a hook was provided, use that value, otherwise just set the specified value
  208. if ( !hooks || !( "set" in hooks ) ||
  209. ( value = hooks.set( elem, value, extra ) ) !== undefined ) {
  210. style[ name ] = value;
  211. }
  212. } else {
  213. // If a hook was provided get the non-computed value from there
  214. if ( hooks && "get" in hooks &&
  215. ( ret = hooks.get( elem, false, extra ) ) !== undefined ) {
  216. return ret;
  217. }
  218. // Otherwise just get the value from the style object
  219. return style[ name ];
  220. }
  221. },
  222. css: function( elem, name, extra, styles ) {
  223. var val, num, hooks,
  224. origName = jQuery.camelCase( name );
  225. // Make sure that we're working with the right name
  226. name = jQuery.cssProps[ origName ] ||
  227. ( jQuery.cssProps[ origName ] = vendorPropName( origName ) || origName );
  228. // Try prefixed name followed by the unprefixed name
  229. hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];
  230. // If a hook was provided get the computed value from there
  231. if ( hooks && "get" in hooks ) {
  232. val = hooks.get( elem, true, extra );
  233. }
  234. // Otherwise, if a way to get the computed value exists, use that
  235. if ( val === undefined ) {
  236. val = curCSS( elem, name, styles );
  237. }
  238. // Convert "normal" to computed value
  239. if ( val === "normal" && name in cssNormalTransform ) {
  240. val = cssNormalTransform[ name ];
  241. }
  242. // Make numeric if forced or a qualifier was provided and val looks numeric
  243. if ( extra === "" || extra ) {
  244. num = parseFloat( val );
  245. return extra === true || isFinite( num ) ? num || 0 : val;
  246. }
  247. return val;
  248. }
  249. } );
  250. jQuery.each( [ "height", "width" ], function( i, name ) {
  251. jQuery.cssHooks[ name ] = {
  252. get: function( elem, computed, extra ) {
  253. if ( computed ) {
  254. // Certain elements can have dimension info if we invisibly show them
  255. // but it must have a current display style that would benefit
  256. return rdisplayswap.test( jQuery.css( elem, "display" ) ) &&
  257. // Support: Safari 8+
  258. // Table columns in Safari have non-zero offsetWidth & zero
  259. // getBoundingClientRect().width unless display is changed.
  260. // Support: IE <=11 only
  261. // Running getBoundingClientRect on a disconnected node
  262. // in IE throws an error.
  263. ( !elem.getClientRects().length || !elem.getBoundingClientRect().width ) ?
  264. swap( elem, cssShow, function() {
  265. return getWidthOrHeight( elem, name, extra );
  266. } ) :
  267. getWidthOrHeight( elem, name, extra );
  268. }
  269. },
  270. set: function( elem, value, extra ) {
  271. var matches,
  272. styles = extra && getStyles( elem ),
  273. subtract = extra && augmentWidthOrHeight(
  274. elem,
  275. name,
  276. extra,
  277. jQuery.css( elem, "boxSizing", false, styles ) === "border-box",
  278. styles
  279. );
  280. // Convert to pixels if value adjustment is needed
  281. if ( subtract && ( matches = rcssNum.exec( value ) ) &&
  282. ( matches[ 3 ] || "px" ) !== "px" ) {
  283. elem.style[ name ] = value;
  284. value = jQuery.css( elem, name );
  285. }
  286. return setPositiveNumber( elem, value, subtract );
  287. }
  288. };
  289. } );
  290. jQuery.cssHooks.marginLeft = addGetHookIf( support.reliableMarginLeft,
  291. function( elem, computed ) {
  292. if ( computed ) {
  293. return ( parseFloat( curCSS( elem, "marginLeft" ) ) ||
  294. elem.getBoundingClientRect().left -
  295. swap( elem, { marginLeft: 0 }, function() {
  296. return elem.getBoundingClientRect().left;
  297. } )
  298. ) + "px";
  299. }
  300. }
  301. );
  302. // These hooks are used by animate to expand properties
  303. jQuery.each( {
  304. margin: "",
  305. padding: "",
  306. border: "Width"
  307. }, function( prefix, suffix ) {
  308. jQuery.cssHooks[ prefix + suffix ] = {
  309. expand: function( value ) {
  310. var i = 0,
  311. expanded = {},
  312. // Assumes a single number if not a string
  313. parts = typeof value === "string" ? value.split( " " ) : [ value ];
  314. for ( ; i < 4; i++ ) {
  315. expanded[ prefix + cssExpand[ i ] + suffix ] =
  316. parts[ i ] || parts[ i - 2 ] || parts[ 0 ];
  317. }
  318. return expanded;
  319. }
  320. };
  321. if ( !rmargin.test( prefix ) ) {
  322. jQuery.cssHooks[ prefix + suffix ].set = setPositiveNumber;
  323. }
  324. } );
  325. jQuery.fn.extend( {
  326. css: function( name, value ) {
  327. return access( this, function( elem, name, value ) {
  328. var styles, len,
  329. map = {},
  330. i = 0;
  331. if ( jQuery.isArray( name ) ) {
  332. styles = getStyles( elem );
  333. len = name.length;
  334. for ( ; i < len; i++ ) {
  335. map[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles );
  336. }
  337. return map;
  338. }
  339. return value !== undefined ?
  340. jQuery.style( elem, name, value ) :
  341. jQuery.css( elem, name );
  342. }, name, value, arguments.length > 1 );
  343. }
  344. } );
  345. return jQuery;
  346. } );