1
+ /*!
2
+ * ReactFire is an open-source JavaScript library that allows you to add a
3
+ * realtime data source to your React apps by providing and easy way to let
4
+ * Firebase populate the state of React components.
5
+ *
6
+ * ReactFire 0.4.0
7
+ * https://github.com/firebase/reactfire/
8
+ * License: MIT
9
+ */
10
+
11
+ ; ( function ( root , factory ) {
12
+ "use strict" ;
13
+ if ( typeof define === "function" && define . amd ) {
14
+ // AMD
15
+ define ( [ ] , function ( ) {
16
+ return ( root . ReactFireMixin = factory ( ) ) ;
17
+ } ) ;
18
+ } else if ( typeof exports === "object" ) {
19
+ // CommonJS
20
+ module . exports = factory ( ) ;
21
+ } else {
22
+ // Global variables
23
+ root . ReactFireMixin = factory ( ) ;
24
+ }
25
+ } ( this , function ( ) {
26
+ "use strict" ;
27
+
28
+ var ReactFireMixin = {
29
+ /********************/
30
+ /* MIXIN LIFETIME */
31
+ /********************/
32
+ /* Initializes the Firebase binding refs array */
33
+ componentWillMount : function ( ) {
34
+ this . firebaseRefs = { } ;
35
+ this . firebaseListeners = { } ;
36
+ } ,
37
+
38
+ /* Removes any remaining Firebase bindings */
39
+ componentWillUnmount : function ( ) {
40
+ for ( var key in this . firebaseRefs ) {
41
+ if ( this . firebaseRefs . hasOwnProperty ( key ) ) {
42
+ this . unbind ( key ) ;
43
+ }
44
+ }
45
+ } ,
46
+
47
+
48
+ /*************/
49
+ /* BINDING */
50
+ /*************/
51
+ /* Creates a binding between Firebase and the inputted bind variable as an array */
52
+ bindAsArray : function ( firebaseRef , bindVar , cancelCallback ) {
53
+ this . _bind ( firebaseRef , bindVar , cancelCallback , true ) ;
54
+ } ,
55
+
56
+ /* Creates a binding between Firebase and the inputted bind variable as an object */
57
+ bindAsObject : function ( firebaseRef , bindVar , cancelCallback ) {
58
+ this . _bind ( firebaseRef , bindVar , cancelCallback , false ) ;
59
+ } ,
60
+
61
+ /* Creates a binding between Firebase and the inputted bind variable as either an array or object */
62
+ _bind : function ( firebaseRef , bindVar , cancelCallback , bindAsArray ) {
63
+ this . _validateBindVar ( bindVar ) ;
64
+
65
+ var errorMessage , errorCode ;
66
+ if ( Object . prototype . toString . call ( firebaseRef ) !== "[object Object]" ) {
67
+ errorMessage = "firebaseRef must be an instance of Firebase" ;
68
+ errorCode = "INVALID_FIREBASE_REF" ;
69
+ }
70
+ else if ( typeof bindAsArray !== "boolean" ) {
71
+ errorMessage = "bindAsArray must be a boolean. Got: " + bindAsArray ;
72
+ errorCode = "INVALID_BIND_AS_ARRAY" ;
73
+ }
74
+
75
+ if ( typeof errorMessage !== "undefined" ) {
76
+ var error = new Error ( "ReactFire: " + errorMessage ) ;
77
+ error . code = errorCode ;
78
+ throw error ;
79
+ }
80
+
81
+ this . firebaseRefs [ bindVar ] = firebaseRef . ref ( ) ;
82
+ this . firebaseListeners [ bindVar ] = firebaseRef . on ( "value" , function ( dataSnapshot ) {
83
+ var newState = { } ;
84
+ if ( bindAsArray ) {
85
+ newState [ bindVar ] = this . _toArray ( dataSnapshot . val ( ) ) ;
86
+ }
87
+ else {
88
+ newState [ bindVar ] = dataSnapshot . val ( ) ;
89
+ }
90
+ this . setState ( newState ) ;
91
+ } . bind ( this ) , cancelCallback ) ;
92
+ } ,
93
+
94
+ /* Removes the binding between Firebase and the inputted bind variable */
95
+ unbind : function ( bindVar ) {
96
+ this . _validateBindVar ( bindVar ) ;
97
+
98
+ if ( typeof this . firebaseRefs [ bindVar ] === "undefined" ) {
99
+ var error = new Error ( "ReactFire: unexpected value for bindVar. \"" + bindVar + "\" was either never bound or has already been unbound" ) ;
100
+ error . code = "UNBOUND_BIND_VARIABLE" ;
101
+ throw error ;
102
+ }
103
+
104
+ this . firebaseRefs [ bindVar ] . off ( "value" , this . firebaseListeners [ bindVar ] ) ;
105
+ delete this . firebaseRefs [ bindVar ] ;
106
+ delete this . firebaseListeners [ bindVar ] ;
107
+ } ,
108
+
109
+
110
+ /*************/
111
+ /* HELPERS */
112
+ /*************/
113
+ /* Validates the name of the variable which is being bound */
114
+ _validateBindVar : function ( bindVar ) {
115
+ var errorMessage ;
116
+
117
+ if ( typeof bindVar !== "string" ) {
118
+ errorMessage = "bindVar must be a string. Got: " + bindVar ;
119
+ }
120
+ else if ( bindVar . length === 0 ) {
121
+ errorMessage = "bindVar must be a non-empty string. Got: \"\"" ;
122
+ }
123
+ else if ( bindVar . length > 768 ) {
124
+ // Firebase can only stored child paths up to 768 characters
125
+ errorMessage = "bindVar is too long to be stored in Firebase. Got: " + bindVar ;
126
+ }
127
+ else if ( / [ \[ \] . # $ \/ \u0000 - \u001F \u007F ] / . test ( bindVar ) ) {
128
+ // Firebase does not allow node keys to contain the following characters
129
+ errorMessage = "bindVar cannot contain any of the following characters: . # $ ] [ /. Got: " + bindVar ;
130
+ }
131
+
132
+ if ( typeof errorMessage !== "undefined" ) {
133
+ var error = new Error ( "ReactFire: " + errorMessage ) ;
134
+ error . code = "INVALID_BIND_VARIABLE" ;
135
+ throw error ;
136
+ }
137
+ } ,
138
+
139
+
140
+ /* Returns true if the inputted object is a JavaScript array */
141
+ _isArray : function ( obj ) {
142
+ return ( Object . prototype . toString . call ( obj ) === "[object Array]" ) ;
143
+ } ,
144
+
145
+ /* Converts a Firebase object to a JavaScript array */
146
+ _toArray : function ( obj ) {
147
+ var out = [ ] ;
148
+ if ( obj ) {
149
+ if ( this . _isArray ( obj ) ) {
150
+ out = obj ;
151
+ }
152
+ else if ( typeof ( obj ) === "object" ) {
153
+ for ( var key in obj ) {
154
+ if ( obj . hasOwnProperty ( key ) ) {
155
+ out . push ( obj [ key ] ) ;
156
+ }
157
+ }
158
+ }
159
+ }
160
+ return out ;
161
+ }
162
+ } ;
163
+
164
+ return ReactFireMixin ;
165
+ } ) ) ;
0 commit comments