18

请记住那条关于目标的客场消息,上面写着如何:

对 Cmabrigde Uinervtisy 的一名研究人员来说,这并不意味着所有的事情都是一样的,所有的 iprmoetnt tihng 是第一个和 lsat ltteer 是在 rghit pclae。rset 可以是一个 toatl mses,你可以在没有 porbelm 的情况下使用它。Tihs is bcuseae the huamn mnid deos 不是 raed ervey lteter by istlef,而是 wrod as a wlohe。

无论如何,我正在尝试制作一个可以对整个页面执行此操作的功能。这个函数有一些规则。

  1. 少于 4 个字符不要理会。
  2. 非字母数字字符不算作单词的一部分。
  3. 连字符真的是两个词
  4. 如果长度> = 4,单词必须是乱码(不能像原来的那样)
  5. 第一个和最后一个字符保持不变,只有中间的字符会乱码(感谢 Hersheezy)
  6. 文本应始终是随机的,并在每次运行时产生独特的乱码
  7. 纯 javascript 并在所有文本节点上迭代
  8. 最短最甜的代码获胜。

无论如何,它似乎很容易实现,如何开始一场比赛,看看谁能写出最干净最清晰的代码来完成这项任务。随意借用而不识别我的代码(我肯定有)

如果我错过了什么,请在评论中添加。无论如何,我非常笨拙地工作,这是我展示我的低于标准的工作

演示

var i, j, words, textNodes, punct = /[^a-zA-Z0-9]/;

Array.prototype.shuffle = function() {
    for (var i = 0; i < this.length; i++) {
        var j = i;
        while (j == i) {
            j = Math.floor(Math.random() * this.length);
        }
        var tmp = this[i];
        this[i] = this[j];
        this[j] = tmp;
    }
    return this;
};

String.prototype.shuffle = function() {
    return this.split('').shuffle().join('');
};

function transverse(element, array) {
    if (!array) array = [];
    if (element.nodeType === 3) {
        array.push(element);
    } else {
        for (var i = 0; i < element.childNodes.length; i++) {
            transverse(element.childNodes[i], array);
        }
    }
    return array;
}

function garble(str) {
    if (!str) return '';
    str = str.trim();
    if (/-/.test(str)) {
        str = str.split('-');
        for (var i = 0; i < str.length; i++) {
            str[i] = garble(str[i]);
        }
        return str.join('-')
    }
    if (punct.test(str.charAt(0))) {
        return str.charAt(0) + garble(str.slice(1));
    }
    if (punct.test(str.charAt(str.length - 1))) {
        return garble(str.slice(0, -1)) + str.charAt(str.length - 1);
    }
    if (str.length < 4) return str;
    if (str.length === 4) return str.charAt(0) + str.charAt(2) + str.charAt(1) + str.charAt(3)
    return str.charAt(0) + str.substr(1, str.length - 2).shuffle() +
        str.charAt(str.length - 1);
}


window.onload = function() {
    textNodes = transverse(document.documentElement);
    for (i = 0; i < textNodes.length; i++) {
        words = textNodes[i].data.split(' ');
        for (j = 0; j < words.length; j++) {
            words[j] = garble(words[j]);
        }
        textNodes[i].data = words.join(' ');
    }
};
4

4 回答 4

9

更新(最新):不要认为它可以变得更小.. DEMO
最新压缩(332):

var e=document.body.getElementsByTagName('*'),j,i,l,x,t,b;for(i=0;e[i];i++)for(j=0;b=e[i].childNodes[j];j++)if(b.nodeType==3)b.data=b.data.replace(/\w{4,}/g,function(w){if(/(^.)(\1)+$/.test(x=w.substring(1,l=w.length-1)))return w;t=w;while(t==w)t=w[0]+x.split('').sort(function(){return 0.5-Math.random()}).join('')+w[l];return t}); 

代码:

var e = document.body.getElementsByTagName('*'),
    j, i, l, x, t, b;
for (i = 0; e[i]; i++)
for (j = 0; b = e[i].childNodes[j]; j++)
if (b.nodeType == 3) b.data = b.data.replace(/\w{4,}/g, function(w) {
    if (/(^.)(\1)+$/.test(x = w.substring(1, l = w.length - 1))) return w;
    t = w;
    while (t == w)
    t = w[0] + x.split('').sort(function() {
        return 0.5 - Math.random();
    }).join('') + w[l];
    return t;
});

更新甚至..更小..

更小的版本
我不知道你使用的缩小器,但这必须至少( EDIT 108)字节更小。
压缩版(365 字节):

var e=document.body.getElementsByTagName('*'),a=[],c,j,i,l,x,t,b;for(i=0;c=e[i];i++)for(j=0;b=c.childNodes[j];j++)if(b.nodeType==3){b.data=b.data.replace(/\b[a-z0-9]{4,}\b/gi,function(w){if(/(^.)(\1)+$/.test(x=w.substring(1,l=w.length-1)))return w;t=w;while(t==w)t=w[0]+x.split('').sort(function(){return Math.floor(Math.random()*2)?1:-1}).join('')+w[l];return t})}  

代码:

var e = document.body.getElementsByTagName('*'),
    a = [],
    c, j, i, l, x, t, b;
for (i = 0; c = e[i]; i++)
for (j = 0; b = c.childNodes[j]; j++)
if (b.nodeType == 3) {
    b.data = b.data.replace(/\b[a-z0-9]{4,}\b/gi, function(w) {
        if (/(^.)(\1)+$/.test(x = w.substring(1, l = w.length - 1))) return w;
        t = w;
        while (t == w)
        t = w[0] + x.split('').sort(function() {
            return Math.floor(Math.random() * 2) ? 1 : -1;
        }).join('') + w[l];
        return t;
    });
}

编辑
新规则演示
代码:

var fn = function(e) {
    var ret = [],c;
    for (var i = 0; i < e.length; i++) {
        c = e[i].childNodes;
        for (var j = 0; j < c.length; j++)
            if (c[j].nodeType === 3) ret.push(c[j]);
    }
    return ret;
};
var es = fn(document.body.getElementsByTagName('*'));
for (var i = 0; i < es.length; i++) {
    var e = es[i],len,x;
    e.data = e.data.replace(/\b[a-z0-9]{4,}\b/gi, function(w) {
        if (/(^.)(\1)+$/.test(x = w.substring(1, len = w.length - 1))) return w;
        var tmp = w;
        while (tmp === w) {
            tmp = w[0] + x.split('').sort(function() {
                return Math.floor(Math.random() * 2) ? 1 : -1;
            }).join('') + w[len];
        }
        return tmp;
    });
}

这应该尊重所有规则,并保持格式和标点符号。演示

//select all nodes in document and perform map on it to filter out
//non text node types, then each one of those elements is processed.
$('*').contents().map(function(i, elem) {
    if (elem.nodeType !== 3) return null;
    else return elem;
}).each(function(i, elem) {
 //call strip funciton defined down to get an object, with a word array, and
 //charecters which was stripped along with there index in the orginal string
    var str1 = '',
        tmp = strip(elem.data),
        words = tmp.words,
        sentence;
    // shuffle all words
    words = $.map(words, function(x, i) {
        return shuffle(x);
    });
    //construct raw sentence (non alphanumeric charecters)
    sentence = words.join('');
    //reinsert spaces and punctiouation 
    $.each(tmp.chars, function(i, elem) {
        sentence = sentence.substring(0, elem.index) + elem.char + sentence.substring(elem.index - 1 + elem.char.length);
    });
    //set the element text
    elem.data = sentence;
});

//shuffle funciton takes a word and shuffle the charecters between the last and the firt
function shuffle(txt) {
    //if the word is smaller than 4 charecters or it has repeated charecters in
    //its middle (i.e. loop, 'oo' cannot be shuffled!) then return it;
    if (txt.length < 4 || /(^.)(\1)+$/.test(txt.substring(1, txt.length - 1)))
        return txt;
    var str = txt.split(''),
        ret = [],
        rand, x = 0,
        tmp = txt;
    //while the txt hasn't changed in the first randomization cycle then repeated
    while (txt === tmp) {
        ret = [];
        $.each(str, function(i, c) {
            if (i === str.length - 1 || i === 0) {
                ret[i] = c;
                return;
            }
            while (true) {
                rand = Math.floor(Math.random() * (str.length - 2) + 1);
                if (!ret[rand]) {
                    ret[rand] = c;
                    break;
                }
            }
        });
        tmp = ret.join('');
    }
    return ret.join('');
}

function strip(txt) {
    var punc = /[^A-Za-z0-9]/g,
        res, nonAlphaNum = [],
        arr;
    //punc regex is all non-alphanumeric charecters which will act on the string
    //to point out unwanted charecters and store them in an array along with
    //their index
    while ((res = punc.exec(txt)) != null) {
        nonAlphaNum.push({
            index: res.index,
            char: res[0]
        });
    }
    //split into words
    arr = txt.split(/\s/);
    //remove punctiuation and other unwanted chars
    arr = $.map(arr, function(x, i) {
        return x.replace(punc, '');
    });
    return {
        words: arr,  //words array
        chars: nonAlphaNum //array of stripped charecter objects (chars, index in orginal)
    };
} 

顺便说一句,这篇文章的不错选择,WWiWieikikb!

于 2011-02-11T05:28:57.307 回答
6

更新

所以我忍不住玩弄了这个东西,看看还有什么其他方法可以用尽可能少的代码来操作文档。可以说它可以缩短以在非此即彼的情况下工作,但我喜欢制作带有选项供用户使用的东西。

话虽如此,以下是上述内容的一些变化和好处/失望:


正式提交(473bytes)

缩小(473 字节)1

function t(e){var r=[],w;for(w=0;w<e.length;w++){if(e[w].nodeType===3)r.push(e[w]);else if(e[w].childNodes)r=r.concat(t(e[w].childNodes));}return r;}var e,x=t(document.body.childNodes),y,z;for(y=0;y<x.length;y++){x[y].data=x[y].data.replace(/\b[a-z]{4,}\b/ig,function(w){if(w.length==4&&(/^.([a-z])\1./i).test(w))return w;e=w;while(e==w){z=w.split('');e=z[0]+(z.slice(1,z.length-1).sort(function(a,b){return(Math.random()*2)>1?1:-1;}).join(''))+z[z.length-1];}return e;});}

未缩小版:(479bytes)1

function t(e){
  var r=[],w;
  for(w=0;w<e.length;w++){
    if(e[w].nodeType===3)r.push(e[w]);
    else if(e[w].childNodes)r=r.concat(t(e[w].childNodes));
  }
  return r;
}
var x=t(document.body.childNodes);
for(var y=0;y<x.length;y++){
  x[y].data=x[y].data.replace(/\b[a-z]{4,}\b/ig,function(w){
    if(w.length==4&&(/^.([a-z])\1./i).test(w))
      return w;
    var e=w;
    while (e==w){
      var x=w.split('');
      e=x[0]+(x.slice(1,x.length-1).sort(function(a,b){
        return(Math.random()*2)>1?1:-1;
      }).join(''))+x[x.length-1];
    }
    return e;
  });
}
  • 不使用 jQuery(“纯 javascript”)
  • <script src="garble.js"></script>在上面添加</body>或将代码包装在 onload 事件中。

1 重新放置 var 声明使其更短,请参阅479bytes vs 473 byes


附加版本

基本演示

// jQuery Garble
// "Basic" version
//
// Requirements:
// 1. Find all words 4+ letters long (exclude hyphens, punctuation or numbers from
//    the classification)
// 2. The words being garbled must follow:
//    a. They can not remain the same as the previous state
//    b. The first and last character must remain in-tact
// 3. The garbling must be random and produce a new result each iteration.
//
// Usage:
// $(selector).garble(options);
//
(function($){
    $.fn.extend({
        garble: function(options){
            // basic options
            var o = $.extend({
                flagChanges: false,
                changeClass: 'modified'
            },options);
            // iterate over elements
            return this.each(function(i,e){
                var txt = $(e).text();
                // locate words with 4+ letters
                $(e).html(txt.replace(/\b[a-z]{4,}\b/ig,function(w){
                    var e = w;
                    // make sure we get an altered word back
                    while (e==w){
                        var x = w.split('');
                        e = x[0]+(x.slice(1,x.length-1).sort(function(y,z){
                            return (Math.random()*2)>1?1:-1; // randomize
                        }).join(''))+x[x.length-1];
                    }
                    return (o.flagChanges?'<span class="'+o.changeClass+'">'+e+'</span>':e);
                }));
            });
        }
    });
})(jQuery);

优点

  1. 非常苗条和修剪
  2. 允许您修改修改过的单词的选项(使用默认的“修改过的”类或您选择的类将每个更改包装在跨度中)。

缺点

  1. 不适用于嵌套元素(这意味着您必须在 DOM 树中选择尽可能低的元素。因此,如果您只是要做没有超链接或跨度的段落,这是您的赢家)
  2. 如果在选择器中使用了具有子元素的元素,它们的 html 格式(例如段落中的链接)将被剥离。

修身和修剪演示

$(function(){                                                              // on load
  $('*','body').contents().map(function(i,e){                              // grab all elements,
    return e.nodeType !== 3 ? null : e;                                    // then filter by textual elements
  }).each(function(i,e){                                                   // amd iterate through them.
    e.data = e.data.replace(/\b[a-z]{4,}\b/ig, function(w) {               // go through and find 4+ letters words
      if (w.length==4&&w.substring(1,2)==w.substring(2,3))                 // (avoid infinite loops on words that
        return w;                                                          // can't be changed [e.g. look])
      var e = w;                                                           // Store the original word for comparison, but
      while (e==w){                                                        // keep scrambling until we have a new word.
        var x = w.split('');                                               // (do so by breaking out middle letters in to array,
        e = x[0] + (x.slice(1, x.length - 1).sort(function(a,b){           // then sort those middle letters
          return (Math.random() * 2) > 1 ? 1 : -1;                         // based on a random number)
        }).join('')) + x[x.length - 1];                                    // Now, rejoin it all back together
      }
      return e;                                                            // and finally return the modified result.
    });
  });
});

全功能演示

// jQuery Garble
// "Feature Rich" version
//
// Requirements:
// 1. Find all words 4+ letters long (exclude hyphens, punctuation or numbers from
//    the classification)
// 2. The words being garbled must follow:
//    a. They can not remain the same as the previous state
//    b. The first and last character must remain in-tact
// 3. The garbling must be random and produce a new result each iteration.
//
// Usage:
// $(selector).garble(options);
//
(function($) {
    $.fn.extend({
        garble: function(options) {
            var o = $.extend({}, $.fn.garble.defaults, options);

            // takes in a string and performs the necessary manipulation(s) on it. Use regex
            // to only collect words greater than or equal to 4 characters long, and consider
            // punctuation not part of the word.
            var garbleStr = function(s,t){
                return s.replace(/\b[a-z]{4,}\b/ig, function(w) {
                    var e = o.algorithm(w);

                    // if we're not performing a low-level parse and they want the changes styled,
                    // return a span with either the detault class or their custom class
                    if (t && !o.lowLevel && o.highLevel.flagChanges)
                        return '<span class="'+o.highLevel.changeClass+'">'+e+'</span>';

                    // just return the new word
                    return e;
                });
            };

            // Very high-level process.
            // Will only change the lowest node's text (so a paragraph
            // with links, only the links will be altered)
            var highLevel = function(i, e) {
                // we're not at the bottom element, keep going
                if ($(e).children().length>0){
                    return $(e).children().each(highLevel);
                }

                var t = $(e).text();
                $(e).html(garbleStr(t,e.tagName!=='TEXTAREA'));
            };
            // Low level process
            // Goes down to each individual element and changes it
            var lowLevel = function(i, e) {
                var d = e.data;
                e.data = garbleStr(d);
            };

            // depending their selection, execute either or
            if (o.lowLevel){
                return this.find('*').contents().map(function(i, e) {
                    return (e.nodeType !== 3 ? null : e);
                }).each(lowLevel);
            }else{
                return this.contents().each(highLevel);
            }
        },
    });

    // Defaults
    $.fn.garble.defaults = {
        // Perform low-level modification? (Modifies all words it finds,
        // not just the one farthests down the tree)
        lowLevel: false,

        // when lowLevel is set to false, these options are available:
        highLevel: {
            // wrap changes in a <span>
            flagChanges: false,

            // the class being applied to the above <span>
            changeClass: 'modified'
        },

        // function used to garble the text. This will be passed each word
        // individually and should return the new word's value.
        algorithm: function(w) {
            // if w = "hello":
            // 1. Make an array out of the letters.
            // 2. keep the first and last in-tact, but use .slice() to extract the middle
            // 3. Perform the specified algorithm on the middle characters
            // 4. return result
            var e = w;
            while (e==w){ // secure it gets changed
                var x = w.split('');
                e = x[0] + (x.slice(1, x.length - 1).sort(function(a,b){
                    return (Math.random() * 2) > 1 ? 1 : -1;
                }).join('')) + x[x.length - 1];
            }
            return e;
        }
    };
})(jQuery);

优点

  1. 灵活的。这几乎适用于所有场景,尽管可以快速处理食物链底部的元素或将其全部调用——这<body>可以处理它。
  2. 非常可定制:
    1. 可以指定执行低级别(每个元素)更改,或高级别(只有没有子元素的元素)
    2. 可以指定是否要显示更改,以及要应用的类(更改包含在具有指定类名的跨度中)
    3. 可以指定一个用于加扰的函数(也许您只想反转单词或使用更好的方法)

缺点

  1. 更多的开销,虽然它仍然很快。
  2. 可能有太多选择或太臃肿。
  3. 我相信有人会发现更多的缺点
于 2011-02-11T02:11:55.300 回答
1

这是我对该功能的看法。在此处查看演示。

  • 它使用出色的jquery.ba-replacetext插件来处理仅查找文本节点
  • 处理所有内部字符相等的任意长度的单词
  • 易于理解的描述性名称

完整版(1187 字节):

  /* Called on document.ready */
  $(function () {
    $("body *").replaceText(/\b([A-z]{4,})\b/g, scramble_inner );
  });
  /* Scramble the inner characters of a word */
  function scramble_inner(word) {
    return word[0] 
      + force_shuffle(word.slice(1, word.length - 1))
      + word[word.length - 1];
  }
  /* Randomize characters in the string, but check to make sure
   * they're different from the original. Handle's the special
   * case where all inner characters are equal, for instance "moooo".
   */
  function force_shuffle(str) {
    if (all_chars_same(str)) return str;
    var result = str;
    while (str === result) {
      result = str.split('').sort(function() {
        return Math.floor(Math.random() * 2) ? 1 : -1;
      }).join('');
    }
    return result;
  }
  /* Check whether all characters in the string are equal, eg "ooo" */
  function all_chars_same(str) {
    for (i = 0; i < str.length; i++) {
      if (str[i] !== str[0]) {
        return false;
      }
    }
    return true;
  }

缩小版(348 字节):

$(function(){$("body *").replaceText(/\b([A-z]{4,})\b/g,a)});function a(w){return w[0]+b(w.slice(1,w.length-1))+w[w.length-1]}function b(s){if(c(s))return s;var r=s;while(s===r){r=s.split('').sort(function(){return Math.floor(Math.random()*2)?1:-1}).join('')}return r}function c(s){for(i=0;i<s.length;i++){if(s[i]!==s[0]){return false}}return true}
于 2011-02-20T23:30:02.253 回答
0

注意:我通过 JSLint 运行它,这可能是个坏主意。无论如何,演示在这里

function shuffle(letters) {
    var i = letters.length - 2;
    while (i > 1) {
        var pos = Math.floor(Math.random() * i) + 1;
        var tmp = letters[i];
        letters[i] = letters[pos];
        letters[pos] = tmp;
        i--;
    }
}

function scramble(word) {
    if (word.slice(1, -2) == word.slice(2, -1)) {
        return word;
    }
    var letters = word.split('');
    var result = word;
    while (result == word) {
        shuffle(letters);
        result = letters.join('');
    }
    return result;
}

function process(node) {
    var data = node.data;
    if (/[a-z]{4}/i.test(data)) {
        node.data = data.replace(/[a-z]{4,}/gi, scramble);
    }
}

function traverse(element) {
    var node = element.firstChild;
    while (node) {
        if (node.nodeType == Node.ELEMENT_NODE) {
            traverse(node);
        } else if (node.nodeType == Node.TEXT_NODE) {
            process(node);
        }
        node = node.nextSibling;
    }
}

function garble() {
    traverse(document.body);
}

window.onload = garble;
于 2011-02-17T21:54:26.200 回答