-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathbacklash.js
More file actions
179 lines (164 loc) · 4.84 KB
/
backlash.js
File metadata and controls
179 lines (164 loc) · 4.84 KB
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
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
/**
* Reactive programming.
* By Riten Vagadiya
*/
/**
* Backlash depends on reckonjs for providing string interpolations (also developed by matterial and MIT licensed)
*/
if (typeof window == "undefined" ) {
var reckon = require("reckonjs");
}
/**
* Object to store utility functions for backlash
* @type {Object}
*/
var bGlobal = {
/**
* List of all backlash initiated variables
* @type {Object}
*/
backlashVariables: {},
backlashEvents: {},
/**
* Evaluate a given backlash expression and return final value
* @param {String} backlashString The backlash expression in its format
* @return {String} The final presentable, usable value
*/
evaluate: function(backlashString) {
return backlashString ? backlashString.reckon(this.backlashVariables) : backlashString;
},
/**
* Evaluate a given variable name and return final value
* @param {String} string The name of the backlash-initiated variable
* @return {String} The final presentable, usable value
*/
getEvaluated: function(string) {
return this.evaluate(this.backlashVariables[string]);
}
}
bGlobal.backlashVariables.length = function() {
var len = 0;
for (var i in this) {
len++;
}
return len;
}
/**
* The returned function which goes into the reference variables for further manipulation of the backlash-initiated object
* @param {Object} instance Backlash instance
* @return {Function} Return a decorated function with extra arms
*/
var returnFn = function(instance) {
if (typeof instance.backlashRef === "undefined") {
throw new Error("ERROR 101: variable used after being trashed");
}
/**
* The returned function will accept a value, this is how mutability is achieved for backlash objects
* @param {Any} newValue Update the backlash value to this value
* @return {Function} Return back the same function for chaining
*/
var fn = function(newValue) {
var b = instance;
/**
* Assumption is, if no value is provided, it is a call to fetch the value
*/
if (typeof newValue === "undefined") {
return bGlobal.getEvaluated(instance.backlashRef);
}
instance.setValue(newValue);
/**
* This magic line enables chaining infinitely - try firstName("Jonh")("Joan")("John") to have the final value set as "John".
*/
return returnFn(instance);
};
/**
* Extend this function with it's own set of extended functions
*/
instance.initReturnFunction.apply(fn, [instance]);
return fn;
};
/**
* The actual backlash object that is instantiated once for every variable
* @param {Object} value If this is the first time, this argument will be the name of the variable
* @param {Object} arg If this is the second time, this argument will be undefined, else it will be the value to be used during initiation (shorthand)
* @return {Function} Return the chaininable reference function for manipulating the variable
*/
var backlash = function(value, arg) {
var $this = this;
/**
* Reading a value
*/
if (typeof value === "undefined") return $this;
/**
* If already defined, it should now set the value
*/
if ($this.constructor.name === "backlash") {
$this.setValue(value);
return returnFn($this);
} else {
/**
* Initialize a backlash variable
* @type {backlash}
*/
var b = new backlash();
/**
* Store a reference to the variable name passed in the 'value' argument
* @type {String}
*/
b.backlashRef = value;
if (typeof arg !== "undefined") {
b.setValue(arg);
}
return returnFn(b);
}
};
/**
* Prototype of the backlash instance
* Initializes in the context of the window for browser, and as root for nodejs
*/
backlash.prototype = (function(context) {
return {
initReturnFunction: function(instance) {
var $this = this;
/**
* If the function is used directly in a string, get the toString equivalent to simulate a normal variable
* @return {String}
*/
$this.toString = function() {
return $this();
};
$this.eventHandlers = [];
$this.$watch = function(fn) {
$this.eventHandlers.push({"change": fn});
};
$this.trash = function() {
delete bGlobal.backlashVariables[instance.backlashRef];
delete instance.backlashRef;
};
$this.trashed = function() {
return (typeof instance.backlashRef === "undefined");
}
},
setValue: function(value) {
bGlobal.backlashVariables[this.backlashRef] = value;
},
toString: function() {
return bGlobal.evaluate(this.backlashRef).toString();
},
get: function() {
return bGlobal.backlashVariables[this.backlashRef];
}
};
})(this);
/**
* Interface both the creating function, and the list of all variables for direct usage
* @return {Object}
*/
if (typeof window !== "undefined" ) {
window.backlash = backlash;
window.backlashVars = bGlobal.backlashVariables;
} else {
module.exports = function() {
return {creator: backlash, variables: bGlobal.backlashVariables};
};
}