-
Notifications
You must be signed in to change notification settings - Fork 18
/
Copy pathfunction.extensions.js
133 lines (127 loc) · 3.14 KB
/
function.extensions.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
/**
* Function#not() -> Function
*
* Returns negated function
*
* Find all hidden elements:
*
* $$('*').findAll(function(element) { return !element.visible() }); // old way
* $$('*').findAll(Element.visible.not()); // using not
*
**/
Function.prototype.not = function() {
var f = this;
return function() {
return !f.apply(f, arguments);
}
};
/**
* Calls and returns function
*
* // old way
* myElement.toggle();
* input.observe('change', myElement.toggle);
*
* // new way
* input.observe('change', myElement.toggle.runOnce());
**/
Function.prototype.runOnce = function() {
this.apply(this, arguments);
return this;
};
/**
* Invokes function as a constructor
*
* var Person = Class.create({
* initialize: function(name){
* this.name = name;
* }
* })
*
* Person._new('Foo Bar');
*
**/
Function.prototype._new = function() {
var __method = this, args = $A(arguments);
function C() { return __method.apply(this, args); };
C.prototype = __method.prototype;
return new C;
};
/**
* Function#toDelayed(timeout) -> Function
* - timeout(Number): interval to call function within (in seconds)
*
* Augments a function into a delayed one
*
* formElement.observe('reset', handler.toDelayed(1));
*
**/
Function.prototype.toDelayed = function(timeout) {
var __method = this;
return function() {
var args = $A(arguments);
setTimeout(function(){ __method.apply(__method, args) }, timeout * 1000);
}
};
/**
* Function#toDeferred() -> Function
*
* Augments a function into a deferred one
*
* formElement.observe('reset', handler.toDeffered());
*
**/
Function.prototype.toDeferred = function() {
return this.toDelayed(0.01);
};
/**
* Creates a function which returns specified value.
* Useful as a closure "wrapper" for blocks of code
* which need to have certain variables stored in their own closure (rather than sharing them)
*
* for (var prop in source) {
* dest[prop] = function(){ return String(prop) } // <= "prop" is "shared" among all methods
* }
*
* for (var prop in source) {
* dest[prop] = Function.K(String(prop)); // <= now each "prop" is stored in Function.K's closure
* }
*
**/
Function.K = function(k){
return function() {
return k;
}
};
/**
* Function.prototype.addAdvice(advices) -> Function
* - advices(Object): collection of key/value pairs where key is type of advice and value is advice itself
*
* function sum(){
* return $A(arguments).inject(0, function(result, value){ return result + value; });
* }
*
* sum = sum.addAdvice({
* before: function() { console.log('receiving: ' + $A(arguments)) },
* after: function() { console.log('returning: ' + $A(arguments)) }
* });
*
* sum(1,2,3);
*
* logs:
* receiving: 1,2,3
* returning: 6
*
**/
Function.prototype.addAdvice = function(advices) {
return this.wrap(function() {
var args = $A(arguments), proceed = args.shift();
var a = advices, bf = a.before, ar = a.around, af = a.after;
bf && bf.apply(proceed, args);
ar && ar.apply(proceed, args);
var result = proceed.apply(proceed, args);
ar && ar.apply(proceed, result);
af && af.apply(proceed, result);
return result;
})
};