2017-05-03 15:35:00 +02:00
'use strict' ;
/ * *
* Copyright ( c ) 2013 - present , Facebook , Inc .
*
2017-10-14 18:40:54 +02:00
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree .
2017-05-03 15:35:00 +02:00
*
* @ typechecks
* /
var invariant = require ( './invariant' ) ;
/ * *
* The CSSCore module specifies the API ( and implements most of the methods )
* that should be used when dealing with the display of elements ( via their
* CSS classes and visibility on screen . It is an API focused on mutating the
* display and not reading it as no logical state should be encoded in the
* display of elements .
* /
/* Slow implementation for browsers that don't natively support .matches() */
function matchesSelector _SLOW ( element , selector ) {
var root = element ;
while ( root . parentNode ) {
root = root . parentNode ;
}
var all = root . querySelectorAll ( selector ) ;
return Array . prototype . indexOf . call ( all , element ) !== - 1 ;
}
var CSSCore = {
/ * *
* Adds the class passed in to the element if it doesn ' t already have it .
*
* @ param { DOMElement } element the element to set the class on
* @ param { string } className the CSS className
* @ return { DOMElement } the element passed in
* /
addClass : function addClass ( element , className ) {
! ! /\s/ . test ( className ) ? process . env . NODE _ENV !== 'production' ? invariant ( false , 'CSSCore.addClass takes only a single class name. "%s" contains ' + 'multiple classes.' , className ) : invariant ( false ) : void 0 ;
if ( className ) {
if ( element . classList ) {
element . classList . add ( className ) ;
} else if ( ! CSSCore . hasClass ( element , className ) ) {
element . className = element . className + ' ' + className ;
}
}
return element ;
} ,
/ * *
* Removes the class passed in from the element
*
* @ param { DOMElement } element the element to set the class on
* @ param { string } className the CSS className
* @ return { DOMElement } the element passed in
* /
removeClass : function removeClass ( element , className ) {
! ! /\s/ . test ( className ) ? process . env . NODE _ENV !== 'production' ? invariant ( false , 'CSSCore.removeClass takes only a single class name. "%s" contains ' + 'multiple classes.' , className ) : invariant ( false ) : void 0 ;
if ( className ) {
if ( element . classList ) {
element . classList . remove ( className ) ;
} else if ( CSSCore . hasClass ( element , className ) ) {
element . className = element . className . replace ( new RegExp ( '(^|\\s)' + className + '(?:\\s|$)' , 'g' ) , '$1' ) . replace ( /\s+/g , ' ' ) // multiple spaces to one
. replace ( /^\s*|\s*$/g , '' ) ; // trim the ends
}
}
return element ;
} ,
/ * *
* Helper to add or remove a class from an element based on a condition .
*
* @ param { DOMElement } element the element to set the class on
* @ param { string } className the CSS className
* @ param { * } bool condition to whether to add or remove the class
* @ return { DOMElement } the element passed in
* /
conditionClass : function conditionClass ( element , className , bool ) {
return ( bool ? CSSCore . addClass : CSSCore . removeClass ) ( element , className ) ;
} ,
/ * *
* Tests whether the element has the class specified .
*
* @ param { DOMNode | DOMWindow } element the element to check the class on
* @ param { string } className the CSS className
* @ return { boolean } true if the element has the class , false if not
* /
hasClass : function hasClass ( element , className ) {
! ! /\s/ . test ( className ) ? process . env . NODE _ENV !== 'production' ? invariant ( false , 'CSS.hasClass takes only a single class name.' ) : invariant ( false ) : void 0 ;
if ( element . classList ) {
return ! ! className && element . classList . contains ( className ) ;
}
return ( ' ' + element . className + ' ' ) . indexOf ( ' ' + className + ' ' ) > - 1 ;
} ,
/ * *
* Tests whether the element matches the selector specified
*
* @ param { DOMNode | DOMWindow } element the element that we are querying
* @ param { string } selector the CSS selector
* @ return { boolean } true if the element matches the selector , false if not
* /
matchesSelector : function matchesSelector ( element , selector ) {
var matchesImpl = element . matches || element . webkitMatchesSelector || element . mozMatchesSelector || element . msMatchesSelector || function ( s ) {
return matchesSelector _SLOW ( element , s ) ;
} ;
return matchesImpl . call ( element , selector ) ;
}
} ;
module . exports = CSSCore ;