Skip to content

Commit

Permalink
Shortcut for Object.create(null), Fix unit adding for some css styles…
Browse files Browse the repository at this point in the history
… and move into normalization code.

This is the first build with the correct RequireJS namespace - "velocity-animate"!
  • Loading branch information
Rycochet committed Mar 4, 2018
1 parent 8fdea04 commit 794d15c
Show file tree
Hide file tree
Showing 16 changed files with 334 additions and 164 deletions.
21 changes: 11 additions & 10 deletions V2_CHANGES.md
Original file line number Diff line number Diff line change
@@ -1,22 +1,23 @@
# Major Changes in Velocity V2

* Transforms - Use these directly within CSS, don't try the old shortcuts as they don't exist.
* APIs for extending Velocity - see the various register* commands in the wiki.
* Chaining - Chaining is awesome, use it. Chained commands are designed to operate on the chained animation, not on the elements within it.
* Colors - All web colors are supported internally.
* SVG - All SVG attributes are supported internally, though they must be placed on the correct type of element.
* Delay - You can pass a negative number to start inside the animation rather than just having a delay before it.
* Display - This is a property, no longer an option.
* Loop - This no longer copies the animation call, it calls it multiple times.
* Per-element - Animations are now copied per-element, and not one a one-animation-per-array basis as in other libraries (and old Velocity v1).
* Repeat - This is almost identical to loop, but only runs one way.
* Chaining - Chaining is awesome, use it. Chained commands are designed to operate on the chained animation, not on the elements within it.
* RequireJS - The namespace is now "velocity-animate" for consistency with the NPMjs project name.
* Reverse - Now reverses the last animation at time of adding, not when playing.
* Scroll - It is now a property, though it's preferred to use scrollTop and scrollLeft. (Working, but not happy with internal code - the API will not change again.)
* Speed - You can control the speed of the animation playback.
* Styles - Use `element.velocity("style", "propertyName"[, value])`, the old .Hook has gone.
* Per-element - Animations are now copied per-element, and not one a one-animation-per-array basis as in other libraries (and old Velocity v1).
* SVG - All SVG attributes are supported internally, though they must be placed on the correct type of element.
* Sync - You can now de-sync animations so they start immediately per-element, rather than waiting for all to be ready.
* Speed - You can control the speed of the animation playback.
* Delay - You can pass a negative number to start inside the animation rather than just having a delay before it.
* There are APIs for extending Velocity - see the various register* commands.
* Display - This is a property, no longer an option.
* Transforms - Use these directly within CSS, don't try the old shortcuts as they don't exist.
* Visibility - This is a property, no longer an option.
* Reverse - Now reverses the last animation at time of adding, not when playing.

# Currently disabled / not updated:

* UI-Pack
* Scroll (working, but not happy with interface - it's a property if people want to play, alias of scrollTop, there's also scrollLeft)
2 changes: 1 addition & 1 deletion src/Velocity/actions/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ namespace VelocityStatic {
* All external method calls should be using actions rather than sub-calls
* of Velocity itself.
*/
export const Actions: {[name: string]: VelocityActionFn} = Object.create(null);
export const Actions: {[name: string]: VelocityActionFn} = createEmptyObject();

/**
* Used to register an action. This should never be called by users
Expand Down
2 changes: 1 addition & 1 deletion src/Velocity/css/camelCase.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ namespace VelocityStatic.CSS {
/**
* Cache every camelCase match to avoid repeating lookups.
*/
const cache: {[property: string]: string} = Object.create(null);
const cache: {[property: string]: string} = createEmptyObject();

/**
* Camelcase a property name into its JavaScript notation (e.g.
Expand Down
2 changes: 1 addition & 1 deletion src/Velocity/css/fixColors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ namespace VelocityStatic.CSS {
* that the actual name conversion can be in a separate file and not
* included for custom builds.
*/
export const ColorNames: {[name: string]: string} = Object.create(null);
export const ColorNames: {[name: string]: string} = createEmptyObject();

/**
* Convert a hex list to an rgba value. Designed to be used in replace.
Expand Down
8 changes: 4 additions & 4 deletions src/Velocity/data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,10 @@ function Data(element: HTMLorSVGElement): ElementData {
types: types,
count: 0,
computedStyle: null,
cache: Object.create(null),
queueList: Object.create(null),
lastAnimationList: Object.create(null),
lastFinishList: Object.create(null)
cache: createEmptyObject(),
queueList: createEmptyObject(),
lastAnimationList: createEmptyObject(),
lastFinishList: createEmptyObject()
};
Object.defineProperty(element, "velocityData", {
value: newData
Expand Down
2 changes: 1 addition & 1 deletion src/Velocity/easing/easings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ interface VelocityEasingsType {
}

namespace VelocityStatic.Easing {
export const Easings: {[name: string]: VelocityEasingFn} = Object.create(null);
export const Easings: {[name: string]: VelocityEasingFn} = createEmptyObject();

/**
* Used to register a easing. This should never be called by users
Expand Down
43 changes: 39 additions & 4 deletions src/Velocity/normalizations/normalizations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,14 @@ namespace VelocityStatic {
*/
export const Normalizations: {[name: string]: VelocityNormalizationsFn}[] = [];

/**
* Store a cross-reference to units to be added to specific normalization
* functions if the user supplies a unit-less number.
*
* This is pretty much confined to adding "px" to several css properties.
*/
export const NormalizationUnits: {[unit: string]: VelocityNormalizationsFn[]} = createEmptyObject();

/**
* Any normalisations that should never be cached are listed here.
* Faster than an array - https://jsperf.com/array-includes-and-find-methods-vs-set-has
Expand Down Expand Up @@ -55,7 +63,7 @@ namespace VelocityStatic {
*
* @private
*/
export function registerNormalization(args?: [ClassConstructor, string, VelocityNormalizationsFn] | [ClassConstructor, string, VelocityNormalizationsFn, boolean]) {
export function registerNormalization(args?: [ClassConstructor, string, VelocityNormalizationsFn] | [ClassConstructor, string, VelocityNormalizationsFn, boolean] | [ClassConstructor, string, VelocityNormalizationsFn, string] | [ClassConstructor, string, VelocityNormalizationsFn, string, boolean]) {
const constructor = args[0],
name: string = args[1],
callback = args[2];
Expand All @@ -67,14 +75,24 @@ namespace VelocityStatic {
} else if (!isFunction(callback)) {
console.warn("VelocityJS: Trying to set 'registerNormalization' callback to an invalid value:", name, callback);
} else {
let index = constructors.indexOf(constructor);
let index = constructors.indexOf(constructor),
nextArg = 3;

if (index < 0) {
MaxType = index = constructors.push(constructor) - 1;
Normalizations[index] = Object.create(null);
Normalizations[index] = createEmptyObject();
}
Normalizations[index][name] = callback;
if (args[3] === false) {
if (isString(args[nextArg])) {
let unit = args[nextArg++] as string,
units = NormalizationUnits[unit];

if (!units) {
units = NormalizationUnits[unit] = [];
}
units.push(callback);
}
if (args[nextArg] === false) {
NoCacheNormalizations.add(name);
}
}
Expand All @@ -91,6 +109,23 @@ namespace VelocityStatic {
return !!Normalizations[index][name];
}

/**
* Get the unit to add to a unitless number based on the normalization used.
*/
export function getNormalizationUnit(fn: VelocityNormalizationsFn) {
for (let unit in NormalizationUnits) {
if (_inArray(NormalizationUnits[unit], fn)) {
return unit;
}
}
return "";
}

/**
* Get the normalization for an element and propertyName combination. This
* value should be cached at asking time, as it may change if the user adds
* more normalizations.
*/
export function getNormalization(element: HTMLorSVGElement, propertyName: string) {
const data = Data(element);
let fn: VelocityNormalizationsFn;
Expand Down
76 changes: 73 additions & 3 deletions src/Velocity/normalizations/style.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,70 @@
*/

namespace VelocityStatic {
/**
* An RegExp pattern for the following list of css words using
* http://kemio.com.ar/tools/lst-trie-re.php to generate:
*
* blockSize
* borderBottomLeftRadius
* borderBottomRightRadius
* borderBottomWidth
* borderImageOutset
* borderImageWidth
* borderLeftWidth
* borderRadius
* borderRightWidth
* borderSpacing
* borderTopLeftRadius
* borderTopRightRadius
* borderTopWidth
* borderWidth
* bottom
* columnGap
* columnRuleWidth
* columnWidth
* flexBasis
* fontSize
* gridColumnGap
* gridGap
* gridRowGap
* height
* inlineSize
* left
* letterSpacing
* margin
* marginBottom
* marginLeft
* marginRight
* marginTop
* maxBlockSize
* maxHeight
* maxInlineSize
* maxWidth
* minBlockSize
* minHeight
* minInlineSize
* minWidth
* objectPosition
* outlineOffset
* outlineWidth
* padding
* paddingBottom
* paddingLeft
* paddingRight
* paddingTop
* perspective
* right
* shapeMargin
* strokeDashoffset
* strokeWidth
* textIndent
* top
* transformOrigin
* width
* wordSpacing
*/
const rxAddPx = /^(b(lockSize|o(rder(Bottom(LeftRadius|RightRadius|Width)|Image(Outset|Width)|LeftWidth|R(adius|ightWidth)|Spacing|Top(LeftRadius|RightRadius|Width)|Width)|ttom))|column(Gap|RuleWidth|Width)|f(lexBasis|ontSize)|grid(ColumnGap|Gap|RowGap)|height|inlineSize|le(ft|tterSpacing)|m(a(rgin(Bottom|Left|Right|Top)|x(BlockSize|Height|InlineSize|Width))|in(BlockSize|Height|InlineSize|Width))|o(bjectPosition|utline(Offset|Width))|p(adding(Bottom|Left|Right|Top)|erspective)|right|s(hapeMargin|troke(Dashoffset|Width))|t(extIndent|op|ransformOrigin)|w(idth|ordSpacing))$/;

/**
* Return a Normalisation that can be used to set / get a prefixed style
Expand All @@ -36,19 +100,25 @@ namespace VelocityStatic {
} as VelocityNormalizationsFn;
}

/**
* Vendor prefixes. Chrome / Safari, Firefox, IE / Edge, Opera.
*/
const rxVendors = /^(webkit|moz|ms|o)[A-Z]/,
rxUnit = /^\d+([a-z]+)/,
prefixElement = State.prefixElement;

for (const propertyName in prefixElement.style) {
if (rxVendors.test(propertyName)) {
let unprefixed = propertyName.replace(/^[a-z]+([A-Z])/, ($, letter: string) => letter.toLowerCase());

if (ALL_VENDOR_PREFIXES || isString(prefixElement.style[unprefixed])) {
registerNormalization([Element, unprefixed, getSetPrefixed(propertyName, unprefixed)]);
let addUnit = rxAddPx.test(unprefixed) ? "px" : undefined;

registerNormalization([Element, unprefixed, getSetPrefixed(propertyName, unprefixed), addUnit]);
}
} else if (!hasNormalization([Element, propertyName])) {
registerNormalization([Element, propertyName, getSetStyle(propertyName)]);
let addUnit = rxAddPx.test(propertyName) ? "px" : undefined;

registerNormalization([Element, propertyName, getSetStyle(propertyName), addUnit]);
}
}
}
32 changes: 32 additions & 0 deletions src/Velocity/runsequence.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,38 @@
* Sequence Running
*/

/**
* Perform a deep copy of an object - also copies children so they're not
* going to be affected by changing original.
*/
function _deepCopyObject<T, U>(target: T, ...sources: U[]): T & U {
if (target == null) { // TypeError if undefined or null
throw new TypeError("Cannot convert undefined or null to object");
}
const to = Object(target),
hasOwnProperty = Object.prototype.hasOwnProperty;
let source: any;

while ((source = sources.shift())) {
if (source != null) {
for (const key in source) {
if (hasOwnProperty.call(source, key)) {
const value = source[key];

if (Array.isArray(value)) {
_deepCopyObject(to[key] = [], value);
} else if (isPlainObject(value)) {
_deepCopyObject(to[key] = {}, value);
} else {
to[key] = value;
}
}
}
}
}
return to;
}

namespace VelocityStatic {
/* Note: Sequence calls must use Velocity's single-object arguments syntax. */
export function RunSequence(originalSequence): void {
Expand Down
39 changes: 3 additions & 36 deletions src/Velocity/tweens.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ namespace VelocityStatic {
return (value as any as VelocityPropertyValueFn).call(element, elementArrayIndex, elements.length);
})
commands.set("number", function(value, element, elements, elementArrayIndex, propertyName, tween) {
return value + (element instanceof HTMLElement ? getUnitType(propertyName) : "");
return value + getNormalizationUnit(tween.fn);
});
commands.set("string", function(value, element, elements, elementArrayIndex, propertyName, tween) {
return CSS.fixColors(value);
Expand All @@ -23,46 +23,13 @@ namespace VelocityStatic {
return CSS.fixColors(CSS.getPropertyValue(element, propertyName, tween.fn) || "");
});

/**
* Properties that take no default numeric suffix.
*/
const unitless = [
"borderImageSlice",
"columnCount",
"counterIncrement",
"counterReset",
"flex",
"flexGrow",
"flexShrink",
"floodOpacity",
"fontSizeAdjust",
"fontWeight",
"lineHeight",
"opacity",
"order",
"orphans",
"shapeImageThreshold",
"tabSize",
"widows",
"zIndex"
];

/**
* Retrieve a property's default unit type. Used for assigning a unit
* type when one is not supplied by the user. These are only valid for
* HTMLElement style properties.
*/
function getUnitType(property: string): string {
return _inArray(unitless, property) ? "" : "px";
}

/**
* Expand a VelocityProperty argument into a valid sparse Tween array. This
* pre-allocates the array as it is then the correct size and slightly
* faster to access.
*/
export function expandProperties(animation: AnimationCall, properties: VelocityProperties) {
const tweens = animation.tweens = Object.create(null),
const tweens = animation.tweens = createEmptyObject(),
elements = animation.elements,
element = animation.element,
elementArrayIndex = elements.indexOf(element),
Expand All @@ -87,7 +54,7 @@ namespace VelocityStatic {
}
continue;
}
const tween: VelocityTween = tweens[propertyName] = Object.create(null) as any;
const tween: VelocityTween = tweens[propertyName] = createEmptyObject() as any;
let endValue: string,
startValue: string;

Expand Down
2 changes: 1 addition & 1 deletion src/core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -360,7 +360,7 @@ function VelocityFn(this: VelocityElements | void, ...__args: any[]): VelocityRe
}
flags |= AnimationFlags.REVERSE & ~(lastAnimation._flags & AnimationFlags.REVERSE);
}
const tweens = Object.create(null),
const tweens = createEmptyObject(),
animation: AnimationCall = Object.assign({
element: element,
tweens: tweens
Expand Down
Loading

0 comments on commit 794d15c

Please sign in to comment.