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