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 = "\
\ \
\ save\
\
\ cancel\
\ \
\
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.\

\ Page Name \

\

\
\

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 "
\ \
\ save\
\ cancel\
\
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(); }