author | ivanl |
Mon, 10 Aug 2009 11:26:10 +0100 | |
changeset 17 | 5dc2963cd75f |
parent 10 | 07ac2f6a36a9 |
child 18 | b73e6caf0031 |
permissions | -rw-r--r-- |
0 | 1 |
// //////////////////////////////////////////////////////////////////////////// |
5 | 2 |
// Symbian Foundation Example Code |
3 |
// |
|
4 |
// This software is in the public domain. No copyright is claimed, and you |
|
5 |
// may use it for any purpose without license from the Symbian Foundation. |
|
6 |
// No warranty for any purpose is expressed or implied by the authors or |
|
7 |
// the Symbian Foundation. |
|
0 | 8 |
// //////////////////////////////////////////////////////////////////////////// |
9 |
||
10 |
// Forums |
|
11 |
||
12 |
// Forums have the following structure: |
|
13 |
// |
|
14 |
// Forum group list |
|
15 |
// Forum list |
|
16 |
// Thread list |
|
17 |
// Message list |
|
18 |
||
19 |
// All four views are based on customised RssReader. We customise two aspects: |
|
20 |
// - Parsing XML - data is not RSS |
|
21 |
// - Handling item selection (e.g. creating a new view for a newly selected forum) |
|
22 |
||
23 |
// ///////////////////////////////////////////////////////////////////////////// |
|
24 |
// Forum groups |
|
25 |
||
26 |
// response parser for forum groups |
|
27 |
function forumGroupsResponseParser(broker, responseStatus, xmlDoc) { |
|
28 |
if (responseStatus == 200 && xmlDoc != null) { |
|
29 |
// node ref for iterating |
|
30 |
var node; |
|
31 |
||
32 |
// for compatibility with rss |
|
33 |
var lastModified = new Date(); |
|
34 |
||
35 |
// init result items array |
|
36 |
var items = []; |
|
37 |
||
38 |
var elements = xmlDoc.getElementsByTagName("group"); |
|
39 |
for (var i = 0; i < elements.length; i++) { |
|
40 |
var groupid = elements[i].getAttribute("id"); |
|
41 |
var grouptitle = elements[i].getAttribute("title"); |
|
42 |
items.push({ id: groupid, title: grouptitle}); |
|
43 |
} |
|
44 |
||
45 |
// update was completed successfully |
|
46 |
return { status: "ok", lastModified: lastModified, items: items }; |
|
47 |
} else { |
|
48 |
// update failed |
|
49 |
return { status: "error" }; |
|
50 |
} |
|
51 |
} |
|
52 |
||
53 |
// FeedPresenter implementation for forum groups |
|
54 |
function ForumGroupsFeedPresenter(rssreader){ |
|
55 |
if (rssreader) { |
|
56 |
this.init(rssreader); |
|
57 |
} |
|
58 |
} |
|
59 |
||
60 |
// ForumGroupsFeedPresenter is a subclass of ButtonFeedPresenter |
|
61 |
ForumGroupsFeedPresenter.prototype = new ButtonFeedPresenter(null); |
|
62 |
||
63 |
// ForumGroupsFeedPresenter "Constructor" |
|
64 |
ForumGroupsFeedPresenter.prototype.init = function(rssreader) { |
|
65 |
ButtonFeedPresenter.prototype.init.call(this, rssreader); |
|
66 |
} |
|
67 |
||
68 |
// Handle the click on a specific item |
|
69 |
ForumGroupsFeedPresenter.prototype.feedClicked = function(event){ |
|
70 |
var buttonid = event.source.id; |
|
71 |
||
72 |
if (buttonid == "latestPosts") { |
|
73 |
// show latest posts |
|
74 |
var url = forumFeedURL; |
|
75 |
var latestPostsView = new RssReader("Latest posts", url, new LatestPostsFeedPresenter(null), this.rssreader, null); |
|
76 |
latestPostsView.show(); |
|
77 |
} |
|
78 |
else { |
|
79 |
// show forum group |
|
80 |
var groupid = this.items[buttonid].id; |
|
81 |
var grouptitle = this.items[buttonid].title; |
|
82 |
||
83 |
var url = forumsListUrl + groupid; |
|
84 |
var forumListView = new RssReader(grouptitle, url, new ForumsListFeedPresenter(null), this.rssreader, forumListResponseParser); |
|
85 |
forumListView.show(); |
|
86 |
} |
|
87 |
} |
|
88 |
||
89 |
// Create and add controls to be shown before items list. |
|
90 |
ForumGroupsFeedPresenter.prototype.addPreambleItems = function(){ |
|
91 |
var feedItemControl = new NavigationButton("latestPosts", "blueright.gif", "Latest posts"); |
|
92 |
var self = this; |
|
93 |
feedItemControl.addEventListener("ActionPerformed", function(event) { self.feedClicked(event); }); |
|
94 |
this.rssreader.addControl(feedItemControl); |
|
95 |
} |
|
96 |
||
97 |
||
98 |
// /////////////////////////////////////////////////////////////////////////// |
|
99 |
// List of forums in a group |
|
100 |
||
101 |
// response parser for forum list - in a group |
|
102 |
function forumListResponseParser(broker, responseStatus, xmlDoc) { |
|
103 |
if (responseStatus == 200 && xmlDoc != null) { |
|
104 |
// node ref for iterating |
|
105 |
var node; |
|
106 |
||
107 |
// for compatibility with rss |
|
108 |
var lastModified = new Date(); |
|
109 |
||
110 |
// init result items array |
|
111 |
var items = []; |
|
112 |
||
113 |
// extract items for all group elements |
|
114 |
var elements = xmlDoc.getElementsByTagName("group"); |
|
115 |
for (var i = 0; i < elements.length; i++) { |
|
116 |
var forumid = elements[i].getAttribute("id"); |
|
117 |
var forumtitle = elements[i].getAttribute("title"); |
|
118 |
items.push({ id: forumid, title: forumtitle}); |
|
119 |
} |
|
120 |
||
121 |
// update was completed successfully |
|
122 |
return { status: "ok", lastModified: lastModified, items: items }; |
|
123 |
} else { |
|
124 |
// update failed |
|
125 |
return { status: "error" }; |
|
126 |
} |
|
127 |
} |
|
128 |
||
129 |
// FeedPresenter implementation for forum groups |
|
130 |
function ForumsListFeedPresenter(rssreader){ |
|
131 |
if (rssreader) { |
|
132 |
this.init(rssreader); |
|
133 |
} |
|
134 |
} |
|
135 |
||
136 |
// ForumsListFeedPresenter is a subclass of ButtonFeedPresenter |
|
137 |
ForumsListFeedPresenter.prototype = new ButtonFeedPresenter(null); |
|
138 |
||
139 |
// ForumsListFeedPresenter constructor |
|
140 |
ForumsListFeedPresenter.prototype.init = function(rssreader) { |
|
141 |
ButtonFeedPresenter.prototype.init.call(this, rssreader); |
|
142 |
} |
|
143 |
||
144 |
||
145 |
// forum has been selected, create a reader showing threads in the forum |
|
146 |
ForumsListFeedPresenter.prototype.feedClicked = function(event){ |
|
147 |
var buttonid = event.source.id; |
|
148 |
if (buttonid == "latestPosts") { |
|
149 |
// show latest posts |
|
150 |
var url = forumFeedURL + "&forumids="; |
|
151 |
// append requested forum ids |
|
152 |
for( var i = 0; i < this.items.length; i++) { |
|
153 |
url += this.items[i].id + ","; |
|
154 |
} |
|
155 |
||
156 |
var latestPostsView = new RssReader( |
|
157 |
"Latest posts in " + this.rssreader.feedName, |
|
158 |
url, |
|
159 |
new LatestPostsFeedPresenter(null), |
|
160 |
this.rssreader, |
|
161 |
null); |
|
162 |
latestPostsView.show(); |
|
163 |
} |
|
164 |
else { |
|
165 |
var forumid = this.items[buttonid].id; |
|
166 |
var forumtitle = this.items[buttonid].title; |
|
167 |
||
168 |
var url = forumFeedURL + forumsForumSpecQuery + forumid; |
|
169 |
var forumListView = new RssReader(forumtitle, url, new ThreadListFeedPresenter(null), this.rssreader, null); |
|
170 |
forumListView.show(); |
|
171 |
} |
|
172 |
} |
|
173 |
||
174 |
// Create and add controls to be shown before items list. |
|
175 |
ForumsListFeedPresenter.prototype.addPreambleItems = function(){ |
|
176 |
var feedItemControl = new NavigationButton("latestPosts", "blueright.gif", "Latest posts in " + this.rssreader.feedName); |
|
177 |
var self = this; |
|
178 |
feedItemControl.addEventListener("ActionPerformed", function(event) { self.feedClicked(event); }); |
|
179 |
this.rssreader.addControl(feedItemControl); |
|
180 |
} |
|
181 |
||
182 |
||
183 |
||
184 |
// /////////////////////////////////////////////////////////////////////////// |
|
185 |
// List of threads in a forum |
|
186 |
||
187 |
// response parser for thread list is the usual rss parser |
|
188 |
||
189 |
// FeedPresenter implementation for forum groups |
|
190 |
function ThreadListFeedPresenter(rssreader){ |
|
191 |
if (rssreader) { |
|
192 |
this.init(rssreader); |
|
193 |
} |
|
194 |
} |
|
195 |
||
196 |
// ThreadListFeedPresenter is a subclass of ButtonFeedPresenter |
|
197 |
ThreadListFeedPresenter.prototype = new ButtonFeedPresenter(null); |
|
198 |
||
199 |
// ThreadListFeedPresenter constructor |
|
200 |
ThreadListFeedPresenter.prototype.init = function(rssreader) { |
|
201 |
ButtonFeedPresenter.prototype.init.call(this, rssreader); |
|
202 |
} |
|
203 |
||
204 |
||
205 |
// Handle the click on a specific item |
|
206 |
ThreadListFeedPresenter.prototype.feedClicked = function(event){ |
|
207 |
var buttonid = event.source.id; |
|
208 |
||
209 |
if (buttonid == "newThread") { |
|
210 |
// extract forum id from rssreader.feedURL |
|
211 |
var ind = this.rssreader.feedURL.indexOf(forumsForumSpecQuery); |
|
212 |
var forumid = this.rssreader.feedURL.substring( ind + forumsForumSpecQuery.length); |
|
213 |
var postForm = new ForumPostForm(this.rssreader, forumid); |
|
214 |
postForm.show(); |
|
215 |
} |
|
216 |
else { |
|
217 |
var weburl = this.items[buttonid].url; |
|
218 |
||
219 |
// extract thread id from url. looking for t=xxx |
|
220 |
var ind1 = weburl.indexOf("?t="); |
|
221 |
if (ind1 == -1) { |
|
222 |
ind1 = weburl.indexOf("&t="); |
|
223 |
} |
|
224 |
if (ind1 != -1) { |
|
225 |
var threadid = ""; |
|
226 |
var ind2 = weburl.indexOf("&", ind1); |
|
227 |
if (ind2 == -1) { |
|
228 |
threadid = weburl.substring(ind1 + 3); // ?t= |
|
229 |
} |
|
230 |
else { |
|
231 |
threadid = weburl.substring(ind1 + 3, ind2); // ?t= |
|
232 |
} |
|
233 |
var url = forumThreadUrl + threadid; |
|
234 |
var title = this.items[buttonid].title; |
|
235 |
if (title.length > 30) { |
|
236 |
title = title.substring(0, 30) + "..."; |
|
237 |
} |
|
238 |
var threadView = new RssReader(title, url, new ThreadFeedPresenter(null), this.rssreader, threadResponseParser); |
|
239 |
threadView.show(); |
|
240 |
} |
|
241 |
} |
|
242 |
} |
|
243 |
||
244 |
// Create and add controls to be shown before items list. |
|
245 |
ThreadListFeedPresenter.prototype.addPreambleItems = function(){ |
|
246 |
var feedItemControl = new NavigationButton("newThread", "blueright.gif", "Post a new thread"); |
|
247 |
var self = this; |
|
248 |
feedItemControl.addEventListener("ActionPerformed", function(event) { self.feedClicked(event); }); |
|
249 |
this.rssreader.addControl(feedItemControl); |
|
250 |
} |
|
251 |
||
252 |
// /////////////////////////////////////////////////////////////////////////// |
|
253 |
// List of messages in a thread |
|
254 |
||
255 |
// response parser for thread list |
|
256 |
function threadResponseParser(broker, responseStatus, xmlDoc) { |
|
257 |
if (responseStatus == 200 && xmlDoc != null) { |
|
258 |
// node ref for iterating |
|
259 |
var node; |
|
260 |
||
261 |
// for compatibility with rss |
|
262 |
var lastModified = new Date(); |
|
263 |
||
264 |
// init result items array |
|
265 |
var items = []; |
|
266 |
||
267 |
// iterate over message elements |
|
268 |
var elements = xmlDoc.getElementsByTagName("message"); |
|
269 |
for (var i = 0; i < elements.length; i++) { |
|
270 |
var postid; |
|
271 |
var threadid; |
|
272 |
var username; |
|
273 |
var title; |
|
274 |
var dateline; |
|
275 |
var pagetext; |
|
276 |
var isdeleted; |
|
277 |
||
278 |
// extract info about the post |
|
279 |
node = elements[i].firstChild; |
|
280 |
while (node != null) { |
|
281 |
if ( node.nodeName == "postid" ) postid=getTextOfNode(node); |
|
282 |
else if ( node.nodeName == "threadid" ) threadid=getTextOfNode(node); |
|
283 |
else if ( node.nodeName == "username" ) username=getTextOfNode(node); |
|
284 |
else if ( node.nodeName == "title" ) title=getTextOfNode(node); |
|
285 |
else if ( node.nodeName == "dateline" ) dateline=getTextOfNode(node); |
|
286 |
else if ( node.nodeName == "pagetext" ) pagetext=getTextOfNode(node); |
|
287 |
else if ( node.nodeName == "isdeleted" ) isdeleted=getTextOfNode(node); |
|
288 |
node = node.nextSibling; |
|
289 |
} |
|
290 |
if ( isdeleted == 1 ) continue; |
|
291 |
||
292 |
items.push({ |
|
293 |
postid: postid, |
|
294 |
threadid: threadid, |
|
295 |
username: username, |
|
296 |
title: title, |
|
297 |
dateline: dateline, |
|
298 |
pagetext: pagetext |
|
299 |
}); |
|
300 |
} |
|
301 |
||
302 |
// update was completed successfully |
|
303 |
return { status: "ok", lastModified: lastModified, items: items }; |
|
304 |
} else { |
|
305 |
// update failed |
|
306 |
return { status: "error" }; |
|
307 |
} |
|
308 |
} |
|
309 |
||
310 |
// FeedPresenter implementation for forum groups |
|
311 |
function ThreadFeedPresenter(rssreader){ |
|
312 |
if (rssreader) { |
|
313 |
this.init(rssreader); |
|
314 |
} |
|
315 |
} |
|
316 |
||
317 |
// ThreadFeedPresenter is a subclass of HtmlFeedPresenter |
|
318 |
ThreadFeedPresenter.prototype = new HtmlFeedPresenter(null); |
|
319 |
||
320 |
// ThreadFeedPresenter constructor |
|
321 |
ThreadFeedPresenter.prototype.init = function(rssreader) { |
|
322 |
HtmlFeedPresenter.prototype.init.call(this, rssreader); |
|
323 |
} |
|
324 |
||
325 |
||
326 |
// Handle the click on a specific item |
|
327 |
ThreadFeedPresenter.prototype.feedClicked = function(event){ |
|
328 |
// do nothing |
|
329 |
} |
|
330 |
||
331 |
// Create a control that represents this item and add it to |
|
332 |
// parent rss reader |
|
333 |
ThreadFeedPresenter.prototype.show = function(item) { |
|
334 |
// get a feed item control from the pool or create one and |
|
335 |
// place it in the pool if there aren't enough feed item controls |
|
336 |
var feedItemControl = new ContentPanel(null, null, null, true); |
|
337 |
||
338 |
// initialize feed item control |
|
339 |
var title = item.title; |
|
4 | 340 |
if ( !title || title.length == 0 ) { |
0 | 341 |
title = "Re:"; |
342 |
item.title = title; |
|
343 |
} |
|
344 |
feedItemControl.setCaption(bbcode2html(title)); |
|
345 |
feedItemControl.setContent(this.getContentHTMLForFeedItem(item)); |
|
346 |
feedItemControl.setExpanded(true); |
|
347 |
||
348 |
// add the feed item control to the main view |
|
349 |
this.rssreader.feedItemControls.push(feedItemControl); |
|
350 |
this.rssreader.addControl(feedItemControl); |
|
351 |
} |
|
352 |
||
353 |
// Generate HTML content from the feed item |
|
354 |
ThreadFeedPresenter.prototype.getContentHTMLForFeedItem = function (item){ |
|
355 |
var buf = ""; |
|
356 |
||
357 |
// item date |
|
358 |
if (item.dateline != null) { |
|
359 |
var date = new Date(); |
|
360 |
date.setTime(item.dateline*1000); |
|
361 |
buf += "<div class=\"FeedItemDate\">" ; |
|
362 |
if ( item.username != null ) { |
|
363 |
buf += item.username + ", "; |
|
364 |
} |
|
365 |
buf += date + "</div>"; |
|
366 |
} |
|
367 |
||
368 |
// item description |
|
369 |
if (item.pagetext != null) { |
|
370 |
var text = bbcode2html(item.pagetext); |
|
371 |
text = text.replace(/\r\n/g, "<br>"); |
|
372 |
buf += "<div class=\"FeedItemDescription\">" + text + "</div>"; |
|
373 |
buf += "<div class=\"FeedItemLink\">"; |
|
374 |
buf += "<a href=\"JavaScript:void(0)\" onclick=\"showReplyForm(" |
|
375 |
+ item.threadid+ "," + item.postid + ", '" + item.title |
|
376 |
+ "'); return false;\">"; |
|
377 |
buf += "<strong>Reply to this post<strong></a>" |
|
378 |
buf += "</div>"; |
|
379 |
} |
|
380 |
||
381 |
return buf; |
|
382 |
} |
|
383 |
||
384 |
// Show the reply-to-post form |
|
385 |
function showReplyForm(threadid, postid, title) { |
|
386 |
var replyForm = new ForumReplyForm(uiManager.currentView, threadid, postid, title); |
|
387 |
replyForm.show(); |
|
388 |
} |
|
389 |
||
390 |
||
391 |
// /////////////////////////////////////////////////////////////////////////// |
|
392 |
// Latest posts - same as ThreadListFeedPresenter, only has no preamble items |
|
393 |
// because it doesn't show one thread (so we can't post to latest items)... |
|
394 |
||
395 |
// FeedPresenter implementation for latest posts |
|
396 |
function LatestPostsFeedPresenter(rssreader){ |
|
397 |
if (rssreader) { |
|
398 |
this.init(rssreader); |
|
399 |
} |
|
400 |
} |
|
401 |
||
402 |
LatestPostsFeedPresenter.prototype = new ThreadListFeedPresenter(null); |
|
403 |
||
404 |
// ForumGroupsFeedPresenter "Constructor" |
|
405 |
LatestPostsFeedPresenter.prototype.init = function(rssreader) { |
|
406 |
ButtonFeedPresenter.prototype.init.call(this, rssreader); |
|
407 |
} |
|
408 |
||
409 |
// LatestPostsFeedPresenter has no preamble items |
|
410 |
LatestPostsFeedPresenter.prototype.addPreambleItems = function(){ |
|
411 |
} |
|
412 |
||
413 |
||
414 |
// /////////////////////////////////////////////////////////////////////////// |
|
415 |
// Utilities |
|
416 |
||
417 |
||
418 |
// Forum posts can be be quite messy and include bbcodes, smilies etc. |
|
419 |
// This function does the minimum by stripping bbcodes and such |
|
420 |
function sanitize(text) { |
|
421 |
var prevind = 0; |
|
422 |
var ind = text.indexOf("["); |
|
423 |
if ( ind == -1 ) return text; |
|
424 |
var buf = ""; |
|
425 |
while ( ind != -1 ) { |
|
426 |
buf += text.substring(prevind, ind); |
|
427 |
var ind2 = text.indexOf("]", ind); |
|
428 |
if ( ind2 != -1 ) { |
|
429 |
prevind = ind2+1; |
|
430 |
} else { |
|
431 |
break; |
|
432 |
} |
|
433 |
ind = text.indexOf("[", prevind); |
|
434 |
} |
|
435 |
if ( prevind > 0 && prevind < text.length) { |
|
436 |
buf += text.substring(prevind); |
|
437 |
} |
|
438 |
return buf; |
|
439 |
} |
|
440 |
||
441 |
||
442 |
||
4 | 443 |
// feeds contain bbcodes - this function should turn the bbcode markup |
444 |
// to HTML |
|
445 |
function bbcode2html(s) { |
|
446 |
var prevind = 0; |
|
447 |
var buf = ""; |
|
448 |
var ind = s.indexOf("["); |
|
449 |
if ( ind == -1 ) return s; |
|
450 |
while ( ind != -1 ) { |
|
451 |
buf += s.substring(prevind, ind); |
|
452 |
var ind2 = s.indexOf("]", ind); // end of tag |
|
453 |
var fulltag = s.substring(ind+1,ind2); |
|
454 |
var tag = fulltag; |
|
455 |
var ind3 = s.indexOf("=", ind); // end of tag name, eg. [URL=http...] |
|
456 |
if ( ind3 != -1 && ind3 < ind2) { |
|
457 |
tag = s.substring(ind+1,ind3); |
|
458 |
} |
|
10
07ac2f6a36a9
1.0rc10 Fixes annoyances and buglets in reading forums and blog.
ivanl
parents:
6
diff
changeset
|
459 |
var ind4 = s.indexOf("[/"+tag+"]", ind2); |
4 | 460 |
var tagContent = s.substring(ind2+1, ind4); |
461 |
buf += convertTag(tag, fulltag, tagContent); |
|
462 |
if ( ind4 != -1 ) { |
|
463 |
prevind = s.indexOf(']',ind4) + 1; |
|
464 |
} else { |
|
465 |
break; |
|
466 |
} |
|
467 |
ind = s.indexOf("[", prevind); |
|
468 |
} |
|
469 |
buf += s.substring(prevind); |
|
470 |
return buf; |
|
471 |
} |
|
472 |
||
473 |
function convertTag(tag, fulltag, tagContent) { |
|
474 |
tag = tag.toLowerCase(); |
|
17 | 475 |
var param = null; |
476 |
var eqsign = fulltag.indexOf("="); // onclick=\"openURL('" + item.url + "'); |
|
477 |
if (eqsign > -1) { |
|
478 |
param = fulltag.substring(eqsign+1); |
|
479 |
} |
|
4 | 480 |
switch(tag) { |
17 | 481 |
case '*': return bbcode2html(tagContent); |
4 | 482 |
case 'b':case 'i':case 'u':case 's':case 'sup':case 'sub':case 'h1':case 'h2':case 'h3':case 'h4':case 'h5':case 'h6':case 'table':case 'tr':case 'th':case 'td': |
483 |
{ |
|
17 | 484 |
return '<' + tag + '>' + bbcode2html(tagContent) + "</" + tag + ">"; |
4 | 485 |
} |
17 | 486 |
case 'font': return '<font face="'+param+'">' + bbcode2html(tagContent) + '</font>'; |
487 |
case 'size': return '<font size="'+param+'">' + bbcode2html(tagContent) + '</font>'; |
|
488 |
case 'color': return '<font color="'+param+'">' + bbcode2html(tagContent) + '</font>'; |
|
489 |
case 'left': return '<div align="left">' + bbcode2html(tagContent) + '</div>'; |
|
490 |
case 'right': return '<div align="right">' + bbcode2html(tagContent) + '</div>'; |
|
491 |
case 'center': return '<div align="center">' + bbcode2html(tagContent) + '</div>'; |
|
492 |
case 'list': return tagContent; // todo |
|
493 |
case 'php': |
|
494 |
case 'code': return '<div class=codebox><code>' + tagContent + '</code></div>'; |
|
495 |
case 'html':{ |
|
496 |
var escaped = tagContent.replace(/</g, "<").replace(/>/g, ">"); |
|
497 |
return '<div class=codebox><code>' + escaped + '</code></div>'; |
|
498 |
} |
|
499 |
case 'quote': return '<div class=codebox><b>Quote:</b><br><i>' + tagContent + '</i></div>'; |
|
4 | 500 |
case 'url': { |
501 |
if ( eqsign > -1 ) { |
|
6 | 502 |
return "<div class=\"FeedItemLink\"><a href=\"JavaScript:void(0)\" onclick=\"openURL( '" |
17 | 503 |
+ param |
6 | 504 |
+ "')\" ><i>" |
4 | 505 |
+ tagContent |
506 |
+ '</i></a></div>'; |
|
507 |
} else { |
|
6 | 508 |
return "<div class=\"FeedItemLink\"><a href=\"JavaScript:void(0)\" onclick=\"openURL( '" |
4 | 509 |
+ tagContent |
6 | 510 |
+ "')\" ><i>" |
4 | 511 |
+ tagContent |
512 |
+ '</i></a></div>'; |
|
513 |
} |
|
514 |
} |
|
515 |
} |
|
516 |
} |