-
Notifications
You must be signed in to change notification settings - Fork 398
/
reactfire.js
137 lines (119 loc) · 4.27 KB
/
reactfire.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
134
135
136
137
var ReactFireMixin = {
/********************/
/* MIXIN LIFETIME */
/********************/
/* Initializes the Firebase binding refs array */
componentWillMount: function() {
this.firebaseRefs = {};
this.firebaseListeners = {};
},
/* Removes any remaining Firebase bindings */
componentWillUnmount: function() {
for (var key in this.firebaseRefs) {
if (this.firebaseRefs.hasOwnProperty(key)) {
this.unbind(key);
}
}
},
/*************/
/* BINDING */
/*************/
/* Creates a binding between Firebase and the inputted bind variable as an array */
bindAsArray: function(firebaseRef, bindVar, cancelCallback) {
this._bind(firebaseRef, bindVar, cancelCallback, true);
},
/* Creates a binding between Firebase and the inputted bind variable as an object */
bindAsObject: function(firebaseRef, bindVar, cancelCallback) {
this._bind(firebaseRef, bindVar, cancelCallback, false);
},
/* Creates a binding between Firebase and the inputted bind variable as either an array or object */
_bind: function(firebaseRef, bindVar, cancelCallback, bindAsArray) {
this._validateBindVar(bindVar);
var errorMessage, errorCode;
if (Object.prototype.toString.call(firebaseRef) !== "[object Object]") {
errorMessage = "firebaseRef must be an instance of Firebase";
errorCode = "INVALID_FIREBASE_REF";
}
else if (typeof bindAsArray !== "boolean") {
errorMessage = "bindAsArray must be a boolean. Got: " + bindAsArray;
errorCode = "INVALID_BIND_AS_ARRAY";
}
if (typeof errorMessage !== "undefined") {
var error = new Error("ReactFire: " + errorMessage);
error.code = errorCode;
throw error;
}
this.firebaseRefs[bindVar] = firebaseRef.ref();
this.firebaseListeners[bindVar] = firebaseRef.on("value", function(dataSnapshot) {
var newState = {};
if (bindAsArray) {
newState[bindVar] = this._toArray(dataSnapshot.val());
}
else {
newState[bindVar] = dataSnapshot.val();
}
this.setState(newState);
}.bind(this), cancelCallback);
},
/* Removes the binding between Firebase and the inputted bind variable */
unbind: function(bindVar) {
this._validateBindVar(bindVar);
if (typeof this.firebaseRefs[bindVar] === "undefined") {
var error = new Error("ReactFire: unexpected value for bindVar. \"" + bindVar + "\" was either never bound or has already been unbound");
error.code = "UNBOUND_BIND_VARIABLE";
throw error;
}
this.firebaseRefs[bindVar].off("value", this.firebaseListeners[bindVar]);
delete this.firebaseRefs[bindVar];
delete this.firebaseListeners[bindVar];
},
/*************/
/* HELPERS */
/*************/
/* Validates the name of the variable which is being bound */
_validateBindVar: function(bindVar) {
var errorMessage;
if (typeof bindVar !== "string") {
errorMessage = "bindVar must be a string. Got: " + bindVar;
}
else if (bindVar.length === 0) {
errorMessage = "bindVar must be a non-empty string. Got: \"\"";
}
else if (bindVar.length > 768) {
// Firebase can only stored child paths up to 768 characters
errorMessage = "bindVar is too long to be stored in Firebase. Got: " + bindVar;
}
else if (/[\[\].#$\/\u0000-\u001F\u007F]/.test(bindVar)) {
// Firebase does not allow node keys to contain the following characters
errorMessage = "bindVar cannot contain any of the following characters: . # $ ] [ /. Got: " + bindVar;
}
if (typeof errorMessage !== "undefined") {
var error = new Error("ReactFire: " + errorMessage);
error.code = "INVALID_BIND_VARIABLE";
throw error;
}
},
/* Returns true if the inputted object is a JavaScript array */
_isArray: function(obj) {
return (Object.prototype.toString.call(obj) === "[object Array]");
},
/* Converts a Firebase object to a JavaScript array */
_toArray: function(obj) {
var out = [];
if (obj) {
if (this._isArray(obj)) {
out = obj;
}
else if (typeof(obj) === "object") {
for (var key in obj) {
if (obj.hasOwnProperty(key)) {
var item = obj[key];
item.$id = key;
out.push(item);
}
}
}
}
return out;
}
};