Wikipedia/Wiki.js
changeset 20 918767a9c8d3
equal deleted inserted replaced
19:f3521a11d878 20:918767a9c8d3
       
     1 // ////////////////////////////////////////////////////////////////////////////
       
     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. 
       
     8 // ////////////////////////////////////////////////////////////////////////////
       
     9 
       
    10 
       
    11 var baseUrl = "http://en.wikipedia.org";
       
    12 
       
    13 var wikiSearchBaseUrl = "/w/api.php?format=xml&action=query&list=search&srsearch=";
       
    14 var wikiSearchOffsetQueryPart = "&sroffset=";
       
    15 var wikiSearchLimitQueryPart = "&srlimit=";
       
    16 var wikiSearchWhatQueryPart = "&srwhat=";
       
    17 
       
    18 var wikiViewPageUrlBase = baseUrl + "/w/index.php?title=";
       
    19 var wikiPrintableParam = "&printable=yes";
       
    20 
       
    21 var MENU_ITEM_READER_SEARCH = 1;
       
    22 var MENU_ITEM_HISTORY_CLEAR = 1;
       
    23 var MENU_ITEM_BOOKMARKS_CLEAR = 1;
       
    24 var MENU_ITEM_MAIN_BACK = 4;
       
    25 var MENU_ITEM_MAIN_NEXT = 5;
       
    26 var MENU_ITEM_MAIN_ADD_BOOKMARK = 6;
       
    27 var MENU_ITEM_MAIN_NAVIGATION = 7;
       
    28 var MENU_ITEM_MAIN_SEARCH = 8;
       
    29 var MENU_ITEM_MAIN_BOOKMARKS = 9;
       
    30 var MENU_ITEM_MAIN_HISTORY = 10; 
       
    31 var MENU_ITEM_MAIN_LANGUAGE =11;
       
    32 var MENU_ITEM_MAIN_UPDATES =12;
       
    33 var MENU_ITEM_MAIN_HELP = 13;
       
    34 
       
    35 var PREDICTIVE_RESULT_COUNT = 0;
       
    36 
       
    37 //var wapediaArticleBase = "http://wapedia.mobi/en/";
       
    38 
       
    39 
       
    40 //var wikiListCategoriesUrl = symbianOrgBaseUrl + "/wiki/api.php?format=xml&action=query&list=allcategories&aclimit=500&acprop=size";
       
    41 //var wikiWatchListUrl = "http://en.wikipedia.org/w/api.php?action=query&list=watchlist&wlallrev&wlprop=ids|title|timestamp|user|comment";
       
    42 //var wikiWatchListFeed = "/wiki/api.php?action=feedwatchlist&feedformat=rss";
       
    43 
       
    44 var wikiSearchOptions = [
       
    45     { value: "title", text: "Search in title only" },
       
    46     { value: "text", text: "Full text search" },
       
    47 ];
       
    48 
       
    49 function WikiHome () {
       
    50 	RssReader.prototype.init.call(this,"Wikipedia", null /*url*/, new WikiFeedPresenter(null), null, wikiResponseParser);	
       
    51 
       
    52 	this.wikiSearchButton = new FormButton(null, "Search");
       
    53 	this.wikiSearchString = new TextField('wikiSearchString', null, "");
       
    54 
       
    55 	var bookmarksButton = new NavigationButton(null, "next.png", "Bookmarks");
       
    56 	var historyButton = new NavigationButton(null, "next.png", "History");
       
    57 	var languageButton = new NavigationButton(null, "next.png", "Language");
       
    58 
       
    59 	var self = this;
       
    60 	bookmarksButton.addEventListener("ActionPerformed", function(){wikiBookmarksView.previousView = self; wikiBookmarksView.show();});
       
    61 	historyButton.addEventListener("ActionPerformed", function(){wikiHistoryView.previousView = self; wikiHistoryView.show();});
       
    62 	languageButton.addEventListener("ActionPerformed", function(){languageSelectView.previousView = self; languageSelectView.show();});
       
    63 	
       
    64 //	this.wikiSearchString.addEventListener("KeyPressed", function(){self.predictiveSearch(0);});
       
    65 	this.wikiSearchButton.addEventListener("ActionPerformed", function(){self.search(0);});
       
    66 
       
    67 	this.addControl(new Label(null, "Search Wiki", null));
       
    68 	this.addControl(this.wikiSearchString);
       
    69 	this.addControl(this.wikiSearchButton);
       
    70 	this.addControl(bookmarksButton);
       
    71 	this.addControl(historyButton);
       
    72 	this.addControl(languageButton);
       
    73 	k.known();
       
    74 }
       
    75 
       
    76 
       
    77 WikiHome.prototype = new RssReader();
       
    78 WikiHome.prototype.wikiMainPageButton = null;
       
    79 WikiHome.prototype.wikiSearchButton = null;
       
    80 WikiHome.prototype.wikiSearchString = null;
       
    81 WikiHome.prototype.wikiSearchSelection = null;
       
    82 WikiHome.prototype.predictiveTimer = null;
       
    83 
       
    84 var lastWikiSearchWasFrom = 0;
       
    85 var lastWikiSearchResultCountWas = 0;
       
    86 
       
    87 WikiHome.prototype.search = function(from) {
       
    88 	try {
       
    89 		lastWikiSearchWasFrom = from;
       
    90 		var srstring = this.wikiSearchString.getText();
       
    91 		var url = this.formSearchUrl(srstring, from, resultsPerPage);
       
    92 		var reader = new RssReader("Wiki: " + srstring, url, new WikiFeedPresenter(null), this, wikiResponseParser);
       
    93 		reader.show();
       
    94 	}catch (X) { alert(X);}
       
    95 }
       
    96 
       
    97 WikiHome.prototype.predictiveSearch = function(from){
       
    98 	if ( this.predictiveTimer != null ) {
       
    99 		clearInterval(this.predictiveTimer);
       
   100 	}
       
   101 	var self = this;
       
   102 	this.predictiveTimer = setInterval(function() {self.doPredictiveSearch(from), 1000}); 
       
   103 }
       
   104 
       
   105 WikiHome.prototype.doPredictiveSearch = function(from) {
       
   106 	if ( this.feedUpdateBroker != undefined && this.feedUpdateBroker != null ) {
       
   107 		this.feedUpdateBroker.cancel();
       
   108 	}
       
   109 	lastWikiSearchWasFrom = from;
       
   110 	var srstring = this.wikiSearchString.getText();
       
   111 	if (srstring.length <= 1) {
       
   112 		return;
       
   113 	}
       
   114 	var url = this.formSearchUrl( srstring , from, resultsPerPage );
       
   115 	this.feedURL = url;
       
   116 	this.update(true, false);
       
   117 }
       
   118 
       
   119 
       
   120 WikiHome.prototype.formSearchUrl = function(query, offset, limit) {
       
   121 	var buf = baseUrl + wikiSearchBaseUrl + query
       
   122 	if (offset > 0) {
       
   123 		buf += wikiSearchOffsetQueryPart + offset;
       
   124 	}
       
   125 	buf += wikiSearchLimitQueryPart + limit;
       
   126 	return buf;
       
   127 }
       
   128 
       
   129 // abstract function for updating per-view menu
       
   130 // only called if window.widget is defined
       
   131 WikiHome.prototype.setupMenu = function(){
       
   132 	if ( window.widget ) {
       
   133 		menu.clear();
       
   134 		var self = this;
       
   135 		var searchMenuItem = new MenuItem("Search", MENU_ITEM_MAIN_SEARCH); 
       
   136 		searchMenuItem.onSelect = function(){wikiHomeView.show();};
       
   137 		menu.append(searchMenuItem);
       
   138 		var historyMenuItem = new MenuItem("History", MENU_ITEM_MAIN_HISTORY); 
       
   139 		historyMenuItem.onSelect = function(){wikiHistoryView.previousView = self; wikiHistoryView.show();};
       
   140 		menu.append(historyMenuItem);
       
   141 		var bookmarksMenuItem = new MenuItem("Bookmarks", MENU_ITEM_MAIN_BOOKMARKS); 
       
   142 		bookmarksMenuItem.onSelect = function(){wikiBookmarksView.previousView = self; wikiBookmarksView.show();};
       
   143 		menu.append(bookmarksMenuItem);
       
   144 		
       
   145 		addHelpMenuItems();		
       
   146 	}
       
   147 }
       
   148 
       
   149 WikiHome.prototype.focusFirst = function(){
       
   150 	// don't change focus - this is predictive search so stick with text field
       
   151 }
       
   152 
       
   153 WikiHome.prototype.show = function(){
       
   154 	View.prototype.show.call(this);
       
   155 	if (window.widget) {
       
   156 		widget.setNavigationEnabled(true);
       
   157 	}
       
   158 }
       
   159 
       
   160 
       
   161 // force right soft key to display "Exit" command
       
   162 //WikiHome.prototype.setupSoftKeys = function()  {
       
   163 //    if (window.widget) {
       
   164 //		alert("WikiHome.prototype.setupSoftKeys");
       
   165 //		menu.setRightSoftkeyLabel();
       
   166 //	}
       
   167 //}
       
   168 
       
   169 
       
   170 // //////////////////////////////////////////////////////////////
       
   171 // Article view
       
   172 function WikiListView(caption){
       
   173 	ListView.prototype.init.call(this, null, null);	
       
   174 	caption = uniDecode(caption); // can be encoded unicode 
       
   175 	var caption = new NavigationButton(1, "titlebar.png", shorten(caption, 30), true);
       
   176 	caption.addEventListener("ActionPerformed", function(){wikiHomeView.show();});
       
   177 	this.addControl(caption);
       
   178 	this.useHistoryForBackButton = 1; // used internally to identify the type 
       
   179 }
       
   180 
       
   181 WikiListView.prototype = new ListView(null,null);
       
   182 
       
   183 
       
   184 WikiListView.prototype.setupMenu = function () {
       
   185 	if ( window.widget ) {
       
   186 		menu.clear();
       
   187 		var self = this;
       
   188 		
       
   189 		var searchMenuItem = new MenuItem("Search", MENU_ITEM_READER_SEARCH); 
       
   190 		searchMenuItem.onSelect = function(){wikiHomeView.show();};
       
   191 		menu.append(searchMenuItem);
       
   192 
       
   193 		var bookmarkMenuItem = new MenuItem("Add bookmark", MENU_ITEM_MAIN_ADD_BOOKMARK); 
       
   194 		bookmarkMenuItem.onSelect = function(){wikiBookmarksView.addItem(pageBeingShown, pageBeingShownContent, pageBeingShownBase);};
       
   195 		menu.append(bookmarkMenuItem);
       
   196 
       
   197 		var backMenuItem = new MenuItem("Back", MENU_ITEM_MAIN_BACK);
       
   198 		backMenuItem.onSelect = function(){self.goBack();};
       
   199 		menu.append(backMenuItem);
       
   200 
       
   201 		if (wikiHistoryView.hasNext()) {
       
   202 			var forwardMenuItem = new MenuItem("Forward", MENU_ITEM_MAIN_NEXT);
       
   203 			forwardMenuItem.onSelect = function(){wikiHistoryView.go(1);};
       
   204 			menu.append(forwardMenuItem);
       
   205 		}
       
   206 		
       
   207 		var historyMenuItem = new MenuItem("History", MENU_ITEM_MAIN_HISTORY); 
       
   208 		historyMenuItem.onSelect = function(){wikiHistoryView.previousView = self; wikiHistoryView.show();};
       
   209 		menu.append(historyMenuItem);
       
   210 
       
   211 		var bookmarksMenuItem = new MenuItem("Bookmarks", MENU_ITEM_MAIN_BOOKMARKS); 
       
   212 		bookmarksMenuItem.onSelect = function(){wikiBookmarksView.previousView = self; wikiBookmarksView.show();};
       
   213 		menu.append(bookmarksMenuItem);
       
   214 
       
   215 		addHelpMenuItems();
       
   216 		
       
   217 	}
       
   218 
       
   219 }
       
   220 
       
   221 WikiListView.prototype.show = function(){
       
   222 	View.prototype.show.call(this);
       
   223 	if (window.widget) {
       
   224 		widget.setNavigationEnabled(true);
       
   225 	}
       
   226 }
       
   227 
       
   228 WikiListView.prototype.setupPreviousView = function() {
       
   229 	if ( uiManager.currentView.useHistoryForBackButton != undefined ) {
       
   230 		this.useHistoryForBackButton = true;
       
   231 		// this signals to uiManager that we want a back button.
       
   232 		// actual value is not used because useHistoryForBackButton = true
       
   233 		this.previousView = wikiHistoryView;
       
   234 	} else {
       
   235 		this.useHistoryForBackButton = false;
       
   236 		this.previousView = uiManager.currentView;
       
   237 	}
       
   238 }
       
   239 
       
   240 WikiListView.prototype.goBack = function() {
       
   241 	if (this.useHistoryForBackButton) {
       
   242 		wikiHistoryView.go(-1);
       
   243 	} else {
       
   244 		View.prototype.goBack.call(this);
       
   245 	}
       
   246 }
       
   247 
       
   248 
       
   249 // /////////////////////////////////////////////////////////////////////////////
       
   250 // RssReader customisations
       
   251 
       
   252 // response parser for forum groups
       
   253 function wikiResponseParser(broker, responseStatus, xmlDoc) {
       
   254     if (responseStatus == 200 && xmlDoc != null) {
       
   255 		// for compatibility with rss
       
   256 		var lastModified = new Date();
       
   257 		
       
   258         // init result items array
       
   259         var items = [];
       
   260 
       
   261 		var elements = xmlDoc.getElementsByTagName("p");
       
   262 
       
   263 		for (var i = 0; i < elements.length; i++) {
       
   264 			var pagetitle = elements[i].getAttribute("title");
       
   265             items.push({ id: ""+i, title: pagetitle});
       
   266 		}
       
   267 
       
   268 		lastWikiSearchResultCountWas = elements.length;
       
   269         // update was completed successfully
       
   270         return { status: "ok", lastModified: lastModified, items: items };
       
   271     } else {
       
   272         // update failed
       
   273         return { status: "error" };
       
   274     }
       
   275 }
       
   276 
       
   277 
       
   278 
       
   279 // ////////////////////////////////////////////////////////////////////////////
       
   280 // FeedPresenter implementation for full search results view
       
   281 function WikiFeedPresenter(rssreader){
       
   282 	if (rssreader) {
       
   283 		this.init(rssreader);
       
   284 	}
       
   285 }
       
   286 
       
   287 // WikiFeedPresenter is a subclass of ButtonFeedPresenter
       
   288 WikiFeedPresenter.prototype = new ButtonFeedPresenter(null);
       
   289 
       
   290 // WikiFeedPresenter "Constructor"
       
   291 WikiFeedPresenter.prototype.init = function(rssreader) {
       
   292 	ButtonFeedPresenter.prototype.init.call(this, rssreader);
       
   293 }
       
   294 
       
   295 // Handle the click on a specific item
       
   296 WikiFeedPresenter.prototype.feedClicked = function(event){
       
   297 	var buttonid = event.source.id;
       
   298 	
       
   299 	if (buttonid == "Next page") {
       
   300 		wikiHomeView.search(lastWikiSearchWasFrom + resultsPerPage);
       
   301 	}
       
   302 	else if (buttonid == "Previous page") {
       
   303 		var from = lastWikiSearchWasFrom - resultsPerPage; 
       
   304 		if ( from < 0 ) from = 0;
       
   305 		wikiHomeView.search(from);
       
   306 	}
       
   307 	else {
       
   308 		// show article
       
   309 		var title = this.items[buttonid].title;
       
   310 		wikiBrowse(title);
       
   311 	}
       
   312 }
       
   313 
       
   314 // Create and add controls to be shown before items list.
       
   315 WikiFeedPresenter.prototype.addFooterItems = function(){
       
   316     var self = this;
       
   317 	if (lastWikiSearchResultCountWas == resultsPerPage) {
       
   318 		var nextPageButton = new NavigationButton("Next page", "next.png", "Next page");
       
   319 		nextPageButton.addEventListener("ActionPerformed", function(event){ self.feedClicked(event); });
       
   320 		this.rssreader.addFeedItemControl(nextPageButton);
       
   321 	}
       
   322 	if (lastWikiSearchWasFrom > 0) {
       
   323 		var prevPageButton = new NavigationButton("Previous page", "prev.png", "Previous page");
       
   324 		prevPageButton.addEventListener("ActionPerformed", function(event) { self.feedClicked(event); });
       
   325 		this.rssreader.addFeedItemControl(prevPageButton);
       
   326 	}
       
   327 }
       
   328 
       
   329 
       
   330 // /////////////////////////////////////////////////////////////////////////////////
       
   331 // Browse / view wiki pages in 'printable format'
       
   332 var wikiAjax;
       
   333 var pageBeingShown;
       
   334 var pageBeingShownBase;
       
   335 var pageBeingShownContent;
       
   336 var gDontAddToHistory;
       
   337 var wikiBrowseCancelled = false;
       
   338 var gViewCache = new ViewCache(10);
       
   339 
       
   340 function wikiBrowse(page, dontAddToHistory, baseUrl) {
       
   341 	pageBeingShown = page;
       
   342 	if ( baseUrl != undefined && baseUrl != null ){
       
   343 		pageBeingShownBase = baseUrl;
       
   344 	} else {
       
   345 		pageBeingShownBase = wikiViewPageUrlBase;
       
   346 	}
       
   347 	//alert("page=" + pageBeingShown + ", baseUrl=" + pageBeingShownBase);
       
   348 	if ( dontAddToHistory != undefined || dontAddToHistory == true) {
       
   349 		gDontAddToHistory = true;
       
   350 	} else {
       
   351 		gDontAddToHistory = false;
       
   352 	}
       
   353 	wikiBrowseCancelled = false;
       
   354 	var t = page.replace(/_/g, ' ');
       
   355 	var v = gViewCache.getView(t);
       
   356 	if ( v != undefined && v != null ) {
       
   357 		v.setupPreviousView();
       
   358 		v.show();
       
   359 		return;
       
   360 	}
       
   361 	try {
       
   362 		pageBeingShownContent = null;
       
   363 		uiManager.showNotification(-1, "wait", "Loading page...", -1);
       
   364 		if (page) {
       
   365 		
       
   366 			wikiAjax = new Ajax();
       
   367 			
       
   368 			wikiAjax.onreadystatechange = function(){
       
   369 				wikiPageDownloadStateChanged();
       
   370 			};
       
   371 			
       
   372 			//		var url = wikiViewPageUrlBase  + encodeURIComponent(page) + wikiPrintableParam; 
       
   373 			var url = pageBeingShownBase + encodeURIComponent(page) + wikiPrintableParam;
       
   374 			//alert("url: " + url);
       
   375 			//		var url = wapediaArticleBase + page 
       
   376 			// initiate the request
       
   377 			wikiAjax.open("GET", url, true);
       
   378 			wikiAjax.send(null);
       
   379 			
       
   380 			if (window.widget) {
       
   381 				menu.setRightSoftkeyLabel("Cancel", function(){
       
   382 					wikiBrowseCancel();
       
   383 				});
       
   384 			}	
       
   385 			
       
   386 		}
       
   387 	} catch(xx) { alert(xx);}
       
   388 }
       
   389 
       
   390 function wikiBrowseCancel() {
       
   391 	wikiBrowseCancelled = true;
       
   392 	wikiAjax.abort();
       
   393 }
       
   394 
       
   395 function wikiPageDownloadStateChanged() {
       
   396 	if ( wikiBrowseCancelled ) {
       
   397 		return;
       
   398 	}
       
   399     if (wikiAjax.readyState == 4) {
       
   400 		uiManager.hideNotification();
       
   401 		try {
       
   402 			showWikiPage(pageBeingShown, wikiAjax.responseText);
       
   403 		}catch(xx) { alert(xx);}
       
   404 	}
       
   405 }
       
   406 
       
   407 function showWikiPage(title, html){
       
   408 	// ensure no underscores
       
   409 	title = title.replace(/_/g, ' ');
       
   410 	title = uniDecode(title);
       
   411 	pageBeingShown = title;
       
   412 	pageBeingShownContent = html;
       
   413 	if (false == gDontAddToHistory) {
       
   414 		wikiHistoryView.addItem(title, html, pageBeingShownBase);
       
   415 	}
       
   416 	var start = html.indexOf('<div id="bodyContent">');
       
   417 	var end = findDivEnd(html, start);
       
   418 	var pageView = new WikiListView(pageBeingShown);
       
   419 	var text = html.substring(start, end);
       
   420 //	text = stripExtStyle(text);
       
   421 //	text = modWikiBox(text, 'class="box"');
       
   422 //	text = modWikiBox(text, 'class="vertical-navbox');
       
   423 //	text = modWikiBox(text, 'class="infobox"');
       
   424 	text = stripStylesFromTag(text, "table", "box"); 
       
   425 	text = stripStylesFromTag(text, "table", "infobox"); 
       
   426 	text = stripStylesFromTag(text, "table", "navbox"); 
       
   427 	text = stripStylesFromTag(text, "table", "vertical-navbox"); 
       
   428 	text = stripStylesFromTag(text, "div", "thumbinner");
       
   429 	// replace inline float: right;
       
   430 	text = text.replace(/float: right|float:right/g, "clear:both; width: 95%; display:block");
       
   431 	text = text.replace(/clear:right|clear: right/g, "");
       
   432 	text = modWikiLinks(text);
       
   433 	
       
   434 	var docModel = ParseIntoDocModel(text);
       
   435 	var preamble = new ContentPanel(null, "Overview", docModel.preface, true, true);
       
   436 	pageView.addControl(preamble);
       
   437 	for (var i = 0; i < docModel.sections.length; i++) {
       
   438 		if ( docModel.sections[i].caption == "Contents" ) {
       
   439 			continue;
       
   440 		}
       
   441 		var control = new ContentPanel(
       
   442 			null, 
       
   443 			docModel.sections[i].caption, 
       
   444 			docModel.sections[i].content, 
       
   445 			true, false); // foldable & expanded
       
   446 		pageView.addControl(control);
       
   447 	}
       
   448 	pageView.setupPreviousView();
       
   449 	gViewCache.addView(title,pageView);
       
   450 	pageView.show();
       
   451 }
       
   452 
       
   453 // ///////////////////////////////////////////////////////////////////////
       
   454 // Parsing and modding HTML to fit
       
   455 
       
   456 function modWikiLinks(text) {
       
   457 //	var tmp = text;//.replace(/ src="/g, ' src="http://www.wikipedia.org');
       
   458 	// images sorted. now links
       
   459 	var tmp = text.replace(/65em/g, '100%');
       
   460 	var strToLookFor = ' href="/wiki/'; //index.php/';
       
   461 
       
   462 //	var tmp = text.replace(/ src="/g, ' src="http://wapedia.mobi');
       
   463 //	// images sorted. now links
       
   464 //	var strToLookFor = ' href="/en/';
       
   465 
       
   466 	var from = 0;
       
   467 	var ind = tmp.indexOf(strToLookFor);
       
   468 	var buf ="";
       
   469 	while ( ind > 0 ) {
       
   470 		buf = buf + tmp.substring(from, ind);
       
   471 		// extract page name
       
   472 		var ind2 = tmp.indexOf('"', ind + strToLookFor.length);
       
   473 		var pageName = tmp.substring(ind + strToLookFor.length, ind2);
       
   474 		buf += " style=\"text-decoration: underline;\""
       
   475 		buf += " href=\"JavaScript:void(0)\"";
       
   476 		buf += " onclick=\"event.stopPropagation();wikiBrowse(uniDecode('" + pageName.replace(/'/g, "\'") + "')); return false;\"";
       
   477 		from = ind2;
       
   478 		ind = tmp.indexOf(strToLookFor, from);
       
   479 	}
       
   480 	buf = buf + tmp.substring(from);
       
   481 	return buf; 
       
   482 }
       
   483 
       
   484 function stripExtStyle(text) {
       
   485 	var ret = text.replace(/style=\".+?\"/g, "");
       
   486 	return ret;
       
   487 }
       
   488 
       
   489 function stripStylesFromTag(text, tag, style) {
       
   490 	var key = "<" + tag + " ";
       
   491 	var ind = text.indexOf(key);
       
   492 	if ( ind == -1 ) return text;
       
   493 	var buf = "";
       
   494 	var prevind = 0;
       
   495 	while(ind != -1 ) {
       
   496 		var ind2 = text.indexOf(">", ind);
       
   497 		if ( ind2 == -1 ) {
       
   498 			// something's wrong, return unedited
       
   499 			return text; 
       
   500 		}
       
   501 		var tag = text.substring(ind, ind2+1);
       
   502 		if ( style != undefined ) {
       
   503 			if ( tag.indexOf(style) != -1 ) {
       
   504 				tag = stripExtStyle(tag);
       
   505 			}
       
   506 		} else {
       
   507 			tag = stripExtStyle(tag);
       
   508 		}
       
   509 		buf += text.substring(prevind, ind);
       
   510 		buf += tag;
       
   511 		prevind = ind2+1;
       
   512 		ind = text.indexOf(key, prevind );
       
   513 	}
       
   514 	buf += text.substring(prevind);
       
   515 	return buf;
       
   516 }
       
   517 
       
   518 function findDivEnd(text, from) {
       
   519 	var openDivCount = 1;
       
   520 	var divind = text.indexOf("<div", from+1);
       
   521 	var cdivind = text.indexOf("</div", from+1);
       
   522 	var pos = from;
       
   523 	while ( openDivCount > 0 && divind > 0 && cdivind > 0 ) {
       
   524 		pos = Math.min(divind, cdivind);
       
   525 		if ( pos == divind ) {
       
   526 			openDivCount ++;
       
   527 		}
       
   528 		if ( pos == cdivind ) {
       
   529 			openDivCount --;
       
   530 		}
       
   531 		divind = text.indexOf("<div", pos+1);
       
   532 		cdivind = text.indexOf("</div", pos+1);
       
   533 	}
       
   534 	return pos;
       
   535 }
       
   536 
       
   537 
       
   538 
       
   539 function DocModel(){
       
   540 	this.preface = null;
       
   541 	this.sections = new Array();
       
   542 }
       
   543 
       
   544 
       
   545 function DocSection(caption, content) {
       
   546 	this.caption = caption;
       
   547 	this.content = content;
       
   548 }
       
   549 
       
   550 
       
   551 function ParseIntoDocModel(text) {
       
   552 	var model = new DocModel(); 
       
   553 	var ind = text.indexOf("<h2");
       
   554 	if ( ind == -1 ) {
       
   555 		model.preface = text;
       
   556 		return model;
       
   557 	}
       
   558 	
       
   559 	model.preface = text.substring(0,ind);
       
   560 	while (ind > 0) {
       
   561 		text = text.substring(ind);
       
   562 		ind = 0;
       
   563 		var ind2 = text.indexOf("</h2>");
       
   564 		var caption = text.substring(ind+4, ind2);
       
   565 		text = text.substring(ind2+5);
       
   566 		ind = text.indexOf("<h2");
       
   567 		var endind = ind;
       
   568 		if ( endind == -1 ) {
       
   569 			endind = text.length-1;
       
   570 		}
       
   571 		var content = text.substring(0,endind);
       
   572 		var section = new DocSection(caption, content);
       
   573 		model.sections.push(section);
       
   574 	}
       
   575 	return model;
       
   576 }
       
   577 
       
   578 
       
   579 
       
   580 
       
   581 
       
   582 
       
   583 
       
   584 // also for vertical-navbox,
       
   585 // clx = 'class="box"' 
       
   586 //function modWikiBox(text, clx) {
       
   587 //	var ind = text.indexOf(clx);
       
   588 //	if ( ind == -1 ) return text;
       
   589 //	var buf = "";
       
   590 //	var prevind = 0;
       
   591 //	while(ind != -1 ) {
       
   592 //		var ind2 = text.lastIndexOf("<table ", ind);
       
   593 //		if ( ind2 == -1 ) {
       
   594 //			// something's wrong, return unedited
       
   595 //			return text; 
       
   596 //		}
       
   597 //		var substr = text.substring(ind2+1, ind);
       
   598 //		if (substr.indexOf(">") == -1 && substr.indexOf("<") == -1 ) {
       
   599 //			// got it
       
   600 //			buf += text.substring(prevind, ind2 + 7);
       
   601 //		} else {
       
   602 //			// not it
       
   603 //			buf += text.substring(prevind, ind);
       
   604 //		}
       
   605 //		prevind = ind;
       
   606 //		ind = text.indexOf(clx, prevind + 1);
       
   607 //	}
       
   608 //	buf += text.substring(prevind);
       
   609 //	return buf;
       
   610 //}
       
   611 //
       
   612 //function modDivs(text, clx) {
       
   613 //	var key = "<div " + clx;
       
   614 //	var ind = text.indexOf(key);
       
   615 //	if ( ind == -1 ) return text;
       
   616 //	var buf = "";
       
   617 //	var prevind = 0;
       
   618 //	while(ind != -1 ) {
       
   619 //		var ind2 = text.indexOf(">", ind);
       
   620 //		if ( ind2 == -1 ) {
       
   621 //			// something's wrong, return unedited
       
   622 //			return text; 
       
   623 //		}
       
   624 //		buf += text.substring(prevind, ind + key.length);
       
   625 //		prevind = ind2;
       
   626 //		ind = text.indexOf(key, prevind );
       
   627 //	}
       
   628 //	buf += text.substring(prevind);
       
   629 //	return buf;
       
   630 //}
       
   631 //
       
   632