var ajax = new sack();
var editMode = false;
var editDisabled = false;
var sectionEditNumber = 0;
var sectionDiv = 0;
urlTable = false;
// Called when "edit whole page" is clicked
function edit() {
// If already editing, do nothing
if( editMode ) {
alert( "You're currently editing a section. Save or cancel your current edit." );
return false;
}
// If editing disabled, do nothing
if( editDisabled ) {
alert( "Editing on this page has been disabled." );
return false;
}
ajax = new sack();
// Get wiki text from server
ajax.setVar( "page", title );
ajax.method = "POST";
ajax.requestFile = "/ajax/edit.php";
ajax.onCompletion = edit_callback;
ajax.runAJAX();
showDelayBar();
return false;
}
// Client callback function
function edit_callback() {
hideDelayBar();
// Put wikitext in textarea
var content = $( "content" );
// Hide uneditable elements
hideUneditable();
// If doc is blank or new, insert starter text
if( /^[ \r\n]*$/.test( ajax.response ) ) {
ajax.response = "| Sample heading\n\
The text in this box is editable. Edit it to create your own memorizable tables.\n\
\n\
Here's a sample table to get you started...\n\
\n\
| Sample table\n\
Country || Capital\n\
France | Paris\n\
Japan | Tokyo\n\
\n\
Click the 'preview' link (to the right) to see what your page will look like. Or click the 'save' link to save your page.\n\
";
}
// Show textarea
content.innerHTML = "\
edit this text, then click one of the links to the right:
\
\
\
Your edits won't immediately be visible to other users\
- \
See Editing for more info.\
\
";
// Show edit buttons
$("editButtons").style.display="block";
$("buttons").style.display="none";
}
// Called when "Save" is clicked
function save( sectionNumber ) {
ajax = new sack();
// Send wiki text to server
// If we want to only save a section
if( sectionNumber ) {
ajax.setVar( "sectionNumber", sectionEditNumber );
ajax.setVar( "wikitext", sectionDiv.getElementsByTagName( "textarea" )[0].value );
} else {
ajax.setVar( "wikitext", $( "editTextArea" ).value );
}
ajax.setVar( "page", title );
ajax.method = "POST";
ajax.requestFile = "/ajax/save.php";
ajax.onCompletion = save_callback;
ajax.runAJAX();
showDelayBar();
return false;
}
// Not used anymore, since we removed the 'edit whole page' > 'delete' link?
function deleteLocal() {
// Delete if they're sure
if( confirm( "Are you sure you want to delete this page? (If this page already existed, only your edits will be deleted)." ) )
deletePage();
return false;
}
// Client callback function
function save_callback() {
hideDelayBar();
// Remember we're not editing any more
editMode = false;
if( ajax.response == "Content Too Large" ) {
alert( "Your page is too large. You may want to create another page and put some of the content there, as in:\n\n| See also\n* [My New Page]" );
return;
}
// Check for too large
// Put html back
var content = $( "content" );
content.innerHTML = ajax.response;
// Show normal buttons
showNormalButtons();
// Show pencil
$( 'pageeditedlocally' ).style.display="block";
// Hide help dialog, just in case
hideHelp();
}
// Called when "cancel" is clicked
function cancel() {
ajax = new sack();
// Send wiki text to server
ajax.setVar( "page", title );
ajax.method = "POST";
ajax.requestFile = "/ajax/cancel.php";
ajax.onCompletion = cancel_callback;
ajax.runAJAX();
showDelayBar();
return false;
}
// Client callback function
function cancel_callback() {
hideDelayBar();
// Close help message at top, since onmouseout will not fire if link goes away.
hideHelp();
// Remember we're not editing any more
editMode = false;
// Put html back
var content = $( "content" );
content.innerHTML = ajax.response;
// Show normal buttons
showNormalButtons();
}
// Called when "delete" is clicked
function deletePage() {
// Send wiki text to server
ajax.setVar( "page", title + ".wik" );
ajax.method = "POST";
ajax.requestFile = "/ajax/delete.php";
ajax.onCompletion = deletePage_callback;
ajax.runAJAX();
showDelayBar();
return false;
}
// Client callback function
function deletePage_callback() {
hideDelayBar();
// Close help message at top, since onmouseout will not fire if link goes away.
hideHelp();
// Remember we're not editing any more
editMode = false;
// Put html back
var content = $( "content" );
content.innerHTML = ajax.response;
// Show normal buttons
showNormalButtons();
// Hide pencil
$( 'pageeditedlocally' ).style.display="none";
}
// Display 'create / find' dialog
function createDialog() {
// If already editing, do nothing
if( editMode ) {
alert( "You're currently editing a section. Save or cancel your current edit." );
return false;
}
// Display dialog
var dialogBox = $( "dialogBox" );
dialogBox.innerHTML =
"
\
\
Create a Page
\
Enter a page name. When you press create a new page will be created, unless a page having that name already exists (in which case you will be shown that page).\
Please use only letters, numbers, and spaces.\
\
\
Who will see your page
\
Your new page will initially only be visible by you, but will be approved and made public shortly. See Editing for more information.\
Advanced Tips
\
You can create the 2nd page for an existing subject by ending the page name with \" 2\". For example, if there is a Gardening page, you could name your new page Gardening 2 to make it the 2nd gardening page. In this example, you'll likely want to go back and add a link to Gardening 2 to the Pages section of the Gardening page. The Pages section will then automatically show up on the Gardening 2 page.\
";
// Give text field focus
$( 'newName' ).focus();
}
// Run when 'create / find' button is clicked on
function create() {
// Ask for page name
var newName = $( "newName" ).value;
// Exit if they cancelled
if( ! newName )
return false;
// Error out if they didn't use [a-z0-9 ]+
if( ! /^[a-z0-9_ ]+$/i.test( newName ) ) {
var errorDiv = $( "errorDiv" );
errorDiv.innerHTML = "You must use letters, numbers, and spaces only";
return false;
}
// Fix spaces and make title case
newName = newName.replace( /_/g, " " );
newName = newName.replace(/\b[a-z]/g, function(w){return w.toUpperCase()})
newName = newName.replace( / /g, "_" );
// Get rid of spaces at beginning, end, and multiple spaces
newName = newName.replace( /_+/g, "_" );
newName = newName.replace( /^_/g, "" );
newName = newName.replace( /_$/g, "" );
// Go to the page
window.location = "/" + newName;
return false;
}
// Called when "Save" is clicked
function preview() {
// Send wiki text to server
ajax.setVar( "wikitext", $( "editTextArea" ).value );
ajax.method = "POST";
ajax.requestFile = "/ajax/preview.php";
ajax.onCompletion = preview_callback;
ajax.runAJAX();
showDelayBar();
return false;
}
// Client callback function
function preview_callback() {
hideDelayBar();
// Disable more editing
editMode = true;
// Display dialog
var dialogBox = $( "dialogBox" );
dialogBox.innerHTML =
"
\
"
+ ajax.response
+ "
";
}
function closeDialog() {
var dialogBox = $( "dialogBox" );
dialogBox.innerHTML = "";
return false;
}
// Handles 'All Public Pages' and 'All Your Edits'
function showPages() {
page( "pages.php", giveFilterFocus );
return false;
}
function giveFilterFocus() {
$( "filterField" ).focus();
}
// Generic function to show a page
function page(name, invokeOnCallback, nearTop) {
// Remember to invoke function on callback, if passed
afterCallbackFunction = invokeOnCallback ? invokeOnCallback : null;
dialogNearTop = nearTop;
// Send wiki text to server
ajax.method = "POST";
ajax.requestFile = "/ajax/" + name;
ajax.onCompletion = page_callback;
ajax.runAJAX();
showDelayBar();
return false;
}
function page_callback() {
hideDelayBar();
// Display dialog
var dialogBox = $( "dialogBox" );
dialogBox.innerHTML =
"
\
"
+ ajax.response
+ "
";
if( afterCallbackFunction )
afterCallbackFunction();
// Exit, to stay at top
if(dialogNearTop)
return;
// Get scrolledDown
var scrolledDown = document.body.scrollTop;
if( window.pageYOffset )
scrolledDown = window.pageYOffset;
// If past header, move it down
if(scrolledDown > 130)
$("previewdialog").style.top = scrolledDown + 4;
}
// Called when 'Alert Me' link is clicked
function alertMe() {
page( "alertme.php" );
return false;
}
// Called when 'Alert Me > Submit' button is clicked
function alertMeSubmit( version ) {
var previewdialog = $( "previewdialog" );
var mailinglist = $( "mailinglist" );
var email = $("emailField").value;
var comment = $("commentsField");
var daysField = $("daysField");
// Error out if none
if( email == "" ) {
alert( "You didn't enter an email address." );
return false;
}
// Error out if invalid
if( ! /.+@..+\...+/.test( email ) ) {
alert( "Not a valid email address." );
return false;
}
// TODO 0 Save email in cookie
document.cookie = 'notify=' + email.replace( /\./g, "`" ).replace( /@/g, "~" ) + ';expires=Fri, 17 Dec 2050 10:00:00 GMT';
// If checkbox checked, add "All Updates"
if( mailinglist && mailinglist.checked )
version += ", All Updates";
// TODO get number of days, also, if it exists
var entry = "Alert me about: " + version + "\n email: " + email + "\n"
if( daysField )
entry += " days until reminder: " + daysField.value + "\n"
+ " page: /" + $("pageTitle").innerHTML.replace( / /g, "_" ) + "\n";
if( comment )
entry += " comment: " + comment.value;
// Send wiki text to server
ajax.setVar( "entry", entry );
ajax.method = "POST";
ajax.requestFile = "/ajax/userlog.php";
ajax.onCompletion = alertMeSubmit_callback;
ajax.runAJAX();
showDelayBar();
return false;
}
// Client callback function
function alertMeSubmit_callback() {
hideDelayBar();
// Display dialog
var dialogBox = $( "dialogBox" );
// If success
if( ajax.response == "success" ) {
// Close dialog
dialogBox.innerHTML = "";
// Show alert
alert( "Thank you. Your info was submitted." );
} else {
alert( ajax.response );
}
}
function showHelp( message ) {
// Display dialog
var helpBox = $( "helpBox" );
helpBox.innerHTML =
"
\
\
\
" + message + "
\
";
$( "motto" ).style.display="none";
$( "mottoShadow" ).style.display="none";
}
function showMemorizeHelp() {
showHelp( "memorize: Click this link to begin a flashcard-like process to help you memorize this table. Follow the directions that will appear at the bottom of the table." );
}
// Shows appropriate help for 'edit', depending on mode
function showEditHelp(node) {
// Div outline
Mem.parents(node, 3).className='sectionBlockActive';
// If already editing
if( editMode ) {
if( urlTable ) {
// There will be no edit links in memorizable url's
// showHelp( "edit: TODO: Make this work for url tables." );
return;
}
showHelp( "alert: You're already editing a section. Save or cancel it before editing other sections." );
return;
}
// Otherwise, show message
showHelp( "edit section: Similar to the edit whole page button, but only edits one section at a time. Don\'t worry, your edits won\'t immediately be visible to other users." );
}
function hideEditHelp(node) {
// Hide div outline
Mem.parents(node, 3).className='sectionBlock';
hideHelp();
}
function hideHelp() {
var helpBox = $( "helpBox" );
helpBox.innerHTML = "";
$( "motto" ).style.display="block";
$( "mottoShadow" ).style.display="block";
}
// Called when mouse is over h1 block
function highlightSection( div, state ) {
// If already editing a section, do nothing
if( editMode || editDisabled )
return;
//alert( "highlightSection" );
// Add edit link
var editSpan = div.getElementsByTagName('span')[0];
var editLink = div.getElementsByTagName('a')[0];
var pencil = div.getElementsByTagName('img')[0];
if( state ) {
// Make orange outline style
div.className='sectionBlockActive';
pencilBrightness( pencil, editLink, true );
// Otherwise, remove style
} else {
div.className='sectionBlock';
if( editLink.innerHTML == "edit section" )
pencilBrightness( pencil, editLink, false );
}
}
function pencilBrightness( pencil, editLink, bright ) {
if( bright ) {
brightWin = "alpha(opacity='100')";
brightMoz = 1.0;
linkColor = "#66a";
linkUnderline = "underline";
} else {
brightWin = "alpha(opacity='15')";
brightMoz = 0.15;
linkColor = "#e4e4e4";
linkUnderline = "none";
}
// If ie
if ( typeof( pencil.style.filter ) == 'string' )
pencil.style.filter = brightWin;
if( typeof( editLink.style.MozOpacity) == 'string' )
pencil.style.MozOpacity=brightMoz;
editLink.style.color = linkColor;
editLink.style.textDecoration = linkUnderline;
}
//
// Called when 'edit' link is clicked.
//
function editSection( a, sectionNumber ) {
// Close dialog, in case it's open
closeDialog();
// Remember sectionNumber for when we save
sectionEditNumber = sectionNumber;
// If already editing, do nothing
if( editMode ) {
alert( "You're already editing. Save or cancel your current edit." );
return false;
}
// If editing disabled, do nothing
if( editDisabled )
return false;
// Remember we're editing
editMode = true;
// Store sectionDiv for callback function to access it
sectionDiv = a.parentNode.parentNode.parentNode;
// Get wiki text from server
ajax.setVar( "page", title );
ajax.setVar( "sectionNumber", sectionNumber );
ajax.method = "POST";
ajax.requestFile = "/ajax/edit.php";
ajax.onCompletion = editSection_callback;
ajax.runAJAX();
showDelayBar();
return false;
}
function editSection_callback() {
hideDelayBar();
var text = ajax.response;
// Remove last \n's from text
text = text.replace(/[\r\n]+$/, "");
// Draw textarea and save/cancel
sectionDiv.innerHTML = drawSectionEditBox( text );
// Get number of lines, and adjust height of div accordingly
var linesRequired = countLines( ajax.response, 70 );
var ta = sectionDiv.getElementsByTagName('textarea')[0];
ta.style.height = linesRequired * 12;
// Add event for alt-s
addEvent2( document, "keydown", saveIfAltS );
// Give it focus
ta.focus();
}
// Counts number of lines in string, accounting for wrapping
function countLines( s, lineLength ) {
var i = -1;
var total = 1;
var lineChars = 0; // Assume at least one line
while( ++i < s.length ) {
lineChars ++;
// If a linebreak or too many chars, add to total
if( ( s.charAt( i ) == "\n".charAt(0) ) || (lineChars >= lineLength) ) {
total++;
lineChars = 0;
}
}
return total;
}
function iveGuessedOnMouseOver() {
// showHelp( "show answer: Click this button after you've guessed in your head what goes in place of guess the answer. Or, press the 1 key as a shortcut." )
}
function iWasRightOnMouseOver() {
// showHelp( "I was right: Click this button if your guess was right. It will be added to the table if it seems as though you've memorized it. Or, press the 2 key as a shortcut." )
}
function iWasWrongOnMouseOver() {
// showHelp( "I was wrong: Click this button if your guess was wrong. This row will come up again later. Or, press the 1 key as a shortcut." )
}
function iveGuessedOnMouseOut() {
hideHelp();
}
function iWasRightOnMouseOut() {
hideHelp();
}
function iWasWrongOnMouseOut() {
hideHelp();
}
// For alt-s when section editing
function saveIfAltS( keyp ) {
// Exit if not in edit mode
if( !editMode )
return;
// Figure out what was pressed, based on browser
if( navigator.appName == "Netscape" ) pressed = keyp.which;
if( navigator.appVersion.indexOf("MSIE") != -1 ) pressed = event.keyCode;
// Try, in case no table in progress
try {
// If alt-s, save
if ( keyp.altKey && pressed == "S".charCodeAt(0) )
save( sectionEditNumber );
} catch(e) {}
}
function addEvent2( obj, type, fn ) {
if ( obj.attachEvent ) {
obj['e'+type+fn] = fn;
obj[type+fn] = function() {obj['e'+type+fn]( window.event );}
obj.attachEvent( 'on'+type, obj[type+fn] );
} else
obj.addEventListener( type, fn, false );
}
// Diffs > 'approve' link
function approve( page, session ) {
ajax = new sack();
// alert(session);
ajax.setVar( "page", page );
if( session )
ajax.setVar( "session", session );
// Remember this, to use in callback
approvalPage = page;
ajax.method = "POST";
ajax.requestFile = "/ajax/approve.php";
ajax.onCompletion = approve_callback;
ajax.runAJAX();
showDelayBar();
return false;
}
// Client callback function
function approve_callback() {
hideDelayBar();
// If permission denied, show error
if( /^\s*PERMISSION_DENIED\s*$/.test( ajax.response ) ) {
page( "requestapproval.php?page=" + approvalPage.replace(/_/g, " ") );
return;
}
// Show any error
// alert( ajax.response );
// Hide pencil if we approved the page we're on
if( approvalPage == title )
$( 'pageeditedlocally' ).style.display="none";
// Refresh diffs
diffs(null, true);
}
function approvalDelete( page, session ) {
// Exit if they're not sure
if( ! session ) // if not admin
if( ! confirm( "Are you sure you want to delete this page? (If this page already existed, only your edits will be deleted)." ) )
return false;
// Remember this, to use in callback
approvalPage = page.replace(/\.wik$/, "");
// If it's not the page we're looking at, don't get a result back
if( ! approvalPage == title );
ajax.setVar( "noresult", "true" );
ajax = new sack();
ajax.setVar( "page", page );
if( session )
ajax.setVar( "session", session );
ajax.method = "POST";
ajax.requestFile = "/ajax/delete.php";
ajax.onCompletion = approvalDelete_callback;
ajax.runAJAX();
showDelayBar();
return false;
}
// Client callback function
function approvalDelete_callback() {
hideDelayBar();
// Refresh diffs
diffs(null, true);
// If we deleted the page we're on
if( approvalPage == title ) {
// Hide pencil and refresh page from disk
$( 'pageeditedlocally' ).style.display="none";
// Restore old page content
var content = $( "content" );
content.innerHTML = ajax.response;
}
}
function login() {
ajax = new sack();
// TODO pass in session, if called by admin
ajax.setVar( "username", $( "username" ).value );
ajax.setVar( "creds", $( "creds" ).value );
ajax.method = "POST";
ajax.requestFile = "/ajax/login.php";
ajax.onCompletion = login_callback;
ajax.runAJAX();
showDelayBar();
return false;
}
// Client callback function
function login_callback() {
hideDelayBar();
//alert( ajax.response );
if( ajax.response != "YES" ) {
alert( "Invalid Login" );
return;
}
alert( "Login succeeded. You may now click 'approve' on the 'Diffs' page to approve pages." );
// Refresh diffs
diffs();
}
function diffs( all, nearTop ) {
var url = 'diffs.php?current=' + title;
// If 'all' param passed, use it and remember for next time
if( all ) {
diffsAll = all;
}
// Otherwise, use last value
else {
all = diffsAll;
}
// Optionally pass all=true
if( all == "yes" )
url += '&all=true'
page(url, null, nearTop);
return false;
}
function logout() {
ajax = new sack();
ajax.requestFile = "/ajax/logout.php";
ajax.onCompletion = logout_callback;
ajax.runAJAX();
showDelayBar();
return false;
}
// Client callback function
function logout_callback() {
hideDelayBar();
// Refresh diffs
diffs();
}
function showNormalButtons() {
$("editButtons").style.display="none";
$("buttons").style.display="block";
// Show 'directions' element if appropriate
if( title != "Home" && title != "Help" && $( 'memTable' ) )
$( "directionsContainer" ).style.display="block";
// Show uneditable sections at bottom
$( "bottomUneditableSections" ).style.display="block";
}
function filterShowPages( textField ) {
var divs = $('filterouter').getElementsByTagName('div');
// For each div
for(var x=0; x= 0 )
divs[x].style.display='block';
else
divs[x].style.display='none';
}
}
function drawSectionEditBox( text ) {
return "
edit this text, then click one of the links to the right:
\
";
}
function addSection( but, sectionNumber ) {
// Close dialog, in case it's open
closeDialog();
// Remember sectionNumber for when we save
sectionEditNumber = sectionNumber;
// If already editing, do nothing
if( editMode ) {
alert( "You're already editing. Save or cancel your current edit." );
return false;
}
// Remember we're editing
editMode = true;
// Section we're editing
sectionDiv = but.parentNode;
// Draw orang border around it
sectionDiv.className='sectionBlockActive';
// Draw textarea and save/cancel
sectionDiv.innerHTML = drawSectionEditBox( "| Change this section title\n\
Edit the text in this box to contribute! Sample table:\n\n\
Paris | France\n\
Japan | Tokyo\n\
" );
var ta = sectionDiv.getElementsByTagName('textarea')[0];
ta.style.height = 100;
// Give it focus
ta.focus();
}
// Hide 'directions' element
function hideDirections() {
$( "directions" ).style.display="none";
$( "directionsClosed" ).style.display="block";
// Remember not to show it anymore
document.cookie = 'hideDirections=true;expires=Fri, 17 Dec 2050 10:00:00 GMT';
return false;
}
// Show 'directions' element
function showDirections() {
$( "directions" ).style.display="block";
$( "directionsClosed" ).style.display="none";
// Remember to show directions - expire cookie
document.cookie = 'hideDirections=false;expires=Fri, 17 Dec 2000 10:00:00 GMT';
return false;
}
function echo( s ) {
if(! s)
s = "[blank]"
// Start at 0 if first
try {prependIndex++;}
catch(e) { prependIndex = 0 }
var d = document.createElement('div');
d.appendChild(document.createTextNode( s ));
d.style.position = "absolute"; d.style.fontSize = 10; d.style.zIndex = 5;
d.style.top = prependIndex*11 + "px";
document.body.insertBefore( d, document.body.childNodes[prependIndex] );
}
function hideUneditable() {
$( "directionsContainer" ).style.display="none";
$( "bottomUneditableSections" ).style.display="none";
}
function showDelayBar() {
$( "delayBar" ).style.display = "block";
}
function hideDelayBar() {
$( "delayBar" ).style.display = "none";
}
function mem_close( table ) {
table.parentNode.className='sectionBlock';
}
function mem_finished( divs ) {
divs[0].innerHTML = "
Congratulations, you've finished. \
";
divs[1].innerHTML = "";
}
function remind(days) {
pTitle = $("pageTitle").innerHTML;
if(! pTitle)
pTitle = "Home";
page( "reminder.php?page=" + pTitle + "&days=" + days, reminderAdjustments );
return false;
}
function reminderAdjustments() {
$('closeDialogButton').innerHTML = "cancel";
}
function $(id) {
return document.getElementById(id);
}
function nextRandomTable(increment) {
// Start at 0 if first
try { randomTable = randomTable + increment; }
catch(e) { randomTable = increment; }
ajax = new sack();
ajax.requestFile = "/ajax/randomtable.php";
ajax.setVar( "randomTable", randomTable );
ajax.onCompletion = nextRandomTable_callback;
ajax.runAJAX();
return false;
}
// Client callback function
function nextRandomTable_callback() {
var t = $('memTable');
var p = t.parentNode;
// If not yet a wrapper div, create one
if(p.id != 'randomTableWrapper') {
var div = document.createElement('div');
div.id = 'randomTableWrapper';
p.replaceChild(div, t);
p = div;
}
p.innerHTML = ajax.response;
Mem.startFirst();
}