乱码函数竞赛

发布于 2024-10-17 01:50:48 字数 2612 浏览 0 评论 0原文

请记住关于目标的离开信息,其中说明了如何:

根据 Cmabrigde Uinervtisy 的一位研究人员的说法,无论单词中的单词是什么,最重要的是第一个单词,而最后一个单词位于正确的位置。 rset 可以是一个 toatl mses,您可以直接读取它而无需 porbelm。这是因为,huamn mnid deos 不是由 istlef 提供的 ervey lteter,而是作为一个 wlohe 的 wrod。

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

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

无论如何,它似乎很容易实现,如何开始一场竞赛,看看谁可以编写最干净、最清晰的代码来完成这项任务。请随意借用而不需要我的代码认可(我肯定有)

如果我错过了任何内容,请在评论中添加它。不管怎样,我的工作非常黑客化,这是我展示我低于标准工作的作品

DEMO

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(' ');
    }
};

Remember that away message on aim that said how:

Aoccdrnig to a rscheearch at Cmabrigde Uinervtisy, it deosn't mttaer in waht oredr the ltteers in a wrod are, the olny iprmoetnt tihng is taht the frist and lsat ltteer be at the rghit pclae. The rset can be a toatl mses and you can sitll raed it wouthit porbelm. Tihs is bcuseae the huamn mnid deos not raed ervey lteter by istlef, but the wrod as a wlohe.

Anyway I'm trying to make a function that would do that to an entire page. There are a few rules for this function.

  1. less then 4 characters leave alone.
  2. non-alphanumeric characters don't count as part of the word.
  3. hyphenated words are really two words
  4. words must get garbled if length >= 4 (can't be like the original)
  5. The first and last chars stay the same and only the middle chars get garbled (Thanks Hersheezy)
  6. the text should always be random and produce unique garbling on each run
  7. Pure javascript and iterates on all text nodes
  8. Shortest sweetest code wins.

Anyway it seems simple enough to implement, how's about starting a contest to see who could make the cleanest clearest code to accomplish this task. Feel free to borrow without recognition from my code (I def have)

If i missed anything add it in the comments. Anyway I worked on it very hackishly and here's me showing my less than par work

DEMO

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(' ');
    }
};

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

内心激荡 2024-10-24 01:50:48

更新(最新):不要认为它会变得更小.. 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;
});

更新甚至..更小..

甚至更小的版本
我不知道您使用的压缩器,但这必须至少小(编辑 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;
    });
}

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

//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!

UPDATE( LATEST ): Don't think it can get any smaller.. DEMO
Latest compressed (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}); 

code:

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;
});

UPDATE even.. smaller..

Even smaller version
I dont know the minifier your using, but this must be at least (EDIT 108) bytes smaller.
compressed version (365 bytes):

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})}  

Code:

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;
    });
}

EDIT
NEW RULES DEMO
CODE:

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;
    });
}

This should respect all the rules, and keep format and punctuation. DEMO

//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)
    };
} 

btw nice choice of the article, WWiWieikikb!!

拥醉 2024-10-24 01:50:48

更新

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

话虽如此,以下是上述内容的一些变化以及优点/缺点:


正式提交(473 字节)

缩小(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”)
  • 在上面添加 或将代码包装在 onload 事件中。

1 重新放置 var 声明使其更短,请参阅 479bytes473 再见)


附加版本

基本 (演示)

// 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. 灵活。这几乎适用于所有场景,尽管是快速处理食物链底部的元素或在整个 上调用它 - 这可以处理它。
  2. 非常可定制:
    1. 可以指定执行低级别(每个元素)更改,或高级别(仅没有子元素的元素)
    2. 可以指定是否要显示更改以及要应用的类(更改包含在具有指定类名的范围内)
    3. 可以指定用于扰乱的函数(也许您只想反转单词或使用更好的方法)

缺点

  1. 开销不大,但仍然很快。
  2. 也许选择太多或者太臃肿。
  3. 我确信有人会发现更多缺点

Updated

So I couldn't help but play around a bit with this thing and see what other ways I could manipulate the document with as little code as possible. Suffice it to say that it can be shortened to work in an either/or scenario, but I like to make things with options for the user to play with.

Having said that, here are some variations on the above and benefits/disappointments:


Official Submission (473bytes)

Minified (473bytes) 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;});}

Un-minified version: (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;
  });
}
  • No use of jQuery ("pure javascript")
  • Add <script src="garble.js"></script> just above </body> or wrap the code in an onload event.

1 re-placement of var declarations makes it shorter, see 479bytes vs 473 byes)


Additional Versions

Basic (demo)

// 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);

Pros

  1. Very slim and trim
  2. Options that allow you to modify the modified word (wraps each change in a span with the default "modified" class, or a class of your choosing).

Cons

  1. Won't work with nested elements (this means you have to select the lowest possible element in the DOM tree. So, if you're just going to be doing paragraphs with no hyperlinks or spans within, this is your winner)
  2. If elements that have children are used in the selector, their html formatting (such as a linkin a paragraph) will be stripped.

Slim and Trim (demo)

$(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.
    });
  });
});

Fully Featured (demo)

// 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);

Pros

  1. Flexible. This will work in just about every scenario, albeit a quick-to process bottom-of-the-food-chain element or calling it on the entire <body>--this can handle it.
  2. Very customizable:
    1. Can specify to perform low level (every element) changes, or highLevel (only elements with no children)
    2. Can specify if you want to show the changes, and what class to apply (changes are wrapped in a span with the specified class name)
    3. Can specify a function to use for scrambling (maybe you want to just reverse the words or use a better method)

Cons

  1. Little more overhead, though it is still fast.
  2. Maybe too many options or just too bloated.
  3. I'm sure someone will find more cons
南巷近海 2024-10-24 01:50:48

这是我对该功能的看法。请参阅此处的演示。

  • 它使用优秀的 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}

Here's my take on the function. See the demo here.

  • It uses the excellent jquery.ba-replacetext plugin to handle finding only text nodes
  • Handles arbitrary length words where all inner characters are equal
  • Easy to understand with descriptive names

Full version (1187 bytes):

  /* 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;
  }

Minified version (348 bytes):

$(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}
悍妇囚夫 2024-10-24 01:50:48

注意:我通过 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;

Note: I ran this through JSLint, which may have been a bad idea. Anyway, the demo is here.

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;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文