@cfpb/cfpb-atomic-component
Advanced tools
Comparing version 0.17.9 to 0.17.14
{ | ||
"name": "@cfpb/cfpb-atomic-component", | ||
"version": "0.17.9", | ||
"version": "0.17.14", | ||
"description": "Design System atomic component micro-framework", | ||
@@ -16,3 +16,3 @@ "less": "src/cfpb-atomic-component.less", | ||
], | ||
"gitHead": "b9b10936fed9da64ee9dfa9cccf355adf62eee6e" | ||
"gitHead": "887291915f64eb35d804fb7ec7d010e81c2bee8d" | ||
} |
@@ -43,3 +43,3 @@ # @cfpb/atomic-component [![Build Status](https://img.shields.io/travis/cfpb/design-system.svg)](https://travis-ci.org/cfpb/design-system) [![npm](https://img.shields.io/npm/v/@cfpb/atomic-component.svg?style=flat-square)](https://www.npmjs.com/package/@cfpb/atomic-component) | ||
Utility functions for checking Javascript types and primitives. | ||
Utility functions for checking Javascript types and primitives. | ||
@@ -82,4 +82,5 @@ #### Example | ||
## Open source licensing info | ||
1. [TERMS](TERMS.md) | ||
2. [LICENSE](LICENSE) | ||
3. [CFPB Source Code Policy](https://github.com/cfpb/source-code-policy/) |
@@ -15,3 +15,3 @@ /* ========================================================================== | ||
import { assign } from '../utilities/object-assign.js'; | ||
const Delegate = require( 'ftdomdelegate' ).Delegate; | ||
const Delegate = require('ftdomdelegate').Delegate; | ||
import EventObserver from '../mixins/EventObserver.js'; | ||
@@ -28,29 +28,29 @@ import typeCheckers from '../utilities/type-checkers.js'; | ||
* @param {HTMLElement} element - The element to set as the base element. | ||
* @param {Object} attributes - Hash of attributes to set on base element. | ||
* @param {object} attributes - Hash of attributes to set on base element. | ||
*/ | ||
function AtomicComponent( element, attributes ) { | ||
function AtomicComponent(element, attributes) { | ||
this.element = element; | ||
this.initializers = []; | ||
this.uId = this.uniqueId( 'ac' ); | ||
assign( this, attributes ); | ||
this.uId = this.uniqueId('ac'); | ||
assign(this, attributes); | ||
this.processModifiers(); | ||
this.ensureElement(); | ||
this.setCachedElements(); | ||
this.initializers.push( this.initialize ); | ||
this.initializers.push(this.initialize); | ||
} | ||
// Public instance Methods and properties. | ||
assign( AtomicComponent.prototype, new EventObserver(), { | ||
assign(AtomicComponent.prototype, new EventObserver(), { | ||
/** | ||
* Run through and call the component's initializers. | ||
* | ||
* @returns {AtomicComponent} An instance. | ||
*/ | ||
init: function() { | ||
this.initializers.forEach( function( func ) { | ||
if ( typeCheckers.isFunction( func ) ) { | ||
func.apply( this, arguments ); | ||
init: function () { | ||
this.initializers.forEach(function (func) { | ||
if (typeCheckers.isFunction(func)) { | ||
func.apply(this, arguments); | ||
} | ||
}, this ); | ||
this.dispatchEvent( 'component:initialized' ); | ||
}, this); | ||
this.dispatchEvent('component:initialized'); | ||
@@ -63,20 +63,17 @@ return this; | ||
* correspond with BEM modifiers. | ||
* | ||
* @param {Object} attributes - Hash of attributes to set on base element. | ||
* @param {Object} atomicComponent - Base component. | ||
*/ | ||
processModifiers: function() { | ||
if ( !this.modifiers ) { | ||
processModifiers: function () { | ||
if (!this.modifiers) { | ||
return; | ||
} | ||
this.modifiers.forEach( function( modifier ) { | ||
const modifierClass = modifier.ui.base.substring( 1 ); | ||
if ( this.element.classList.contains( modifierClass ) ) { | ||
if ( modifier.initialize ) { | ||
this.initializers.push( modifier.initialize ); | ||
this.modifiers.forEach(function (modifier) { | ||
const modifierClass = modifier.ui.base.substring(1); | ||
if (this.element.classList.contains(modifierClass)) { | ||
if (modifier.initialize) { | ||
this.initializers.push(modifier.initialize); | ||
} | ||
assign( this, modifier ); | ||
assign(this, modifier); | ||
} | ||
}, this ); | ||
}, this); | ||
}, | ||
@@ -89,3 +86,3 @@ | ||
*/ | ||
render: function() { | ||
render: function () { | ||
return this; | ||
@@ -97,13 +94,14 @@ }, | ||
*/ | ||
ensureElement: function() { | ||
if ( !this.element ) { // eslint-disable-line no-negated-condition | ||
const attrs = assign( {}, this.attributes ); | ||
ensureElement: function () { | ||
if (!this.element) { | ||
// eslint-disable-line no-negated-condition | ||
const attrs = assign({}, this.attributes); | ||
attrs.id = this.id || this.u_id; | ||
if ( this.className ) attrs.class = this.className; | ||
this.setElement( document.createElement( TAG_NAME ) ); | ||
this.setElementAttributes( attrs ); | ||
if (this.className) attrs.class = this.className; | ||
this.setElement(document.createElement(TAG_NAME)); | ||
this.setElementAttributes(attrs); | ||
} else { | ||
this.setElement( this.element ); | ||
this.setElement(this.element); | ||
} | ||
setInitFlag( this.element ); | ||
setInitFlag(this.element); | ||
}, | ||
@@ -117,4 +115,4 @@ | ||
*/ | ||
setElement: function( element ) { | ||
if ( this.element ) { | ||
setElement: function (element) { | ||
if (this.element) { | ||
this.undelegateEvents(); | ||
@@ -133,15 +131,15 @@ } | ||
* | ||
* @returns {Object} Hash of event names and cached elements. | ||
* @returns {object} Hash of event names and cached elements. | ||
*/ | ||
setCachedElements: function() { | ||
const ui = assign( {}, this.ui ); | ||
setCachedElements: function () { | ||
const ui = assign({}, this.ui); | ||
let key; | ||
let element; | ||
for ( key in ui ) { | ||
if ( ui.hasOwnProperty( key ) ) { | ||
element = this.element.querySelectorAll( ui[key] ); | ||
if ( element.length === 1 ) { | ||
for (key in ui) { | ||
if ({}.hasOwnProperty.call(ui, key)) { | ||
element = this.element.querySelectorAll(ui[key]); | ||
if (element.length === 1) { | ||
ui[key] = element[0]; | ||
} else if ( element.length > 1 ) { | ||
} else if (element.length > 1) { | ||
ui[key] = element; | ||
@@ -165,10 +163,10 @@ } else { | ||
*/ | ||
destroy: function() { | ||
if ( this.element ) { | ||
this.element.parentNode.removeChild( this.element ); | ||
if ( this.element.view ) delete this.element.view; | ||
destroy: function () { | ||
if (this.element) { | ||
this.element.parentNode.removeChild(this.element); | ||
if (this.element.view) delete this.element.view; | ||
delete this.element; | ||
} | ||
this.undelegateEvents(); | ||
this.dispatchEvent( 'component:destroyed' ); | ||
this.dispatchEvent('component:destroyed'); | ||
@@ -181,10 +179,10 @@ return true; | ||
* | ||
* @param {Object} attributes - Hash of attributes to set on base element. | ||
* @param {object} attributes - Hash of attributes to set on base element. | ||
*/ | ||
setElementAttributes: function( attributes ) { | ||
setElementAttributes: function (attributes) { | ||
let property; | ||
for ( property in attributes ) { | ||
if ( attributes.hasOwnProperty( property ) ) { | ||
this.element.setAttribute( property, attributes[property] ); | ||
for (property in attributes) { | ||
if ({}.hasOwnProperty.call(attributes, property)) { | ||
this.element.setAttribute(property, attributes[property]); | ||
} | ||
@@ -200,6 +198,6 @@ } | ||
* | ||
* @param {Object} events - Hash of events to bind to the dom element. | ||
* @param {object} events - Hash of events to bind to the dom element. | ||
* @returns {AtomicComponent} An instance. | ||
*/ | ||
delegateEvents: function( events ) { | ||
delegateEvents: function (events) { | ||
const delegateEventSplitter = /^(\S+)\s*(.*)$/; | ||
@@ -210,4 +208,4 @@ let key; | ||
events = events || ( events = this.events ); | ||
if ( !events ) { | ||
events = events || (events = this.events); | ||
if (!events) { | ||
return this; | ||
@@ -217,16 +215,16 @@ } | ||
this.undelegateEvents(); | ||
this._delegate = new Delegate( this.element ); | ||
for ( key in events ) { | ||
if ( {}.hasOwnProperty.call( events, key ) ) { | ||
this._delegate = new Delegate(this.element); | ||
for (key in events) { | ||
if ({}.hasOwnProperty.call(events, key)) { | ||
method = events[key]; | ||
if ( typeCheckers.isFunction( this[method] ) ) { | ||
if (typeCheckers.isFunction(this[method])) { | ||
method = this[method]; | ||
} | ||
if ( method ) { | ||
match = key.match( delegateEventSplitter ); | ||
this.delegate( match[1], match[2], method.bind( this ) ); | ||
if (method) { | ||
match = key.match(delegateEventSplitter); | ||
this.delegate(match[1], match[2], method.bind(this)); | ||
} | ||
} | ||
} | ||
this.dispatchEvent( 'component:bound' ); | ||
this.dispatchEvent('component:bound'); | ||
@@ -245,4 +243,4 @@ return this; | ||
*/ | ||
delegate: function( eventName, selector, listener ) { | ||
this._delegate.on( eventName, selector, listener ); | ||
delegate: function (eventName, selector, listener) { | ||
this._delegate.on(eventName, selector, listener); | ||
@@ -257,7 +255,7 @@ return this; | ||
*/ | ||
undelegateEvents: function() { | ||
if ( this._delegate ) { | ||
undelegateEvents: function () { | ||
if (this._delegate) { | ||
this._delegate.destroy(); | ||
} | ||
this.element.removeAttribute( 'data-js-hook' ); | ||
this.element.removeAttribute('data-js-hook'); | ||
@@ -273,8 +271,7 @@ return this; | ||
*/ | ||
uniqueId: function( prefix ) { | ||
return prefix + '_' + Math.random().toString( 36 ).substr( 2, 9 ); | ||
} | ||
uniqueId: function (prefix) { | ||
return prefix + '_' + Math.random().toString(36).substr(2, 9); | ||
}, | ||
}); | ||
} ); | ||
// Static Methods | ||
@@ -286,9 +283,9 @@ | ||
* | ||
* @param {Object} attributes - Hash of attributes to set on base element. | ||
* @param {object} attributes - Hash of attributes to set on base element. | ||
* @returns {Function} Extended child constructor function. | ||
*/ | ||
function extend( attributes ) { | ||
function extend(attributes) { | ||
/** | ||
* Function used as constructor in order to establish inheritance chain. | ||
* | ||
* @returns {AtomicComponent} An instance. | ||
@@ -298,11 +295,13 @@ */ | ||
this._super = AtomicComponent.prototype; | ||
return AtomicComponent.apply( this, arguments ); | ||
return AtomicComponent.apply(this, arguments); | ||
} | ||
child.prototype = Object.create( AtomicComponent.prototype ); | ||
assign( child.prototype, attributes ); | ||
assign( child, AtomicComponent ); | ||
child.prototype = Object.create(AtomicComponent.prototype); | ||
assign(child.prototype, attributes); | ||
assign(child, AtomicComponent); | ||
if ( attributes.hasOwnProperty( 'ui' ) && | ||
attributes.ui.hasOwnProperty( 'base' ) ) { | ||
if ( | ||
{}.hasOwnProperty.call(attributes, 'ui') && | ||
{}.hasOwnProperty.call(attributes.ui, 'base') | ||
) { | ||
child.selector = attributes.ui.base; | ||
@@ -320,7 +319,7 @@ } | ||
* | ||
* @param {HTMLNode} scope - Where to search for components within. | ||
* @param {HTMLElement} scope - Where to search for components within. | ||
* @returns {Array} List of AtomicComponent instances. | ||
*/ | ||
function init( scope ) { | ||
const components = instantiateAll( this.selector, this, scope ); | ||
function init(scope) { | ||
const components = instantiateAll(this.selector, this, scope); | ||
return components; | ||
@@ -327,0 +326,0 @@ } |
/** | ||
* EventObserver | ||
* | ||
* @class | ||
* | ||
* @classdesc Used for creating an object | ||
* that can be used to dispatch and listen to custom events. | ||
* @returns {Object} An EventObserver instance. | ||
* @returns {object} An EventObserver instance. | ||
*/ | ||
function EventObserver() { | ||
// The events registered on this instance. | ||
@@ -16,11 +15,12 @@ const _events = {}; | ||
* Register an event listener. | ||
* | ||
* @param {string} event - The event name to listen for. | ||
* @param {Function} callback - The function called when the event has fired. | ||
* @returns {Object} The instance this EventObserver instance is decorating. | ||
* @returns {object} The instance this EventObserver instance is decorating. | ||
*/ | ||
function addEventListener( event, callback ) { | ||
if ( _events.hasOwnProperty( event ) ) { | ||
_events[event].push( callback ); | ||
function addEventListener(event, callback) { | ||
if ({}.hasOwnProperty.call(_events, event)) { | ||
_events[event].push(callback); | ||
} else { | ||
_events[event] = [ callback ]; | ||
_events[event] = [callback]; | ||
} | ||
@@ -34,15 +34,16 @@ | ||
* Must match a call made to addEventListener. | ||
* | ||
* @param {string} event - The event name to remove. | ||
* @param {Function} callback - The function attached to the event. | ||
* @returns {Object} The instance this EventObserver instance is decorating. | ||
* @returns {object} The instance this EventObserver instance is decorating. | ||
*/ | ||
function removeEventListener( event, callback ) { | ||
if ( !_events.hasOwnProperty( event ) ) { | ||
function removeEventListener(event, callback) { | ||
if (!{}.hasOwnProperty.call(_events, event)) { | ||
return this; | ||
} | ||
const index = _events[event].indexOf( callback ); | ||
const index = _events[event].indexOf(callback); | ||
// Check if there are any callbacks associated with a particular event. | ||
if ( index !== -1 ) { | ||
_events[event].splice( index, 1 ); | ||
if (index !== -1) { | ||
_events[event].splice(index, 1); | ||
} | ||
@@ -55,8 +56,9 @@ | ||
* Broadcast an event. | ||
* | ||
* @param {string} event - The type of event to broadcast. | ||
* @param {Object} options - The event object to pass to the event handler. | ||
* @returns {Object} The instance this EventObserver instance is decorating. | ||
* @param {object} options - The event object to pass to the event handler. | ||
* @returns {object} The instance this EventObserver instance is decorating. | ||
*/ | ||
function dispatchEvent( event, options ) { | ||
if ( !_events.hasOwnProperty( event ) ) { | ||
function dispatchEvent(event, options) { | ||
if (!{}.hasOwnProperty.call(_events, event)) { | ||
return this; | ||
@@ -68,4 +70,4 @@ } | ||
const evts = _events[event]; | ||
for ( let i = 0, len = evts.length; i < len; i++ ) { | ||
evts[i].call( this, options ); | ||
for (let i = 0, len = evts.length; i < len; i++) { | ||
evts[i].call(this, options); | ||
} | ||
@@ -77,3 +79,3 @@ | ||
/** | ||
* @returns {Object} Map of registered events. | ||
* @returns {object} Map of registered events. | ||
*/ | ||
@@ -80,0 +82,0 @@ function getRegisteredEvents() { |
@@ -27,50 +27,55 @@ /* ========================================================================== | ||
/** | ||
* Check that a particular element passed into the constructor of | ||
* an atomic component exists and that the correct atomic class | ||
* is present on the element. | ||
* @param {HTMLNode} element | ||
* The DOM element within which to search for the atomic element class. | ||
* @param {HTMLElement} element - The DOM element within which to search for | ||
* the atomic element class. | ||
* @param {string} baseClass - The CSS class name for the atomic element. | ||
* @returns {HTMLNode} The DOM element for the atomic element. | ||
* @returns {HTMLElement} The DOM element for the atomic element. | ||
* @throws {Error} If DOM element passed into the atomic element is not valid. | ||
*/ | ||
function checkDom( element, baseClass ) { | ||
_verifyElementExists( element, baseClass ); | ||
const dom = _verifyClassExists( element, baseClass ); | ||
function _verifyElementExists(element, baseClass) { | ||
if (!element || !element.classList) { | ||
const msg = | ||
element + | ||
' is not valid. ' + | ||
'Check that element is a DOM node with class "' + | ||
baseClass + | ||
'"'; | ||
throw new Error(msg); | ||
} | ||
return dom; | ||
return element; | ||
} | ||
/** | ||
* @param {HTMLNode} element | ||
* The DOM element within which to search for the atomic element class. | ||
* @param {HTMLElement} element - The DOM element within which to search | ||
* for the atomic element class. | ||
* @param {string} baseClass - The CSS class name for the atomic element. | ||
* @returns {HTMLNode} The DOM element for the atomic element. | ||
* @throws {Error} If DOM element passed into the atomic element is not valid. | ||
* @returns {HTMLElement} The DOM element for the atomic element. | ||
* @throws {Error} If baseClass was not found on the element. | ||
*/ | ||
function _verifyElementExists( element, baseClass ) { | ||
if ( !element || !element.classList ) { | ||
const msg = element + ' is not valid. ' + | ||
'Check that element is a DOM node with class "' + | ||
baseClass + '"'; | ||
throw new Error( msg ); | ||
function _verifyClassExists(element, baseClass) { | ||
const dom = element.classList.contains(baseClass) | ||
? element | ||
: element.querySelector('.' + baseClass); | ||
if (!dom) { | ||
const msg = baseClass + ' not found on or in passed DOM node.'; | ||
throw new Error(msg); | ||
} | ||
return element; | ||
return dom; | ||
} | ||
/** | ||
* @param {HTMLNode} element | ||
* The DOM element within which to search for the atomic element class. | ||
* @param {string} baseClass The CSS class name for the atomic element. | ||
* @returns {HTMLNode} The DOM element for the atomic element. | ||
* @throws {Error} If baseClass was not found on the element. | ||
* Check that a particular element passed into the constructor of | ||
* an atomic component exists and that the correct atomic class | ||
* is present on the element. | ||
* | ||
* @param {HTMLElement} element - The DOM element within which to search | ||
* for the atomic element class. | ||
* @param {string} baseClass - The CSS class name for the atomic element. | ||
* @returns {HTMLElement} The DOM element for the atomic element. | ||
* @throws {Error} If DOM element passed into the atomic element is not valid. | ||
*/ | ||
function _verifyClassExists( element, baseClass ) { | ||
const dom = element.classList.contains( baseClass ) ? | ||
element : element.querySelector( '.' + baseClass ); | ||
if ( !dom ) { | ||
const msg = baseClass + ' not found on or in passed DOM node.'; | ||
throw new Error( msg ); | ||
} | ||
function checkDom(element, baseClass) { | ||
_verifyElementExists(element, baseClass); | ||
const dom = _verifyClassExists(element, baseClass); | ||
@@ -84,13 +89,13 @@ return dom; | ||
* is initializing when it has already been initialized elsewhere. | ||
* @param {HTMLNode} element - The DOM element for the atomic component. | ||
* @param {null} destroy - Pass in true to . | ||
* | ||
* @param {HTMLElement} element - The DOM element for the atomic component. | ||
* @returns {boolean} True if the init data-js-* hook attribute was set, | ||
* false otherwise. | ||
*/ | ||
function setInitFlag( element ) { | ||
if ( contains( element, INIT_FLAG ) ) { | ||
function setInitFlag(element) { | ||
if (contains(element, INIT_FLAG)) { | ||
return false; | ||
} | ||
add( element, INIT_FLAG ); | ||
add(element, INIT_FLAG); | ||
@@ -103,12 +108,13 @@ return true; | ||
* This might be used if the DOM of an atomic element is cloned. | ||
* @param {HTMLNode} element - The DOM element for the atomic component. | ||
* | ||
* @param {HTMLElement} element - The DOM element for the atomic component. | ||
* @returns {boolean} True if the init data-js-* hook attribute was destroyed, | ||
* otherwise false if it didn't exist. | ||
*/ | ||
function destroyInitFlag( element ) { | ||
if ( !contains( element, INIT_FLAG ) ) { | ||
function destroyInitFlag(element) { | ||
if (!contains(element, INIT_FLAG)) { | ||
return false; | ||
} | ||
remove( element, INIT_FLAG ); | ||
remove(element, INIT_FLAG); | ||
@@ -121,18 +127,18 @@ return true; | ||
* @param {Function} Constructor - A constructor function. | ||
* @param {HTMLNode} [scope] - A dom node in which to query the selector. | ||
* @param {HTMLElement} [scope] - A dom node in which to query the selector. | ||
* If not supplied, it defaults to the `document`. | ||
* @returns {Array} List of instances that were instantiated. | ||
*/ | ||
function instantiateAll( selector, Constructor, scope ) { | ||
function instantiateAll(selector, Constructor, scope) { | ||
const base = scope || document; | ||
const elements = base.querySelectorAll( selector ); | ||
const elements = base.querySelectorAll(selector); | ||
const insts = []; | ||
let inst; | ||
let element; | ||
for ( let i = 0, len = elements.length; i < len; i++ ) { | ||
for (let i = 0, len = elements.length; i < len; i++) { | ||
element = elements[i]; | ||
if ( contains( element, INIT_FLAG ) === false ) { | ||
inst = new Constructor( element ); | ||
if (contains(element, INIT_FLAG) === false) { | ||
inst = new Constructor(element); | ||
inst.init(); | ||
insts.push( inst ); | ||
insts.push(inst); | ||
} | ||
@@ -144,7 +150,2 @@ } | ||
// Expose public methods. | ||
export { | ||
checkDom, | ||
destroyInitFlag, | ||
instantiateAll, | ||
setInitFlag | ||
}; | ||
export { checkDom, destroyInitFlag, instantiateAll, setInitFlag }; |
@@ -5,5 +5,4 @@ // Required modules. | ||
/** | ||
* @param {HTMLNode} element - DOM element. | ||
* @param {string} value | ||
* Value to add to the element's JS data-* hook. | ||
* @param {HTMLElement} element - DOM element. | ||
* @param {string} value - Value to add to the element's JS data-* hook. | ||
* @returns {string} The value that was added. | ||
@@ -13,13 +12,13 @@ * @throws {Error} If supplied value contains a space, | ||
*/ | ||
function add( element, value ) { | ||
if ( value.indexOf( ' ' ) !== -1 ) { | ||
function add(element, value) { | ||
if (value.indexOf(' ') !== -1) { | ||
const msg = JS_HOOK + ' values cannot contain spaces!'; | ||
throw new Error( msg ); | ||
throw new Error(msg); | ||
} | ||
const values = element.getAttribute( JS_HOOK ); | ||
if ( values !== null ) { | ||
const values = element.getAttribute(JS_HOOK); | ||
if (values !== null) { | ||
value = values + ' ' + value; | ||
} | ||
element.setAttribute( JS_HOOK, value ); | ||
element.setAttribute(JS_HOOK, value); | ||
@@ -30,14 +29,13 @@ return value; | ||
/** | ||
* @param {HTMLNode} element - DOM element. | ||
* @param {string} value | ||
* Value to remove from the JS data-* hook value. | ||
* @param {HTMLElement} element - DOM element. | ||
* @param {string} value - Value to remove from the JS data-* hook value. | ||
* @returns {boolean} True if value was removed, false otherwise. | ||
*/ | ||
function remove( element, value ) { | ||
const values = element.getAttribute( JS_HOOK ); | ||
const index = values.indexOf( value ); | ||
const valuesList = values.split( ' ' ); | ||
if ( index > -1 ) { | ||
valuesList.splice( index, 1 ); | ||
element.setAttribute( JS_HOOK, valuesList.join( ' ' ) ); | ||
function remove(element, value) { | ||
const values = element.getAttribute(JS_HOOK); | ||
const index = values.indexOf(value); | ||
const valuesList = values.split(' '); | ||
if (index > -1) { | ||
valuesList.splice(index, 1); | ||
element.setAttribute(JS_HOOK, valuesList.join(' ')); | ||
return true; | ||
@@ -50,21 +48,20 @@ } | ||
/** | ||
* @param {HTMLNode} element - DOM element. | ||
* @param {string} value | ||
* Value to check as existing as a JS data-* hook value. | ||
* @param {HTMLElement} element - DOM element. | ||
* @param {string} value - Value to check as existing as a JS data-* hook value. | ||
* @returns {boolean} True if the data-* hook value exists, false otherwise. | ||
*/ | ||
function contains( element, value ) { | ||
if ( !element ) { return false; } | ||
let values = element.getAttribute( JS_HOOK ); | ||
function contains(element, value) { | ||
if (!element) { | ||
return false; | ||
} | ||
let values = element.getAttribute(JS_HOOK); | ||
// If JS data-* hook is not set return immediately. | ||
if ( !values ) { return false; } | ||
values = values.split( ' ' ); | ||
if (!values) { | ||
return false; | ||
} | ||
values = values.split(' '); | ||
return values.indexOf( value ) > -1 ? true : false; | ||
return values.indexOf(value) > -1 ? true : false; | ||
} | ||
export { | ||
add, | ||
contains, | ||
remove | ||
}; | ||
export { add, contains, remove }; |
import typeCheckers from './type-checkers.js'; | ||
/** | ||
* Queries for the first match unless an HTMLNode is passed | ||
* @param {(HTMLNode|string)} expr HTMLNode or string to query for | ||
* @param {Object} con The document location to query | ||
* @returns {HTMLNode} The elem | ||
* Queries for the first match unless an HTMLElement is passed | ||
* | ||
* @param {(HTMLElement|string)} expr - An element or selector query string. | ||
* @param {object} con - The document location to query. | ||
* @returns {HTMLElement} The element. | ||
*/ | ||
function queryOne( expr, con ) { | ||
return typeCheckers.isString( expr ) ? | ||
( con || document ).querySelector( expr ) : | ||
expr || null; | ||
function queryOne(expr, con) { | ||
return typeCheckers.isString(expr) | ||
? (con || document).querySelector(expr) | ||
: expr || null; | ||
} | ||
/** | ||
* Search for support of the matches() method by looking at | ||
* browser prefixes. | ||
* | ||
* @param {HTMLElement} elem - The element to check | ||
* for support of matches() method. | ||
* @returns {Function} The appropriate matches() method of elem. | ||
*/ | ||
function _getMatchesMethod(elem) { | ||
return ( | ||
elem.matches || | ||
elem.webkitMatchesSelector || | ||
elem.mozMatchesSelector || | ||
elem.msMatchesSelector | ||
); | ||
} | ||
/** | ||
* Traverse the element and its parents (heading toward the document root) | ||
@@ -21,13 +39,13 @@ * until a node is found that matches the provided selector string. | ||
* | ||
* @param {HTMLNode} elem - A DOM element. | ||
* @param {HTMLElement} elem - A DOM element. | ||
* @param {string} selector - CSS selector. | ||
* @returns {HTMLNode} Element or nearest parent node that matches the selector. | ||
* @returns {HTMLElement} Element or nearest parent node that matches the selector. | ||
* Or null, if nothing is found. | ||
*/ | ||
function closest( elem, selector ) { | ||
if ( 'closest' in elem ) { | ||
return elem.closest( selector ); | ||
function closest(elem, selector) { | ||
if ('closest' in elem) { | ||
return elem.closest(selector); | ||
} | ||
const matchesSelector = _getMatchesMethod( elem ); | ||
const matchesSelector = _getMatchesMethod(elem); | ||
@@ -37,4 +55,4 @@ try { | ||
let match; | ||
while ( parent ) { | ||
if ( matchesSelector.bind( parent )( selector ) ) { | ||
while (parent) { | ||
if (matchesSelector.bind(parent)(selector)) { | ||
match = parent; | ||
@@ -45,7 +63,7 @@ } else { | ||
if ( match ) { | ||
if (match) { | ||
return parent; | ||
} | ||
} | ||
} catch ( err ) { | ||
} catch (err) { | ||
return null; | ||
@@ -57,20 +75,2 @@ } | ||
/** | ||
* Search for support of the matches() method by looking at | ||
* browser prefixes. | ||
* @param {HTMLNode} elem | ||
* The element to check for support of matches() method. | ||
* @returns {Function} The appropriate matches() method of elem. | ||
*/ | ||
function _getMatchesMethod( elem ) { | ||
return elem.matches || | ||
elem.webkitMatchesSelector || | ||
elem.mozMatchesSelector || | ||
elem.msMatchesSelector; | ||
} | ||
export { | ||
queryOne, | ||
closest | ||
}; | ||
export { queryOne, closest }; |
@@ -8,2 +8,3 @@ /* ========================================================================== | ||
* Query the browser's user agent string to see if it's on a mobile OS. | ||
* | ||
* @returns {boolean} True if on a mobile user agent, false otherwise. | ||
@@ -15,12 +16,9 @@ */ | ||
); | ||
if ( regex.test( navigator.userAgent ) ) { | ||
if (regex.test(navigator.userAgent)) { | ||
return true; | ||
} | ||
return false; | ||
} | ||
// Expose public methods. | ||
export { | ||
isMobileUserAgent | ||
}; | ||
export { isMobileUserAgent }; |
@@ -15,4 +15,4 @@ /* ========================================================================== | ||
*/ | ||
function _isPlainObject( object ) { | ||
return Object.prototype.toString.call( object ) === '[object Object]'; | ||
function _isPlainObject(object) { | ||
return Object.prototype.toString.call(object) === '[object Object]'; | ||
} | ||
@@ -27,15 +27,15 @@ | ||
* | ||
* @param {Object} destination object. | ||
* @returns {Object} assigned destination object. | ||
*/ | ||
function assign( destination ) { | ||
* @param {object} destination - object. | ||
* @returns {object} assigned destination object. | ||
*/ | ||
function assign(destination) { | ||
destination = destination || {}; | ||
for ( let i = 1, len = arguments.length; i < len; i++ ) { | ||
for (let i = 1, len = arguments.length; i < len; i++) { | ||
const source = arguments[i] || {}; | ||
let key; | ||
for ( key in source ) { | ||
if ( Object.prototype.hasOwnProperty.call( source, key ) ) { | ||
for (key in source) { | ||
if ({}.hasOwnProperty.call(source, key)) { | ||
const value = source[key]; | ||
if ( _isPlainObject( value ) ) { | ||
assign( destination[key] || ( destination[key] = {} ), value ); | ||
if (_isPlainObject(value)) { | ||
assign(destination[key] || (destination[key] = {}), value); | ||
} else { | ||
@@ -53,4 +53,2 @@ destination[key] = value; | ||
// Expose public methods. | ||
export { | ||
assign | ||
}; | ||
export { assign }; |
@@ -18,3 +18,2 @@ /** | ||
* the JavaScript loads. | ||
* | ||
* @example | ||
@@ -35,3 +34,2 @@ * A component may flag that it has certain JavaScript behaviors attached, | ||
* state set in the data-* JavaScript hook. | ||
* | ||
* @example | ||
@@ -61,14 +59,8 @@ * A component may flag that it has been initialized by setting | ||
const DIRECTIONS = { | ||
UP: 0, | ||
UP: 0, | ||
RIGHT: 1, | ||
DOWN: -1, | ||
LEFT: -2 | ||
DOWN: -1, | ||
LEFT: -2, | ||
}; | ||
export { | ||
BEHAVIOR_PREFIX, | ||
JS_HOOK, | ||
noopFunct, | ||
STATE_PREFIX, | ||
DIRECTIONS | ||
}; | ||
export { BEHAVIOR_PREFIX, JS_HOOK, noopFunct, STATE_PREFIX, DIRECTIONS }; |
@@ -8,5 +8,5 @@ // Required modules. | ||
CSS_PROPERTY: 'opacity', | ||
BASE_CLASS: 'u-alpha-transition', | ||
ALPHA_100: 'u-alpha-100', | ||
ALPHA_0: 'u-alpha-0' | ||
BASE_CLASS: 'u-alpha-transition', | ||
ALPHA_100: 'u-alpha-100', | ||
ALPHA_0: 'u-alpha-0', | ||
}; | ||
@@ -16,13 +16,17 @@ | ||
* AlphaTransition | ||
* | ||
* @class | ||
* | ||
* @classdesc Initializes new AlphaTransition behavior. | ||
* | ||
* @param {HTMLNode} element | ||
* DOM element to apply opacity transition to. | ||
* @param {HTMLElement} element - DOM element to apply opacity transition to. | ||
* @returns {AlphaTransition} An instance. | ||
*/ | ||
function AlphaTransition( element ) { | ||
function AlphaTransition(element) { | ||
const _baseTransition = new BaseTransition(element, CLASSES); | ||
const _baseTransition = new BaseTransition( element, CLASSES ); | ||
/** | ||
* Handle the end of a transition. | ||
*/ | ||
function _transitionComplete() { | ||
this.dispatchEvent(BaseTransition.END_EVENT, { target: this }); | ||
} | ||
@@ -34,3 +38,3 @@ /** | ||
_baseTransition.init(); | ||
const _transitionCompleteBinded = _transitionComplete.bind( this ); | ||
const _transitionCompleteBinded = _transitionComplete.bind(this); | ||
_baseTransition.addEventListener( | ||
@@ -44,14 +48,8 @@ BaseTransition.END_EVENT, | ||
/** | ||
* Handle the end of a transition. | ||
*/ | ||
function _transitionComplete() { | ||
this.dispatchEvent( BaseTransition.END_EVENT, { target: this } ); | ||
} | ||
/** | ||
* Fade to 100% by applying a utility alpha class. | ||
* | ||
* @returns {AlphaTransition} An instance. | ||
*/ | ||
function fadeIn() { | ||
_baseTransition.applyClass( CLASSES.ALPHA_100 ); | ||
_baseTransition.applyClass(CLASSES.ALPHA_100); | ||
@@ -63,6 +61,7 @@ return this; | ||
* Fade to nothing by applying a utility alpha class. | ||
* | ||
* @returns {AlphaTransition} An instance. | ||
*/ | ||
function fadeOut() { | ||
_baseTransition.applyClass( CLASSES.ALPHA_0 ); | ||
_baseTransition.applyClass(CLASSES.ALPHA_0); | ||
@@ -69,0 +68,0 @@ return this; |
@@ -7,15 +7,12 @@ // Required modules. | ||
* BaseTransition | ||
* | ||
* @class | ||
* | ||
* @classdesc Initializes new BaseTransition behavior. | ||
* This shouldn't be used directly, but instead should be | ||
* the base class used through composition by a specific transition. | ||
* | ||
* @param {HTMLNode} element | ||
* DOM element to apply transition to. | ||
* @param {Object} classes | ||
* The classes to apply to this transition. | ||
* @param {HTMLElement} element - DOM element to apply transition to. | ||
* @param {object} classes - The classes to apply to this transition. | ||
* @returns {BaseTransition} An instance. | ||
*/ | ||
function BaseTransition( element, classes ) { | ||
function BaseTransition(element, classes) { | ||
const _classes = classes; | ||
@@ -32,7 +29,9 @@ let _dom; | ||
// Make sure required attributes are passed in. | ||
if ( typeof _classes.CSS_PROPERTY === 'undefined' || | ||
typeof _classes.BASE_CLASS === 'undefined' ) { | ||
if ( | ||
typeof _classes.CSS_PROPERTY === 'undefined' || | ||
typeof _classes.BASE_CLASS === 'undefined' | ||
) { | ||
throw new Error( | ||
'Transitions require CSS_PROPERTY and BASE_CLASS ' + | ||
'to be passed into BaseTransition.' | ||
'to be passed into BaseTransition.' | ||
); | ||
@@ -42,82 +41,2 @@ } | ||
/** | ||
* @returns {BaseTransition} An instance. | ||
*/ | ||
function init() { | ||
_transitionCompleteBinded = _transitionComplete.bind( this ); | ||
_addEventListenerBinded = _addEventListener.bind( this ); | ||
setElement( element ); | ||
return this; | ||
} | ||
/** | ||
* Set the HTML element target of this transition. | ||
* @param {HTMLNode} targetElement - The target of the transition. | ||
*/ | ||
function setElement( targetElement ) { | ||
/* | ||
If the element has already been set, | ||
clear the transition classes from the old element. | ||
*/ | ||
if ( _dom ) { | ||
remove(); | ||
animateOn(); | ||
} | ||
_dom = targetElement; | ||
_dom.classList.add( _classes.BASE_CLASS ); | ||
_transitionEndEvent = _getTransitionEndEvent( _dom ); | ||
} | ||
/** | ||
* Add a "transition-duration: 0s" utility CSS class. | ||
* @returns {BaseTransition} An instance. | ||
*/ | ||
function animateOn() { | ||
if ( !_dom ) { return this; } | ||
_dom.classList.remove( BaseTransition.NO_ANIMATION_CLASS ); | ||
return this; | ||
} | ||
/** | ||
* Remove a "transition-duration: 0s" utility CSS class. | ||
* @returns {BaseTransition} An instance. | ||
*/ | ||
function animateOff() { | ||
if ( !_dom ) { return this; } | ||
_dom.classList.add( BaseTransition.NO_ANIMATION_CLASS ); | ||
return this; | ||
} | ||
/** | ||
* @returns {boolean} Whether the transition has a duration or not. | ||
* Returns false if this transition has not been initialized. | ||
*/ | ||
function isAnimated() { | ||
if ( !_dom ) { return false; } | ||
return !_dom.classList.contains( BaseTransition.NO_ANIMATION_CLASS ); | ||
} | ||
/** | ||
* Halt an in-progress animation and call the complete event immediately. | ||
*/ | ||
function halt() { | ||
if ( !_isAnimating ) { return; } | ||
_dom.style.webkitTransitionDuration = '0'; | ||
_dom.style.mozTransitionDuration = '0'; | ||
_dom.style.oTransitionDuration = '0'; | ||
_dom.style.transitionDuration = '0'; | ||
_dom.removeEventListener( | ||
_transitionEndEvent, | ||
_transitionCompleteBinded | ||
); | ||
_transitionCompleteBinded(); | ||
_dom.style.webkitTransitionDuration = ''; | ||
_dom.style.mozTransitionDuration = ''; | ||
_dom.style.oTransitionDuration = ''; | ||
_dom.style.transitionDuration = ''; | ||
} | ||
/** | ||
* Add an event listener to the transition, or call the transition | ||
@@ -127,3 +46,3 @@ * complete handler immediately if transition not supported. | ||
function _addEventListener() { | ||
_dom.classList.add( BaseTransition.ANIMATING_CLASS ); | ||
_dom.classList.add(BaseTransition.ANIMATING_CLASS); | ||
_isAnimating = true; | ||
@@ -136,8 +55,10 @@ | ||
*/ | ||
if ( _transitionEndEvent && | ||
!_dom.classList.contains( BaseTransition.NO_ANIMATION_CLASS ) ) { | ||
_dom.addEventListener( _transitionEndEvent, _transitionCompleteBinded ); | ||
this.dispatchEvent( BaseTransition.BEGIN_EVENT, { target: this } ); | ||
if ( | ||
_transitionEndEvent && | ||
!_dom.classList.contains(BaseTransition.NO_ANIMATION_CLASS) | ||
) { | ||
_dom.addEventListener(_transitionEndEvent, _transitionCompleteBinded); | ||
this.dispatchEvent(BaseTransition.BEGIN_EVENT, { target: this }); | ||
} else { | ||
this.dispatchEvent( BaseTransition.BEGIN_EVENT, { target: this } ); | ||
this.dispatchEvent(BaseTransition.BEGIN_EVENT, { target: this }); | ||
_transitionCompleteBinded(); | ||
@@ -151,3 +72,3 @@ } | ||
function _removeEventListener() { | ||
_dom.removeEventListener( _transitionEndEvent, _transitionCompleteBinded ); | ||
_dom.removeEventListener(_transitionEndEvent, _transitionCompleteBinded); | ||
} | ||
@@ -157,2 +78,3 @@ | ||
* Handle the end of a transition. | ||
* | ||
* @param {TransitionEvent} evt - Transition event object. | ||
@@ -162,4 +84,4 @@ * @returns {boolean} True if transition was cleaned up, | ||
*/ | ||
function _transitionComplete( evt ) { | ||
if ( evt && evt.propertyName !== _classes.CSS_PROPERTY ) { | ||
function _transitionComplete(evt) { | ||
if (evt && evt.propertyName !== _classes.CSS_PROPERTY) { | ||
return false; | ||
@@ -169,4 +91,4 @@ } | ||
_removeEventListener(); | ||
_dom.classList.remove( BaseTransition.ANIMATING_CLASS ); | ||
this.dispatchEvent( BaseTransition.END_EVENT, { target: this } ); | ||
_dom.classList.remove(BaseTransition.ANIMATING_CLASS); | ||
this.dispatchEvent(BaseTransition.END_EVENT, { target: this }); | ||
_isAnimating = false; | ||
@@ -182,7 +104,9 @@ return true; | ||
let prop; | ||
for ( prop in _classes ) { | ||
if ( _classes.hasOwnProperty( prop ) && | ||
_classes[prop] !== _classes.BASE_CLASS && | ||
_dom.classList.contains( _classes[prop] ) ) { | ||
_dom.classList.remove( _classes[prop] ); | ||
for (prop in _classes) { | ||
if ( | ||
{}.hasOwnProperty.call(_classes, prop) && | ||
_classes[prop] !== _classes.BASE_CLASS && | ||
_dom.classList.contains(_classes[prop]) | ||
) { | ||
_dom.classList.remove(_classes[prop]); | ||
} | ||
@@ -193,3 +117,23 @@ } | ||
/** | ||
* Halt an in-progress animation and call the complete event immediately. | ||
*/ | ||
function halt() { | ||
if (!_isAnimating) { | ||
return; | ||
} | ||
_dom.style.webkitTransitionDuration = '0'; | ||
_dom.style.mozTransitionDuration = '0'; | ||
_dom.style.oTransitionDuration = '0'; | ||
_dom.style.transitionDuration = '0'; | ||
_dom.removeEventListener(_transitionEndEvent, _transitionCompleteBinded); | ||
_transitionCompleteBinded(); | ||
_dom.style.webkitTransitionDuration = ''; | ||
_dom.style.mozTransitionDuration = ''; | ||
_dom.style.oTransitionDuration = ''; | ||
_dom.style.transitionDuration = ''; | ||
} | ||
/** | ||
* Remove all transition classes, if transition is initialized. | ||
* | ||
* @returns {boolean} | ||
@@ -199,5 +143,5 @@ * True, if the element's CSS classes were touched, false otherwise. | ||
function remove() { | ||
if ( _dom ) { | ||
if (_dom) { | ||
halt(); | ||
_dom.classList.remove( _classes.BASE_CLASS ); | ||
_dom.classList.remove(_classes.BASE_CLASS); | ||
_flush(); | ||
@@ -211,36 +155,38 @@ return true; | ||
/** | ||
* @param {string} className - A CSS class. | ||
* @returns {boolean} False if the class is already applied | ||
* or the transition is not initialized, | ||
* otherwise true if the class was applied. | ||
* Add a "transition-duration: 0s" utility CSS class. | ||
* | ||
* @returns {BaseTransition} An instance. | ||
*/ | ||
function applyClass( className ) { | ||
if ( !_dom ) { return false; } | ||
if ( !_isFlushed ) { | ||
_flush(); | ||
_isFlushed = true; | ||
function animateOn() { | ||
if (!_dom) { | ||
return this; | ||
} | ||
_dom.classList.remove(BaseTransition.NO_ANIMATION_CLASS); | ||
if ( _dom.classList.contains( className ) ) { | ||
return false; | ||
return this; | ||
} | ||
/** | ||
* Remove a "transition-duration: 0s" utility CSS class. | ||
* | ||
* @returns {BaseTransition} An instance. | ||
*/ | ||
function animateOff() { | ||
if (!_dom) { | ||
return this; | ||
} | ||
_dom.classList.add(BaseTransition.NO_ANIMATION_CLASS); | ||
_removeEventListener(); | ||
_dom.classList.remove( _lastClass ); | ||
_lastClass = className; | ||
_addEventListenerBinded(); | ||
_dom.classList.add( _lastClass ); | ||
return true; | ||
return this; | ||
} | ||
/** | ||
* @param {HTMLNode} elem | ||
* The element to check for support of transition end event. | ||
* @param {HTMLElement} elem - The element to check | ||
* for support of transition end event. | ||
* @returns {string} The browser-prefixed transition end event. | ||
*/ | ||
function _getTransitionEndEvent( elem ) { | ||
if ( !elem ) { | ||
function _getTransitionEndEvent(elem) { | ||
if (!elem) { | ||
const msg = 'Element does not have TransitionEnd event. It may be null!'; | ||
throw new Error( msg ); | ||
throw new Error(msg); | ||
} | ||
@@ -251,11 +197,13 @@ | ||
WebkitTransition: 'webkitTransitionEnd', | ||
MozTransition: 'transitionend', | ||
OTransition: 'oTransitionEnd otransitionend', | ||
transition: 'transitionend' | ||
MozTransition: 'transitionend', | ||
OTransition: 'oTransitionEnd otransitionend', | ||
transition: 'transitionend', | ||
}; | ||
let transitionEvent; | ||
for ( transitionEvent in transitions ) { | ||
if ( transitions.hasOwnProperty( transitionEvent ) && | ||
typeof elem.style[transitionEvent] !== 'undefined' ) { | ||
for (transitionEvent in transitions) { | ||
if ( | ||
{}.hasOwnProperty.call(transitions, transitionEvent) && | ||
typeof elem.style[transitionEvent] !== 'undefined' | ||
) { | ||
transition = transitions[transitionEvent]; | ||
@@ -268,2 +216,71 @@ break; | ||
/** | ||
* Set the HTML element target of this transition. | ||
* | ||
* @param {HTMLElement} targetElement - The target of the transition. | ||
*/ | ||
function setElement(targetElement) { | ||
/* | ||
If the element has already been set, | ||
clear the transition classes from the old element. | ||
*/ | ||
if (_dom) { | ||
remove(); | ||
animateOn(); | ||
} | ||
_dom = targetElement; | ||
_dom.classList.add(_classes.BASE_CLASS); | ||
_transitionEndEvent = _getTransitionEndEvent(_dom); | ||
} | ||
/** | ||
* @returns {BaseTransition} An instance. | ||
*/ | ||
function init() { | ||
_transitionCompleteBinded = _transitionComplete.bind(this); | ||
_addEventListenerBinded = _addEventListener.bind(this); | ||
setElement(element); | ||
return this; | ||
} | ||
/** | ||
* @returns {boolean} Whether the transition has a duration or not. | ||
* Returns false if this transition has not been initialized. | ||
*/ | ||
function isAnimated() { | ||
if (!_dom) { | ||
return false; | ||
} | ||
return !_dom.classList.contains(BaseTransition.NO_ANIMATION_CLASS); | ||
} | ||
/** | ||
* @param {string} className - A CSS class. | ||
* @returns {boolean} False if the class is already applied | ||
* or the transition is not initialized, | ||
* otherwise true if the class was applied. | ||
*/ | ||
function applyClass(className) { | ||
if (!_dom) { | ||
return false; | ||
} | ||
if (!_isFlushed) { | ||
_flush(); | ||
_isFlushed = true; | ||
} | ||
if (_dom.classList.contains(className)) { | ||
return false; | ||
} | ||
_removeEventListener(); | ||
_dom.classList.remove(_lastClass); | ||
_lastClass = className; | ||
_addEventListenerBinded(); | ||
_dom.classList.add(_lastClass); | ||
return true; | ||
} | ||
// Attach public events. | ||
@@ -270,0 +287,0 @@ const eventObserver = new EventObserver(); |
@@ -8,6 +8,6 @@ // Required modules. | ||
CSS_PROPERTY: 'max-height', | ||
BASE_CLASS: 'u-max-height-transition', | ||
MH_DEFAULT: 'u-max-height-default', | ||
MH_SUMMARY: 'u-max-height-summary', | ||
MH_ZERO: 'u-max-height-zero' | ||
BASE_CLASS: 'u-max-height-transition', | ||
MH_DEFAULT: 'u-max-height-default', | ||
MH_SUMMARY: 'u-max-height-summary', | ||
MH_ZERO: 'u-max-height-zero', | ||
}; | ||
@@ -17,32 +17,29 @@ | ||
* MoveTransition | ||
* | ||
* @class | ||
* | ||
* @classdesc Initializes new MoveTransition behavior. | ||
* | ||
* @param {HTMLNode} element | ||
* DOM element to apply transition to. | ||
* @param {HTMLElement} element - DOM element to apply transition to. | ||
* @returns {MaxHeightTransition} An instance. | ||
*/ | ||
function MaxHeightTransition( element ) { | ||
const _baseTransition = new BaseTransition( element, CLASSES ); | ||
function MaxHeightTransition(element) { | ||
const _baseTransition = new BaseTransition(element, CLASSES); | ||
let previousHeight; | ||
/** | ||
* @returns {MaxHeightTransition} An instance. | ||
* Refresh the max height set on the element. | ||
* This may be useful if resizing the window and the content height changes. | ||
*/ | ||
function init() { | ||
_baseTransition.init(); | ||
function refresh() { | ||
element.style.maxHeight = element.scrollHeight + 'px'; | ||
} | ||
/* The scrollHeight of an element may be incorrect if the page hasn't | ||
fully loaded yet, so we listen for that to happen before calculating | ||
the element max-height. */ | ||
window.addEventListener( 'load', _pageLoaded ); | ||
/** | ||
* Handle the end of a transition. | ||
*/ | ||
function _transitionComplete() { | ||
this.dispatchEvent(BaseTransition.END_EVENT, { target: this }); | ||
const _transitionCompleteBinded = _transitionComplete.bind( this ); | ||
_baseTransition.addEventListener( | ||
BaseTransition.END_EVENT, | ||
_transitionCompleteBinded | ||
); | ||
return this; | ||
if (element.scrollHeight > previousHeight) { | ||
element.style.maxHeight = element.scrollHeight + 'px'; | ||
} | ||
} | ||
@@ -55,3 +52,3 @@ | ||
function _pageLoaded() { | ||
window.removeEventListener( 'load', _pageLoaded ); | ||
window.removeEventListener('load', _pageLoaded); | ||
refresh(); | ||
@@ -61,10 +58,19 @@ } | ||
/** | ||
* Handle the end of a transition. | ||
* @returns {MaxHeightTransition} An instance. | ||
*/ | ||
function _transitionComplete() { | ||
this.dispatchEvent( BaseTransition.END_EVENT, { target: this } ); | ||
function init() { | ||
_baseTransition.init(); | ||
if ( element.scrollHeight > previousHeight ) { | ||
element.style.maxHeight = element.scrollHeight + 'px'; | ||
} | ||
/* The scrollHeight of an element may be incorrect if the page hasn't | ||
fully loaded yet, so we listen for that to happen before calculating | ||
the element max-height. */ | ||
window.addEventListener('load', _pageLoaded); | ||
const _transitionCompleteBinded = _transitionComplete.bind(this); | ||
_baseTransition.addEventListener( | ||
BaseTransition.END_EVENT, | ||
_transitionCompleteBinded | ||
); | ||
return this; | ||
} | ||
@@ -74,8 +80,9 @@ | ||
* Reset the max-height to the default size. | ||
* @returns {PostitionTransition} An instance. | ||
* | ||
* @returns {MaxHeightTransition} An instance. | ||
*/ | ||
function maxHeightDefault() { | ||
_baseTransition.applyClass( CLASSES.MH_DEFAULT ); | ||
_baseTransition.applyClass(CLASSES.MH_DEFAULT); | ||
if ( !previousHeight || element.scrollHeight > previousHeight ) { | ||
if (!previousHeight || element.scrollHeight > previousHeight) { | ||
previousHeight = element.scrollHeight; | ||
@@ -89,6 +96,7 @@ } | ||
* Collapses the max-height to just a summary height. | ||
* @returns {PostitionTransition} An instance. | ||
* | ||
* @returns {MaxHeightTransition} An instance. | ||
*/ | ||
function maxHeightSummary() { | ||
_baseTransition.applyClass( CLASSES.MH_SUMMARY ); | ||
_baseTransition.applyClass(CLASSES.MH_SUMMARY); | ||
@@ -102,6 +110,7 @@ previousHeight = element.scrollHeight; | ||
* Collapses thte max-height completely. | ||
* @returns {PostitionTransition} An instance. | ||
* | ||
* @returns {MaxHeightTransition} An instance. | ||
*/ | ||
function maxHeightZero() { | ||
_baseTransition.applyClass( CLASSES.MH_ZERO ); | ||
_baseTransition.applyClass(CLASSES.MH_ZERO); | ||
@@ -114,12 +123,5 @@ previousHeight = element.scrollHeight; | ||
/** | ||
* Refresh the max height set on the element. | ||
* This may be useful if resizing the window and the content height changes. | ||
*/ | ||
function refresh() { | ||
element.style.maxHeight = element.scrollHeight + 'px'; | ||
} | ||
/** | ||
* Remove style attribute. | ||
* Remove all transition classes, if transition is initialized. | ||
* | ||
* @returns {boolean} | ||
@@ -126,0 +128,0 @@ * True, if the element's CSS classes were touched, false otherwise. |
@@ -7,10 +7,10 @@ // Required modules. | ||
const CLASSES = { | ||
CSS_PROPERTY: 'transform', | ||
BASE_CLASS: 'u-move-transition', | ||
CSS_PROPERTY: 'transform', | ||
BASE_CLASS: 'u-move-transition', | ||
MOVE_TO_ORIGIN: 'u-move-to-origin', | ||
MOVE_LEFT: 'u-move-left', | ||
MOVE_LEFT_2X: 'u-move-left-2x', | ||
MOVE_LEFT_3X: 'u-move-left-3x', | ||
MOVE_RIGHT: 'u-move-right', | ||
MOVE_UP: 'u-move-up' | ||
MOVE_LEFT: 'u-move-left', | ||
MOVE_LEFT_2X: 'u-move-left-2x', | ||
MOVE_LEFT_3X: 'u-move-left-3x', | ||
MOVE_RIGHT: 'u-move-right', | ||
MOVE_UP: 'u-move-up', | ||
}; | ||
@@ -20,13 +20,17 @@ | ||
* MoveTransition | ||
* | ||
* @class | ||
* | ||
* @classdesc Initializes new MoveTransition behavior. | ||
* | ||
* @param {HTMLNode} element | ||
* DOM element to apply move transition to. | ||
* @param {HTMLElement} element - DOM element to apply move transition to. | ||
* @returns {MoveTransition} An instance. | ||
*/ | ||
function MoveTransition( element ) { | ||
function MoveTransition(element) { | ||
const _baseTransition = new BaseTransition(element, CLASSES); | ||
const _baseTransition = new BaseTransition( element, CLASSES ); | ||
/** | ||
* Handle the end of a transition. | ||
*/ | ||
function _transitionComplete() { | ||
this.dispatchEvent(BaseTransition.END_EVENT, { target: this }); | ||
} | ||
@@ -38,3 +42,3 @@ /** | ||
_baseTransition.init(); | ||
const _transitionCompleteBinded = _transitionComplete.bind( this ); | ||
const _transitionCompleteBinded = _transitionComplete.bind(this); | ||
_baseTransition.addEventListener( | ||
@@ -48,14 +52,8 @@ BaseTransition.END_EVENT, | ||
/** | ||
* Handle the end of a transition. | ||
*/ | ||
function _transitionComplete() { | ||
this.dispatchEvent( BaseTransition.END_EVENT, { target: this } ); | ||
} | ||
/** | ||
* Move to the element's original coordinates. | ||
* | ||
* @returns {MoveTransition} An instance. | ||
*/ | ||
function moveToOrigin() { | ||
_baseTransition.applyClass( CLASSES.MOVE_TO_ORIGIN ); | ||
_baseTransition.applyClass(CLASSES.MOVE_TO_ORIGIN); | ||
@@ -67,7 +65,8 @@ return this; | ||
* Move to the left by applying a utility move class. | ||
* @param {Number} count | ||
* How many times to move left as a multiplication of the element's width. | ||
* | ||
* @param {number} count - How many times to move left | ||
* as a multiplication of the element's width. | ||
* @returns {MoveTransition} An instance. | ||
*/ | ||
function moveLeft( count ) { | ||
function moveLeft(count) { | ||
count = count || 1; | ||
@@ -77,10 +76,10 @@ const moveClasses = [ | ||
CLASSES.MOVE_LEFT_2X, | ||
CLASSES.MOVE_LEFT_3X | ||
CLASSES.MOVE_LEFT_3X, | ||
]; | ||
if ( count < 1 || count > moveClasses.length ) { | ||
throw new Error( 'MoveTransition: moveLeft count is out of range!' ); | ||
if (count < 1 || count > moveClasses.length) { | ||
throw new Error('MoveTransition: moveLeft count is out of range!'); | ||
} | ||
_baseTransition.applyClass( moveClasses[count - 1] ); | ||
_baseTransition.applyClass(moveClasses[count - 1]); | ||
@@ -92,6 +91,7 @@ return this; | ||
* Move to the right by applying a utility move class. | ||
* | ||
* @returns {MoveTransition} An instance. | ||
*/ | ||
function moveRight() { | ||
_baseTransition.applyClass( CLASSES.MOVE_RIGHT ); | ||
_baseTransition.applyClass(CLASSES.MOVE_RIGHT); | ||
@@ -103,6 +103,7 @@ return this; | ||
* Move up by applying a utility move class. | ||
* | ||
* @returns {MoveTransition} An instance. | ||
*/ | ||
function moveUp() { | ||
_baseTransition.applyClass( CLASSES.MOVE_UP ); | ||
_baseTransition.applyClass(CLASSES.MOVE_UP); | ||
@@ -109,0 +110,0 @@ return this; |
@@ -18,33 +18,26 @@ /* ========================================================================== | ||
* @kind function | ||
* | ||
* @description | ||
* Determines if a reference is undefined. | ||
* | ||
* @param {*} value Reference to check. | ||
* @param {*} value - Reference to check. | ||
* @returns {boolean} True if `value` is undefined. | ||
*/ | ||
function isUndefined( value ) { | ||
function isUndefined(value) { | ||
return typeof value === 'undefined'; | ||
} | ||
/** | ||
* @name isDefined | ||
* @kind function | ||
* | ||
* @description | ||
* Determines if a reference is defined. | ||
* | ||
* @param {*} value Reference to check. | ||
* @param {*} value - Reference to check. | ||
* @returns {boolean} True if `value` is defined. | ||
*/ | ||
function isDefined( value ) { | ||
function isDefined(value) { | ||
return typeof value !== 'undefined'; | ||
} | ||
/** | ||
* @name isObject | ||
* @kind function | ||
* | ||
* @description | ||
@@ -54,7 +47,6 @@ * Determines if a reference is an `Object`. | ||
* considered to be objects. Note that JavaScript arrays are objects. | ||
* | ||
* @param {*} value Reference to check. | ||
* @param {*} value - Reference to check. | ||
* @returns {boolean} True if `value` is an `Object` but not `null`. | ||
*/ | ||
function isObject( value ) { | ||
function isObject(value) { | ||
// http://jsperf.com/isobject4 | ||
@@ -64,22 +56,17 @@ return value !== null && typeof value === 'object'; | ||
/** | ||
* @name isString | ||
* @kind function | ||
* | ||
* @description | ||
* Determines if a reference is a `String`. | ||
* | ||
* @param {*} value Reference to check. | ||
* @param {*} value - Reference to check. | ||
* @returns {boolean} True if `value` is a `String`. | ||
*/ | ||
function isString( value ) { | ||
return _toString.call( value ) === '[object String]'; | ||
function isString(value) { | ||
return _toString.call(value) === '[object String]'; | ||
} | ||
/** | ||
* @name isNumber | ||
* @kind function | ||
* | ||
* @description | ||
@@ -94,53 +81,45 @@ * Determines if a reference is a `Number`. | ||
* method. | ||
* | ||
* @param {*} value Reference to check. | ||
* @param {*} value - Reference to check. | ||
* @returns {boolean} True if `value` is a `Number`. | ||
*/ | ||
function isNumber( value ) { | ||
return _toString.call( value ) === '[object Number]'; | ||
function isNumber(value) { | ||
return _toString.call(value) === '[object Number]'; | ||
} | ||
/** | ||
* @name isDate | ||
* @kind function | ||
* | ||
* @description | ||
* Determines if a value is a date. | ||
* | ||
* @param {*} value Reference to check. | ||
* @param {*} value - Reference to check. | ||
* @returns {boolean} True if `value` is a `Date`. | ||
*/ | ||
function isDate( value ) { | ||
return _toString.call( value ) === '[object Date]'; | ||
function isDate(value) { | ||
return _toString.call(value) === '[object Date]'; | ||
} | ||
/** | ||
* @name isArray | ||
* @kind function | ||
* | ||
* @description | ||
* Determines if a reference is an `Array`. | ||
* | ||
* @param {*} value Reference to check. | ||
* @param {*} value - Reference to check. | ||
* @returns {boolean} True if `value` is an `Array`. | ||
*/ | ||
const isArray = Array.isArray || function isArray( value ) { | ||
return _toString.call( value ) === '[object Array]'; | ||
}; | ||
const isArray = | ||
Array.isArray || | ||
function isArray(value) { | ||
return _toString.call(value) === '[object Array]'; | ||
}; | ||
/** | ||
* @name isFunction | ||
* @kind function | ||
* | ||
* @description | ||
* Determines if a reference is a `Function`. | ||
* | ||
* @param {*} value Reference to check. | ||
* @param {*} value - Reference to check. | ||
* @returns {boolean} True if `value` is a `Function`. | ||
*/ | ||
function isFunction( value ) { | ||
return _toString.call( value ) === '[object Function]'; | ||
function isFunction(value) { | ||
return _toString.call(value) === '[object Function]'; | ||
} | ||
@@ -153,15 +132,14 @@ | ||
* @kind function | ||
* | ||
* @description | ||
* Determines if a reference is empty. | ||
* | ||
* @param {*} value Reference to check. | ||
* @param {*} value - Reference to check. | ||
* @returns {boolean} True if `value` is empty. | ||
*/ | ||
function isEmpty( value ) { | ||
return isUndefined( value ) || | ||
value === null || | ||
isString( value ) && | ||
value.length <= 0 || | ||
( /^\s*$/ ).test( value ); | ||
function isEmpty(value) { | ||
return ( | ||
isUndefined(value) || | ||
value === null || | ||
(isString(value) && value.length <= 0) || | ||
/^\s*$/.test(value) | ||
); | ||
} | ||
@@ -180,3 +158,3 @@ /* eslint-enable complexity, no-mixed-operators */ | ||
isFunction: isFunction, | ||
isEmpty: isEmpty | ||
isEmpty: isEmpty, | ||
}; |
13
TERMS.md
@@ -14,6 +14,5 @@ As a work of the United States Government, this package is in the | ||
## CC0 1.0 Universal Summary | ||
This is a human-readable summary of the [Legal Code (read the full text)][CC0]. | ||
This is a human-readable summary of the [Legal Code (read the full text)][cc0]. | ||
@@ -27,3 +26,3 @@ ### No Copyright | ||
You can copy, modify, distribute and perform the work, even for commercial | ||
You can copy, modify, distribute and perform the work, even for commercial | ||
purposes, all without asking permission. See Other Information below. | ||
@@ -44,8 +43,8 @@ | ||
[policy]: https://github.com/cfpb/design-system/blob/main/TERMS.md | ||
[CC0]: http://creativecommons.org/publicdomain/zero/1.0/legalcode | ||
[cc0]: http://creativecommons.org/publicdomain/zero/1.0/legalcode | ||
## This project makes use of: | ||
* [Respond.js](https://github.com/scottjehl/Respond) by Scott Jehl, licensed under the MIT license. | ||
* [The HTML5 Shiv](https://github.com/aFarkas/html5shiv), dual licensed under the MIT or GPL Version 2 licenses. | ||
* | ||
- [Respond.js](https://github.com/scottjehl/Respond) by Scott Jehl, licensed under the MIT license. | ||
- [The HTML5 Shiv](https://github.com/aFarkas/html5shiv), dual licensed under the MIT or GPL Version 2 licenses. | ||
- |
30
usage.md
@@ -5,3 +5,2 @@ Atomic Component is a micro framework for building Atomic Design components | ||
## Table of contents | ||
@@ -11,3 +10,2 @@ | ||
## Usage | ||
@@ -54,18 +52,18 @@ | ||
const NotificationMolecule = Molecule.extend( { | ||
classes: { | ||
isVisible: 'm-notification__visible' | ||
}, | ||
const NotificationMolecule = Molecule.extend({ | ||
classes: { | ||
isVisible: 'm-notification__visible', | ||
}, | ||
ui: { | ||
base: '.m-notification', | ||
explanation: '.m-notification_explanation', | ||
message: '.m-notification_message' | ||
}, | ||
ui: { | ||
base: '.m-notification', | ||
explanation: '.m-notification_explanation', | ||
message: '.m-notification_message', | ||
}, | ||
initialize: function() { | ||
this.ui.message.textContent = CONSTANTS.MESSAGE; | ||
this.ui.explanation.textContent = CONSTANTS.EXPLANATION; | ||
} | ||
} ); | ||
initialize: function () { | ||
this.ui.message.textContent = CONSTANTS.MESSAGE; | ||
this.ui.explanation.textContent = CONSTANTS.EXPLANATION; | ||
}, | ||
}); | ||
@@ -72,0 +70,0 @@ NotificationMolecule.constants = CONSTANTS; |
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
85
61277
1494