MediaWiki:Gadget-wikEd.js

// \n'; if (obj.focusLine.plain != '') { obj.changed.plain = '\n' + obj.changed.plain + '\n'; }			}			else { obj.changed.plain = '\n{| class="wikitable" border="1"\n|+ ' + wikEd.config.text['table caption'] + ' \n! ' + wikEd.config.text['table heading'] + ' !! ' + wikEd.config.text['table heading'] + ' \n|-\n| ' + wikEd.config.text['table cell'] + ' || ' + wikEd.config.text['table cell'] + ' \n|-\n| ' + wikEd.config.text['table cell'] + ' || ' + wikEd.config.text['table cell'] + ' \n|}\n'; if (obj.focusLine.plain != '') { obj.changed.plain = '\n' + obj.changed.plain + '\n'; }			}			break;

// wikify: always done above case 'wikEdWikify': break;

// textify: strip html from pasted content case 'wikEdTextify': wikEd.Textify(obj.changed); if (parameters == 'shift') { highlightNoTimeOut = true; }			break;

// redirect case 'wikEdRedirect': var linkTarget; if (obj.selection.plain != '') { linkTarget = obj.selection.plain; }			else if (obj.selectionWord.plain != '') { linkTarget = obj.selectionWord.plain; }			else { linkTarget = ' ' + wikEd.config.text['redirect article link'] + ' '; }

// remove link text after | linkTarget = linkTarget.replace(/\|(.|\n)*/, '');

// remove formatting and spaces linkTarget = linkTarget.replace(/^(=+|'+|<[^>]*>|\s+|\[)+((.|\n)*?)(=+|'+|<[^>]*>|\s+|\])+$/g, '$2'); linkTarget = linkTarget.replace(/&lt;/g, '<'); linkTarget = linkTarget.replace(/&gt;/g, '>'); linkTarget = linkTarget.replace(/\s+/g, ' '); linkTarget = linkTarget.replace(/^\s+|\s+$/g, '');

obj.changed.plain = '#REDIRECT ' + linkTarget + '';

// append to summary if (wikEd.wikiGlobals.wgUseAutomaticEditSummaries != true) { if (wikEd.inputElement.summary != null) { if ( (obj.selection.plain != ) || (obj.selectionWord.plain != ) ) { wikEd.inputElement.summary.value = wikEd.inputElement.summary.value.replace(/#REDIRECT( \[\^\*\]\])?(, *)?/g, ''); wikEd.inputElement.summary.value = wikEd.AppendToSummary(wikEd.inputElement.summary.value, '#REDIRECT ' + linkTarget + ''); }					else { wikEd.inputElement.summary.value = wikEd.AppendToSummary(wikEd.inputElement.summary.value, '#REDIRECT'); }				}			}			selectChanged = false; break;

// find and replace case 'wikEdFindPrev': case 'wikEdFindNext': case 'wikEdJumpPrev': case 'wikEdJumpNext': case 'wikEdReplacePrev': case 'wikEdReplaceNext': case 'wikEdFindAll': case 'wikEdReplaceAll':

// get the find text var findText;

// unescape <, >, and & obj.changed.plain = obj.changed.plain.replace(/&lt;/g, '<'); obj.changed.plain = obj.changed.plain.replace(/&gt;/g, '>'); obj.changed.plain = obj.changed.plain.replace(/&amp;/g, '&');

// copy selection/word under cursor to find field if ( (parameters == 'shift') && ( (buttonId == 'wikEdFindNext') || (buttonId == 'wikEdReplaceNext') ) ) { if (/\n/.test(obj.changed.plain) == false) { if (buttonId == 'wikEdFindNext') { wikEd.inputElement.find.value = obj.changed.plain; }					else { wikEd.inputElement.replace.value = obj.changed.plain; }					obj.changed.keepSel = true; obj.changed.plain = null; break; }			}

// get the find text from the selection if ( (buttonId == 'wikEdJumpPrev') || (buttonId == 'wikEdJumpNext') ) { findText = obj.changed.plain; if (obj.selection.plain == '') { obj.changed.keepSel = true; obj.changed.plain = null; break; }			}

// get the find text from the find field else { if (wikEd.inputElement.find.value != '') { findText = wikEd.inputElement.find.value; }				else { obj.changed.plain = null; break; }			}

// get button status var regExpChecked = wikEd.GetAttribute(wikEd.regExp, 'checked'); var caseSensitiveChecked = wikEd.GetAttribute(wikEd.caseSensitive, 'checked');

// get the replace text var replaceText = wikEd.inputElement.replace.value;

// format the find and replace texts for a plain text search var useRegExp = true; if ( (regExpChecked == 'false') || (buttonId == 'wikEdJumpPrev') || (buttonId == 'wikEdJumpNext') ) { useRegExp = false; }

// format the replace text for a regular expression search if ( (buttonId == 'wikEdReplacePrev') || (buttonId == 'wikEdReplaceNext') || (buttonId == 'wikEdReplaceAll') ) { if (useRegExp == true) {

// substitute \\ \n \r \t \' \" \127 \x1f \u12ef					replaceText = replaceText.replace(/\\\\/g, '\x00');					replaceText = replaceText.replace(/\\n/g, '\n');					replaceText = replaceText.replace(/\\r/g, '\r');					replaceText = replaceText.replace(/\\t/g, '\t');					replaceText = replaceText.replace(/\\'/g, '\'');					replaceText = replaceText.replace(/\\"/g, '\"');

replaceText = replaceText.replace(/\\([0-7]{3})/g,						function(p, p1) {							return(String.fromCharCode(parseInt(p1, 8)));						}					); replaceText = replaceText.replace(/\\x([0-9a-fA-F]{2})/g,						function(p, p1) {							return(String.fromCharCode(parseInt(p1, 16)));						}					); replaceText = replaceText.replace(/\\u([0-9a-fA-F]{4})/g,						function(p, p1) {							return(String.fromCharCode(parseInt(p1, 16)));						}					); replaceText = replaceText.replace(/\x00/g, '\\'); }			}

// check the regexp var replacedFlag = false; var regExpFind; if (				(buttonId == 'wikEdReplacePrev') || (buttonId == 'wikEdReplaceNext') || (buttonId == 'wikEdReplaceAll') ||				(buttonId == 'wikEdFindPrev') || (buttonId == 'wikEdFindNext') || (buttonId == 'wikEdFindAll')			) { var regExpFindText = findText; if (useRegExp != true){ regExpFindText = regExpFindText.replace(/([\\^$*+?.\[\]{}:=!|,\-])/g, '\\$1'); }				var regExpFlags = 'gm'; if (caseSensitive != true) { regExpFlags += 'i'; }				try { regExpFind = new RegExp(regExpFindText, regExpFlags); }				catch (error) { return; }			}

// replace all if (buttonId == 'wikEdReplaceAll') { if (regExpFind.test(obj.changed.plain)) { obj.changed.plain = obj.changed.plain.replace(regExpFind, replaceText); replacedFlag = true; }				else { obj.changed.plain = null; }			}

// replace an existing selection else if ( (buttonId == 'wikEdReplacePrev') || (buttonId == 'wikEdReplaceNext') ) { if (regExpFind.test(obj.selection.plain)) { var replaced = obj.selection.plain.replace(regExpFind, replaceText); if (obj.changed.plain != replaced) { obj.changed.plain = replaced; replacedFlag = true; }					else { obj.changed.plain = null; }				}				else { obj.changed.plain = null; }			}

else if (				(buttonId == 'wikEdFindPrev') || (buttonId == 'wikEdFindNext') ||				(buttonId == 'wikEdJumpPrev') || (buttonId == 'wikEdJumpNext')			) { obj.changed.plain = null; }

if (				(buttonId == 'wikEdFindPrev') || (buttonId == 'wikEdFindNext') ||				(buttonId == 'wikEdJumpPrev') || (buttonId == 'wikEdJumpNext') ||				(buttonId == 'wikEdReplacePrev') || (buttonId == 'wikEdReplaceNext') ||				(buttonId == 'wikEdFindAll')			) { if (replacedFlag == false) {

// get direction var backwards = false; if ( (buttonId == 'wikEdFindPrev') || (buttonId == 'wikEdJumpPrev') || (buttonId == 'wikEdReplacePrev') ) { backwards = true; }

// get case sensitive var caseSensitive = false; if (caseSensitiveChecked == 'true') { caseSensitive = true; }

// find all if (buttonId == 'wikEdFindAll') { var found; var foundRanges = [];

// start at top of text wikEd.RemoveAllRanges(obj.sel); var range = wikEd.frameDocument.createRange; if (wikEd.frameBody.firstChild != null) { range.setStartBefore(wikEd.frameBody.firstChild); }						range.collapse(true); range = obj.sel.addRange(range);

// cycle through matches var scrollTop = wikEd.frameBody.scrollTop; do {

// wikEd.Find(obj, findText, caseSensitive, backwards, wrap, useRegExp) found = wikEd.Find(obj, findText, caseSensitive, false, false, useRegExp); if (found == true) { foundRanges.push(obj.changed.range.cloneRange); }						} while (found == true);

// scroll back if (regExpChecked == 'false') { wikEd.frameBody.scrollTop = scrollTop; }

// add the found ranges, Webkit does not support multiple selections wikEd.RemoveAllRanges(obj.sel); for (var i = 0; i < foundRanges.length; i ++) { obj.sel.addRange(foundRanges[i]); }						obj.changed.plain = null; selectChanged = false; }

// normal find else { obj.selectChanged = selectChanged; wikEd.Find(obj, findText, caseSensitive, backwards, true, useRegExp); selectChanged = obj.selectChanged; }				}			}

// escape <, >, and & if (obj.changed.plain != null) { obj.changed.plain = obj.changed.plain.replace(/&/g, '&amp;'); obj.changed.plain = obj.changed.plain.replace(//g, '&gt;'); }

// save search history to settings if ( (buttonId == 'wikEdFindPrev') || (buttonId == 'wikEdFindNext') || (buttonId == 'wikEdFindAll') ) { wikEd.AddToHistory('find'); }			if ( (buttonId == 'wikEdReplacePrev') || (buttonId == 'wikEdReplaceNext') || (buttonId == 'wikEdReplaceAll') ) { wikEd.AddToHistory('find'); wikEd.AddToHistory('replace'); }			obj.changed.keepSel = true; break;

// fixbasic: fix characters, spaces, empty lines, certain headings, needed for all fixing functions // to do: only certain changes in multiline tags: comments, tables, subst case 'wikEdFixBasic': wikEd.FixBasic(obj.changed); obj.changed.keepSel = true; break; case 'wikEdFixPunct': wikEd.FixPunct(obj.changed); obj.changed.keepSel = true; break; case 'wikEdFixMath': wikEd.FixMath(obj.changed); obj.changed.keepSel = true; break; case 'wikEdFixChem': wikEd.FixChem(obj.changed); obj.changed.keepSel = true; break; case 'wikEdFixUnicode': wikEd.FixUnicode(obj.changed); obj.changed.keepSel = true; break; case 'wikEdFixRedirect': wikEd.FixRedirectCall(obj.changed); return; case 'wikEdFixRedirectReplace': wikEd.FixRedirectReplace(obj.changed); obj.changed.keepSel = true; break; case 'wikEdFixUnits': wikEd.FixUnits(obj.changed); obj.changed.keepSel = true; break; case 'wikEdFixDashes': wikEd.FixDashes(obj.changed); obj.changed.keepSel = true; break; case 'wikEdFixHtml': wikEd.FixHTML(obj.changed); obj.changed.keepSel = true; break; case 'wikEdFixRegExTypo': if ( (wikEd.config.regExTypoFix == true) && (wikEd.typoRulesFind.length > 0) ) { wikEd.FixTypos(obj.changed); }			else { obj.changed.plain = null; }			obj.changed.keepSel = true; break; case 'wikEdFixCaps': wikEd.FixCaps(obj.changed); obj.changed.keepSel = true; break; case 'wikEdFixAll': wikEd.FixAll(obj.changed); obj.changed.keepSel = true; break;

// source on		case 'wikEdSource': obj.changed.plain = obj.changed.code; obj.changed.plain = obj.changed.plain.replace(/(<(br|p)\b.*?>)/g, '$1\n\n'); obj.changed.plain = obj.changed.plain.replace(/&/g, '&amp;'); obj.changed.plain = obj.changed.plain.replace(//g, '&gt;'); highlightSyntax = false; break;

// insert tags case 'wikEdInsertTags': var tagOpen = parameters[0] || ''; var tagClose = parameters[1] || ''; var sampleText = parameters[2] || ''; tagOpen = tagOpen.replace(/&/g, '&amp;'); tagOpen = tagOpen.replace(//g, '&gt;'); tagClose = tagClose.replace(/&/g, '&amp;'); tagClose = tagClose.replace(//g, '&gt;'); tagsampleText = sampleText.replace(/&/g, '&amp;'); tagsampleText = sampleText.replace(//g, '&gt;');

// single string to insert if ( (tagOpen.length > 0) && (tagClose.length == 0) && (sampleText.length == 0) ) { obj.changed = obj.cursor; obj.changed.plain = tagOpen; }			else if ( (tagOpen.length == 0) && (tagClose.length == 0) && (sampleText.length > 0) ) { obj.changed = obj.cursor; obj.changed.plain = sampleText; }

// opening and closing strings else if ( (obj.changed.plain == '') && (sampleText.length > 0) ) { obj.changed.plain = tagOpen + sampleText + tagClose;

// select sample text selectChangedText = sampleText; obj.changed.keepSel = true; }			else { obj.changed.plain = tagOpen + obj.changed.plain + tagClose; }			break;

// convert wiki tables to html // case 'wikEdTablify': obj.changed.keepSel = true; if (wikEd.tableMode == true) { wikEd.WikiTableToHtml(obj.changed); }			break;

// update text view using current control button settings // case 'wikEdUpdateAll': obj.changed.keepSel = true; if (parameters != null) { if (parameters.keepSel == false) { obj.changed.keepSel = false; }			}			break;

// custom edit functions default: if (CustomHandler != null) { CustomHandler(obj); }			else { alert('Unknown edit function \ + buttonId + '\); }			break; }

// pause frame spellchecking var pauseFrameSpellchecking = false; var frameSpellchecking = wikEd.frameBody.spellcheck; if (frameSpellchecking == true) { var wholeLength = 0; var changedLength = 0; if (obj.whole != null) { if (obj.whole.plain != null) { wholeLength = obj.whole.plain.length; }		}		if (obj.changed.plain != null) { changedLength = obj.changed.plain.length; }		if ( (changedLength > 10000) || (wholeLength > 10000) ) { pauseFrameSpellchecking = true; wikEd.frameBody.spellcheck = false; }	}

// get the scroll position var frameScrollTop = wikEd.frameBody.scrollTop; var frameScrollLeft = wikEd.frameBody.scrollLeft;

// update the selection ranges, do not add any text changes if (obj.changed.plain == null) { if (buttonId != 'wikEdFindAll') { wikEd.RemoveAllRanges(obj.sel); obj.sel.addRange(obj.changed.range);

// scroll the selected text into the viewport if (selectChanged != false) { wikEd.ScrollToSelection; }		}	}

// apply text changes else {

// a text change erases the last version for redo all if ( (buttonId != 'wikEdUndo') && (buttonId != 'wikEdRedo') && (buttonId != 'wikEdUndoAll') ) { wikEd.lastVersion = null; }

// highlight the syntax obj.html = obj.changed.plain; if (highlightSyntax == true) { if (obj.changed.from == 'whole') { obj.whole = true; }			wikEd.HighlightSyntax(obj, highlightNoTimeOut); }

// at least highlight tab characters else { obj.html = obj.html.replace(/(\t)/g, ' $1 '); }

// display multiple blanks as blank- obj.html = obj.html.replace(/(^|\n) /g, '$1 '); obj.html = obj.html.replace(/ (\n|$)/g, ' $1'); obj.html = obj.html.replace(/ {2}/g, ' '); obj.html = obj.html.replace(/ {2}/g, ' ');

// newlines to 		obj.html = obj.html.replace(/\n/g, ' ');

// make changed range text the current selection wikEd.RemoveAllRanges(obj.sel); var range = obj.changed.range; obj.sel.addRange(range);

// replace the selection with changed text // Opera 9.50beta bug: inserthtml removes blanks and generates consecutive text nodes if (obj.html != '') { var reselectBefore = ''; var reselectAfter = ''; if (obj.changed.from != 'whole') { wikEd.insertCounter ++; reselectBefore = ' '; reselectAfter = ' '; }			wikEd.FrameExecCommand('inserthtml', reselectBefore + obj.html + reselectAfter); }		else if (obj.sel.isCollapsed == false) { wikEd.FrameExecCommand('delete'); }

// select the whole text after replacing the whole text and scroll to same height if (obj.changed.from == 'whole') { wikEd.RemoveAllRanges(obj.sel); var range = wikEd.frameDocument.createRange; range.setStartBefore(wikEd.frameBody.firstChild); range.setEndAfter(wikEd.frameBody.lastChild); obj.sel.addRange(range); selectChanged = false;

// scheduling needed for Firefox 9.0.1 setTimeout( function { wikEd.frameBody.scrollTop = frameScrollTop; }, 0); }

// select the changed text and scroll it into the viewport else if (selectChanged != false) { wikEd.RemoveAllRanges(obj.sel); var range = wikEd.frameDocument.createRange; var startNodeReselect = wikEd.frameDocument.getElementById('wikEdScrollBefore' + wikEd.insertCounter); var endNodeReselect = wikEd.frameDocument.getElementById('wikEdScrollAfter' + wikEd.insertCounter); range.setStartAfter(startNodeReselect); // should be range.setEndAfter, but that causes caret at start of next line due to https://bugzilla.mozilla.org/show_bug.cgi?id=587461 range.setEndAfter(endNodeReselect); obj.sel.addRange(range); wikEd.ScrollToNodes(startNodeReselect, endNodeReselect); }	}

// remove selection, keep whole text auto-selection as warning if (		( (obj.changed.keepSel != true) && (obj.changed.from != 'whole') ) ||		(obj.changed.keepSel == false) ||		(buttonId == 'wikEdRedirect') ||		( (buttonId == 'wikEdWikify') && (parameters == 'whole') )	) { if (obj.sel.rangeCount == 0) { obj.sel.collapse(wikEd.frameBody, 0); }		else { obj.sel.collapseToEnd; }

// focus edit area to continue editing as there is no selection that would be overwritten wikEd.frameWindow.focus; }

// reset button to active, reset cursor if (buttonObj != null) { if (buttonObj.className != 'wikEdButtonInactive') { buttonObj.className = 'wikEdButton'; }		buttonObj.style.cursor = 'auto'; }

// grey out inactive buttons wikEd.InactiveButtons;

// add event handlers to unhide refs and templates if ( (highlightSyntax == true) && (obj.changed.plain != null) ) {

// add ref and template names to hide buttons wikEd.HighlightNamedHideButtons;

// add event handlers to unhide refs and templates wikEd.HideAddHandlers;

// add event handlers to make highlighted frame links ctrl-clickable wikEd.LinkifyAddHandlers; }

// resume frame spellchecking if (pauseFrameSpellchecking == true) { wikEd.frameBody.spellcheck = true; }

return; };

// // wikEd.LocalPreviewAjaxHandler: process the returned article preview //

wikEd.LocalPreviewAjaxHandler = function(ajax) {

wikEd.previewIsAjax = true;

// get response var html = ajax.responseText;

// livepreview if (html.indexOf(' ') != -1) { html = html.replace(/\s*<\/livepreview>\s*/, ''); html = html.replace(/\s*<\/preview>\s*/, ''); html = html.replace(/&lt;/g, '<'); html = html.replace(/&gt;/g, '>'); html = html.replace(/&quot;/g, '"');		html = html.replace(/&apos;/g, '\);		html = html.replace(/&amp;/g, '&');		html = html.replace(/(.|\n)*(.|\n)*?<\/div>/, );	}

// full preview page else {

// attach stylesheet declarations to document (GeSHi) var regExpMatch; var regExp = /]*?type="text\/css">((.|\n)*?)<\/style>/gi; while ( (regExpMatch = regExp.exec(html)) != null) { var css = regExpMatch[2]; var stylesheet = new wikEd.StyleSheet(document); stylesheet.AddCSSRules(css); }

// get preview html html = wikEd.StringGetInnerHTML(html, 'div', 'id', 'wikiPreview', true); html = wikEd.StringGetInnerHTML(html, 'div', 'class', 'previewnote', true, false, true); html = html.replace(//g, ''); html = html.replace(/\s+$/g, ''); }

// clean form elements html = html.replace(/<\/?form\b[^>]*>/g, ''); html = html.replace(/(<\/?input\b[^>]*?)\bname="search"([^>]*>)/g, '$1$2');

// remove cite errors for automatic section preview refs html = html.replace(/(]*?\bclass="wikEdPreviewRefs"[^>]*>(.|\s)*$)/,		function (p, p1, p2) {			p1 = p1.replace(/]*?\bclass="error"[^>]*>(.|\s)*?<\/strong>/g, '');			return(p1);		}	); wikEd.previewBox.innerHTML = html;

// init sortable tables (wikibits.js) if (typeof(sortables_init) == 'function') { sortables_init; }

// init collapsible tables (common.js) if (typeof(createCollapseButtons) == 'function') { createCollapseButtons; }

// scroll to button, textarea, or preview field wikEd.ScrollToPreview;

// run scheduled custom functions wikEd.ExecuteHook(wikEd.config.previewHook);

return; };

// // wikEd.FilePreviewAjaxHandler: process the returned image addresses //

wikEd.FilePreviewAjaxHandler = function(ajax) {

// get response var html = ajax.responseText;

// html-ize html = html.replace(/\s*<\/preview>\s*/, ''); html = html.replace(/\s*<\/livepreview>\s*/, ''); html = html.replace(/&lt;/g, '<'); html = html.replace(/&gt;/g, '>'); html = html.replace(/&amp;/g, '&'); html = html.replace(/&quot;/g, '"');	html = html.replace(/&apos;/g, '\'');	html = html.replace(/<\/?(br|p)\b.*?>/g, '\n');

// parse response into file url cache var regExpFile = new RegExp('\\n((Image|File|' + wikEd.config.text['wikicode Image'] + '|' + wikEd.config.text['wikicode File'] + '):[^ ]+) +(\\d+) +(.*)', 'ig'); var regExpMatch; while ( (regExpMatch = regExpFile.exec(html)) != null) { var file = regExpMatch[1]; var filePreviewSize = regExpMatch[3]; var links = regExpMatch[4]; var fileObj = {}; var regExpMatch; if ( (regExpMatch = /\bsrc="(.+?)"/.exec(links)) != null) { fileObj.url = regExpMatch[1]; if ( (regExpMatch = /\bwidth="(\d+)"/.exec(links)) != null) { fileObj.width = parseInt(regExpMatch[1]); }			if ( (regExpMatch = /\bheight="(\d+)"/.exec(links)) != null) { fileObj.height = parseInt(regExpMatch[1]); }		}		else { fileObj.url = wikEd.config.image['noFile']; fileObj.width = 16; fileObj.height = 16; }		wikEd.filePreviewCache['wikEd' + file + filePreviewSize] = fileObj; }

// cycle through file preview spans and add missing images as background for (var i = 0; i < wikEd.filePreviewNo; i ++) { if (wikEd.filePreviewIds[i] != '') { var span = wikEd.frameDocument.getElementById('wikEdFilePreview' + i); var fileNameSize = wikEd.filePreviewIds[i]; var fileObj = wikEd.filePreviewCache['wikEd' + fileNameSize]; if (fileObj != null) { span.style.backgroundImage = 'url(' + fileObj.url + ')'; if (fileObj.height != null) { span.style.height = fileObj.height + 'px'; }				if (fileObj.width != null) { span.style.width = fileObj.width + 'px'; }				span.style.display = 'block'; }			wikEd.filePreviewIds[i] = ''; }	}

return; };

// // wikEd.DiffResponse: calculate and linkify the diff between two versions (code copied to wikEdDiff.js) //

wikEd.DiffResponse = function(oldVersion, newVersion) {

// add trailing newline if (oldVersion.substr(oldVersion.length - 1, 1) != '\n') { oldVersion += '\n'; }	if (newVersion.substr(newVersion.length - 1, 1) != '\n') { newVersion += '\n'; }

// call external diff program var diffText = WDiffString(oldVersion, newVersion); if (wikEd.config.fullDiff != true) { diffText = WDiffShortenOutput(diffText); }

// linkify blockwise with breaks at delete and block move tags var diffTextLinkified = ''; var regExp = /]+?\bclass="wDiffHtml(Delete|Block)"[^>]*>/g; var regExpMatch; var pos = 0; while ( (regExpMatch = regExp.exec(diffText)) != null) { diffTextLinkified += wikEd.DiffLinkify(diffText.substring(pos, regExpMatch.index)) + regExpMatch[0]; pos = regExp.lastIndex; }	diffTextLinkified += wikEd.DiffLinkify(diffText.substr(pos));

return(diffTextLinkified); };

// // wikEd.DiffLinkify: linkify external links and wikilinks in diffed text as  anchor elements (code copied to wikEdDiff.js) //

wikEd.DiffLinkify = function(html) {

// &lt; &gt; to \x00 \x01 html = html.replace(/&lt;/g, '\x00'); html = html.replace(/&gt;/g, '\x01');

// split into valid html tags and plain text fragments var linkified = ''; var regExp = /(<[^<>]*>)|([^<>]+|<|>)/g; while ( (regExpMatch = regExp.exec(html)) != null) { var tag = regExpMatch[1] || ''; var plain = regExpMatch[2] || '';

// process tags if (tag != '') { linkified += tag; }

// process plain tags else {

// escape bogus plain = plain.replace(/>/g, '&gt;'); plain = plain.replace(/]|<[^>]*>)+?(?=([!".,:;‘-•]*\s|[\x00-\x20\s"\[\]\x7f|{}]|$))/gi,				function (p) {					var whole = p;

var title = whole; title = title.replace(/\x00!--.*?--\x01/g, ''); title = title.replace(/.*--\x01|\x00!--.*/g, ''); title = title.replace(/<.*?>/g, ''); title = title.replace(/^.*>|<.*$/g, ''); title = title.replace(/^\s+|\s+$/g, ''); title = decodeURI(title);

var url = title; url = encodeURI(url); url = url.replace(/ /g, '%20'); url = url.replace(/"/g, '%22');					url = url.replace(/'/g, '%27');					url = url.replace(/#/g, '%23');

var linkTitle = title.replace(/"/g, '&quot;');

// linkify all url text fragments between highlighting s seperately var anchorOpen = ''; var anchorClose = ''; whole = whole.replace(/(<[^>]*>)/g, anchorClose + '$1' + anchorOpen); return(anchorOpen + whole + anchorClose); }			);

// linkify links and templates if ( (wikEd.wikiGlobals.wgServer != null) && (wikEd.wikiGlobals.wgArticlePath != null) ) {

//                    1  text       3   1 4 {{ 5title        56                6 4 plain = plain.replace(/(\[\[([^|\[\]{}\n]+)(\|[^\[\]{}<>]*)?\]\])|(\{\{([^|\[\]{}\n]*)([^\[\]{}<>]*\}\})?)/g,				function (p, p1, p2, p3, p4, p5, p6) {						var articleName = p2 || ;						var templateName = p5 || ;						var whole = p;

// extract title var title = articleName; if (title == '') { title = templateName; }						title = title.replace(/\x00!--.*?--\x01/g, ''); title = title.replace(/.*--\x01|\x00!--.*/g, ''); title = title.replace(/<.*?>/g, ''); title = title.replace(/^.*>|<.*$/g, ''); title = title.replace(/^\s+|\s+$/g, '');

// /subpage refers to a subpage of the current page, to a section of the current page if ( (title.indexOf('/') == 0) || (title.indexOf('#') == 0) ) { title = wikEd.pageName + title; }

// create url var url = title.replace(/\s/g, '_'); url = encodeURI(url); url = url.replace(/"/g, '%22');						url = url.replace(/'/g, '%27');						url = url.replace(/#/g, '%23');						var articleTitle = title.replace(/"/g, '&quot;'); if (templateName != '') { if (/:/.test(title) == false) { url = 'Template:' + url; articleTitle = 'Template:' + articleTitle; }						}						url = wikEd.wikiGlobals.wgServer + wikEd.wikiGlobals.wgArticlePath.replace(/\$1/, url);

// linkify all text fragments between highlighting s seperately var anchorOpen = ''; var anchorClose = '</a>'; whole = whole.replace(/(<[^>]*>)/g, anchorClose + '$1' + anchorOpen); return(anchorOpen + whole + anchorClose); }				);			}			linkified += plain;		}	}

// \x00 and \x01 back to &lt; and &gt; linkified = linkified.replace(/\x00/g, '&lt;'); linkified = linkified.replace(/\x01/g, '&gt;');

return(linkified); };

// // wikEd.StringGetInnerHTML: get innerHTML of element from html in a string; can also get text before or after node //

wikEd.StringGetInnerHTML = function(html, tag, attrib, value, defaultToWholeHTML, getBeforeHTML, getAfterHTML) {

var startPos; var startLength; var endPos; var endLength; var level = 0; var string = ''; var regExpMatch;

var attribValue = ''; if (attrib != '') { attribValue = '[^>]*?' + attrib + '\\s*=\\s*("|\\\')?' + value + '\\1';	}	var regExpStart = new RegExp('<' + tag + '\\b' + attribValue + '[^>]*>', 'gi');	if ( (regExpMatch = regExpStart.exec(html)) != null) {		startPos = regExpMatch.index;		startLength = regExpMatch[0].length;		var regExpParse = new RegExp('<(\\/?)' + tag + '\\b.*?>', 'g');		regExpParse.lastIndex = startPos;		while ( (regExpMatch = regExpParse.exec(html)) != null) {			var p1 = regExpMatch[1] || ;			if (p1 == ) {				level ++;			}			else {				level --;				if (level == 0) {					endPos = regExpMatch.index;					endLength = regExpMatch[0].length;					break;				}			}		}	}

// return whole html if node does not exist if (endPos == null) { if (defaultToWholeHTML == true) { string = html; }	}

// return text before node else if (getBeforeHTML == true) { string = html.substr(0, startPos); }

// return text after node else if (getAfterHTML == true) { string = html.substr(endPos + endLength); }

// return innerHTML of node else { string = html.substring(startPos + startLength, endPos); }

return(string); };

// // wikEd.ScrollToPreview: scroll to edit buttons, textarea, or preview field depending on current position //

wikEd.ScrollToPreview = function {

// reset fixed height to auto wikEd.previewBox.style.height = 'auto';

var scrollOffset = window.pageYOffset || document.body.scrollTop; var inputOffset = wikEd.GetOffsetTop(wikEd.inputWrapper); var editOffset = wikEd.GetOffsetTop(wikEd.editWrapper); var submitOffset = 0; if (wikEd.saveButton != null) { submitOffset = wikEd.GetOffsetTop(wikEd.saveButton); }	else if (wikEd.previewButton != null) { submitOffset = wikEd.GetOffsetTop(wikEd.previewButton); }	else if (wikEd.diffPreviewButton != null) { submitOffset = wikEd.GetOffsetTop(wikEd.diffPreviewButton); }	var editHeight = wikEd.editWrapper.clientHeight;

if (scrollOffset > submitOffset) { window.scroll(0, submitOffset); }	else if (scrollOffset > (editHeight / 2 + editOffset) ) { window.scroll(0, submitOffset); }	else if (scrollOffset > editOffset) { window.scroll(0, editOffset); }	else { window.scroll(0, inputOffset); }	return; };

// // wikEd.LinkifyAddHandlers: register click handlers to make highlighted frame links ctrl-clickable (linkify) //

wikEd.LinkifyAddHandlers = function {

if (wikEd.config.linkify != true) { return; }

// much faster than individual getElementById in SeaMonkey 1.1.18 var spans = wikEd.frameDocument.getElementsByTagName('span'); for (var i = 0; i < spans.length; i ++) { var spanId = spans[i].id; if (spanId != null) { if (spanId.indexOf('wikEdLinkify') == 0) { wikEd.AddEventListener(spans[i], 'click', wikEd.LinkifyHandler, true); }		}	}	return; };

// // wikEd.HighlightNamedHideButtons: register :before text for named hiding buttons //

wikEd.HighlightNamedHideButtons = function {

if (wikEd.refHide != true) { return; }

var rules = '';

// references for (var i = 0; i < wikEd.referenceArray.length; i ++) { if (wikEd.referenceArray[i].added == true) { continue; }		rules += '.wikEdRefButton' + i + ' { border: 1px solid; border-color: #e8e8e8 #444 #444 #e8e8e8; background: #d8d4d0; }\n';

rules += '.wikEdRefButtonShow' + i + ' { border: 1px solid; border-color: #000 #e8e8e8 #e8e8e8 #000; background: #c8c4c0; }\n';

rules += '.wikEdRefButton' + i + ':before, .wikEdRefButtonShow' + i + ':before { content: "' + wikEd.config.text.hideRef + ' ' + wikEd.referenceArray[i].text + '"; line-height: 0.75em; font-size: 65%; color: #000; font-family: sans-serif; }\n';

wikEd.referenceArray[i].added = true; }

// templates for (var i = 0; i < wikEd.templateArray.length; i ++) { if (wikEd.templateArray[i].added == true) { continue; }		rules += '.wikEdTemplButton' + i + ' { border: 1px solid; border-color: #e8e8e8 #444 #444 #e8e8e8; background: #d8d4d0; }\n';

rules += '.wikEdTemplButtonShow' + i + ' { border: 1px solid; border-color: #000 #e8e8e8 #e8e8e8 #000; background: #c8c4c0; }\n';

rules += '.wikEdTemplButton' + i + ':before, .wikEdTemplButtonShow' + i + ':before { content: "' + wikEd.config.text.hideTempl + ' ' + wikEd.templateArray[i].text + '"; line-height: 0.75em; font-size: 65%; color: #000; font-family: sans-serif; }\n';

wikEd.templateArray[i].added = true; }

// character entities for (var i = 0; i < wikEd.charEntityArray.length; i ++) { if (wikEd.charEntityArray[i].added == true) { continue; }		var character = wikEd.charEntityArray[i].text; if (character == '"') {			character = '\\' + character;		}		rules += '.wikEdCharEntityButton' + i + ' { border: 1px solid; border-color: #e8e8e8 #444 #444 #e8e8e8; background: #d8d4d0; border-color: rgba(255, 255, 255, 0.75) rgba(64, 64, 64, 0.5)  rgba(64, 64, 64, 0.5) rgba(255, 255, 255, 0.75); background: rgba(192, 192, 192, 0.3); }\n';

rules += '.wikEdCharEntityButtonShow' + i + ' { border: 1px solid; border-color: #000 #e8e8e8 #e8e8e8 #000; background: #c8c4c0; border-color: rgba(64, 64, 64, 0.5) rgba(255, 255, 255, 0.75) rgba(255, 255, 255, 0.75) rgba(64, 64, 64, 0.5); background: rgba(192, 192, 192, 0.3); }\n';

rules += '.wikEdCharEntityButton' + i + ':before, .wikEdCharEntityButtonShow' + i + ':before { content: "' + character + '"; }\n';

wikEd.charEntityArray[i].added = true; }

// add or replace existing css rules if (rules != '') { wikEd.HighlightNamedHideButtonsStylesheet.AddCSSRules(rules); }	return; };

// // wikEd.HideAddHandlers: register mouseover handlers for tabs to unhide refs, templates, and character entities //

wikEd.HideAddHandlers = function {

if ( (wikEd.config.hideContent != true) || (wikEd.refHide != true) ) { return; }	var hideButton = wikEd.frameDocument.getElementsByTagName('button'); for (var i = 0; i < hideButton.length; i ++) { var tabClass = hideButton[i].className; if (			(tabClass.indexOf('wikEdRefButton') == 0) ||			(tabClass.indexOf('wikEdTemplButton') == 0) ||			(tabClass.indexOf('wikEdCharEntityButton') == 0)		) { wikEd.AddEventListener(hideButton[i], 'click', wikEd.HideShowHandler, true); if (				(tabClass.indexOf('wikEdRefButtonShow') == -1) &&				(tabClass.indexOf('wikEdTemplButtonShow') == -1) &&				(tabClass.indexOf('wikEdCharEntityButtonShow') == -1)			) { wikEd.AddEventListener(hideButton[i], 'mouseover', wikEd.HideShowHandler, true); }		}	}	return; };

// // wikEd.HideShowHandler: display hidden ref or template on mouse over hide tab //

wikEd.HideShowHandler = function(event) {

// event compatibility fixes event = wikEd.EventWrapper(event, this); if (event == null) { return; }	event.preventDefault;

// find hidden content node var hideTarget; var hideInto; var hideButtonClass; var hideClass; var hideButton; var hideContainer; var hide; if ( (event.type == 'mouseover') || (event.type == 'mouseout') || (event.type == 'click') ) { hideTarget = event.currentTarget; hideInto = event.safeRelatedTarget;

//    text

// target == button if (/^wikEd(Ref|Templ|CharEntity)Button(Show)?\d*$/.test(hideTarget.className) == true) { hideButton = hideTarget; hideContainer = hideButton.parentNode; if (hideContainer != null) { if (/^wikEd(Ref|Templ|CharEntity)Container$/.test(hideContainer.className) == false) { hideContainer = null; }				else {

// get hide text hide = wikEd.GetNextSiblingNode(hideContainer); if (hide != null) { if (/^wikEd(Ref|Templ|TemplNs|CharEntity)(Show)?$/.test(hide.className) == false) { hide = null; }					}				}			}		}

// target == hide text else if (/^wikEd(Ref|Templ|TemplNs|CharEntity)(Show)?$/.test(hideTarget.className) == true) {

hide = hideTarget; hideContainer = wikEd.GetPreviousSiblingNode(hideTarget); if (hideContainer != null) { if (/^wikEd(Ref|Templ|CharEntity)Container$/.test(hideContainer.className) == false) { hideContainer = null; }				else {

// get button hideButton = wikEd.GetFirstChildNode(hideContainer); if (hideButton != null) { if (/^wikEd(Ref|Templ|CharEntity)Button(Show)?\d*$/.test(hideButton.className) == false) { hideButton = null; }					}				}			}		}

if ( (hideContainer == null) || (hideButton == null) || (hide == null) ) { return; }

// get classes hideButtonClass = hideButton.className; hideClass = hide.className; }

// schedule unhide on later shift or ctrl key push if (event.type == 'mouseover') { if (wikEd.config.unhideShift == true) { if ( (event.type == 'mouseover') && (wikEd.config.unhideShift == true) && (event.shiftKey == false) && (event.ctrlKey == false) ) { wikEd.scheduledUnhide = [hide, hideButton]; wikEd.AddEventListener(wikEd.frameDocument, 'keydown', wikEd.HideShowHandler, true); wikEd.AddEventListener(hideButton, 'mouseout', wikEd.HideShowHandler, true); return; }		}	}

// scheduled unhide on shift or ctrl keydown if (event.type == 'keydown') { if ( (wikEd.scheduledUnhide != null) && ( (event.shiftKey == true) || (event.ctrlKey == true) ) ) { hide = wikEd.scheduledUnhide[0]; hideButton = wikEd.scheduledUnhide[1]; hideButtonClass = hideButton.className; hideClass = hide.className; }	}

// open on hover if ( (event.type == 'mouseover') || ( (event.type == 'keydown') && (wikEd.scheduledUnhide != null) ) ) {

hideClass = hideClass.replace(/Show/, '') + 'Show'; hide.className = hideClass;

wikEd.RemoveEventListener(hideButton, 'mouseover', wikEd.HideShowHandler, true); wikEd.AddEventListener(hide, 'mouseout', wikEd.HideShowHandler, true); wikEd.AddEventListener(hideButton, 'mouseout', wikEd.HideShowHandler, true); }

// close after hover else if (event.type == 'mouseout') { if ( (hideInto != hideContainer) && (hideInto != hideButton) && (hideInto != hide) ) { if (/^wikEd(Ref|Templ|CharEntity)Button\d*$/.test(hideButton.className) == true) { var hideOut = false; var node = hideInto; while (node != null) { if (node == wikEd.frameBody) { hideOut = true; break; }					if ( (node == hideContainer) || (node == hide) ) { break; }					node = node.parentNode; }				if (hideOut == true) {

hideClass = hideClass.replace(/Show/, ''); hide.className = hideClass;

wikEd.RemoveEventListener(hide, 'mouseout', wikEd.HideShowHandler, true); wikEd.RemoveEventListener(hideButton, 'mouseout', wikEd.HideShowHandler, true); wikEd.AddEventListener(hideButton, 'mouseover', wikEd.HideShowHandler, true);

// move cursor out of hidden text wikEd.UnhideCursor(hideContainer, hide); }			}		}	}

// hide on click else if (event.type == 'click') { if (/^wikEd(Ref|Templ|CharEntity)ButtonShow\d*$/.test(hideButtonClass) == true) {

hideClass = hideClass.replace(/Show/, ''); hide.className = hideClass;

hideButtonClass = hideButtonClass.replace(/Show/, ''); hideButton.className = hideButtonClass; hideButton.title = wikEd.config.text[hideButtonClass.replace(/\d+$/g, '') + 'Tooltip'];

wikEd.AddEventListener(hideButton, 'mouseover', wikEd.HideShowHandler, true);

// move cursor out of hidden text wikEd.UnhideCursor(hideContainer, hide); }

// open on click else if (/^wikEd(Ref|Templ|CharEntity)Button\d*$/.test(hideButtonClass) == true) {

hideClass = hideClass.replace(/Show/, '') + 'Show'; hide.className = hideClass;

hideButtonClass = hideButtonClass.replace(/Button(Show)?/, 'ButtonShow'); hideButton.className = hideButtonClass; hideButton.title = wikEd.config.text[hideButtonClass.replace(/\d+$/g, '') + 'Tooltip'];

wikEd.RemoveEventListener(hideButton, 'mouseover', wikEd.HideShowHandler, true); wikEd.RemoveEventListener(hide, 'mouseout', wikEd.HideShowHandler, true); wikEd.RemoveEventListener(hideButton, 'mouseout', wikEd.HideShowHandler, true); }	}

// clear scheduled unhide if (wikEd.scheduledUnhide != null) { wikEd.RemoveEventListener(wikEd.frameDocument, 'keydown', wikEd.HideShowHandler, true); wikEd.scheduledUnhide = null; }

return; };

// // wikEd.UnhideCursor: move cursor out of hidden element for wikEd.HideShowHandler //

wikEd.UnhideCursor = function(firstHiddenParent, lastHiddenParent) {

// get selection and clone range var sel = wikEd.GetSelection; var range = sel.getRangeAt(sel.rangeCount - 1); if (range != null) {

// check if selected text is hidden var startHidden = false; var node = range.startContainer; while (node != null) { if (node == wikEd.frameBody) { break; }			if ( (node == lastHiddenParent) || (node == firstHiddenParent) ) { startHidden = true; break; }			node = node.parentNode; }		var endHidden = false; var node = range.endContainer; while (node != null) { if (node == wikEd.frameBody) { break; }			if ( (node == lastHiddenParent) || (node == firstHiddenParent) ) { endHidden = true; break; }			node = node.parentNode; }

// unselect hidden text if ( (startHidden == false) && (endHidden == true) ) { range.setEndBefore(firstHiddenParent); }		else if ( (startHidden == true) && (endHidden == false) ) { range.setStartAfter(lastHiddenParent); }		else if ( (startHidden == true) && (endHidden == true) ) { range.setEndAfter(lastHiddenParent); range.collapse(false); }	}	return; };

// // wikEd.GetText: get the text fragments to manipulate //

wikEd.GetText = function(obj, whichFragment, wikify) {

// remove dynamically inserted nodes by other scripts wikEd.CleanNodes(wikEd.frameDocument);

// get selection object if (obj.sel == null) { obj.sel = wikEd.GetSelection; }

// cursor for the cursor position (always done) if (obj.cursor == null) { obj.cursor = { 'from': 'cursor', 'keepSel': null, 'plain': '' };

// set cursor range obj.cursor.range = wikEd.frameDocument.createRange; wikEd.SetRangeStart(obj.cursor.range, obj.sel.focusNode, obj.sel.focusOffset); obj.cursor.range.collapse(true); }

// whole for the whole text if (obj.whole == null) { if (/whole|selectionWord|selectionLine|selectionPara|focusWord|focusLine|focusPara/.test(whichFragment) == true) { obj.whole = { 'plainArray': [], 'plainNode': [], 'plainStart': [], 'from': 'whole', 'keepSel': null };

// set whole range obj.whole.range = wikEd.frameDocument.createRange; obj.whole.range.setStart(wikEd.frameBody, 0); obj.whole.range.setEnd(wikEd.frameBody, wikEd.frameBody.childNodes.length);

// get whole plain text wikEd.GetInnerHTML(obj.whole, wikEd.frameBody); obj.whole.code = obj.whole.html; wikEd.RemoveHighlightingWikify(obj.whole, wikify); obj.whole.plain = obj.whole.html; obj.whole.plain = obj.whole.plain.replace(/[\n ]*<br\b[^>]*>[\n ]*/g, '\n'); obj.whole.plain = obj.whole.plain.replace(/\xa0/g, ' '); }	}

// selection for the selected text if (obj.selection == null) { if (/selection\b|selectionWord|selectionLine|selectionPara/.test(whichFragment) == true) { obj.selection = { 'from': 'selection', 'keepSel': null };

// copy range to document fragment if (obj.sel.rangeCount == 0) { obj.sel.collapse(wikEd.frameBody, 0); }			obj.selection.range = obj.sel.getRangeAt(obj.sel.rangeCount - 1); var documentFragment = obj.selection.range.cloneContents;

// get selected text wikEd.GetInnerHTML(obj.selection, documentFragment); obj.selection.code = obj.selection.html; wikEd.RemoveHighlightingWikify(obj.selection, wikify); obj.selection.plain = obj.selection.html; obj.selection.plain = obj.selection.plain.replace(/[\n ]*<br\b[^>]*>[\n ]*/g, '\n'); obj.selection.plain = obj.selection.plain.replace(/\xa0/g, ' '); }	}

// focusWord, focusLine, and focusPara for the word, line, and paragraph under the cursor if (obj.focusWord == null) { if (/focusWord|focusLine|focusPara/.test(whichFragment) == true) { obj.focusWord = { 'from': 'focusWord', 'keepSel': false, 'range': wikEd.frameDocument.createRange, 'tableEdit': obj.tableEdit };

// setup focusLine object for the line under the cursor obj.focusLine = { 'from': 'focusLine', 'keepSel': false, 'range': wikEd.frameDocument.createRange, 'tableEdit': obj.tableEdit };

// setup focusPara object for the paragraph under the cursor obj.focusPara = { 'from': 'focusPara', 'keepSel': false, 'range': wikEd.frameDocument.createRange, 'tableEdit': obj.tableEdit };

// find the word and line boundaries wikEd.FindBoundaries(obj.focusWord, obj.focusLine, obj.focusPara, obj.whole, obj.cursor);

// get the wikified plain text for the word under the cursor var documentFragment = obj.focusWord.range.cloneContents; wikEd.GetInnerHTML(obj.focusWord, documentFragment); obj.focusWord.code = obj.focusWord.html; wikEd.RemoveHighlightingWikify(obj.focusWord, wikify); obj.focusWord.plain = obj.focusWord.html; obj.focusWord.plain = obj.focusWord.plain.replace(/[\n ]*<br\b[^>]*>[\n ]*/g, '\n'); obj.focusWord.plain = obj.focusWord.plain.replace(/\xa0/g, ' ');

// get the wikified plain text for the line under the cursor var documentFragment = obj.focusLine.range.cloneContents; wikEd.GetInnerHTML(obj.focusLine, documentFragment); obj.focusLine.code = obj.focusLine.html; wikEd.RemoveHighlightingWikify(obj.focusLine, wikify); obj.focusLine.plain = obj.focusLine.html; obj.focusLine.plain = obj.focusLine.plain.replace(/[\n ]*<br\b[^>]*>[\n ]*/g, '\n'); obj.focusLine.plain = obj.focusLine.plain.replace(/\xa0/g, ' ');

// get the wikified plain text for the paragraph under the cursor var documentFragment = obj.focusPara.range.cloneContents; wikEd.GetInnerHTML(obj.focusPara, documentFragment); obj.focusPara.code = obj.focusPara.html; wikEd.RemoveHighlightingWikify(obj.focusPara, wikify); obj.focusPara.plain = obj.focusPara.html; obj.focusPara.plain = obj.focusPara.plain.replace(/[\n ]*<br\b[^>]*>[\n ]*/g, '\n'); obj.focusPara.plain = obj.focusPara.plain.replace(/\xa0/g, ' '); }	}

// selectionWord and selectionLine for the complete words and lines under the selection if (obj.selectionWord == null) { if (/selectionWord|selectionLine|selectionPara/.test(whichFragment) == true) {

// setup selectionWord object for the words under the selection obj.selectionWord = { 'from': 'selectionWord', 'keepSel': false, 'range': wikEd.frameDocument.createRange, 'tableEdit': obj.tableEdit };

// setup selectionLine object for the lines under the selection obj.selectionLine = { 'from': 'selectionLine', 'keepSel': false, 'range': wikEd.frameDocument.createRange, 'tableEdit': obj.tableEdit };

// setup focusPara object for the paragraph under the selection obj.selectionPara = { 'from': 'selectionPara', 'keepSel': false, 'range': wikEd.frameDocument.createRange, 'tableEdit': obj.tableEdit };

// find the word and line boundaries wikEd.FindBoundaries(obj.selectionWord, obj.selectionLine, obj.selectionPara, obj.whole, obj.selection);

// get the wikified plain text for the words under the selection var documentFragment = obj.selectionWord.range.cloneContents; wikEd.GetInnerHTML(obj.selectionWord, documentFragment); obj.selectionWord.code = obj.selectionWord.html; wikEd.RemoveHighlightingWikify(obj.selectionWord, wikify); obj.selectionWord.plain = obj.selectionWord.html; obj.selectionWord.plain = obj.selectionWord.plain.replace(/[\n ]*<br\b[^>]*>[\n ]*/g, '\n'); obj.selectionWord.plain = obj.selectionWord.plain.replace(/\xa0/g, ' ');

// get the wikified plain text for the lines under the selection var documentFragment = obj.selectionLine.range.cloneContents; wikEd.GetInnerHTML(obj.selectionLine, documentFragment); obj.selectionLine.code = obj.selectionLine.html; wikEd.RemoveHighlightingWikify(obj.selectionLine, wikify); obj.selectionLine.plain = obj.selectionLine.html; obj.selectionLine.plain = obj.selectionLine.plain.replace(/[\n ]*<br\b[^>]*>[\n ]*/g, '\n'); obj.selectionLine.plain = obj.selectionLine.plain.replace(/\xa0/g, ' ');

// get the wikified plain text for the paragraph under the selection var documentFragment = obj.selectionPara.range.cloneContents; wikEd.GetInnerHTML(obj.selectionPara, documentFragment); obj.selectionPara.code = obj.selectionPara.html; wikEd.RemoveHighlightingWikify(obj.selectionPara, wikify); obj.selectionPara.plain = obj.selectionPara.html; obj.selectionPara.plain = obj.selectionPara.plain.replace(/[\n ]*<br\b[^>]*>[\n ]*/g, '\n'); obj.selectionPara.plain = obj.selectionPara.plain.replace(/\xa0/g, ' '); }	}	return; };

// // wikEd.Find: custom find function with regexp properties, sets obj.changed.range, uses obj ranges //

wikEd.Find = function(obj, findText, caseSensitive, backwards, wrap, useRegExp) {

var found = false;

// get selection if (obj.sel == null) { obj.sel = wikEd.GetSelection; }	if (obj.sel.rangeCount == 0) { obj.sel.collapse(wikEd.frameBody, 0); }	var range = obj.sel.getRangeAt(obj.sel.rangeCount - 1);

if (obj.changed == null) { obj.changed = {}; }	obj.selectChanged = false;

// empty the range to avoid error messages for reverse direction ranges obj.changed.range = wikEd.frameDocument.createRange;

// regexp instead of plain text search for browser lacking .find (Opera), built in .find ignores newlines if (useRegExp != true) { if (typeof(wikEd.frameWindow.find) != 'function') { useRegExp = true; findText = findText.replace(/([\\^$*+?.\[\]{}:=!|,\-])/g, '\\$1'); }	}

// create the regexp var regExpFind; if (useRegExp == true) { var regExpFlags = 'gm'; if (caseSensitive != true) { regExpFlags += 'i'; }		try { regExpFind = new RegExp(findText, regExpFlags); }		catch (error) { return(false); }	}

// use the fast built-in find function for non-regexp searches; Opera does not have .find if (useRegExp != true) {

// parameters: window.find(string, caseSensitive, backwards, wrapAround, wholeWord, searchInFrames, showDialog) found = wikEd.frameWindow.find(findText, caseSensitive, backwards, wrap, false, true, false); if (found == true) { range = obj.sel.getRangeAt(obj.sel.rangeCount - 1); }		obj.changed.range = range; }

// slow javascript regexp find and replace else {

// perform find if (obj.plainArray === undefined) { wikEd.ParseDOM(obj, wikEd.frameBody); }		var regExpMatch = [];

// find next, search to the right if (backwards == false) {

// set start position for search to right regExpFind.lastIndex = obj.plainFocus;

// execute the regexp search to the right regExpMatch = regExpFind.exec(obj.plain);

// remember position for repeated searches obj.plainFocus = regExpFind.lastIndex;

// wrap around, start at beginning if ( (wrap == true) && (regExpMatch == null) ) { regExpFind.lastIndex = 0; regExpMatch = regExpFind.exec(obj.plain); }		}

// find previous, search to the left else {

// cycle through the matches to the left var regExpMatchNext; do { regExpMatch = regExpMatchNext; regExpMatchNext = regExpFind.exec(obj.plain); if (regExpMatchNext == null) { break; }			} while (regExpMatchNext.index < obj.plainAnchor);

// wrap around, find last occurrence if ( (wrap == true) && (regExpMatch == null) ) { do { regExpMatch = regExpMatchNext; regExpMatchNext = regExpFind.exec(obj.plain); } while (regExpMatchNext != null); }		}

// select the find if (regExpMatch != null) { found = true;

var i = 0; while ( (obj.plainStart[i + 1] <= regExpMatch.index) && (obj.plainStart[i + 1] != null) ) { i ++; }

var j = i;			while ( (obj.plainStart[j + 1] <= regExpMatch.index + regExpMatch[0].length) && (obj.plainStart[j + 1] != null) ) { j ++; }

var startNode = obj.plainNode[i]; var startOffset = regExpMatch.index - obj.plainStart[i]; var endNode = obj.plainNode[j]; var endOffset = regExpMatch.index + regExpMatch[0].length - obj.plainStart[j]; wikEd.SetRange(obj.changed.range, startNode, startOffset, endNode, endOffset); obj.selectChanged = true; }	}	return(found); };

// // wikEd.ScrollToSelection: scroll iframe range into viewport //  for MSIE see http://www.webmasterworld.com/javascript/3820483.htm //  removig helper nodes gives Error: Node was not found = NS_ERROR_DOM_NOT_FOUND_ERR for certain undo actions //  adding nodes breaks the undo history in Chrome and Opera

wikEd.ScrollToSelection = function(frameScrollTop, frameScrollLeft, removeHelperNodes) {

// get selection and clone range var obj = {}; obj.sel = wikEd.GetSelection; if (obj.sel.rangeCount == 0) { return; }

// get selection plain text range = obj.sel.getRangeAt(obj.sel.rangeCount - 1); var documentFragment = range.cloneContents; wikEd.GetInnerHTML(obj, documentFragment); var plainText = obj.plain; plainText = plainText.replace(/&lt;/g, '<'); plainText = plainText.replace(/&gt;/g, '>'); plainText = plainText.replace(/&amp;/g, '&'); plainText = plainText.replace(/\xa0/g, ' ');

// select using backwards built-in find if ( (typeof(wikEd.frameWindow.find) == 'function') && (plainText.length > 0) ) { obj.sel.collapseToEnd;

// Chrome; parameters: wikEd.Find(obj, findText, caseSensitive, backwards, wrap, useRegExp) var found = wikEd.Find(obj, plainText, true, true, false, false);

// Firefox (removes \n), if (found == false) { wikEd.Find(obj, range.toString, true, true, false, false); }

// reinstate original range if it starts or ends with \n or spaces if (/^(\n| )|(\n| )$/.test(plainText) == true) { wikEd.RemoveAllRanges(obj.sel); obj.sel.addRange(range); }	}

// select empty range using backwards built-in find for previous character else if ( (typeof(wikEd.frameWindow.find) == 'function') && (plainText.length == 0) ) { var backwards = true;

// get plain text from start to selection var rangeClone = range.cloneRange; rangeClone.setStartBefore(wikEd.frameBody.firstChild); var documentFragment = rangeClone.cloneContents; wikEd.GetInnerHTML(obj, documentFragment); var plainText = obj.plain; plainText = plainText.replace(/&lt;/g, '<'); plainText = plainText.replace(/&gt;/g, '>'); plainText = plainText.replace(/&amp;/g, '&'); plainText = plainText.replace(/^([\s\S]*?)([^\n]\n*)$/, '$2');

// get plain text from selection to end for potentially less newlines if (plainText.length > 1) { var plainTextBack = plainText; var obj = {};

var rangeClone = range.cloneRange; rangeClone.setEndAfter(wikEd.frameBody.lastChild); var documentFragment = rangeClone.cloneContents; wikEd.GetInnerHTML(obj, documentFragment); var plainText = obj.plain; plainText = plainText.replace(/&lt;/g, '<'); plainText = plainText.replace(/&gt;/g, '>'); plainText = plainText.replace(/&amp;/g, '&'); plainText = plainText.replace(/^(\n*[^\n])([\s\S]*?)$/, '$1');

// backward or forward find if (plainTextBack.length > plainText.length) { backwards = false; }			else { plainText = plainTextBack; }		}

// Chrome; parameters: wikEd.Find(obj, findText, caseSensitive, backwards, wrap, useRegExp) var found = wikEd.Find(obj, plainText, true, backwards, false, false);

// Firefox if ( (found == false) && (/\n/.test(plainText) == true) ) { plainText = plainText.replace(/\n/g, ''); plainText = plainText.replace(/\xa0/g, ' '); wikEd.Find(obj, plainText, true, backwards, false, false); }		if (backwards == true) { obj.sel.collapseToEnd; }		else { obj.sel.collapseToStart; }	}

// use inserted spans as scroll marker, breaks undo history in Chrome and Opera else { var rangeStart = range.cloneRange; var rangeEnd = range.cloneRange;

// spans to be temporarily inserted before and after selection range to get range position wikEd.insertCounter ++; var scrollStartNode = wikEd.frameDocument.createElement('span'); scrollStartNode.className = 'wikEdScrollBefore'; scrollStartNode.id = 'wikEdScrollBefore' + wikEd.insertCounter; var scrollEndNode = wikEd.frameDocument.createElement('span'); scrollEndNode.className = 'wikEdScrollAfter'; scrollEndNode.id = 'wikEdScrollAfter' + wikEd.insertCounter;

// get the range border nodes and offsets var startNode = range.startContainer; var startOffset = range.startOffset; var endNode = range.endContainer; var endOffset = range.endOffset;

var startLength; if (startNode.nodeName == '#text') { startLength = startNode.nodeValue.length; }		var endLength; if (endNode.nodeName == '#text') { endLength = endNode.nodeValue.length; }

// insert end node if (endNode.nodeName == '#text') { if (endOffset == 0) { endNode.parentNode.insertBefore(scrollEndNode, endNode); }			else if (endOffset == endLength - 1) { endNode.parentNode.insertBefore(scrollEndNode, endNode.nextSibling); }			else { rangeEnd.collapse(false); rangeEnd.insertNode(scrollEndNode); }		}		else { var refNode = endNode.childNodes.item(endOffset); endNode.insertBefore(scrollEndNode, refNode); }

// insert start node if (startNode.nodeName == '#text') { if (startOffset == 0) { startNode.parentNode.insertBefore(scrollStartNode, startNode); }			else if (startOffset == startLength - 1) { startNode.parentNode.insertBefore(scrollStartNode, startNode.nextSibling); }			else {

// collapse as a Firefox bug work around; http://stackoverflow.com/questions/665676 rangeStart.collapse(true); rangeStart.insertNode(scrollStartNode); }		}		else { var refNode = startNode.childNodes.item(startOffset); startNode.insertBefore(scrollStartNode, refNode); }

wikEd.ScrollToNodes(scrollStartNode, scrollEndNode);

// set selection range.setStartBefore(scrollStartNode); range.setEndAfter(scrollEndNode); wikEd.RemoveAllRanges(sel); sel.addRange(range); }

return; };

// // wikEd.ScrollToNodes: scroll iframe range into viewport //

wikEd.ScrollToNodes = function(scrollStartNode, scrollEndNode) {

// absolute span for line height detection (Opera and Chrome do not vertically align empty span at bottom) var lineHeightNode = wikEd.frameDocument.createElement('span'); lineHeightNode.innerHTML = ' '; lineHeightNode.className = 'wikEdScrollLineHeight'; scrollEndNode.appendChild(lineHeightNode); lineHeight = lineHeightNode.clientHeight; lineHeightNode.innerHTML = ''; scrollEndNode.removeChild(lineHeightNode);

// scroll to node coordinates scrollStartNode.style.verticalAlign = 'top'; scrollEndNode.style.verticalAlign = 'top'; var startOffsetLeft = wikEd.GetOffsetLeft(scrollStartNode); var startOffsetTop = wikEd.GetOffsetTop(scrollStartNode); var endOffsetRight = wikEd.GetOffsetLeft(scrollEndNode); var endOffsetBottom = wikEd.GetOffsetTop(scrollEndNode); scrollStartNode.style.verticalAlign = 'baseline'; scrollEndNode.style.verticalAlign = 'baseline'; var frameScrollTop = wikEd.frameBody.scrollTop; var frameScrollLeft = wikEd.frameBody.scrollLeft; var x = frameScrollLeft; var y = frameScrollTop;

// current scroll position

// selection above viewport if (endOffsetBottom < frameScrollTop) { y = startOffsetTop; }

// selection below viewport else if (startOffsetTop > frameScrollTop + wikEd.frameBody.clientHeight) { y = endOffsetBottom - wikEd.frameBody.clientHeight + lineHeight; }

// selection left of viewport if (endOffsetRight < frameScrollLeft) { if (endOffsetRight <= wikEd.frameBody.clientWidth) { x = 0; }		else { x = startOffsetLeft; }	}

// selection right of viewport else if (startOffsetLeft > frameScrollLeft + wikEd.frameBody.clientWidth) { x = endOffsetRight - wikEd.frameBody.clientWidth; }

// do scroll wikEd.frameWindow.scrollTo(x, y);

return; };

// // wikEd.WikiTableToHtml: convert wiki tables to html // //

wikEd.WikiTableToHtml = function(obj) {

////	return; };

// // wikEd.Textify: strip html off of text //

wikEd.Textify = function(obj) {

// convert html to plain obj.plain = obj.html;

// conserve spaces and linebreaks in tags obj.plain = obj.plain.replace(/(<pre\b[^>]*>)((.|\n)*?)(<\/pre>)/g,		function (p, p1, p2, p3, p4) {			p2 = p2.replace(/ /g, '\x03');			p2 = p2.replace(/\n/g, '\x04');			return(p1 + p2 + p4);		}	);

// remove linebreaks obj.plain = obj.plain.replace(/ \n|\n /g, ' '); obj.plain = obj.plain.replace(/\n/g, ' ');

// delete content tags obj.plain = obj.plain.replace(/<(style|script|object|applet|embed)\b[^>]*>.*?<\/\1>/g, '');

// delete outlook tags obj.plain = obj.plain.replace(/<(w:|m:)\b[^>]*>.*?<\/\1>/g, '');

// newlines obj.plain = obj.plain.replace(/[\n ]*<br\b[^>]*>[\n ]*/g, '\n');

// ... to for Safari, Chrome, WebKit if ( (wikEd.safari == true) || (wikEd.chrome == true) || (wikEd.webkit == true) ) { obj.plain = wikEd.RemoveTag(obj.plain, 'div', null, '\x00', '\x00'); obj.plain = obj.plain.replace(/\x00\n\x01/g, '\x01'); obj.plain = obj.plain.replace(/\x01\n/g, '\x01'); obj.plain = obj.plain.replace(/\n\x00/g, '\x00'); obj.plain = obj.plain.replace(/\x01\x00/g, '\x01'); obj.plain = obj.plain.replace(/^\x00|\x01$/g, ''); obj.plain = obj.plain.replace(/[\x00\x01]/g, '\n'); }

// remove empty lines from block tags obj.plain = obj.plain.replace(/(<(blockquote|center|div|p|pre|gallery)\b[^>]*>)[\s\x00]+/gi, '$1'); obj.plain = obj.plain.replace(/[\s\x00]+(<\/(blockquote|center|div|p|pre|gallery|syntaxhighlight|source|poem|categorytree|hiero|imagemap|inputbox|timeline|references)>)/gi, '$1');

// remove highlighting pre tags var isRemove = []; obj.plain = wikEd.RemoveTag(obj.plain, 'pre', /\bclass="wikEd[\w\/]+"/);

// blocks obj.plain = obj.plain.replace(/<\/?(address|blockquote|center|div|hr|isindex|p|pre)\b.*?>/g, '\x00\x00');

// keep headings only if starting with a newline obj.plain = obj.plain.replace(/[\s|\x00]*(^|\n|\x00)[\s|\x00]*<h[1-6]\b[^>]*>(.*?)<\/h[1-6]>[\s|\x00]*/g, '\x00\x00$2\x00\x00');

// lists obj.plain = obj.plain.replace(/<\/?(dir|dl|menu|ol|ul)\b.*?>/g, '\x00'); obj.plain = obj.plain.replace(/<\/(dd|dt|li)>/g, '\x00');

// forms obj.plain = obj.plain.replace(/<\/?(select|textarea)\b.*?>/g, '\x00'); obj.plain = obj.plain.replace(/<\/(option|legend|optgroup)>/g, '\x00');

// tables if (wikEd.tableMode == true) {

// override pasted table class // obj.plain = obj.plain.replace(/( '; }						else { insertLeft = ' '; insertRight = ' '; }						break; }				break; case 'block': switch (tag) {

// pushRight instead of insertRight if enclosed text can contain other highlighting, e.g. single character highlighting case 'linkNamespace': insertLeft = ' '; pushRight = ' '; break; case 'linkInter': insertLeft = ' '; pushRight = ' '; break; case 'inlineURL': var url = ''; var regExpMatch; if ( (regExpMatch = /\w\S+/.exec(tagMatch)) != null) { url = regExpMatch[0]; }						insertLeft = '<span class="wikEdURLName" ' + wikEd.HighlightLinkify(, , url) + '>'; pushRight = ' '; break; case 'externalURL': insertLeft = ' '; pushRight = ' '; break; case 'templateModifier': insertLeft = ' '; pushRight = ' '; break; case 'templateNamespace': insertLeft = ' '; pushRight = ' '; break; case 'templateParserFunct': insertLeft = ' '; pushRight = ' '; break; case 'PMID': var idNumber = ''; var regExpMatch; if ( (regExpMatch = /\d+/.exec(tagMatch)) != null) { idNumber = regExpMatch[0]; }						insertLeft = '<span class="wikEdPMID" ' + wikEd.HighlightLinkify(, , '//www.ncbi.nlm.nih.gov/pubmed/' + idNumber) + '>'; insertRight = ' '; break; case 'ISBN': var idNumber = ''; var regExpMatch; if ( (regExpMatch = /\d[\s\d\-]+x?/.exec(tagMatch)) != null) { idNumber = regExpMatch[0].replace(/\D/g, ''); }						insertLeft = '<span class="wikEdISBN" ' + wikEd.HighlightLinkify('', 'Special:BookSources/' + idNumber) + '>'; pushRight = ' '; break; case 'RFC': var idNumber = ''; var regExpMatch; if ( (regExpMatch = /\d[\s\d\-]+x?/.exec(tagMatch)) != null) { idNumber = regExpMatch[0].replace(/\D/g, ''); }						insertLeft = '<span class="wikEdISBN" ' + wikEd.HighlightLinkify(, , '//tools.ietf.org/html/rfc' + idNumber) + '>'; pushRight = ' '; break; case 'magic': insertLeft = ' '; insertRight = ' '; break; case 'signature': var title = wikEd.config.text['wikEdSignature' + tagLength]; insertLeft = '<span class="wikEdSignature" title="' + title + '">'; insertRight = ' '; break; case 'hr': pushLeft = ' '; pushRight = ' '; break; case 'linkParam': insertLeft = ' '; insertRight = ' '; break; case 'fileParam':

// make text parameters a caption var params = ''; if (pairedTagPos != null) { params = obj.html.substring(tagFrom + 1, parseObj.tree[node.parent].pairedTagPos - 1); }						if (/^\s*(thumb|thumbnail|frame|right|left|center|none|\d+px|\d+x\d+px|link\=.*?|upright|border)\s*(\||$)/.test(params) == true) { insertLeft = ' '; insertRight = ' '; }						else { insertLeft = ' '; insertRight = ' '; }						break; case 'redirect': insertLeft = ' '; pushRight = ' '; break; case 'templateParam': insertLeft = ' '; pushRight = ' '; break; case 'parameterDefault': insertLeft = ' '; insertRight = ' '; break; case 'br'://inlineTag class case 'html': case 'htmlEmpty': insertLeft = ' '; pushRight = ' '; break; case 'htmlUnknown': insertLeft = '<span class="wikEdHtmlUnknown" title="' + wikEd.config.text.wikEdErrorHtmlUnknown + '">'; pushRight = ' '; break; case 'ref': var refName = ''; var regExpMatch; if ( (regExpMatch = /(\bname\s*=\s*('|"))([^\x01]+?)\2/i.exec(tagMatch)) != null) {							refName = regExpMatch[3];							wikEd.HighlightBuildTree('refName', 'block', tagFrom + regExpMatch.index + regExpMatch[1].length, regExpMatch[3].length, parseObj);						}						else if ( (regExpMatch = /(\bname\s*=\s*)(\w+)/i.exec(tagMatch)) != null) {							refName = regExpMatch[2];							wikEd.HighlightBuildTree('refName', 'block', tagFrom + regExpMatch.index + regExpMatch[1].length, regExpMatch[2].length, parseObj);						}						if (wikEd.refHide == true) {							if (refName != '') {								insertLeft = ' <button class="wikEdRefButton' + wikEd.referenceArray.length + '" title="' + wikEd.config.text.wikEdRefButtonTooltip + '"> ';								wikEd.referenceArray.push( {'text': refName + ' ↑', 'added': false} );							}							else {								insertLeft = ' <button class="wikEdRefButton" title="' + wikEd.config.text.wikEdRefButtonTooltip + '"> '; }						}						insertLeft += ' '; pushRight = ' '; break; case 'references': insertLeft = ' '; pushRight = ' '; break; case 'pre': insertLeft = ' '; pushRight = ' '; break; case 'math': insertLeft = ' '; pushRight = ' '; break; case 'nowiki': insertLeft = ' '; pushRight = ' '; break; case 'listTag': insertLeft = ' '; insertRight = ' '; break; case 'preformTag': insertLeft = ' '; insertRight = ' '; break; case 'refName': insertLeft = ' '; pushRight = ' '; break; case 'list': pushLeft = ' '; pushRight = ' '; break; case 'preform': pushLeft = ' '; pushRight = ' '; break; case 'caption': case 'row': case 'header': case 'headerParam': case 'headerSep': case 'cell': /*						if (parseObj.tableMode == true) { var regExpTable = /\| *((\w+ *= *('|")[^\n'"]*\3 *)*)\|\|/gi; regExpTable.lastIndex = tagFrom; var regExpMatch; if ( (regExpMatch = regExpTable.exec(obj.html) ) != null) { if (regExpMatch.index == tagFrom) { var params = regExpMatch[1]; if (params != '') { params += ' '; }									insertLeft = '