不用PS 两句代码 菜鸟都能伪造网页

今天突然想到了很多人通过PS修改了Google或者百度的页面, 得到诸如 “抱歉, 没有找到比XX更帅的人.” 这样的效果. 当然, 也有人把页面保存下来, 修改后再打开, 或者像我从前一样, 使用JS的innerHTML. 然后今天突然灵感一现, 想到了contentEditable属性, 用它不是更方便吗?

废话不多说, 如果你不懂JS, 请按下面的步骤进行修改. 当然, 如果你懂, 看完上面的一段就行了.

经测试兼容IE/FF/Chrome (如有兼容问题, 欢迎反馈: www.vilic.info)

在浏览器地址栏输入:
javascript:void(document.body.contentEditable=true);

现在, 整个页面都变成可编辑的了, 编辑的方法就像使用Word一样, 可惜的是没有什么多的功能. IE中编辑模式下会使元素有些错位, 不过不要在意, 一会儿退出编辑模式后, 一切都会恢复正常. 将想要编辑的文字修改后, 再使用下面的代码还原:
javascript:void(document.body.contentEditable=false);

现在就搞定啦, 是不是特别简单? 除了简单地修改文本, 你还可以拖动它们(和图片), 让他们换个排列方法. 不过, 这样做可能会使页面很难看哦!

祝同学们恶搞愉快!

Nokia X6 官方OVI无痛刷机 港版变国行 可更换颜色

买了个X6的换壳机, 16G, 蓝白色, 不过拿到手后发现界面依旧是粉红色的… 郁闷之际, 想通过刷机解决问题.

原来用过凤凰刷过6120c, 这次相应的应该也可以用凤凰来刷, 但是无意间看到一个通过修改手机CODE的方式来实现刷机的方法, 觉得甚妙, 于是写下来分享.

免责声明: 作者(Vilic)通过以下方法成功将固件从 “港版 白/粉红” 更新为 “国行 白/蓝”, 但是不保证此方法在其他人品条件下同样可用, 对于使用此方法造成的一切损失, 都与作者无关. 谢谢~

在刷机之前, 需要找到想要刷的版本的CODE, 你可能会用到这些:

0595776:诺基亚RM-559 国行3G 16GB的黑色/黑色
0595705:诺基亚RM-559 国行3G 16GB的白/粉红
0595778:诺基亚RM-559 国行3G 16GB的白色/黄色
0595196:诺基亚RM-559 国行3G 32GB的白/蓝
0595084:诺基亚RM-559 国行3G黑/红

如果上面没有你想刷的, 可以Google下X6 CODE. 请注意机型一定要一样. 输入*#0000#可以看到一个类似于RM-XXX的东西, 保证它和你要更改的CODE所对应的相同.

除了安装好的OVI套件, 我们还需要准备一个小软件, 叫NSS, 官方网站: http://www.b-phreaks.co.uk/, 到现在, NSS的下载地址为: http://www.b-phreaks.co.uk/index.php?main_page=page_2. 下载并完成安装.

  1. 退出NOKIA PC SUIT和OVI SUIT, 运行NSS.
  2. 使用USB数据线连接电脑和手机, 并且选择PC套件模式(其他模式未试).
  3. 单击NSS右上角的放大镜, 这时NSS会搜索设备.
  4. 完成搜索后, 在下方选择手机样式的图标(Phone Info).
  5. 在右边Production Data Edit处点Read, 来读取相应信息. (此步非必要)
  6. 将想要刷的固件对于的CODE填入Product Code文本框中, 并且勾选Enable.
  7. 点击Write写入新的CODE.
  8. 点击Read确认新的CODE已经写入成功.
  9. 关闭NSS.

现在, CODE就改好了, 下面需要做的就是打开OVI套件, 并且选择软件更新. OVI会自动检测可用的固件更新, 如果提示固件已经是最新版本, 则选择重新安装即可. 一般情况下, 数据不会丢的, 但是为了防止万一, 还是备份一下吧!

发现国行的简体中文和港版的简体中文字体上还是有区别的,  其他倒没发现什么(当然, 我换了颜色), 祝刷机成功!

JavaScript RegExp 正则表达式g模式的使用

说明下, 文章中的有些东西来自Franky大神的文章<浏览器中的 正则表达式陷阱>.

试考虑如下代码:

var re = /^\w$/g;
re.test(‘a’); //返回true
re.test(‘b’); //还是true吗?

猜猜返回值都是什么呢? 如果你已经阅读了Franky大神的那篇文章, 或者自己动手试了下, 就会发现, 一次是true, 一次是false. 原因在于正则表达式中的g, 使得搜索过程后, 如果匹配成功, 则记录上一次的位置, 如果匹配不成功, 则会归零. 所以, 如果在上面的语句中再加一条re.test(‘s’), 那么返回的将又会是我们期望的true了.

不过一般情况下, 我们自然会希望得到同样的结果, 这个时候可以在其中添加一条语句, 人工将位置归零, 防止这个 “错误” 的发生:

var re = /^\w$/g;
re.test(‘a’); //返回true
re.lastIndex = 0; //归零搜索的位置
re.test(‘b’); //返回true

或者我们可以更简单地直接将g去掉:

var re = /^\w$/;
re.test(‘a’); //返回true
re.test(‘b’); //返回true

于是, 利用g模式的这个性质, 可以这样使用. 考虑下面的代码:

var re = /\w/g; //注意, 我将分别表示开头的^和$去掉了
re.test(‘ab’);
re.test(‘ab’);

猜猜现在会返回什么呢? 答案是两个true. 用之前说到的东西也很好解释, 因为第一次记录了一个lastIndex, 但是在这个lastIndex的情况下, 同样能匹配成功第二个. 也就是说, 第一次匹配的是字符串中的a字母, 第二次则是b字母. 我在这里刻意地使用了两个相同的字符串, 因为我想告诉大家, 这才是g模式下, 正确的用法. 下面我们继续讨论这种机制存在的意义, 我也直接切入要害. 考虑下面的代码:

var re = /\d+/g;
var str = ‘1## %$xx 34*&920 3’; //包含了数字的字符串

var arr = [];

while (re.test(str))
    arr.push(RegExp.lastMatch);
/*
    上面的代码我更愿意写成:
    var parts;
    while (parts = re.exec(str))
        arr.push(parts[0]);
    这样可以避免全局的RegExp对象造成的一些问题.
*/

alert(arr); //”1,34,920,3″

点到这里, 相信大家已经初步明白这种机制的用意了,它方便自定义的遍历 (当lastIndex已经达到字符串末尾时, 并不归零), 要知道, 在明白这点之前, 我一直用着replace来完成这一步. 现在, 大家可以用自己的循环来搞定了. 这种情况也提醒了我们, 要正确地使用g参数, 像前面那种正则中包含^或者$的加上g参数, 就是完全的画蛇添足, 这些是应当避免的.

当然, 以上也只是Vilic的个人认识, 欢迎大家指正!

Vlight 开发笔记 2010.8.19

Github https://github.com/vilic/vlight

昨天主要是添加了HTML代码高亮和CSS代码高亮, 并且自动识别HTML/CSS/JS. 同时也能高亮HTML中嵌套的CSS和JS. 有些判断并不是很严谨, 但是多数情况下是适用的. 下面分别是HTML/CSS/JS代码示例.

HTML代码:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <!-- HTML Code -->
    <title>Vlight Demo</title>
    <style type="text/css">
        /* CSS Code */
        body { margin: 0px; line-height: 16px; font-size: 12px; font-family: Microsoft Yahei, Arial; }
        #test_div { height: 40px; }
        .test { background-color: #FFFFFF; }
    </style>
    <script src="vejis.js" type="text/javascript"></script>
    <script src="vlight.js" type="text/javascript"></script>
    <script type="text/javascript">
        /* JavaScript Code */
        vejis.use(vejis, true); //use vejis namespace
        _event.add(window, 'resize', resize); //add an event

        function resize() {
            var width = document.body.offsetWidth;
            alert(width);
        }
    </script>
</head>
<body>
    <h1>Vlight Demo</h1>
    <div id="test_div">
        <a href="http://www.vilic.info/" title="VILIC's Blog">VILIC's Blog</a>
        <img alt="" src="http://www.vilic.info/xxx.jpg" />
        <div></div>
    </div>
</body>
</html>

独立的CSS代码:

/* CSS Code */
body { margin: 0px; line-height: 16px; font-size: 12px; font-family: Microsoft Yahei, Arial; }
#test_div { height: 40px; }
.test { background-color: #FFFFFF; }

独立的JavaScript代码:

/* JavaScript Code */
vejis.use(vejis, true); //use vejis namespace
_event.add(window, 'resize', resize); //add an event

function resize() {
    var width = document.body.offsetWidth;
    alert(width);
}

var multilineStr = "abc\
def\
ghi";

Vlight & Vejis 开发笔记 2010.8.18

Github https://github.com/vilic/vlight

同志们可能已经发现了, 现在有代码高亮了.

这个属于心血来潮, 突然想到写一个, 然后就写了一个, 不过后来兼容IE6还是费了点事. 最后在样式上也动用了JS. 不过顺道, 也进一步完善了Vejis (Vlight需要Vejis). 代码不多, 去掉注释的话只有80+行. 所以直接贴出来, 也顺道测试下.

/*
Vlight JS Code Highlight (Style from Visual Studio 2010)

Version 0.3
Vejis JavaScript Library 0.0.0.5 is needed.

By Vilic Vane
http://www.vilic.info/

©2010 Groinup Studio
All rights reserved.

Redistribution and use in source and binary forms,
with or without modification, are permitted provided
that the following conditions are met:
Redistributions of source code must retain the above
copyright notice, this list of conditions and the
following disclaimer.
Redistributions in binary form must reproduce the
above copyright notice, this list of conditions and
the following disclaimer in the documentation and/or
other materials provided with the distribution.
Neither the name of the Groinup Studio nor the names
of its contributors may be used to endorse or promote
products derived from this software without specific
prior written permission.
*/

vejis.ready(function () {
    var className = 'vlight', //自定义类名
        maxLineCount = 20, //最多同时显示的行数
        lineHeight = 16, //行高
        scrollBarWidth = 24, //预计滚动条宽度
        cssText = //CSS内容
        'div.vlight { position: relative; margin: 5px 0px; border: solid 1px #FFF3D0; line-height: ' + lineHeight + 'px; color: #000000; font-size: 12px; font-family: Courier New, monospace; white-space: nowrap; overflow: hidden; }' +
        'div.vlight div.vlight_top { height: 5px; background-color: #FFE8A6; font-size: 0px; }' +
        'div.vlight div.vlight_left { position: absolute; width: 65px; left: 0px; text-align: right; color: #2B91AF; overflow: hidden; }' +
        'div.vlight div.vlight_left div { position: relative; width: 40px; left: 0px; padding-right: 5px; border-left: solid 16px #F0F0F0; border-right: solid 4px #6CE26C; }' +
        'div.vlight div.vlight_main { position: relative; margin-left: 65px; padding-left: 5px; overflow-x: scroll; overflow-y: auto; }' +
        'div.vlight span.vlight_comm { color: #008000; }' +
        'div.vlight span.vlight_re { color: #000000; }' +
        'div.vlight span.vlight_str { color: #800000; }' +
        'div.vlight span.vlight_key { color: #0000FF; }';

    cssText = cssText.replace(/vlight/g, className); //替换类名
    vejis.html.createStyleSheet(cssText); //创建样式

    var eles = vejis.html.getElementsByClassName(className); //获取元素
    var spanl = '<span>',
        spanr = '</span>';

    //处理每一个类名符合的元素
    vejis.foreach(eles, function (ele) {
        var div = document.createElement('div');
        div.className = className;
        div.innerHTML =
        '<div></div>' +
        '<div></div>';

        var top = div.childNodes[0],
            left = div.childNodes[1];

        var main = document.createElement('div');
        main.className = className + '_main';

        var oText;
        if (ele.tagName == 'TEXTAREA') oText = ele.value; //如果是textarea则直接取value
        else if (ele.tagName == 'PRE') oText = ele.innerText || ele.innerHTML;
        else oText = ele.innerHTML.replace(/\r?\n/g, '').replace(/<p( [^>]*)?>([\s\S]*?)<\/p>/gi, '$2\r\n\r\n').replace(/<div( [^>]*)?>([\s\S]*?)<\/div>/gi, '$2\r\n').replace(/<([a-z]+)( [^>]*)?>([\s\S]*?)<\/\1>/gi, '$3').replace(/<br[^>]*>/gi, '\r\n').replace(/&nbsp;/g, ' ').replace(/&lt;/g, '<').replace(/&gt;/g, '>').replace(/&amp;/g, '&');

        var result = convert(oText); //转换文本到高亮的HTML
        main.innerHTML = result.html;
        div.appendChild(main);

        //创建行号
        var lines = ''
        for (var i = 1; i <= result.count; i++)
            lines += i + '<br />';
        left.innerHTML = '<div>' + lines + '</div>';

        //将原来的元素替换成代码高亮区域
        ele.parentNode.replaceChild(div, ele);

        //设置高宽
        left.style.height = main.style.height = lineHeight * (result.count > maxLineCount ? maxLineCount : result.count) + scrollBarWidth + 'px';
        left.childNodes[0].style.height = result.count * lineHeight + scrollBarWidth + 'px';

        //绑定事件
        vejis._event.add(window, 'resize', resize);
        vejis._event.add(main, 'scroll', scroll);

        resize(); //初始化

        function resize() {
            try {
                main.style.width = top.offsetWidth - left.offsetWidth - 5 + 'px';
            } catch (e) { }
        }

        function scroll() {
            left.childNodes[0].style.marginTop = -main.scrollTop + 'px';
        }
    });

    function convert(text) {
        var names = ['comm', 're', 'str', 'key']; //类名的后缀

        //全局正则表达式
        var globalRE = /((\/\*[\s\S]*?\*\/|\/\/.*)|('('|.*?([^\\]'|\\\\'))|"("|.*?([^\\]"|\\\\")))|\/(\/|.*?([^\\]\/|\\\\\/))[gim]{0,3}|([^\w]|^)(break|delete|function|return|typeof|case|do|if|switch|var|catch|else|in|this|void|continue|false|instanceof|throw|while|debugger|finally|new|true|with|default|for|null|try)(?=[^\w]|$))/g;
       
        //拆分开的正则表达式
        var res = [
            /^(\/\*[\s\S]*?\*\/|\/\/.*)$/,
            /^\/(\/|.*?([^\\]\/|\\\\\/))[gim]{0,3}$/,
            /^'('|.*?([^\\]'|\\\\'))|"("|.*?([^\\]"|\\\\"))$/,
            /(break|delete|function|return|typeof|case|do|if|switch|var|catch|else|in|this|void|continue|false|instanceof|throw|while|debugger|finally|new|true|with|default|for|null|try)$/
        ];

        text = text.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;'); //符号处理

        //匹配
        text = text.replace(globalRE, function (s) {
            for (var i = 0; i < res.length; i++) {
                if (!res[i].test(s)) continue;
                var spanl2m = spanl + names[i] + spanm;

                s = s.replace(res[i], function (s) {
                    return spanl2m + s + spanr; //加标签
                });
                return s;
            }
        });

        var count = 1; //行数

        //字符处理
        text = text.replace(/\t/g, '    ').replace(/  /g, '&nbsp; ').replace(/  /g, ' &nbsp;').replace(/(\r?\n)+$/g, '').replace(/\r?\n/g, function () { count++; return '<br />'; });

        return { html: text, count: count };
    }
});

Vejis主要改进是在事件处理上(没有完全测试过, 所以可能还有大量bug), 琐碎的就不说了, 上代码:

var _event = this._event = new function () {
    var objects = [];
    var holders = [];

    this.add = _(Object, String, Function, function (obj, name, callback) {
        name = name.toLowerCase();

        var index = array.indexOf(objects, obj),
            subHolder;

        if (index < 0) {
            index = objects.length;
            objects.push(obj);
            var holder = {};
            holders.push(holder);
            createListener(holder);
        }
        else {
            var holder = holders[index];
            subHolder = holder[name];
            if (subHolder) {
                if (array.exists(subHolder, callback)) return false;
                subHolder.push(callback);
            }
            else createListener(holder);
        }

        return true;

        function createListener(holder) {
            var subHolder = holder[name] = [callback];
            subHolder.handler = handler;
            if (obj.addEventListener) obj.addEventListener(name, handler, false);
            else if (obj.attachEvent) obj.attachEvent('on' + name, handler);
        }

        function handler(ev) {
            var e = window.event || ev;
            onEvent(e, obj, name);
        }
    });

    this.remove = _(Object, String, Function, function (obj, name, callback) {
        name = name.toLowerCase();
        var index = array.indexOf(objects, obj);
        if (index < 0) return false;
        else {
            var holder = holders[index],
                subHolder;
            if (holder && (subHolder = holder[name])) {
                var idx = array.indexOf(subHolder, callback);
                if (idx < 0) return false;
                else {
                    array.removeByIndex(subHolder, idx);
                    if (!subHolder.length) {
                        var handler = subHolder.handler;
                        if (obj.removeEventListener) obj.removeEventListener(name, handler);
                        else if (obj.detachEvent) obj.detachEvent('on' + name, handler);
                        delete holder[name];
                        if (object.isEmpty(holder)) {
                            array.remove(holders, index);
                            array.remove(objects, index);
                        }
                    }
                    return true;
                }
            }
            return false;
        }
    });

    function onEvent(e, obj, name) {
        var index = array.indexOf(objects, obj);
        var callbacks = holders[index][name];

        foreach(callbacks, function (callback) {
            callback(e);
        });
    }
} ();

Vejis 开发笔记 2010.8.17

Version: 0.0.0.4

昨天做的东西比较多, 有大致有cookie的操作, 简单的get和post, json.

cookie的操作目前有1个集合, 5种方法共8次重载. (vejis的重载是我的大爱啊!) 简单操作的例子.

vejis.use(vejis, true); //使用vejis命名空间.

cookies.set(‘name’, ‘Vilic’); //添加名称为name的cookie, 值为’Vilic’.
cookies.set([‘age’, ‘sex’], [’17’, ‘male’]); //批量添加.

alert(cookies[‘name’]);

cookies.del(‘name’); //删除名称为name的cookie.

alert(cookies[‘name’]);

然后是xmlhttp, 做得比较简单, 够我用就好了:

vejis.use(vejis, true);

var data = new xmlhttp.Data();
data.title = ‘This is a test!’;
data.content = ‘Hello, I\’m Vilic!’;

var callback = _(Boolean, String, Number, function (done, text, status) {
    alert(‘Done:\n’ + done + ‘\nText:\n’ + text + ‘\nStatus:\n’ + status);
});

var xhr = xmlhttp.post(‘sample.ashx’, data, callback);

最后是json, 这个我只做了post带callback的, 因为一般不会用get来传递json.

vejis.use(vejis, true);

var callback = _(Boolean, Object, Number, function (done, value, status) {
    alert(JSON.stringify(value));
});

var obj = { name: ‘Vilic’, age: 18, hobbies: [‘Physics’, ‘JavaScript’, ‘Drawing’] };

json.post(‘sample.ashx’, ‘json’, obj, callback);

现在文件已经有500多行了, 虽然与一些专业的框架还相距甚远. 呵呵, 比不得. 顺便昨天七夕, 我跟代码从早到晚都在一起…

Vejis 开发笔记 2010.8.16

Version: 0.0.0.3

再次改进了重载算法. 然后开始各种杂项的开发, 比如string, array命名空间. 其中部分有enhance方法, 用于加强相应的原型.

之前创建可重载的函数时, 是通过函数内部创建之后return的. 但是一直想使用类似new的方法. 今天也算巩固了下之前很久听说过的一个知识:

function Test() {
    return fn;
    function fn() {
        alert(‘Test OK!’);
    }
}

var test = new Test();
test();

你认为上面的代码能弹出 “Test OK!” 吗? 答案是可以的. 但是这个时候, test instanceof Text == false. 也就是说, test此时并非Test的实例, 而是一个function(){}.

在vejis里, 虽然我最终用类似的方法实现了new Method的操作, 但得到的方法也并非Method的实例:

vejis.use(vejis, true); //使用vejis命名空间, 并且覆盖已有的方法和属性.

var test = new Method(); //创建一个可重载的方法.
test.overload(function(){ //添加一个无参数的重载.
    alert(‘Test’);
});

test(); //执行test方法.
alert(test instanceof Method); //结果是false;

另外还有包含了JSON2.js文件, 准备起床之后实现简单的AJAX函数, 我看着JQuery的, 头晕啊. 太有跳跃性了. 没打算做得它那么全, 满足我日常使用即可.

Vejis 开发笔记 2010.8.15

Version: 0.0.0.2

更改了函数重载的实现, 将原来的字符串变成了类, 扩展性更强. 见下面的MyClass.

vejis.use(vejis, true);

var test = _();

test._(Integer, function (n) {
    alert(‘Integer: ‘ + n);
});

test._(MyClass, function (obj) {
    obj.alert();
});

var obj = new MyClass();
test(18);
test(obj);

function MyClass() {
    this.alert = function () {
        alert(‘It\’s a new Class!’);
    };
}

Vejis 开发笔记 2010.8.14

Version: 0.0.0.1

选择的是BSD协议. 现在有接近200行了. 主要功能是createFunction. 下面来一段演示的代码:

vejis.use(vejis, true);

var test = createFunction();

test._(‘string’, function (name) {
    alert(‘name: ‘ + name);
});

test._(‘int’, function (age) {
   alert(‘age: ‘ + age);
});

呵呵, 看出来了吧, 函数重载. 不过在这个简单的例子上, 你可能觉得有点多余, 看看这个, 这个是vejis里的一个函数, 有4个重载:

var argsCountError = this.argsCountError = createFunction();

argsCountError._(‘integer’, function (count) {
   if (arguments.callee._caller.arguments.length != count)
      error(‘The method needs ‘ + count + ‘ argument’ + (count > 1 ? ‘s.’ : ‘.’));
});

argsCountError._(‘integer, integer’, function (least, most) {
   if (least >= most) error(‘”least” must be smaller than “most”‘);
   var count = arguments.callee._caller.arguments.length;
   if (count < least) error(‘The method needs at least ‘ + least + ‘ argument’ + (least > 1 ? ‘s.’ : ‘.’));
   if (count > most) error(‘The method needs at most ‘ + most + ‘ argument’ + (most > 1 ? ‘s.’ : ‘.’));
});

argsCountError._(‘null, integer’, function (least, most) {
   arguments = arguments.callee._caller.arguments;
   least = 0;
   argsCountError(least, most);
});

argsCountError._(‘integer, null’, function (least, most) {
   arguments = arguments.callee._caller.arguments;
   most = 25;
   argsCountError(least, most);
});

目前为止, 变量类型支持string, number, number:integer, boolean, object, object:array, object:null, function, 考虑到不同人的习惯, integer和boolean分别可以简写作int和bool. 个人觉得在函数重载很多, 而调用次数不多(其实只要不是大数量的枚举, 遍历什么的, 都不算多)时, 这个功能是非常实用的.

另外vejis.use(namespace, overwrite)也是个比较实用的东西, 虽然目前功能还非常简单, 但以后会慢慢增强.

其他的很弱, 也没什么特色了. 慢慢来.

全新WordPress主题

在两三天的艰苦劳作后, 把最基本东功能做完了. 因为心里比较着急, 就先用上了这个未完成的主题.

该主题将逐步添加更多的CSS3甚至HTML5的特性,对IE8以下的浏览器保持可用性,但是推荐使用IE8+及其他现代的浏览器。

在接下来的时间里, 我会利用空闲时间逐步完善, 并且尽快搞定一个完整的, 可发布的版本. 欢迎有兴趣的朋友关注!

Follow me on Twitter! twitter.com/vilicvane