From SwissExperiment
TagExtensionInstallation
Tag Extension
Summary
Tag Extension extends the MediaWiki (1.8.2) with the features of social-bookmarking. It is used in the Swiss Experiment project.
Key features of TagExtension:
- Embedding the social-bookmarking features into the wiki.This allows the users to collaboratively use 'tags', thus giving personalized access to content.
- Enabling structured tags, with key-value pairs, for more contexual information in tags.
Configurations
After downloading and installing the Mediawiki, the Tag related configurations are made in the LocalSettings.php.
The additions are as follows :-
- Add new namespaces TAG, TAG_TALK, BOOKMARKS, BOOKMARKS_TALK, COMPLEX_TYPE, COMPLEX_TYPE_TALK as follows :-
$wgExtraNamespaces[112] = "Tag";
$wgExtraNamespaces[113] = "Tag_talk";
$wgExtraNamespaces[114] = "Bookmarks";
$wgExtraNamespaces[115] = "Bookmarks_talk";
$wgExtraNamespaces[122] = "Complex_type";
$wgExtraNamespaces[123] = "Complex_type_talk";
- Other related configurations are :-
if ($TAGS_ENABLED){
include_once('includes/TagExtension.php');
include_once('includes/BookmarksExtension.php');
include_once('includes/SpecialSearchTags.php');
#SwissEx Complex Type Tags
include_once('includes/SpecialCreateComplexType.php');
include_once('includes/SpecialTagComplex.php');
$wgSpecialPages['CreateComplexType'] = array('SpecialPage','CreateComplexType');
$wgSpecialPages['TagComplex'] = array('SpecialPage','TagComplex');
$wgSpecialPages['AddArticle'] = array('SpecialPage','AddArticle');
#SwissEx Complex Type Tags
$wgSpecialPages['TagCloud'] = array('SpecialPage','TagCloud');
define('NS_TAG', 112);
define('NS_TAG_TALK', 113);
define('NS_BOOKMARKS', 114);
define('NS_BOOKMARKS_TALK', 115);
define('NS_CTYPE', 122);
define('NS_CTYPE_TALK', 123);
#if (!is_array($wgExtraNamespaces)) { $wgExtraNamespaces=array(); }
# $wgExtraNamespaces = $wgExtraNamespaces + array( NS_TAG => 'Tag',
# NS_TAG_TALK => 'Tag_talk',
# NS_BOOKMARKS => 'Bookmarks',
# NS_BOOKMARKS_TALK => 'Bookmarks_talk'
# );
#
// Support subpages only for talk pages by default
$wgNamespacesWithSubpages = $wgNamespacesWithSubpages + array(
NS_TAG_TALK => true,
NS_BOOKMARKS_TALK => true
);
//Additon to the global hooks array, for the tags, and bookmarks functionalities
$wgHooks['OutputPageBeforeHTML'][] = 'tagExtensionHook';
$wgHooks['OutputPageBeforeHTML'][] = 'bookmarksDisplayHook';
$wgHooks['OutputPageBeforeHTML'][] = 'tagDisplayHook';
$wgHooks['ArticleAfterFetchContent'][] = 'addTagsToFactbox';
//This is to specify the namespaces where the tags' display box will be shown
$wgTagDisplayNamespaces = array(NS_MAIN, NS_USER, NS_TAG, NS_BOOKMARKS, 100, 102, 104, 106, 108, 110, 116, 118, 120, 124);
# SwissEx addition ends here
}
- In the above addition, the TAGS_ENABLED flag can be set to false, to disable the Tag and Bookmarks Extension.
Translations
The installations has translations only in English presently.
These are the additions to the MessagesEn.php file :-
- For the tag functionality :
'searchtags' => 'Search Tags',
'tagcloud' => 'Tag Cloud',
'tag' => 'Tag',
'untag' => 'Untag',
'tagarticle' => 'Tag',
'Tag this page' => 'Tag this page with:',
'notype' => 'No Type Specified',
'complextype' => 'Complex type',
'tagnologin' => 'Not logged in',
'tagnologintext' => 'You must be [[Special:Userlogin|logged in]] to add a tag for a page.',
'tagempty' => 'Empty tag',
'tagemptytext' => 'You must enter a non-empty tag for a page.',
'tagexists' => 'Tag exists',
'tagexiststext' => 'You have already used this tag for [[:$1]].',
'addedtag' => 'Tag Addition',
'addedtagtext' => "The page \"[[:$1]]\" has been added to your [[Bookmarks:$2|bookmarks]]",
'createcomplextype' => 'Create Complex Type',
'tagcomplex' => 'Tag with Complex Types',
'mybookmarks' => 'My bookmarks',
'bookmarks' => 'Bookmarks',
'bookmarksfor' => "(for '''$1''')",
'nobookmarks' => 'You have no bookmarks.',
'bookmarksanontext' => 'Please $1 to view your bookmarks.',
'bookmarkscount' => "$2 has {{PLURAL:$1|$1 item|$1 items}} in his/her bookmarks",
'bookmarksnologin' => 'Not logged in',
'deletedbookmark' => 'Bookmark Deleted',
'deletedbookmarktext' => 'The bookmark has been deleted',
'savedbookmark' => 'Bookmark Saved',
'savedbookmarktext' => 'The bookmark has been saved',
Modified Files
Extending wiki articles for tags functionality
Article.php
This file includes SwissEx additions for the tagging. We add a new function addTag. Also, we add code to the existing wiki function view, in order to invalidate the wiki cache, so that newly added tags are immediately visible (rather than having to refresh, whenever adding tags)
Functionality to invalidate cache :
Inside the wiki function view() add the following lines of code :
if( $ns == NS_USER){
$this->mTitle->invalidateCache();
}
Functionality to add tags:
function addTag($name, $sem_id=NULL, $ctype_id = NULL){
global $wgOut, $wgUser;
$fname = 'Article::addTag';
$tag_id = 0;
//this part is not needed as we are taking care of the name when creating a Title object
// $name = str_replace(' ','_',ucwords(strtolower($name)));
// Create a new taggeditem for our purpose.
$dbw =& wfGetDB( DB_MASTER );
$dbr =& wfGetDB( DB_SLAVE);
if ( $wgUser->isAnon() ) {
$wgOut->setPagetitle( wfMsg( 'tagnologin' ) );
$text = wfMsg( 'tagnologintext');
$wgOut->addWikiText( $text );
$wgOut->returnToMain( true, $this->mTitle->getPrefixedText() );
return;
}
if($name == NULL){
$wgOut->setPagetitle( wfMsg( 'tagempty' ) );
$text = wfMsg( 'tagemptytext');
$wgOut->addWikiText( $text );
$wgOut->returnToMain( true, $this->mTitle->getPrefixedText() );
return;
}
// First, we want to add an empty page in the wiki related to the tag in the TAG namespace.
$tagTitle =& Title::newfromText($name, NS_TAG);
$tag = new TaggedItem($tagTitle->getDBkey());
if ($tag->isNewTag($dbr)){
$tagArticle = new Article($tagTitle);
$tagArticle->doEdit('You can add some information about this tag here.','');
}
// Add a Bookmarks page for the user, if he is new tagger adding his first bookmark
if($tag->isNewTagger($dbr, $wgUser->getId())) {
$userName = $wgUser->getName();
$bookmarkTitle =& Title::makeTitle(NS_BOOKMARKS, str_replace(' ','_', $userName));
$bookmarkArticle = new Article($bookmarkTitle);
$bookmarkArticle->doEdit('<!--BOOKMARKS-->','');
//BookmarksExtension::getBookmarks($wgUser->getId(), $dbr);
//Also create the user_page entry, as page_id for the user page is needed for a lot of functionality
$userTitle = $wgUser->getUserPage(); // & Title::makeTitle(NS_USER, str_replace(' ','_', $userName));
if (!$userTitle->exists()){
$userHomePage = new Article($userTitle);
$userHomePage->doEdit('User '.$userName.'\'s homepage.','', EDIT_NEW);
}
}
//This query locks the user_tags table for the complete tagging process
$dbw->query('LOCK TABLES user_tags write, tagging_users_total write, tag_stats write, tags write');
//here we update - tagging_users_total, if the current user is new and has not participated in tagging before
$sql1 = "SELECT count(*) as taggers from user_tags where tg_user_id = {$wgUser->getId()}";
$res1 = $dbr->query($sql1, $fname);
$row1 = $dbr->fetchObject($res1);
$taggers = $row1->taggers;
$dbr->freeResult($res1);
if($taggers == 0){
//No entry with the user_id in user_tags -- SO NEW USER -- We need to revamp popularity, as tagging_users_total will change
$sql2 = "Update tagging_users_total set users_total = users_total + 1 ";
$res2 = $dbw->query($sql2, $fname);
$sql2_1 = "select users_total as taggers from tagging_users_total";
$res2_1 = $dbr->query($sql2_1, $fname);
$row2_1 = $dbr->fetchObject($res2_1);
$taggingUsers = $row2_1->taggers;
$dbr->freeResult($res2_1);
$factor = ($taggingUsers - 1)/$taggingUsers;
$sql2_2 = "Update tags set popularity = popularity * ".$factor;
$res2_2 = $dbw->query($sql2_2, $fname);
}
if ($tag->isNewTag($dbr)){
$dbw->insert( $dbw->tableName('tags'),
array( 'tag_name' => $tag->getName(),
'popularity' => 0,
'author_id' => $wgUser->getId(),
'tag_timestamp' => $dbw->timestamp()
),
$fname);
$tag_id = $tag->getTagId($dbr);
$tag->setId($tag_id);
$dbw->insert( $dbw->tableName('tag_stats'),
array( 'ts_tag_id' => $tag_id,
'user_count' => 1,
'usage_count' => 1,
'tagged_items' => 1),
$fname);
}
else{
$tag_id = $tag->getTagId($dbr);
$tag->setId($tag_id);
//There can be two cases
// 9 APRIL -- check tagExists for a user and a semantic id and/or ctype_id.
if ( $tag->tagExists($dbr, $wgUser->getId(), $this->mTitle, $sem_id)){
$dbw->query('UNLOCK TABLES');
return 'Exists';
}
$tag->updateStats( $dbr, $dbw, $wgUser->getId(), $this->mTitle );
}
// Add user tag here.. also add the semantic id and/or ctype_id.
$tag->updatePopularityandUserTags($dbr, $dbw, $wgUser->getId(), $this->mTitle, $sem_id, $ctype_id);
$dbw->query('UNLOCK TABLES');
// $tag->addTagAsRelation($dbr, $dbw, $this->mTitle);
return 'Added';
}
Note: A function addAnnotation is also present in this file, which was also developed in parallel to tagging. This feature is currently not used in the wiki, and may be required at some point. It may also be preserved as part of the file, to be recovered later if needed.
Skintemplate.php
- /includes/SkinTemplate.php
To the function buildPersonalUrls add the following code, to show 'my bookmarks' link on the top bar(when the user is logged in)
global $TAGS_ENABLED;
if ($TAGS_ENABLED){
$href = $wgScript.'/Bookmarks:'.$wgUser->getName();
$personal_urls['bookmarks'] = array(
'text' => wfMsg( 'mybookmarks' ),
'href' => $href,
'active' => ( $href == $pageurl )
);
}
Wiki.php
To the function initializeSpecialCases, add the following code segment. This code escapes the execute path of the special page, when tagging a Special page :
else if ($request->getVal('action') == 'Tag') {
return false;
}
To the function performAction, add the following case :
case 'Tag':
global $wgScript, $wgOut;
$sem_id = $request->getVal('sem_id');
$value = $request->getVal( 'tagName' );
$ctype_id = $request->getVal('ctype');
if ($sem_id != 'unknown'){
$article->addTag($value, $sem_id, $ctype_id);
}
break;
Note: For annotation functionality (which is currently switched off in every wiki version, the following code can be added. It may be used if the functionality is needed later on
case 'Annotate':
$relation = $request->getVal( 'r_annotate' );
$subject = $request->getVal( 's_annotate' );
$article->addAnnotation($relation, $subject);
break;
Changing the Front End
The tag extension required many changes in the front end of the wiki. For example, we add a form in the side panel to tag a page. These changes are incorporated
in Monobook.php. The stylesheet changes are put in main.css, and the javascript changes are put in wikibits.js.
MonoBook.php
Add the following scripts to the head of the html.
<script src="<?php $this->text('stylepath' ) ?>/tabs/jquery-1.1.1.js" type="text/javascript"><!-- jquery- js --></script>
<script src="<?php $this->text('stylepath' ) ?>/tabs/history/jquery.history.pack.js" type="text/javascript"><!-- history js --></script>
<script src="<?php $this->text('stylepath' ) ?>/tabs/tabs/jquery.tabs.pack.js" type="text/javascript"><!-- tabs js --></script>
<script type="text/javascript">//<![CDATA[
// Add styles via JavaScript for graceful degradation...
document.write('<link rel="stylesheet" href="<?php $this->text('stylepath' ) ?>/tabs/tabs/tabs_js.css"
type="text/css" media="projection, screen" />');
//]]></script>
<script type="text/javascript">//<![CDATA[
function createCallback(type) {
return function() {
alert('callback: ' + type);
}
}
$(document).ready(function() {
$('#container-1').tabs();
$('#container-2').tabs(2);
$('#container-3').tabs({fxSlide: true});
$('#container-4').tabs({fxFade: true, fxSpeed: 'fast'});
$('#container-5').tabs({fxSlide: true, fxFade: true, fxSpeed: 'fast'});
$('#container-6').tabs({fxFade: true, fxSpeed: 'fast', onClick: createCallback('onClick'),
onHide: createCallback('onHide'), onShow: createCallback('onShow')});
$('#container-7').tabs({fxAutoHeight: true});
$('#container-8').tabs({fxShow: {height: 'show', opacity: 'show'}});
$('#container-9').tabs({remote: true});
$('#container-10').tabs({fxFade: true, fxAutoHeight: true, tabStruct: 'div>div'});
$('<p><a href="#">Activate third tab</a>
<code>$(\'#container-1\').triggerTab(3);</code></p>').appendTo('#trigger-tab')
.find('a').click(function() {
$('#container-1').triggerTab(3);
return false;
}
);
$('<p><a href="#">Disable third tab</a>
<code>$(\'#container-1\').disableTab(3);</code></p>').appendTo('#trigger-tab')
.find('a').click(function() {
$('#container-1').disableTab(3);
return false;
}
);
$('<p><a href="#">Enable third tab</a>
<code>$(\'#container-1\').enableTab(3);</code></p>').appendTo('#trigger-tab')
.find('a').click(function() {
$('#container-1').enableTab(3);
return false;
}
);
});
//]]></script>
Add the following 'div' to the Monobook.php 'body' tag, just after the 'div'(id = "p-search") finishes.
<?php global $TAGS_ENABLED; if ($TAGS_ENABLED) { ?>
<div id ="p-tag" class="portlet">
<h5><label for="tagInput"><?php $this->msg('Tag this page') ?> </label></h5>
<div id="tagBody" class="pBody">
<form name ="tagForm" action="<?php $this->text('tagaction') ?>" id="tagform"><div>
<input name="title" type="hidden" value=<?php global $wgTitle;echo wfUrlencode( $wgTitle->getPrefixedDBkey()); ?> >
<input id="tag" name="tagvalue" type="text" <?php
if($this->haveMsg('accesskey-tag')) {
?>accesskey="<?php $this->msg('accesskey-tag') ?>"<?php }
if( isset( $this->data['tagvalue'] ) ) {
?> value="<?php $this->text('tagname') ?>"<?php } ?> />
<input type='submit' name="action" class="tagButton" id="searchGoButton" value="<?php $this->msg('tagarticle') ?>" />
</div></form>
</div>
</div>
<?php } ?>
main.css
This file is in skins/monobook/ . The additions made are as follows :-
/* Tagbox template style - SwissEx addition */
.tagbox {
border: 1px solid #aaa;
background-color: #f9f9f9;
color: black;
margin-bottom: 0.5em;
margin-left: 1em;
padding: 0.2em;
float: right;
clear: right;
width: 30%;
}
.tagbox td,
.tagbox th {
vertical-align: top;
}
.tagbox caption {
font-size: larger;
margin-left: inherit;
}
.tagbox.bordered {
border-collapse: collapse;
}
.tagbox.bordered td,
.tagbox.bordered th {
border: 1px solid #aaa;
}
.tagbox.bordered .borderless td,
.tagbox.bordered .borderless th {
border: 0;
}
.tagbox.sisterproject {
width: 20em;
font-size: 90%;
}
.tagbox a {
text-decoration:none;
}
.tagbox a:hover {
background-color: white;
}
.tagbox body {
padding: 10px;
line-height: 1.4;
font-size: 16px;
}
.tagbox body * {
font-size: 87.5%;
font-family: "Trebuchet MS", Trebuchet, Verdana, Helvetica, Arial, sans-serif;
}
.tagbox body * * {
font-size: 100%;
}
.tagbox h1 {
margin: 0 0 1em;
font-size: 143%;
}
.tagbox h2 {
margin: 2em 0 1em;
}
.tagbox h3 {
margin: 0 0 1em;
}
.tagbox ul {
list-style: none;
}
.tagbox p, pre {
margin: 1em 0 0;
}
.tagbox code {
font-family: "Courier New", Courier, monospace;
}
.tagbox div {
margin: 1.2em 0 0;
width: 50%;
}
.tagbox div div {
margin: 0;
width: auto;
}
.tagbox #container-1 div {
border: 1px solid #eaeaea;
background: transparent;
}
.tagbox #container-1 div div {
border: 0;
}
.tagbox li{
display: inline;
width: 33%;
}
.tagbox.sisterproject {
width: 20em;
font-size: 90%;
}
@media print {
.tagbox.sisterproject {
display: none;
}
}
/* styles for bordered infobox with merged rows */
.tagbox.bordered .mergedtoprow td,
.tagbox.bordered .mergedtoprow th {
border: 0;
border-top: 1px solid #aaa;
border-right: 1px solid #aaa;
}
.tagbox.bordered .mergedrow td,
.tagbox.bordered .mergedrow th {
border: 0;
border-right: 1px solid #aaa;
}
/*
Tabs - important styles to ensure accessibility in print
*/
@media projection, screen { /* Use class for showing/hiding tab content, so that visibility can be better controlled in different media types... */
.tabs-hide {
display: none;
}
}
@media print {
.anchors {
display: none;
}
}
/*
Tabs - not important for accessibility, just for the look of it...
*/
.anchors {
list-style: none;
margin: 0;
padding: 0 0 1px;
}
.anchors:after {
display: block;
clear: both;
content: " ";
}
.anchors li {
float: left;
margin: 0 1px 0 0;
}
.anchors a {
display: block;
position: relative;
top: 1px;
border: 1px solid #eaeaea;
border-bottom: 0;
z-index: 2;
padding: 2px 9px 1px;
color: #000;
text-decoration: none;
}
.anchors .tabs-selected a {
padding-bottom: 2px;
font-weight: bold;
}
.anchors .tabs-selected a, .anchors a:hover, .anchors a:focus, .anchors a:active,
.fragment {
background: #eaeaea;
}
.anchors .tabs-selected a:link, .anchors .tabs-selected a:visited,
.anchors .tabs-disabled a:link, .anchors .tabs-disabled a:visited {
cursor: text;
}
.anchors a:hover, .anchors a:focus, .anchors a:active {
cursor: pointer;
}
.anchors .tabs-disabled {
opacity: .4;
}
.anchors .tabs-disabled a:hover, .anchors .tabs-disabled a:focus, .anchors .tabs-disabled a:active {
background: transparent;
}
.fragment {
padding: 0 1px;
}
.anchors .tabs-selected .tabs-loading {
padding-left: 25px;
background-image: url(loading.gif);
background-position: 4px 50%;
background-repeat: no-repeat;
}
wikibits.js
This file is located in skins/common. The following are the additions made :-
function toggleDiv(id, id1, id2){
var el=document.getElementById(id);
el.style.display=el.style.display=='block'? 'none' : 'block';
var el1=document.getElementById(id1);
var el2=document.getElementById(id2);
el1.style.display=el1.style.display=='none'? 'block' : 'none';
el2.style.display=el2.style.display=='none'? 'block' : 'none';
}
function toggleLC(anchor1, anchor2){
var el1 = document.getElementById('Relatedlist');
var el2 = document.getElementById('Relatedcloud');
var el3 = document.getElementById('Popularlist');
var el4 = document.getElementById('Popularcloud');
var el5 = document.getElementById('Mylist');
var el6 = document.getElementById('Mycloud');
el1.style.display = el1.style.display=='block'?'none':'block';
el2.style.display = el2.style.display=='block'?'none':'block';
el3.style.display = el3.style.display=='block'?'none':'block';
el4.style.display = el4.style.display=='block'?'none':'block';
el5.style.display = el5.style.display=='block'?'none':'block';
el6.style.display = el6.style.display=='block'?'none':'block';
var tagBox = document.getElementById('tags');
//tagBox.style.width=tagBox.style.width=='16em'? '23em' : '16em';
var linkreset = document.getElementById(anchor1);
var href = linkreset.getAttribute("href");
linkreset.setAttribute("href_bak", href);
linkreset.removeAttribute("href");
linkreset.style.color="gray";
var linkset = document.getElementById(anchor2);
linkset.setAttribute("href", linkset.attributes["href_bak"].nodeValue);
linkset.style.color="blue";
}
function toggleRPM(anchor1) {
var el1 = document.getElementById('Related');
var el2 = document.getElementById('Popular');
var el3 = document.getElementById('My');
if(anchor1 == 'Related'){
el1.style.display = 'block';
el2.style.display = 'none';
el3.style.display = 'none';
}
if(anchor1 == 'Popular'){
el1.style.display = 'none';
el2.style.display = 'block';
el3.style.display = 'none';
}
if(anchor1 == 'My'){
el1.style.display = 'none';
el2.style.display = 'none';
el3.style.display = 'block';
}
}
function initializeTags() {
var linkreset = document.getElementById('cloudTags');
var href = linkreset.getAttribute("href");
linkreset.setAttribute("href_bak", href);
linkreset = document.getElementById('listTags');
href = linkreset.getAttribute("href");
linkreset.setAttribute("href_bak", href);
}
function disableClouds() {
var el1 = document.getElementById('Relatedcloud');
if (el1.style.display=='block'){
var linkreset = document.getElementById('cloudTags');
var href = linkreset.getAttribute("href");
linkreset.setAttribute("href_bak", href);
linkreset.removeAttribute("href");
linkreset.style.color="gray";
var linkset = document.getElementById('listTags');
linkset.setAttribute("href", linkset.attributes["href_bak"].nodeValue);
linkset.style.color="blue";
}
else {
var linkreset = document.getElementById('listTags');
var href = linkreset.getAttribute("href");
linkreset.setAttribute("href_bak", href);
linkreset.removeAttribute("href");
linkreset.style.color="gray";
var linkset = document.getElementById('cloudTags');
linkset.setAttribute("href", linkset.attributes["href_bak"].nodeValue);
linkset.style.color="blue";
}
}
function enableClouds() {
var link1 = document.getElementById('cloudTags');
link1.setAttribute("href", link1.attributes["href_bak"].nodeValue);
var link2 = document.getElementById('listTags');
link2.setAttribute("href", link2.attributes["href_bak"].nodeValue);
}
var myEffects = {
fade: function(elid) {
var el = document.getElementById('showTagBox');
var opacs = ["0",".1",".2",".3",".4",".5",".6",".7",".8",".9","1"];
if (document.getElementById(elid).style.display == 'none'){
document.getElementById(elid).style.opacity = '0';
document.getElementById(elid).style.display = 'block';
for (var i = 0; i < 11; i++){
setTimeout('document.getElementById(\''+elid+'\').style.opacity = "'+opacs[i]+'";', i * 40);
}
el.style.display='none';
}else{
el.style.display='block';
opacs.reverse();
for (var i = 0; i < 11; i++) {
setTimeout('document.getElementById(\''+elid+'\').style.opacity = "'+opacs[i]+'";', i * 40);
}
setTimeout('document.getElementById(\''+elid+'\').style.display = "none";', i * 40);
}
}
}
// The next function is for complex types form display
function addauthor() {
mytable = document.getElementById("authors");
mytablebody =mytable.getElementsByTagName("TBODY").item(0);
mycurrent_row=document.createElement("TR");
mycurrent_cell=document.createElement("TD");
mycurrent_cell.align="center";
file=document.createElement("INPUT");
file.type="text";
file.name="keyName[]";
file.size="25";
mycurrent_cell.appendChild(file);
mycurrent_row.appendChild(mycurrent_cell);
mycurrent_cell=document.createElement("TD");
mycurrent_cell.align="center";
src=document.createElement("SELECT");
ftype = document.getElementById("keyTypes");
for(i=0; i<ftype.options.length; i++ ) {
opt=new Option(ftype.options[i].text);
opt.value=ftype.options[i].value;
src.options[i]= opt;
}
src.name="keyType[]";
mycurrent_cell.appendChild(src);
mycurrent_row.appendChild(mycurrent_cell);
mycurrent_cell=document.createElement("TD");
mycurrent_cell.align="center";
file=document.createElement("INPUT");
file.type="text";
file.name="keyDesc[]";
file.size="25";
mycurrent_cell.appendChild(file);
mycurrent_row.appendChild(mycurrent_cell);
mytablebody.appendChild(mycurrent_row);
}
Added files
The changes to the original wiki files have been kept to the minimum. Most of the added functionality is in the form of new files. The wiki extension mechanism 'Hooks' have been widely used to make the desired changes. These files are present in the svn.
TagExtension.php
The file TagExtension.php captures the functionality to add tags in the database, to view tags on every page, and to display the Tags namespace.
svn location: /swissex/trunk/tagging/src/includes/TagExtension.php
BookmarksExtension.php
The file BookmarksExtension.php enables the view for the Bookmarks namespace.
svn Location: /swissex/trunk/tagging/src/includes/BookmarksExtension.php
SpecialCreateComplex.php
This file adds functionality, as the name suggests, to create a new complex type in the wiki.
svn Location: /swissex/trunk/tagging/src/includes/SpecialCreateComplex.php
SpecialTagComplex.php
The file SpecialTagComplex.php handles the functionality to add complex tags for a given article. This file gets the 'tagging' requests from the wiki, and passes it
to the file TagExtension.php
svn Location: /swissex/trunk/tagging/src/includes/SpecialTagComplex.php
SpecialTagPreferences.php
The file SpecialTagPreferences.php handles the settings of 'tag viewing' preferences in the tagbox for each individual user.
svn Location: /swissex/trunk/tagging/src/includes/SpecialTagPreferences.php
SpecialSerachTags.php
Special page to search tags
Javascript
svn Location: /swissex/trunk/tagging/src/skins/common/
The tagging module has the following javascript modules.
Some javascript functions are also in the wikibits.js (wiki js file - location /skins/common/)
Paging.js
Paging.js creates a 'pager' in the lists view of the tags in the tagbox on every page.
validation.js
This file validates the user input (dates, email addresses etc.) in the complex tagging form.
BubbleTooltips.js
This addition creates information tooltips in the tagbox. It gives brief information of the different views in the tagbox.
sendInfo.js
This addition is an Ajax functionality for supporting the changes in Tag preferences.