User:Ilmari Karonen/rot13.js

/* This script can be used to encode/decode text with ROT13. Just select the text you want to transform and click the "rot13" button (or press alt-R). * * Known bugs * - Should encode/decode the entire page (or just the content section) if nothing is selected. * - Does not work on textbox content. * - Only works in Mozilla (and maybe Safari?); an IE port should be possible, but would take a lot of work. */

var rot13map; function rot13(a) {   if (!rot13map) { rot13map = new Array; var s = "abcdefghijklmnopqrstuvwxyz"; for (var i = 0; i < s.length; i++) rot13map[s.charAt(i)] = s.charAt((i+13)%26); s = s.toUpperCase; for (var i = 0; i < s.length; i++) rot13map[s.charAt(i)] = s.charAt((i+13)%26); }   var s = ""; for (var i = 0; i < a.length; i++) { var b = rot13map[a.charAt(i)]; s += (b ? b : a.charAt(i)); }   //alert("rot13('"+a+"') = '"+s+"'"); return s; }

function getTextNodesInRange (range) { var retVal = new Array; retVal.startOffset = retVal.endOffset = -1; var nodes = retVal.nodes = new Array;

var currNode = range.startContainer; var lastNode = range.endContainer;

if (currNode.nodeType == 3) retVal.startOffset = range.startOffset; else if (currNode.firstChild) currNode = currNode.childNodes[range.startOffset];

if (lastNode.nodeType == 3) retVal.endOffset = range.endOffset; else if (lastNode.firstChild) lastNode = (range.endOffset > 0 ? lastNode.childNodes[range.endOffset] : lastNode.prevSibling);

search: while (currNode) { while (currNode.firstChild) if ((currNode = currNode.firstChild) == lastNode) break; if (currNode.nodeType == 3) nodes.push(currNode); if (currNode == lastNode) break; while (!currNode.nextSibling) if ((currNode = currNode.parentNode) == lastNode) break search; currNode = currNode.nextSibling; }   if (retVal.startOffset < 0) retVal.startOffset = 0; if (retVal.endOffset < 0) retVal.endOffset = (nodes.length ? nodes[nodes.length-1].length : 0); return retVal; }

function rot13Selection { if (!window.getSelection && !document.getSelection) { alert("Browser does not support getSelection."); return; }   var selection = (window.getSelection ? window.getSelection : document.getSelection); if (!selection || selection.isCollapsed) return;

if (!selection.getRangeAt) { alert("Browser does not support selection.getRangeAt."); return; }   var texts = new Array; for (var i = 0; i < selection.rangeCount; i++) { var textNodes = getTextNodesInRange(selection.getRangeAt(i)); //alert("processing "+textNodes.nodes.length+" nodes"); texts.push(textNodes); var j = 0; if (textNodes.nodes.length < 1) continue; else if (textNodes.nodes.length < 2) textNodes.nodes[j].nodeValue = (textNodes.nodes[j].nodeValue.substring(0, textNodes.startOffset) +                                           rot13(textNodes.nodes[j].nodeValue.substring(textNodes.startOffset, textNodes.endOffset)) +                                            textNodes.nodes[j].nodeValue.substring(textNodes.endOffset)); else { textNodes.nodes[j].nodeValue = (textNodes.nodes[j].nodeValue.substring(0, textNodes.startOffset) +                                           rot13(textNodes.nodes[j].nodeValue.substring(textNodes.startOffset))); for (j = 1; j < textNodes.nodes.length-1; j++) textNodes.nodes[j].nodeValue = rot13(textNodes.nodes[j].nodeValue); textNodes.nodes[j].nodeValue = (rot13(textNodes.nodes[j].nodeValue.substring(0, textNodes.endOffset)) +                                           textNodes.nodes[j].nodeValue.substring(textNodes.endOffset)); }   }    selection = window.getSelection; selection.removeAllRanges; for (var i = 0; i < texts.length; i++) { if (texts[i].nodes.length < 1) continue; var range = document.createRange; range.setStart(texts[i].nodes[0], texts[i].startOffset); range.setEnd(texts[i].nodes[texts[i].nodes.length-1], texts[i].endOffset); selection.addRange(range); } }

addOnloadHook(function {    mw.util.addPortletLink('p-cactions', 'javascript:rot13Selection', 'rot13', 'ca-rot13', 'Encrypt/decrypt selection with ROT-13', 'R'); });