Meta
VILIC02:10 - 05.28 2011

再为腾讯的比赛写程序, 话说这个程序本身没什么难度, 就是普通的富JS页面的网页而已, 要比的有两点, 一个是主题, 一个是UI. 不过难度在我刚开始两天, 还有不到十天的时间. 虽然说貌似不用在那之前作出成品, 但半成品总得有吧.

后台选择的是PHP, 我最恨的一种脚本, 哪有什么语法, 纯粹就是堆砌! (PHPer莫生气)

那说下今天给vejis添加/改变的内容.

1. enum_ 用法如下:

var Option = enum_("abc", "def", "ghi");
//Option.abc instanceof Option == true

2. static_/public_/private_这个是针对类的, 例子如下:

var Class = class_(function (pub, pri) {
    this._(function () {
        //pub.test1 == "123"
        //pri.test2 == "321"
    });
}).static_(function () {
    this.public_(function () {
        this.test1 = "123";
    });
    this.private_(function () {
        this.test2 = "321";
    });
});

//Class.test1 == "123"
//Class.test2 == undefined

3. Typed Dictionary, 例子如下:

var dict = new (Dictionary(Object, Integer))();
var o1 = {}, o2 = {}, o3 = {};
dict.set(o1, 123);
dict.set(o2, 456);
//dict.get(o1) == 123
//dict.get(o2) == 456
//dict.exists(o3) == false

Original link of this archive: http://www.vilic.info/blog/archives/687
本文的原始链接: http://www.vilic.info/blog/archives/687

VILIC11:54 - 03.30 2011

刚刚群里有人问到JavaScript的Cookies操作, 于是想到之前也写过一个, 刚刚一搜, 是去年8月份的事情了... 不过功能还算不错, 而且使用方便, 于是整理一下, 献上:

<!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>
    <title></title>
    <script src="http://www.vilic.info/vejis/vejis.1.0.0.js" type="text/javascript"></script>
    <script src="http://www.vilic.info/vejis/cookies.1.0.0.js" type="text/javascript"></script>
    <script type="text/javascript">
        /*
        cookies[String name] 获取cookies集合中名为name的Cookie的值.
        cookies.clear() 清除所有Cookie, 并更新cookies集合, 无返回值.
        cookies.del(String name) 删除相应名称的Cookie, 并更新cookies集合, 无返回值.
        cookies.del(Array names) 批量删除相应名称的Cookie, 并更新cookies集合, 无返回值.
        cookies.get(String name) 更新cookies集合, 获取相应名称的Cookie的值, 返回值为String.
        cookies.refresh() 更新cookies集合, 无返回值.
        cookies.set(String name, String value) 设置相应名称的Cookie的值, 并更新cookies集合, 无返回值.
        cookies.set(String name, String value, Date date) 设置相应名称的Cookie的值与过期时间, 并更新cookies集合, 无返回值.
        cookies.set(Array names, Array values) 批量设置相应名称的Cookie的值, 并更新cookies集合, 无返回值.
        */

        if (cookies["abc"] == undefined) {
            alert("set cookie");
            cookies.set("abc", "123");
        }

        alert(cookies["abc"]);
    </script>
</head>
<body>

</body>
</html>

相关文件:
http://www.vilic.info/vejis/vejis.1.0.0.js
http://www.vilic.info/vejis/cookies.1.0.0.js

Original link of this archive: http://www.vilic.info/blog/archives/646
本文的原始链接: http://www.vilic.info/blog/archives/646

VILIC03:24 - 03.13 2011

这个是之前一篇 (http://www.vilic.info/blog/archives/610) 的升级版, 添加了更强的对 "类" 的支持, 取消了Null类型, 顺便修正了一些bug.

脚本链接: http://www.vilic.info/vejis/vejis-mo.js

然后是用法:

/* 函数的用法 */

//创建一个函数并定义重载1
//这里也可以使用 var fn = _(); 创建空函数, 并在以后添加重载
var fn = _(function () {
    alert("No arguments!");
});

//重载2
fn._(String, function (str) {
    alert("You got me a string: " + str + ".");
});

//重载3
fn._(String, Integer, function (str, n) {
    alert("The string is: " + str + "; and the integer is: " + n + ".");
});

fn();
fn("test1");
fn("test2", 123);

/* 类的用法 */
//定义一个类
var C = class_(function () {
    var x;

    //成员函数
    this.getX = _(function () {
        return x;
    });

    /* 也可无构造函数 */
    //构造函数重载1
    C._(Integer, function (i) {
        x = "Integer: " + i;
    });

    //构造函数重载2
    C._(String, function (s) {
        x = "String: " + s;
    });
});

//创建两个C的实例
var c1 = new C("abc");
var c2 = new C(123);

alert(c1.getX());
alert(c2.getX());

Original link of this archive: http://www.vilic.info/blog/archives/638
本文的原始链接: http://www.vilic.info/blog/archives/638

VILIC02:20 - 08.18 2010

Vlight Version: 0.3
Vejis Version: 0.0.0.5

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

这个属于心血来潮, 突然想到写一个, 然后就写了一个, 不过后来兼容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);
        });
    }
} ();

Original link of this archive: http://www.vilic.info/blog/archives/519
本文的原始链接: http://www.vilic.info/blog/archives/519

VILIC00:59 - 08.17 2010

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多行了, 虽然与一些专业的框架还相距甚远. 呵呵, 比不得. 顺便昨天七夕, 我跟代码从早到晚都在一起...

Original link of this archive: http://www.vilic.info/blog/archives/509
本文的原始链接: http://www.vilic.info/blog/archives/509