diff options
author | Christian Franke <nobody@nowhere.ws> | 2013-03-12 06:12:24 +0100 |
---|---|---|
committer | Christian Franke <nobody@nowhere.ws> | 2013-03-12 06:22:17 +0100 |
commit | 8733f95d481d341a74d95cd97ecbef39a1f0609f (patch) | |
tree | 2862af920799e90da7ed9dd86e612ae6347f26d2 | |
parent | 18d1778eeda305b5ee65d22500905640e2fbacc5 (diff) |
World day against cyber censorship
-rw-r--r-- | public/css/sublab-2013-03-12.css (renamed from public/css/sublab-2012-09-16.css) | 20 | ||||
-rw-r--r-- | public/inc/zensur.js | 169 | ||||
-rw-r--r-- | template/template/template.html | 17 |
3 files changed, 205 insertions, 1 deletions
diff --git a/public/css/sublab-2012-09-16.css b/public/css/sublab-2013-03-12.css index 9ad8eda..68a1a97 100644 --- a/public/css/sublab-2012-09-16.css +++ b/public/css/sublab-2013-03-12.css @@ -4,6 +4,26 @@ color: #ddd; } +.censored { + color: #ddd; + background-color: #ddd; +} + +#zensurinfo { + padding: 0.5em; + position: absolute; + left: 0px; + top: 0px; + right: 0px; + font-size: 1.5em; + font-weight: bold; + color: white; + background-color: red; +} +#zensurinfo * { color: white } +#zensurinfo .censored { color: white; background-color: grey; } +#zensurinfo a, #zensurinfo a:hover, #zensurinfo a:visited { color: yellow } + iframe.youtube { margin: 5px 15px 0px 15px; width: 300px; diff --git a/public/inc/zensur.js b/public/inc/zensur.js new file mode 100644 index 0000000..d6b4d29 --- /dev/null +++ b/public/inc/zensur.js @@ -0,0 +1,169 @@ +(function() { + // states + // 0: uncensored + // 1: start_censor + // 2: censored + // state transition probabilities: + var p_trans = [ + // x uncensored -> uncensored + 0.08, // uncensored -> start_censor + // 0 uncensored -> censored + // 0 start_censor -> uncensored + // 0 start_censor -> start_censor + // 1 start_censor -> censored + 0.55, // censored -> uncensored + // 0 censored -> start_censor + // x censored -> censored + ]; + var censored_tag = "span"; + var censored_class = "censored"; + var start_censor = "<" + censored_tag + " class=\"" + censored_class + "\">"; + var stop_censor = "</" + censored_tag + ">"; + var re_censor = /[0-9A-Za-z]/; + var isCensored = true; + var censoredElements = []; + + function splitWords(text) { + // some older IEs don't suppport capturing parentheses + // return text.split(/([\t\n\r ])/); + if (text.length === 0) { + return [""]; + } + var words = []; + var last_i = 0; + for (var i = 0; i < text.length; i++) { + switch(text[i]) { + case '\t': + case '\n': + case '\r': + case ' ': + if (last_i !== i) { + words.push(text.slice(last_i, i)); + } + words.push(text[i]); + last_i = i + 1; + } + } + if (last_i !== text.length) { + words.push(text.slice(last_i)); + } + return words; + } + + function censorWord(state, word) { + // ignore words not containing letters (may be spaces only) + if (!word.match(re_censor)) { + return word; + } + + var r = Math.random(); + var prefix = ""; + var suffix = ""; + + if (state.s === 1) { + // start_censor -> censored + state.s = 2; + prefix = start_censor; + } + + if (state.s === 0 && r < p_trans[0]) { + // uncensored -> start_censor + state.s = 1; + } + else if (state.s === 2 && r < p_trans[1]) { + // censored -> uncensored + state.s = 0; + suffix = stop_censor; + } + + return prefix + word + suffix; + } + + function censorTextNode(node) { + var state = { s: 0 }; + if (Math.random() < p_trans[0]) { + // start_censor + state.s = 1; + } + var words = splitWords(node.nodeValue); + for (var i in words) { + words[i] = censorWord(state, words[i]); + } + if (state.s === 2) { + words[words.length-1] = words[words.length-1] + stop_censor; + } + var newnode = document.createElement(censored_tag); + newnode.innerHTML = words.join(""); + return newnode; + } + + function censorElement(element, on) { + var childs = element.childNodes; + var uncensored = false; + for (var i in childs) { + + if (childs[i].nodeType === 1 && + childs[i].nodeName !== "OPTION" && + childs[i].nodeName !== "SCRIPT" && + childs[i].nodeName !== "SELECT" && + childs[i].nodeName !== "STYLE" && + childs[i].nodeName !== "TEXTAREA" && + childs[i].nodeName !== "TITLE") + { + if (!on && + childs[i].nodeName === censored_tag.toUpperCase() && + childs[i].className === censored_class && + childs[i].childNodes.length === 1) + { + uncensored = true; + element.replaceChild(childs[i].childNodes[0], childs[i]); + } + + var childUncensored = censorElement(childs[i], on); + if (!on && childUncensored) + { + var newnode = document.createTextNode(""); + for (var j in childs[i].childNodes) { + if (!childs[i].childNodes[j].nodeType === 3) { + return; + } + if (childs[i].childNodes[j].nodeValue) { + newnode.nodeValue += childs[i].childNodes[j].nodeValue; + } + } + element.replaceChild(newnode, childs[i]); + } + } + + else if (on && + childs[i].nodeType === 3 && + childs[i].nodeValue.match(re_censor)) + { + element.replaceChild(censorTextNode(childs[i]), childs[i]); + } + + } + + return uncensored; + } + + function doCensor(on) { + for (var i in censoredElements) { + censorElement(censoredElements[i], on); + } + } + + window.zensurjs = function(arg) { + if (arg === undefined) { + isCensored = !isCensored; + doCensor(isCensored); + } + else { + censoredElements.push(arg); + if (isCensored) { + censorElement(arg, true); + } + } + return isCensored; + }; +})(); diff --git a/template/template/template.html b/template/template/template.html index 3c8f053..66c8987 100644 --- a/template/template/template.html +++ b/template/template/template.html @@ -15,16 +15,31 @@ <meta name="description" lang="de" content="$template_desc_de"> <meta name="description" lang="en" content="$template_desc_en"> - <link rel="stylesheet" href="/css/sublab-2012-09-16.css" type="text/css"> + <link rel="stylesheet" href="/css/sublab-2013-03-12.css" type="text/css"> <link rel="stylesheet" href="/css/taifun.status.css" type="text/css"> <link rel="stylesheet" href="/css/trieste.status.css" type="text/css"> <link rel="stylesheet" href="/css/nautilus.status.css" type="text/css"> <link rel="stylesheet" href="/css/sublab.status.css" type="text/css"> <link rel="shortcut icon" href="/img/favicon.png"> <link rel="space-api" href="/status.json" /> + + <script type="text/javascript" src="/inc/zensur.js"></script> + <script type="text/javascript"> + window.onload = function() { zensurjs(document.body); }; + function toggleZensur() { + var state = zensurjs(); + document.getElementById("zensurstate").innerHTML={true: 'Diese Seite ist zensiert.', false: 'Diese Seite könnte zensiert sein.'}[state]; + document.getElementById("zensurlink").innerHTML={true: 'Ich bin gegen Zensur!', false: 'Ich bin für Zensur!'}[state]; + } + </script> </head> <body> + <div id="zensurinfo"> + <span id="zensurstate">Diese Seite ist zensiert.</span> + <a href="https://march12.rsf.org/en/">Lies Warum!</a> + <small><a href="" id="zensurlink" onclick="toggleZensur(); return false;">Ich bin gegen Zensur!</a></small> + </div> <div class="hiddenframe"> <div class="frame"> |