mirror of
https://github.com/flynx/actions.js.git
synced 2025-10-28 18:00:11 +00:00
adde action pre-call test and debounce test generator...
Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
This commit is contained in:
parent
03b52f6f9f
commit
7b23e84dcc
66
README.md
66
README.md
@ -158,6 +158,29 @@ n
|
||||
languages such as Python where the order is reversed.
|
||||
|
||||
|
||||
## Index
|
||||
- [Actions](#actions)
|
||||
- [The problem:](#the-problem)
|
||||
- [The solution:](#the-solution)
|
||||
- [What we get:](#what-we-get)
|
||||
- [Restrictions comparing to native JavaScript:](#restrictions-comparing-to-native-javascript)
|
||||
- [Index](#index)
|
||||
- [The main entities:](#the-main-entities)
|
||||
- [The action system main protocols:](#the-action-system-main-protocols)
|
||||
- [1. Documentation generation and introspection (`MetaActions`)](#1-documentation-generation-and-introspection-metaactions)
|
||||
- [2. Event-like callbacks for actions (`MetaActions`, `Action`)](#2-event-like-callbacks-for-actions-metaactions-action)
|
||||
- [3. A mechanism to define and extend already defined actions](#3-a-mechanism-to-define-and-extend-already-defined-actions)
|
||||
- [Secondary action protocols:](#secondary-action-protocols)
|
||||
- [1. A mechanism to manually call the pre/post stages of an action](#1-a-mechanism-to-manually-call-the-prepost-stages-of-an-action)
|
||||
- [2. A mechanism to chain/wrap actions or an action and a function.](#2-a-mechanism-to-chainwrap-actions-or-an-action-and-a-function)
|
||||
- [3. `.__actioncall__` action / handler](#3-__actioncall__-action--handler)
|
||||
- [4. Action attributes](#4-action-attributes)
|
||||
- [5. Pre-call testing if an action can be called](#5-pre-call-testing-if-an-action-can-be-called)
|
||||
- [6. Scheduling a call after the running action](#6-scheduling-a-call-after-the-running-action)
|
||||
- [7. Calling action handlers sorted independently of the prototype chain](#7-calling-action-handlers-sorted-independently-of-the-prototype-chain)
|
||||
- [Alias protocols:](#alias-protocols)
|
||||
- [License](#license)
|
||||
|
||||
|
||||
### The main entities:
|
||||
|
||||
@ -479,6 +502,17 @@ the second arguments, and as normal a result on the post phase.
|
||||
|
||||
#### 4. Action attributes
|
||||
|
||||
Setting action attributes:
|
||||
```javascript
|
||||
someAction: [
|
||||
{attr: 'value', .. },
|
||||
function(){
|
||||
...
|
||||
}],
|
||||
|
||||
```
|
||||
|
||||
Attribute access:
|
||||
```
|
||||
<action-set>.getActionAttr('action', 'attr')
|
||||
-> <value>
|
||||
@ -487,7 +521,35 @@ the second arguments, and as normal a result on the post phase.
|
||||
-> <value>
|
||||
```
|
||||
|
||||
#### 5. Scheduling a call after the running action
|
||||
|
||||
#### 5. Pre-call testing if an action can be called
|
||||
|
||||
A pre call test is called before the action's pre handlers are called and if
|
||||
it returns anything truthy the action is not called and that return value is
|
||||
returned instead.
|
||||
|
||||
To return a falsey value wrap it in `actions.ASIS(..)`
|
||||
|
||||
Only the top-most pre call test is called.
|
||||
|
||||
Defining a pre call test:
|
||||
```javascript
|
||||
someAction: [
|
||||
{precall: actions.debounce(200, true)},
|
||||
function(){
|
||||
...
|
||||
}],
|
||||
```
|
||||
|
||||
The test is called in the context of the `<action-set>`
|
||||
```
|
||||
<pre-call-test>(<action>, ...)
|
||||
-> undefined
|
||||
-> <value>
|
||||
```
|
||||
|
||||
|
||||
#### 6. Scheduling a call after the running action
|
||||
|
||||
This enables the action code to schedule a call after the current
|
||||
action level or the root action is done.
|
||||
@ -520,7 +582,7 @@ Example:
|
||||
- This is pointless outside of an action call, thus an exception will be thrown.
|
||||
|
||||
|
||||
#### 6. Calling action handlers sorted independently of the prototype chain
|
||||
#### 7. Calling action handlers sorted independently of the prototype chain
|
||||
|
||||
This sorts action handlers by priority `.sortedActionPriority` then
|
||||
order and calls them.
|
||||
|
||||
108
actions.js
108
actions.js
@ -58,6 +58,46 @@ function(func){
|
||||
return func.apply(this, [handlers.pop()].concat(args)) } }
|
||||
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
// pre-call tests...
|
||||
|
||||
// Debounce action call...
|
||||
//
|
||||
// debounce()
|
||||
// debounce(timeout[, postcall])
|
||||
// -> this
|
||||
// -> false
|
||||
//
|
||||
//
|
||||
// XXX would be good to add a version of this that would debounce taking
|
||||
// into acoount args...
|
||||
// XXX EXPERIMENTAL (precall)...
|
||||
var debounce =
|
||||
module.debounce =
|
||||
function(timeout=200, postcall=true){
|
||||
var debounced = false
|
||||
var last_args
|
||||
|
||||
return function(action, ...args){
|
||||
// call...
|
||||
if(!debounced){
|
||||
debounced = setTimeout(
|
||||
function(){
|
||||
debounced = false
|
||||
// post call...
|
||||
postcall
|
||||
&& last_args !== undefined
|
||||
&& action.call(this, ...last_args) }.bind(this),
|
||||
timeout)
|
||||
// cleanup...
|
||||
last_args = undefined
|
||||
return false
|
||||
// skip...
|
||||
} else {
|
||||
last_args = args
|
||||
return this } } }
|
||||
|
||||
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
// String action parser/runner...
|
||||
@ -483,6 +523,29 @@ object.Constructor('Action', Function, {
|
||||
|| MetaActions.getHandlers
|
||||
var handlers = getHandlers.call(context, outer)
|
||||
|
||||
// precall test...
|
||||
// NOTE: we are calling only the top-most precall method, the
|
||||
// rest are ignored...
|
||||
// XXX EXPERIMENTAL (precall)...
|
||||
var precall = handlers
|
||||
.map(function(h){
|
||||
return (h.pre || {}).precall ?
|
||||
[h.pre.precall]
|
||||
: [] })
|
||||
.flat()
|
||||
.pop()
|
||||
if(typeof(precall) == 'function'){
|
||||
// XXX revise args...
|
||||
precall = precall.call(context, this, ...args)
|
||||
if(precall){
|
||||
return {
|
||||
rejected: true,
|
||||
// XXX revise how default value is returned...
|
||||
result: precall instanceof ASIS ?
|
||||
precall.value
|
||||
: precall,
|
||||
} } }
|
||||
|
||||
// handle cases where .func is not in handlers...
|
||||
//
|
||||
// NOTE: see Special cases in method doc above...
|
||||
@ -554,13 +617,10 @@ object.Constructor('Action', Function, {
|
||||
throw error }
|
||||
|
||||
// return context if nothing specific is returned...
|
||||
res = res === undefined ? context
|
||||
: res instanceof ASIS ? res.value
|
||||
// XXX returning an explicit [undefined]...
|
||||
//: res instanceof Array
|
||||
// && res.length == 1
|
||||
// && res.indexOf(undefined) == 0 ?
|
||||
// undefined
|
||||
res = res === undefined ?
|
||||
context
|
||||
: res instanceof ASIS ?
|
||||
res.value
|
||||
: res
|
||||
|
||||
return {
|
||||
@ -626,12 +686,17 @@ object.Constructor('Action', Function, {
|
||||
// chaining...
|
||||
//
|
||||
// For docs see: MetaActions.chainApply(..) and the base module doc.
|
||||
chainApply: function(context, inner, args){
|
||||
args = [...(args || [])]
|
||||
chainCall: function(context, inner, ...args){
|
||||
args = args || []
|
||||
var outer = this.name
|
||||
|
||||
var data = this.pre(context, args)
|
||||
|
||||
// precall test...
|
||||
// XXX EXPERIMENTAL (precall)...
|
||||
if(data.rejected == true){
|
||||
return data.result }
|
||||
|
||||
// call the inner action/function if preset....
|
||||
// NOTE: this is slightly different (see docs) to what happens in
|
||||
// .pre(..)/.post(..), thus we are doing this separately and
|
||||
@ -640,9 +705,9 @@ object.Constructor('Action', Function, {
|
||||
var res = inner instanceof Function ?
|
||||
inner.apply(context, args)
|
||||
: inner instanceof Array && inner.length > 0 ?
|
||||
context[inner.pop()].chainApply(context, inner, args)
|
||||
context[inner.pop()].chainCall(context, inner, ...args)
|
||||
: typeof(inner) == typeof('str') ?
|
||||
context[inner].chainApply(context, null, args)
|
||||
context[inner].chainCall(context, null, ...args)
|
||||
: undefined
|
||||
|
||||
// call the resulting function...
|
||||
@ -667,8 +732,8 @@ object.Constructor('Action', Function, {
|
||||
return that.post(context, data) }) }
|
||||
|
||||
return this.post(context, data) },
|
||||
chainCall: function(context, inner){
|
||||
return this.chainApply(context, inner, [...arguments].slice(2)) },
|
||||
chainApply: function(context, inner, args){
|
||||
return this.chainCall(context, inner, ...args) },
|
||||
|
||||
|
||||
// constructor...
|
||||
@ -686,7 +751,7 @@ object.Constructor('Action', Function, {
|
||||
|
||||
// create the actual instance we will be returning...
|
||||
var meth = function(){
|
||||
return meth.chainApply(this, null, arguments) }
|
||||
return meth.chainCall(this, null, ...arguments) }
|
||||
meth.__proto__ = this.__proto__
|
||||
|
||||
// precess args...
|
||||
@ -1481,14 +1546,13 @@ module.MetaActions = {
|
||||
|
||||
// Apply/call a function/action "inside" an action...
|
||||
//
|
||||
// .chainApply(outer, inner)
|
||||
// .chainApply(outer, inner, arguments)
|
||||
// -> result
|
||||
//
|
||||
// .chainCall(outer, inner)
|
||||
// .chainCall(outer, inner, ..)
|
||||
// -> result
|
||||
//
|
||||
// .chainApply(outer, inner)
|
||||
// .chainApply(outer, inner, arguments)
|
||||
// -> result
|
||||
//
|
||||
// The inner action call is completely nested as base of the outer
|
||||
// action.
|
||||
@ -1514,10 +1578,10 @@ module.MetaActions = {
|
||||
// NOTE: these call the action's .chainApply(..) and .chainCall(..)
|
||||
// methods, thus is not compatible with non-action methods...
|
||||
// NOTE: .chainCall('action', ..) is equivalent to .action.chainCall(..)
|
||||
chainApply: function(outer, inner, args){
|
||||
return this[outer].chainApply(this, inner, args) },
|
||||
chainCall: function(outer, inner){
|
||||
return this[outer].chainApply(this, inner, [...arguments].slice(2)) },
|
||||
chainCall: function(outer, inner, ...args){
|
||||
return this[outer].chainCall(this, inner, ...args) },
|
||||
chainApply: function(outer, inner, ...args){
|
||||
return this[outer].chainCall(this, inner, args) },
|
||||
|
||||
|
||||
// Call action handlers serted by .sortedActionPriority...
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "ig-actions",
|
||||
"version": "3.24.19",
|
||||
"version": "3.24.20",
|
||||
"description": "",
|
||||
"main": "actions.js",
|
||||
"scripts": {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user