Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions src/constants.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
export const NAMESPACE = 'markerAnimation';
export const PREFIX = 'ma_';
export const RESET_KEYS = [
'background',
'padding-bottom',
'font-weight',
'transition',
];
export const MARKER_DATA = 'data-marker_animation';
export const ZERO_SEC = '0s';
export const DESTROY_EVENT = `destroy.${ NAMESPACE }`;
export const REFRESH_EVENT = `refresh.${ NAMESPACE }`;
export const INVIEW_EVENT = `inview.${ NAMESPACE }`;
15 changes: 15 additions & 0 deletions src/defaults.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
export const SETTINGS_DEFAULTS = {
color: '#fe9',
paddingBottom: '.6em',
thickness: '.6em',
delay: '.1s',
duration: '2s',
function: 'ease',
fontWeight: 'bold',
repeat: false,
stripe: false,
stripeThickness: 2,
cssFilter: function( css ) {
return css;
},
};
154 changes: 154 additions & 0 deletions src/functions.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
import { RESET_KEYS, MARKER_DATA, ZERO_SEC, NAMESPACE, INVIEW_EVENT, REFRESH_EVENT } from './constants';

/**
* @param {object} target target
* @returns {object} target
*/
export const reset = target => {
if ( target.attr( MARKER_DATA ) ) {
destroy( target );
removeEvent( target );
}
return target;
};

/**
* @param {object} target target
* @returns {object} target
*/
export const destroy = target => {
if ( target[ 0 ].resetValues ) {
RESET_KEYS.forEach( key => {
target.css( key, target[ 0 ].resetValues[ key ] );
} );
delete target[ 0 ].resetValues;
}
target.attr( MARKER_DATA, false );
return target;
};

/**
* @param {object} target target
* @param {object} options options
* @returns {object} target
*/
export const create = ( target, options ) => {
target[ 0 ].resetValues = {};
RESET_KEYS.forEach( key => target[ 0 ].resetValues[ key ] = target.css( key ) );

if ( ! isStatic( options ) ) {
target.data( 'inview', false ).on( INVIEW_EVENT, ( event, isInView ) => {
if ( isInView ) {
onInView( target, options );
} else {
offInView( target, options );
}
} );
}
target.css( getCss( options ) ).attr( MARKER_DATA, true );
return target;
};

/**
* @param {object} options options
* @returns {boolean} is static?
*/
export const isStatic = options => options.stripe || ( ZERO_SEC === options.delay && ZERO_SEC === options.duration );

/**
* @param {object} options options
* @returns {object} css
*/
export const getCss = options => options.cssFilter( options.stripe ? getStripeCss( options ) : getMarkerCss( options ) );

/**
* @param {object} options options
* @returns {object} css
*/
const getCommonCss = options => Object.assign( {
'display': 'inline',
'background-position': 'left 0 center',
'padding-bottom': options.paddingBottom,
}, options.fontWeight ? {
'font-weight': options.fontWeight,
} : {} );

/**
* @param {object} options options
* @returns {object} css
*/
const getMarkerCss = options => Object.assign( {}, getCommonCss( options ), {
'background-size': `200% ${ options.thickness }`,
'background-repeat': 'repeat-x',
'background-image': `linear-gradient(to right, rgba(255,255,255,0) 50%, ${ options.color } 50%)`,
}, isStatic( options ) ? {
'background-position': 'left -100% center',
} : {} );

/**
* @param {object} options options
* @returns {object} css
*/
const getStripeCss = options => Object.assign( {}, getCommonCss( options ), {
'background-size': `100% ${ options.thickness }`,
'background-repeat': 'no-repeat',
// eslint-disable-next-line no-magic-numbers
'background-image': `repeating-linear-gradient(-45deg, ${ options.color }, ${ options.color } ${ options.stripeThickness }px, transparent ${ options.stripeThickness }px, transparent ${ options.stripeThickness * 2 }px)`,
} );

/**
* @param {object} target target
* @param {object} options options
* @returns {object} target
*/
export const refresh = ( target, options ) => {
destroy( target );
stop( target );
return create( target, options );
};

/**
* @param {object} target target
* @returns {object} target
*/
export const removeEvent = target => {
target.off( `.${ NAMESPACE }` );
return target;
};

/**
* @param {object} target target
* @returns {object} target
*/
export const stop = target => {
target.off( INVIEW_EVENT );
return target;
};

/**
* @param {object} target target
* @param {object} options options
* @returns {object} target
*/
export const onInView = ( target, options ) => {
target.stop( true, true ).css( {
transition: `background-position ${ options.duration } ${ options.function } ${ options.delay }`,
'background-position': 'left -100% center',
} );
if ( ! options.repeat ) {
stop( target );
}
return target;
};

/**
* @param {object} target target
* @param {object} options options
* @returns {object} target
*/
export const offInView = ( target, options ) => {
if ( options.repeat ) {
target.trigger( REFRESH_EVENT );
}
return target;
};
157 changes: 3 additions & 154 deletions src/index.js
Original file line number Diff line number Diff line change
@@ -1,160 +1,9 @@
require( 'jquery-inview' );
import $ from 'jquery';
import { setup } from './setup';

$.fn.markerAnimation = function( ...args ) {
return this.each( function() {
const target = $( this );
const namespace = 'markerAnimation';
const overridePrefix = 'ma_';
const markerAnimationObj = {
op: {
'color': '#fe9',
'padding_bottom': '.6em',
'thickness': '.6em',
'delay': '.1s',
'duration': '2s',
'function': 'ease',
'font_weight': 'bold',
'repeat': false,
'stripe': false,
'stripe_thickness': 2,
'cssFilter': function( css ) {
return css;
},
},
resetKeys: [
'background',
'padding-bottom',
'font-weight',
'transition',
],
setOption: function( op ) {
$.extend( this.op, op );
},
destroy: function() {
const $this = this;
if ( target[ 0 ].resetValues ) {
$this.resetKeys.forEach( function( key ) {
target.css( key, target[ 0 ].resetValues[ key ] );
} );
target[ 0 ].resetValues = null;
}
target.attr( 'data-marker_animation', false );
},
create: function( op ) {
const $this = this;
this.setOption( op );
let css = {
'display': 'inline',
'background-position': 'left 0 center',
'padding-bottom': $this.op.padding_bottom,
};
if ( $this.op.stripe ) {
css [ 'background-size' ] = '0 ' + $this.op.thickness;
css [ 'background-repeat' ] = 'no-repeat';
// eslint-disable-next-line no-magic-numbers
css[ 'background-image' ] = 'repeating-linear-gradient(-45deg, ' + $this.op.color + ', ' + $this.op.color + ' ' + $this.op.stripe_thickness + 'px,transparent ' + $this.op.stripe_thickness + 'px,transparent ' + ( $this.op.stripe_thickness * 2 ) + 'px)';
} else {
css[ 'background-size' ] = '200% ' + $this.op.thickness;
css[ 'background-repeat' ] = 'repeat-x';
css[ 'background-image' ] = 'linear-gradient(to right, rgba(255,255,255,0) 50%, ' + $this.op.color + ' 50%)';
}
if ( $this.op.font_weight ) {
css[ 'font-weight' ] = $this.op.font_weight;
}
target[ 0 ].resetValues = {};
$this.resetKeys.forEach( function( key ) {
target[ 0 ].resetValues[ key ] = target.css( key );
} );
css = $this.op.cssFilter( css );
if ( $this.op.stripe ) {
target.css( css ).css( {
'background-size': '100% ' + $this.op.thickness,
} ).attr( 'data-marker_animation', true );
} else if ( '0s' === $this.op.delay && '0s' === $this.op.duration ) {
target.css( css ).css( {
'background-position': 'left -100% center',
} ).attr( 'data-marker_animation', true );
} else {
target.data( 'inview', false ).on( 'inview.' + namespace, function( event, isInView ) {
if ( isInView ) {
$this.onInView();
} else {
$this.offInView();
}
} ).css( css ).attr( 'data-marker_animation', true );
}
},
refresh: function() {
this.destroy();
this.stop();
this.create();
},
removeEvent: function() {
target.off( '.' + namespace );
},
stop: function() {
target.off( 'inview.' + namespace );
},
onInView: function() {
target.stop( true, true ).css( {
'transition': 'background-position ' + this.op.duration + ' ' + this.op.function + ' ' + this.op.delay,
'background-position': 'left -100% center',
} );
if ( ! this.op.repeat ) {
this.stop();
}
},
offInView: function() {
if ( this.op.repeat ) {
target.trigger( 'refresh.' + namespace );
}
},
};
if ( typeof args[ 0 ] === 'string' && args[ 0 ] === 'destroy' ) {
target.trigger( 'destroy.' + namespace );
} else if ( typeof args[ 0 ] === 'string' && args[ 0 ] === 'refresh' ) {
target.trigger( 'refresh.' + namespace );
} else {
if ( target.attr( 'data-marker_animation' ) ) {
markerAnimationObj.destroy();
markerAnimationObj.removeEvent();
}

const options = $.extend( {}, args[ 0 ] );
Object.keys( markerAnimationObj.op ).forEach( function( key ) {
const data = target.data( overridePrefix + key );
if ( undefined !== data ) {
options[ key ] = data;
}
if ( 'string' === typeof options[ key ] ) {
options[ key ] = options[ key ].trim();
if ( 'delay' === key || 'duration' === key ) {
if ( ! /^-?\d*\.?\d+m?s$/.test( options[ key ] ) ) {
options[ key ] = '0s';
} else if ( /^-?0?\.?0+m?s$/.test( options[ key ] ) ) {
options[ key ] = '0s';
}
} else if ( 'stripe_thickness' === key ) {
options[ key ] = parseInt( options[ key ], 10 );
if ( isNaN( options[ key ] ) ) {
options[ key ] = 2;
}
}
}
} );
markerAnimationObj.create( options );

target.on( 'destroy.' + namespace, function() {
markerAnimationObj.destroy();
markerAnimationObj.removeEvent();
} ).on( 'refresh.' + namespace, function() {
markerAnimationObj.refresh();
} );

if ( options.test ) {
target[ 0 ].markerAnimationObj = markerAnimationObj;
}
}
setup( $( this ), args );
} );
};
};
Loading