some more restructuring

This commit is contained in:
janis
2024-01-09 09:32:41 +01:00
parent a1fa8bea3d
commit e326b2635f
8 changed files with 4 additions and 3 deletions

View File

@@ -1,105 +0,0 @@
Impress.js Libraries
====================
The `src/lib/*.js` files contain library functions. The main difference to plugins is that:
1. Libraries are closer to the impress.js core than plugins (arguably a subjective metric)
2. Libraries are common utility functions used by many plugins
3. Libraries are called synchronously, which is why the event based paradigm that plugins use to
communicate isn't useful.
Plugins can access libraries via the API:
var api;
document.addEventListener( "impress:init", function(event){
api = event.detail.api;
api().lib.<libraryName>.<libaryFunction>();
});
...which is equivalent to:
impress().lib.<libraryName>.<libraryFunction>();
Implementing a library
----------------------
1. Create a file under `src/lib/`.
2. Start with the standard boilerplate documentation, and the (function(document, window){})();
wrapper.
3. The library should implement a factory function, and make its existence known to impress.js core:
window.impress.addLibraryFactory( { libName : libraryFactory} );
4. The library function should return a similar API object as core `impress()` function does:
var libraryFactory = function(rootId) {
/* implement library functions ... */
var lib = {
libFunction1: libFunction1,
libFunction2: libFunction2
}
return lib;
};
5. While rarely used, impress.js actually supports multiple presentation root div elements on a
single html page. Each of these have their own API object, identified by the root element id
attribute:
impress("other-root-id").init();
(The default rootId obviously is `"impress"`.)
Libraries MUST implement this support for multiple root elements as well.
- impress.js core will call the factory once for each separate root element being initialized via
`impress.init(rootId)`.
- Any state that a library might hold, MUST be stored *per `rootId`*.
- Note that as we now support also `impress(rootId).tear()`, the same root element might be
initialized more than once, and each of these MUST be treated as a new valid initialization.
Putting all of the above together, a skeleton library file will look like:
/**
* Example library libName
*
* Henrik Ingo (c) 2016
* MIT License
*/
(function ( document, window ) {
'use strict';
// Singleton library variables
var roots = [];
var singletonVar = {};
var libraryFactory = function(rootId) {
if (roots["impress-root-" + rootId]) {
return roots["impress-root-" + rootId];
}
// Per root global variables (instance variables?)
var instanceVar = {};
// LIBRARY FUNCTIONS
var libraryFunction1 = function () {
/* ... */
};
var libraryFunction2 = function () {
/* ... */
};
var lib = {
libFunction1: libFunction1,
libFunction2: libFunction2
}
roots["impress-root-" + rootId] = lib;
return lib;
};
// Let impress core know about the existence of this library
window.impress.addLibraryFactory( { libName : libraryFactory } );
})(document, window);

View File

@@ -1,238 +0,0 @@
/**
* Garbage collection utility
*
* This library allows plugins to add elements and event listeners they add to the DOM. The user
* can call `impress().lib.gc.teardown()` to cause all of them to be removed from DOM, so that
* the document is in the state it was before calling `impress().init()`.
*
* In addition to just adding elements and event listeners to the garbage collector, plugins
* can also register callback functions to do arbitrary cleanup upon teardown.
*
* Henrik Ingo (c) 2016
* MIT License
*/
( function( document, window ) {
"use strict";
var roots = [];
var rootsCount = 0;
var startingState = { roots: [] };
var libraryFactory = function( rootId ) {
if ( roots[ rootId ] ) {
return roots[ rootId ];
}
// Per root global variables (instance variables?)
var elementList = [];
var eventListenerList = [];
var callbackList = [];
recordStartingState( rootId );
// LIBRARY FUNCTIONS
// Definitions of the library functions we return as an object at the end
// `pushElement` adds a DOM element to the gc stack
var pushElement = function( element ) {
elementList.push( element );
};
// `appendChild` is a convenience wrapper that combines DOM appendChild with gc.pushElement
var appendChild = function( parent, element ) {
parent.appendChild( element );
pushElement( element );
};
// `pushEventListener` adds an event listener to the gc stack
var pushEventListener = function( target, type, listenerFunction ) {
eventListenerList.push( { target:target, type:type, listener:listenerFunction } );
};
// `addEventListener` combines DOM addEventListener with gc.pushEventListener
var addEventListener = function( target, type, listenerFunction ) {
target.addEventListener( type, listenerFunction );
pushEventListener( target, type, listenerFunction );
};
// `pushCallback` If the above utilities are not enough, plugins can add their own callback
// function to do arbitrary things.
var pushCallback = function( callback ) {
callbackList.push( callback );
};
pushCallback( function( rootId ) { resetStartingState( rootId ); } );
// `teardown` will
// - execute all callbacks in LIFO order
// - call `removeChild` on all DOM elements in LIFO order
// - call `removeEventListener` on all event listeners in LIFO order
// The goal of a teardown is to return to the same state that the DOM was before
// `impress().init()` was called.
var teardown = function() {
// Execute the callbacks in LIFO order
var i; // Needed by jshint
for ( i = callbackList.length - 1; i >= 0; i-- ) {
callbackList[ i ]( rootId );
}
callbackList = [];
for ( i = 0; i < elementList.length; i++ ) {
elementList[ i ].parentElement.removeChild( elementList[ i ] );
}
elementList = [];
for ( i = 0; i < eventListenerList.length; i++ ) {
var target = eventListenerList[ i ].target;
var type = eventListenerList[ i ].type;
var listener = eventListenerList[ i ].listener;
target.removeEventListener( type, listener );
}
};
var lib = {
pushElement: pushElement,
appendChild: appendChild,
pushEventListener: pushEventListener,
addEventListener: addEventListener,
pushCallback: pushCallback,
teardown: teardown
};
roots[ rootId ] = lib;
rootsCount++;
return lib;
};
// Let impress core know about the existence of this library
window.impress.addLibraryFactory( { gc: libraryFactory } );
// CORE INIT
// The library factory (gc(rootId)) is called at the beginning of impress(rootId).init()
// For the purposes of teardown(), we can use this as an opportunity to save the state
// of a few things in the DOM in their virgin state, before impress().init() did anything.
// Note: These could also be recorded by the code in impress.js core as these values
// are changed, but in an effort to not deviate too much from upstream, I'm adding
// them here rather than the core itself.
var recordStartingState = function( rootId ) {
startingState.roots[ rootId ] = {};
startingState.roots[ rootId ].steps = [];
// Record whether the steps have an id or not
var steps = document.getElementById( rootId ).querySelectorAll( ".step" );
for ( var i = 0; i < steps.length; i++ ) {
var el = steps[ i ];
startingState.roots[ rootId ].steps.push( {
el: el,
id: el.getAttribute( "id" )
} );
}
// In the rare case of multiple roots, the following is changed on first init() and
// reset at last tear().
if ( rootsCount === 0 ) {
startingState.body = {};
// It is customary for authors to set body.class="impress-not-supported" as a starting
// value, which can then be removed by impress().init(). But it is not required.
// Remember whether it was there or not.
if ( document.body.classList.contains( "impress-not-supported" ) ) {
startingState.body.impressNotSupported = true;
} else {
startingState.body.impressNotSupported = false;
}
// If there's a <meta name="viewport"> element, its contents will be overwritten by init
var metas = document.head.querySelectorAll( "meta" );
for ( i = 0; i < metas.length; i++ ) {
var m = metas[ i ];
if ( m.name === "viewport" ) {
startingState.meta = m.content;
}
}
}
};
// CORE TEARDOWN
var resetStartingState = function( rootId ) {
// Reset body element
document.body.classList.remove( "impress-enabled" );
document.body.classList.remove( "impress-disabled" );
var root = document.getElementById( rootId );
var activeId = root.querySelector( ".active" ).id;
document.body.classList.remove( "impress-on-" + activeId );
document.documentElement.style.height = "";
document.body.style.height = "";
document.body.style.overflow = "";
// Remove style values from the root and step elements
// Note: We remove the ones set by impress.js core. Otoh, we didn't preserve any original
// values. A more sophisticated implementation could keep track of original values and then
// reset those.
var steps = root.querySelectorAll( ".step" );
for ( var i = 0; i < steps.length; i++ ) {
steps[ i ].classList.remove( "future" );
steps[ i ].classList.remove( "past" );
steps[ i ].classList.remove( "present" );
steps[ i ].classList.remove( "active" );
steps[ i ].style.position = "";
steps[ i ].style.transform = "";
steps[ i ].style[ "transform-style" ] = "";
}
root.style.position = "";
root.style[ "transform-origin" ] = "";
root.style.transition = "";
root.style[ "transform-style" ] = "";
root.style.top = "";
root.style.left = "";
root.style.transform = "";
// Reset id of steps ("step-1" id's are auto generated)
steps = startingState.roots[ rootId ].steps;
var step;
while ( step = steps.pop() ) {
if ( step.id === null ) {
step.el.removeAttribute( "id" );
} else {
step.el.setAttribute( "id", step.id );
}
}
delete startingState.roots[ rootId ];
// Move step div elements away from canvas, then delete canvas
// Note: There's an implicit assumption here that the canvas div is the only child element
// of the root div. If there would be something else, it's gonna be lost.
var canvas = root.firstChild;
var canvasHTML = canvas.innerHTML;
root.innerHTML = canvasHTML;
if ( roots[ rootId ] !== undefined ) {
delete roots[ rootId ];
rootsCount--;
}
if ( rootsCount === 0 ) {
// In the rare case that more than one impress root elements were initialized, these
// are only reset when all are uninitialized.
document.body.classList.remove( "impress-supported" );
if ( startingState.body.impressNotSupported ) {
document.body.classList.add( "impress-not-supported" );
}
// We need to remove or reset the meta element inserted by impress.js
var metas = document.head.querySelectorAll( "meta" );
for ( i = 0; i < metas.length; i++ ) {
var m = metas[ i ];
if ( m.name === "viewport" ) {
if ( startingState.meta !== undefined ) {
m.content = startingState.meta;
} else {
m.parentElement.removeChild( m );
}
}
}
}
};
} )( document, window );

0
src/lib/position.ts Normal file
View File

View File

@@ -1,429 +0,0 @@
/**
* Helper functions for rotation.
*
* Tommy Tam (c) 2021
* MIT License
*/
( function( document, window ) {
"use strict";
// Singleton library variables
var roots = [];
var libraryFactory = function( rootId ) {
if ( roots[ "impress-root-" + rootId ] ) {
return roots[ "impress-root-" + rootId ];
}
/**
* Round the number to 2 decimals, it's enough for use
*/
var roundNumber = function( num ) {
return Math.round( ( num + Number.EPSILON ) * 100 ) / 100;
};
/**
* Get the length/norm of a vector.
*
* https://en.wikipedia.org/wiki/Norm_(mathematics)
*/
var vectorLength = function( vec ) {
return Math.sqrt( vec.x * vec.x + vec.y * vec.y + vec.z * vec.z );
};
/**
* Dot product of two vectors.
*
* https://en.wikipedia.org/wiki/Dot_product
*/
var vectorDotProd = function( vec1, vec2 ) {
return vec1.x * vec2.x + vec1.y * vec2.y + vec1.z * vec2.z;
};
/**
* Cross product of two vectors.
*
* https://en.wikipedia.org/wiki/Cross_product
*/
var vectorCrossProd = function( vec1, vec2 ) {
return {
x: vec1.y * vec2.z - vec1.z * vec2.y,
y: vec1.z * vec2.x - vec1.x * vec2.z,
z: vec1.x * vec2.y - vec1.y * vec2.x
};
};
/**
* Determine wheter a vector is a zero vector
*/
var isZeroVector = function( vec ) {
return !roundNumber( vec.x ) && !roundNumber( vec.y ) && !roundNumber( vec.z );
};
/**
* Scalar triple product of three vectors.
*
* It can be used to determine the handness of vectors.
*
* https://en.wikipedia.org/wiki/Triple_product#Scalar_triple_product
*/
var tripleProduct = function( vec1, vec2, vec3 ) {
return vectorDotProd( vectorCrossProd( vec1, vec2 ), vec3 );
};
/**
* The world/absolute unit coordinates.
*
* This coordinate is used by browser to position objects.
* It will not be affected by object rotations.
* All relative positions will finally be converted to this
* coordinate to be used.
*/
var worldUnitCoordinate = {
x: { x:1, y:0, z:0 },
y: { x:0, y:1, z:0 },
z: { x:0, y:0, z:1 }
};
/**
* Make quaternion from rotation axis and angle.
*
* q = [ cos(½θ), sin(½θ) axis ]
*
* If the angle is zero, returns the corresponded quaternion
* of axis.
*
* If the angle is not zero, returns the rotating quaternion
* which corresponds to rotation about the axis, by the angle θ.
*
* https://en.wikipedia.org/wiki/Quaternion
* https://en.wikipedia.org/wiki/Quaternions_and_spatial_rotation
*/
var makeQuaternion = function( axis, theta = 0 ) {
var r = 0;
var t = 1;
if ( theta ) {
var radians = theta * Math.PI / 180;
r = Math.cos( radians / 2 );
t = Math.sin( radians / 2 ) / vectorLength( axis );
}
var q = [ r, axis.x * t, axis.y * t, axis.z * t ];
return q;
};
/**
* Extract vector from quaternion
*/
var quaternionToVector = function( quaternion ) {
return {
x: roundNumber( quaternion[ 1 ] ),
y: roundNumber( quaternion[ 2 ] ),
z: roundNumber( quaternion[ 3 ] )
};
};
/**
* Returns the conjugate quaternion of a quaternion
*
* https://en.wikipedia.org/wiki/Quaternion#Conjugation,_the_norm,_and_reciprocal
*/
var conjugateQuaternion = function( quaternion ) {
return [ quaternion[ 0 ], -quaternion[ 1 ], -quaternion[ 2 ], -quaternion[ 3 ] ];
};
/**
* Left multiple two quaternion.
*
* Is's used to combine two rotating quaternion into one.
*/
var leftMulQuaternion = function( q1, q2 ) {
return [
( q1[ 0 ] * q2[ 0 ] - q1[ 1 ] * q2[ 1 ] - q1[ 2 ] * q2[ 2 ] - q1[ 3 ] * q2[ 3 ] ),
( q1[ 1 ] * q2[ 0 ] + q1[ 0 ] * q2[ 1 ] - q1[ 3 ] * q2[ 2 ] + q1[ 2 ] * q2[ 3 ] ),
( q1[ 2 ] * q2[ 0 ] + q1[ 3 ] * q2[ 1 ] + q1[ 0 ] * q2[ 2 ] - q1[ 1 ] * q2[ 3 ] ),
( q1[ 3 ] * q2[ 0 ] - q1[ 2 ] * q2[ 1 ] + q1[ 1 ] * q2[ 2 ] + q1[ 0 ] * q2[ 3 ] )
];
};
/**
* Convert a rotation into a quaternion
*/
var rotationToQuaternion = function( baseCoordinate, rotation ) {
var order = rotation.order ? rotation.order : "xyz";
var axes = order.split( "" );
var result = [ 1, 0, 0, 0 ];
for ( var i = 0; i < axes.length; i++ ) {
var deg = rotation[ axes[ i ] ];
if ( !deg || ( Math.abs( deg ) < 0.0001 ) ) {
continue;
}
// All CSS rotation is based on the rotated coordinate
// So we need to calculate the rotated coordinate first
var coordinate = baseCoordinate;
if ( i > 0 ) {
coordinate = {
x: rotateByQuaternion( baseCoordinate.x, result ),
y: rotateByQuaternion( baseCoordinate.y, result ),
z: rotateByQuaternion( baseCoordinate.z, result )
};
}
result = leftMulQuaternion(
makeQuaternion( coordinate[ axes[ i ] ], deg ),
result );
}
return result;
};
/**
* Rotate a vector by a quaternion.
*/
var rotateByQuaternion = function( vec, quaternion ) {
var q = makeQuaternion( vec );
q = leftMulQuaternion(
leftMulQuaternion( quaternion, q ),
conjugateQuaternion( quaternion ) );
return quaternionToVector( q );
};
/**
* Rotate a vector by rotaion sequence.
*/
var rotateVector = function( baseCoordinate, vec, rotation ) {
var quaternion = rotationToQuaternion( baseCoordinate, rotation );
return rotateByQuaternion( vec, quaternion );
};
/**
* Given a rotation, return the rotationed coordinate
*/
var rotateCoordinate = function( coordinate, rotation ) {
var quaternion = rotationToQuaternion( coordinate, rotation );
return {
x: rotateByQuaternion( coordinate.x, quaternion ),
y: rotateByQuaternion( coordinate.y, quaternion ),
z: rotateByQuaternion( coordinate.z, quaternion )
};
};
/**
* Return the angle between two vector.
*
* The axis is used to determine the rotation direction.
*/
var angleBetweenTwoVector = function( axis, vec1, vec2 ) {
var vecLen1 = vectorLength( vec1 );
var vecLen2 = vectorLength( vec2 );
if ( !vecLen1 || !vecLen2 ) {
return 0;
}
var cos = vectorDotProd( vec1, vec2 ) / vecLen1 / vecLen2 ;
var angle = Math.acos( cos ) * 180 / Math.PI;
if ( tripleProduct( vec1, vec2, axis ) > 0 ) {
return angle;
} else {
return -angle;
}
};
/**
* Return the angle between a vector and a plane.
*
* The plane is determined by an axis and a vector on the plane.
*/
var angleBetweenPlaneAndVector = function( axis, planeVec, rotatedVec ) {
var norm = vectorCrossProd( axis, planeVec );
if ( isZeroVector( norm ) ) {
return 0;
}
return 90 - angleBetweenTwoVector( axis, rotatedVec, norm );
};
/**
* Calculated a order specified rotation sequence to
* transform from the world coordinate to required coordinate.
*/
var coordinateToOrderedRotation = function( coordinate, order ) {
var axis0 = order[ 0 ];
var axis1 = order[ 1 ];
var axis2 = order[ 2 ];
var reversedOrder = order.split( "" ).reverse().join( "" );
var rotate2 = angleBetweenPlaneAndVector(
coordinate[ axis2 ],
worldUnitCoordinate[ axis0 ],
coordinate[ axis0 ] );
// The r2 is the reverse of rotate for axis2
// The coordinate1 is the coordinate before rotate of axis2
var r2 = { order: reversedOrder };
r2[ axis2 ] = -rotate2;
var coordinate1 = rotateCoordinate( coordinate, r2 );
// Calculate the rotation for axis1
var rotate1 = angleBetweenTwoVector(
coordinate1[ axis1 ],
worldUnitCoordinate[ axis0 ],
coordinate1[ axis0 ] );
// Calculate the rotation for axis0
var rotate0 = angleBetweenTwoVector(
worldUnitCoordinate[ axis0 ],
worldUnitCoordinate[ axis1 ],
coordinate1[ axis1 ] );
var rotation = { };
rotation.order = order;
rotation[ axis0 ] = roundNumber( rotate0 );
rotation[ axis1 ] = roundNumber( rotate1 );
rotation[ axis2 ] = roundNumber( rotate2 );
return rotation;
};
/**
* Returns the possible rotations from unit coordinate
* to specified coordinate.
*/
var possibleRotations = function( coordinate ) {
var orders = [ "xyz", "xzy", "yxz", "yzx", "zxy", "zyx" ];
var rotations = [ ];
for ( var i = 0; i < orders.length; ++i ) {
rotations.push(
coordinateToOrderedRotation( coordinate, orders[ i ] )
);
}
return rotations;
};
/**
* Calculate a degree which in range (-180, 180] of baseDeg
*/
var nearestAngle = function( baseDeg, deg ) {
while ( deg > baseDeg + 180 ) {
deg -= 360;
}
while ( deg < baseDeg - 180 ) {
deg += 360;
}
return deg;
};
/**
* Given a base rotation and multiple rotations, return the best one.
*
* The best one is the one has least rotate from base.
*/
var bestRotation = function( baseRotate, rotations ) {
var bestScore;
var bestRotation;
for ( var i = 0; i < rotations.length; ++i ) {
var rotation = {
order: rotations[ i ].order,
x: nearestAngle( baseRotate.x, rotations[ i ].x ),
y: nearestAngle( baseRotate.y, rotations[ i ].y ),
z: nearestAngle( baseRotate.z, rotations[ i ].z )
};
var score = Math.abs( rotation.x - baseRotate.x ) +
Math.abs( rotation.y - baseRotate.y ) +
Math.abs( rotation.z - baseRotate.z );
if ( !i || ( score < bestScore ) ) {
bestScore = score;
bestRotation = rotation;
}
}
return bestRotation;
};
/**
* Given a coordinate, return the best rotation to achieve it.
*
* The baseRotate is used to select the near rotation from it.
*/
var coordinateToRotation = function( baseRotate, coordinate ) {
var rotations = possibleRotations( coordinate );
return bestRotation( baseRotate, rotations );
};
/**
* Apply a relative rotation to the base rotation.
*
* Calculate the coordinate after the rotation on each axis,
* and finally find out a one step rotation has the effect
* of two rotation.
*
* If there're multiple way to accomplish, select the one
* that is nearest to the base.
*
* Return one rotation has the same effect.
*/
var combineRotations = function( rotations ) {
// No rotation
if ( rotations.length <= 0 ) {
return { x:0, y:0, z:0, order:"xyz" };
}
// Find out the base coordinate
var coordinate = worldUnitCoordinate;
// One by one apply rotations in order
for ( var i = 0; i < rotations.length; i++ ) {
coordinate = rotateCoordinate( coordinate, rotations[ i ] );
}
// Calculate one rotation from unit coordinate to rotated
// coordinate. Because there're multiple possibles,
// select the one nearest to the base
var rotate = coordinateToRotation( rotations[ 0 ], coordinate );
return rotate;
};
var translateRelative = function( relative, prevRotation ) {
var result = rotateVector(
worldUnitCoordinate, relative, prevRotation );
result.rotate = combineRotations(
[ prevRotation, relative.rotate ] );
return result;
};
var lib = {
translateRelative: translateRelative
};
roots[ "impress-root-" + rootId ] = lib;
return lib;
};
// Let impress core know about the existence of this library
window.impress.addLibraryFactory( { rotation: libraryFactory } );
} )( document, window );

0
src/lib/rotation.ts Normal file
View File

View File

@@ -1,131 +0,0 @@
/**
* Common utility functions
*
* Copyright 2011-2012 Bartek Szopka (@bartaz)
* Henrik Ingo (c) 2016
* MIT License
*/
( function( document, window ) {
"use strict";
var roots = [];
var libraryFactory = function( rootId ) {
if ( roots[ rootId ] ) {
return roots[ rootId ];
}
// `$` returns first element for given CSS `selector` in the `context` of
// the given element or whole document.
var $ = function( selector, context ) {
context = context || document;
return context.querySelector( selector );
};
// `$$` return an array of elements for given CSS `selector` in the `context` of
// the given element or whole document.
var $$ = function( selector, context ) {
context = context || document;
return arrayify( context.querySelectorAll( selector ) );
};
// `arrayify` takes an array-like object and turns it into real Array
// to make all the Array.prototype goodness available.
var arrayify = function( a ) {
return [].slice.call( a );
};
// `byId` returns element with given `id` - you probably have guessed that ;)
var byId = function( id ) {
return document.getElementById( id );
};
// `getElementFromHash` returns an element located by id from hash part of
// window location.
var getElementFromHash = function() {
// Get id from url # by removing `#` or `#/` from the beginning,
// so both "fallback" `#slide-id` and "enhanced" `#/slide-id` will work
var encoded = window.location.hash.replace( /^#\/?/, "" );
return byId( decodeURIComponent( encoded ) );
};
// `getUrlParamValue` return a given URL parameter value if it exists
// `undefined` if it doesn't exist
var getUrlParamValue = function( parameter ) {
var chunk = window.location.search.split( parameter + "=" )[ 1 ];
var value = chunk && chunk.split( "&" )[ 0 ];
if ( value !== "" ) {
return value;
}
};
// Throttling function calls, by Remy Sharp
// http://remysharp.com/2010/07/21/throttling-function-calls/
var throttle = function( fn, delay ) {
var timer = null;
return function() {
var context = this, args = arguments;
window.clearTimeout( timer );
timer = window.setTimeout( function() {
fn.apply( context, args );
}, delay );
};
};
// `toNumber` takes a value given as `numeric` parameter and tries to turn
// it into a number. If it is not possible it returns 0 (or other value
// given as `fallback`).
var toNumber = function( numeric, fallback ) {
return isNaN( numeric ) ? ( fallback || 0 ) : Number( numeric );
};
/**
* Extends toNumber() to correctly compute also relative-to-screen-size values 5w and 5h.
*
* Returns the computed value in pixels with w/h postfix removed.
*/
var toNumberAdvanced = function( numeric, fallback ) {
if ( typeof numeric !== "string" ) {
return toNumber( numeric, fallback );
}
var ratio = numeric.match( /^([+-]*[\d\.]+)([wh])$/ );
if ( ratio == null ) {
return toNumber( numeric, fallback );
} else {
var value = parseFloat( ratio[ 1 ] );
var config = window.impress.getConfig();
var multiplier = ratio[ 2 ] === "w" ? config.width : config.height;
return value * multiplier;
}
};
// `triggerEvent` builds a custom DOM event with given `eventName` and `detail` data
// and triggers it on element given as `el`.
var triggerEvent = function( el, eventName, detail ) {
var event = document.createEvent( "CustomEvent" );
event.initCustomEvent( eventName, true, true, detail );
el.dispatchEvent( event );
};
var lib = {
$: $,
$$: $$,
arrayify: arrayify,
byId: byId,
getElementFromHash: getElementFromHash,
throttle: throttle,
toNumber: toNumber,
toNumberAdvanced: toNumberAdvanced,
triggerEvent: triggerEvent,
getUrlParamValue: getUrlParamValue
};
roots[ rootId ] = lib;
return lib;
};
// Let impress core know about the existence of this library
window.impress.addLibraryFactory( { util: libraryFactory } );
} )( document, window );

0
src/lib/util.ts Normal file
View File