1
1
/**
2
2
* jquery-json-feed
3
3
* ================
4
- * JSONP -> html with recursive parsing
4
+ * JSONP -> html with recursive parsing, source polling and pagination
5
+ * Copyright (c) 2011 Dan Drinkard
6
+ * MIT License.
5
7
*
6
8
* Usage:
7
9
* ------
53
55
* `data`
54
56
*
55
57
*/
56
- ( function ( $ , window , undefined ) {
58
+ ( function ( $ , window ) {
57
59
$ . fn . JSONFeed = function ( opts ) {
58
-
59
60
var defaults = {
60
- url : 'http://projects.washingtonpost .com/moderation/twitter-feed/washington-post-tweets/recent .json' ,
61
+ url : 'http://api.twitter .com/1/statuses/public_timeline .json' ,
61
62
jsonp : 'callback' ,
62
63
jsonpCallback : '?' ,
63
64
iterator : function ( data ) { return data ; } ,
64
65
num : 5 ,
66
+ avatar_width : 48 ,
67
+ avatar_height : 48 ,
65
68
poll : 0 ,
66
69
pollUrlGenerator : function ( prev_url , prev_response , options ) {
67
70
return prev_url ;
70
73
paginationUrlGenerator : function ( prev_url , prev_response , options ) {
71
74
return prev_url ;
72
75
} ,
73
- spinner : '<span>Loading...</span>' ,
74
- newTweetsMessage : '<a href="#">Click to show new tweets.</a>' ,
76
+ spinner : '<span class="jf-loading" >Loading...</span>' ,
77
+ newContentMessage : '<a href="#">Click to show new tweets.</a>' ,
75
78
paginationButton : '<a href="#">Load more...</a>' ,
76
79
template : '<p style="color:#a00">You haven't set a template for this feed!</p>' ,
77
80
jsonVarP : / \{ \{ ( [ ^ \} ] + ) \} \} / gm,
78
81
optionP : / \{ % ( [ ^ % ] + ) % \} / gm,
79
- renderCallback : function ( str ) { return str } ,
82
+ renderCallback : function ( str ) { return str ; } ,
80
83
appendCallback : function ( ) { }
81
- } ,
82
- options = $ . extend ( { } , defaults , opts ) ,
84
+ } , is_unique , request , render , pageFactory , poll , paginate ;
85
+ // confirms uniqueness of generated element for pagination & polling
83
86
is_unique = function ( el ) {
84
87
if ( $ ( el ) . attr ( 'id' ) ) {
85
88
return ! $ ( '#' + $ ( el ) . attr ( 'id' ) ) . length ;
86
89
} else {
87
90
// always unique if no ids
88
- return true
91
+ return true ;
89
92
}
90
- } ,
91
- request = function ( url , ctx ) {
93
+ } ;
94
+ // gets a resource and fires a success callback
95
+ request = function ( url , ctx , options ) {
92
96
var self = $ ( ctx ) ,
93
97
action = ( self . attr ( 'className' ) . match ( / p a g e - / ) !== null ? 'poll' : 'page' ) ,
94
98
num = self . parent ( ) . attr ( 'data-num' ) || options . num ,
100
104
var objs = options . iterator ( data ) ;
101
105
$ . each ( objs , function ( idx , item ) {
102
106
// exempt from limit if this is a polling request
103
- if ( idx < num || action == 'poll' ) {
104
- var el = $ ( render ( item ) ) ;
107
+ if ( idx < num || action === 'poll' ) {
108
+ var el = $ ( render ( item , options ) ) ;
105
109
if ( is_unique ( el ) ) {
106
110
self . append ( el ) ;
107
111
}
108
112
} else {
109
113
return false ;
110
114
}
111
115
} ) ;
116
+ // handle empty
117
+ if ( ! options . paginate && objs . length === 0 && typeof options . empty !== 'undefined' ) {
118
+ self . append ( options . empty ) ;
119
+ }
112
120
// handle buttons & data cache
113
- if ( action == 'poll' ) {
121
+ if ( action === 'poll' ) {
114
122
if ( self . children ( ) . length && self . is ( ':hidden' ) ) {
115
123
var showBtn = self . siblings ( '.jf-show-new' ) ;
116
124
if ( showBtn . length ) {
117
125
self . before ( showBtn ) ;
118
126
} else {
119
- self . before ( options . newTweetsMessage ) . prev ( ) . addClass ( 'jf-show-new' ) ;
127
+ self . before ( options . newContentMessage ) . prev ( ) . addClass ( 'jf-show-new' )
128
+ . hide ( ) . slideDown ( ) ;
120
129
}
121
130
}
122
131
var _poll = self . parent ( ) . data ( '_poll' ) ;
123
132
_poll [ 'data' ] = data ;
124
133
self . parent ( ) . data ( '_poll' , _poll ) ;
125
- } else {
126
- if ( objs . length == 0 ) { // last page
134
+ } else { // this is pagination or first call
135
+ if ( objs . length === 0 ) { // last page
127
136
self . siblings ( '.jf-show-more' ) . remove ( ) ;
128
137
} else {
129
138
self . siblings ( '.jf-show-more' ) . removeClass ( 'disabled' ) ;
134
143
}
135
144
}
136
145
}
137
-
138
146
self . each ( options . appendCallback ) ;
139
147
}
140
- }
148
+ } ;
141
149
142
150
if ( options . jsonpCallback ) {
143
- if ( options . jsonpCallback != '?' ) {
151
+ if ( options . jsonpCallback !== '?' ) {
144
152
ajaxOpts . jsonpCallback = options . jsonpCallback ;
145
153
ajaxOpts . jsonp = options . jsonp ;
146
154
} else {
154
162
} else {
155
163
ajaxOpts . success ( [ ] , 'skipped' ) ;
156
164
}
157
- } ,
158
- render = function ( data ) {
165
+ } ;
166
+ // renders a feed item against the template
167
+ render = function ( data , options ) {
159
168
// data
160
169
var str = options . template . replace ( options . jsonVarP , function ( $0 , $1 ) {
161
170
var keys = $1 . split ( '.' ) ,
162
171
response = data ;
163
172
$ . each ( keys , function ( idx , key ) {
164
- if ( typeof response [ key ] != 'undefined' ) {
173
+ if ( typeof response [ key ] !== 'undefined' ) {
165
174
response = response [ key ] ;
166
175
} else { response = '' ; }
167
176
} ) ;
172
181
var keys = $1 . split ( '.' ) ,
173
182
response = options ;
174
183
$ . each ( keys , function ( idx , key ) {
175
- if ( typeof options [ key ] != 'undefined' ) {
184
+ if ( typeof options [ key ] !== 'undefined' ) {
176
185
response = response [ key ] ;
177
- } else { response = '' }
186
+ } else { response = '' ; }
178
187
} ) ;
179
188
return response ;
180
189
} ) ;
181
190
return options . renderCallback ( str ) ;
182
- } ,
191
+ } ;
192
+ // returns a page div
183
193
pageFactory = function ( num ) {
184
194
return '<div class="jf-page page' + num + '"></div>' ;
185
- }
186
- poll = function ( ctx ) {
195
+ } ;
196
+ // generates a request for new content
197
+ poll = function ( ctx , options ) {
198
+ console . log ( ctx , options ) ;
187
199
var self = $ ( ctx ) ,
188
200
locals = self . data ( '_poll' ) ;
189
201
locals . count += 1 ;
196
208
}
197
209
locals . lastUrl = options . pollUrlGenerator ( locals . lastUrl , locals [ 'data' ] , options ) ;
198
210
self . data ( '_poll' , locals ) ;
199
- request ( locals . lastUrl , page ) ;
200
- window . setTimeout ( function ( ) { poll ( self ) } , locals . interval * 1000 ) ;
201
- } ,
202
- paginate = function ( ctx ) {
211
+ request ( locals . lastUrl , page , options ) ;
212
+ window . setTimeout ( function ( ) { poll ( self , options ) ; } , locals . interval * 1000 ) ;
213
+ } ;
214
+ // generates a request for old content
215
+ paginate = function ( ctx , options ) {
203
216
var self = $ ( ctx ) ,
204
217
locals = self . data ( '_page' ) ;
205
218
locals . page += 1 ;
206
219
var page = self . find ( '.jf-page' ) . eq ( - 1 ) . after ( pageFactory ( locals . page ) ) . next ( ) ;
207
220
locals . lastUrl = options . paginationUrlGenerator ( locals . lastUrl , locals [ 'data' ] , options ) ;
208
221
self . data ( '_page' , locals ) ;
209
- request ( locals . lastUrl , page ) ;
222
+ request ( locals . lastUrl , page , options ) ;
210
223
} ;
211
-
224
+ // plugin constructor/closure
212
225
return $ ( this ) . each ( function ( ) {
213
226
var self = $ ( this ) ,
214
- locals = {
215
- url : self . attr ( 'data-url' ) || options . url ,
216
- poll : self . attr ( 'data-poll' ) || options . poll ,
217
- paginate : self . attr ( 'data-paginate' ) || options . paginate
218
- } ,
227
+ options = $ . extend ( { } , defaults , opts , {
228
+ url : self . attr ( 'data-url' ) || opts . url ,
229
+ poll : self . attr ( 'data-poll' ) || opts . poll ,
230
+ paginate : self . attr ( 'data-paginate' ) || opts . paginate
231
+ } ) ,
219
232
page = self . append ( pageFactory ( 0 ) ) . find ( '.page0' ) . eq ( 0 ) ;
220
- request ( locals . url , page ) ;
233
+ request ( options . url , page , options ) ;
221
234
$ ( this ) . delegate ( 'a.jf-show-new' , 'click' , function ( e ) {
222
235
e . preventDefault ( ) ;
223
236
e . stopPropagation ( ) ;
224
- $ ( this ) . nextAll ( '.jf-page' ) . filter ( ':hidden' ) . show ( )
237
+ $ ( this ) . nextAll ( '.jf-page' ) . filter ( ':hidden' ) . show ( ) ;
225
238
$ ( this ) . remove ( ) ;
226
239
} ) ;
227
- if ( locals . poll > 0 ) {
240
+ if ( options . poll > 0 ) {
228
241
self . data ( '_poll' , {
229
- lastUrl : locals . url ,
242
+ lastUrl : options . url ,
230
243
lastTime : new Date ( ) ,
231
- interval : locals . poll ,
244
+ interval : options . poll ,
232
245
count : 0 ,
233
246
page :0
234
247
} ) ;
235
- window . setTimeout ( function ( ) { poll ( self ) } , locals . poll * 1000 ) ;
248
+ window . setTimeout ( function ( ) { poll ( self , options ) ; } , options . poll * 1000 ) ;
236
249
}
237
- if ( locals . paginate == 'true' ) {
250
+ if ( options . paginate = == 'true' ) {
238
251
self . data ( '_page' , {
239
- lastUrl : locals . url ,
240
- page : 0 ,
252
+ lastUrl : options . url ,
253
+ page : 0
241
254
} ) ;
242
255
self . append ( $ ( options . paginationButton ) . addClass ( 'jf-show-more' ) . click ( function ( e ) {
243
256
e . preventDefault ( ) ;
244
- if ( ! $ ( this ) . hasClass ( '. disabled' ) ) {
257
+ if ( ! $ ( this ) . hasClass ( 'disabled' ) ) {
245
258
$ ( this ) . addClass ( 'disabled' ) ;
246
- paginate ( self ) ;
259
+ paginate ( self , options ) ;
247
260
}
248
261
} ) ) ;
249
262
}
250
263
} ) ;
251
- }
264
+ } ;
252
265
$ . fn . JSONFeed . docsURL = 'http://github.com/dandrinkard/jquery-json-feed/' ;
253
- $ . fn . JSONFeed . presets = { } ;
254
- $ . fn . JSONFeed . utils = { } ;
266
+ $ . fn . JSONFeed . presets = $ . fn . JSONFeed . presets || { } ;
267
+ $ . fn . JSONFeed . utils = $ . fn . JSONFeed . utils || { } ;
255
268
} ) ( jQuery , window ) ;
0 commit comments