jQuery Select

TextMate下的中文看起来实在是费劲,所以就都去掉了。

使用很简单,select还是按照原来的BOM去写,然后构造对应DOM的jQuery对象,再调用selectinput方法即可。

BTW:下拉菜单的样式需要自己去写一下,对应的样式参数在conf.css这个对象下。

/*
 * Select zhangjingwei
 * Released under the MIT, BSD, and GPL Licenses.
 */
(function ($) {
 
    $.tools = $.tools || {
        version: '1.3'
    };
 
    var instances = [],
    tool = $.tools.selectinput = {
        conf: {
            offset: 0, // 弹出菜单偏移量
            trigger: false, // 默认触发
            css: {
                // ids
                root: 0,
                head: 0,
 
                // classnames
                list: 0,    // liststyle ?
                off: 0,     // 鼠标移动上的样式
                focus: 0,   // 获取焦点样式
                disabled: 0, // 禁止选择样式
                trigger: 0, // 触发后的样式
                current: 0, // 节点被选中的样式
                mouseon: 0  // 鼠标移动触发样式
            }
        }
    }
 
    function Selects(select, conf, i) {
        var self = this,
        css = conf.css,
        hid = css.head || "selhead_jQuery" + i,
        rid = css.root || "selroot_jQuery" + i,
        root = $("#" + rid),
        head = $("#" + hid),
        title,
        index,
        currentClass = css.current,
        opened,
        selstyle = select.offset(),
        fire = select.add(self);
        // 容灾处理
        if (!root.length && !head.length) {
            var body = $("body");
            index = getSelectIndex(), title = getSelectText();
 
            root = $('<ul />').css(selstyle).css({ "position": "absolute", "height": "auto" }).addClass(css.list).attr("id", rid).hide();
 
            select.find("option").each(function (i, n) {
                var val = n.value, text = n.firstChild.nodeValue || n.innerText;
                root.append("<li data-value='" + val + "' data-index='" + i + "'><a href='#'>" + text + "</a></li>")
            });
            root.find("li").eq(index).addClass(currentClass);
 
            head = $("<a />").attr("href", "#").html(title).css(selstyle).css({ "position": "absolute" }).addClass(css.off).attr("id", hid).click(function (e) {
                self.show();
                return e.preventDefault();
            }).appendTo(body);
 
            body.append(root);
 
            select.css("visibility", "hidden");
 
			$(window).resize(function () {
                var pos = select.offset();
                head.css(pos);
            });
        }
 
        if (conf.trigger) {
            self.show();
        }
 
        function onShow(ev) {
            ev.type = "onShow";
            fire.trigger(ev);
 
            // click outside select
            $(document).bind("click.sel", function (e) {
                var el = e.target;
 
                if (el != head[0]) {
                    self.hide(e);
                }
            });
        }
 
        // 选择函数
        function selected(index, e) {
            var elem = root.find("li"),
			currentElem = elem.eq(index),
			currentText = currentElem.text();
 
            elem.removeClass(css.current);
            currentElem.addClass(css.current);
            head.html(currentText);
            setSelected(index);
 
            // change
            e = e || $.Event("api");
            e.type = "change";
 
            fire.trigger(e, index);
            if (e.isDefaultPrevented()) {
                return;
            }
 
            self.hide(e);
        }
 
        /*
        * 设置selectindex
        */
        function setSelected(index) {
            select[0].selectedIndex = index;
        }
 
        /*
        * 获取选中项值
        */
        function getSelectVal() {
            return select.find("option:selected").val();
        }
 
        /*
        * 获取选中项文本
        */
        function getSelectText() {
            return select.find("option:selected").text();
        }
 
        /*
        * 获取selectindex
        */
        function getSelectIndex() {
            return select[0].selectedIndex;
        }
 
        $.extend(self, {
            show: function (e) {
                if (select.attr("disabled") || opened) {
                    return;
                }
                // onBeforeShow
                e = e || $.Event();
                e.type = "onBeforeShow";
                fire.trigger(e);
                if (e.isDefaultPrevented()) {
                    return;
                }
 
                // 关闭所有已打开select
                $.each(instances, function () {
                    this.hide();
                });
                opened = true;
 
                root.find("li").unbind("click mouseenter mouseleave").click(function (e) {
                    self.setValue($(this).index(), e);
                    return false;
                }).hover(
                    function () {
                        $(this).addClass(css.mouseon);
                    },
                    function () {
                        $(this).removeClass(css.mouseon);
                    }
                );
 
                // show select
                var pos = select.offset();
 
                // iPad position fix
                if (/iPad/i.test(navigator.userAgent)) {
                    pos.top -= $(window).scrollTop();
                }
 
                if (conf.offset) {
                    root.css({
                        top: pos.top + conf.offset[0],
                        left: pos.left + conf.offset[1]
                    });
                }
 
                root.show();
                onShow(e);
 
                return self;
            },
            hide: function (e, slis) {
                if (opened) {
                    // onHide
                    e = $.Event();
                    e.type = "onHide";
                    fire.trigger(e);
 
                    $(document).unbind("click.sel").unbind("keydown.sel");
 
                    // cancelled ?
                    if (e.isDefaultPrevented()) {
                        return;
                    }
 
                    // do the hide
                    root.hide();
                    root.find("li").unbind("click");
                    opened = false;
                }
 
                return self;
            },
            setValue: function (index, evt) {
                evt = evt || $.Event("api");
                selected(index, evt, conf);
                return self;
            },
            reflow: function () {
                var pos = select.offset(),
				headelem = select.data("selectinput");
 
                if (headelem) {
                    head.css({ top: pos.top, left: pos.left });
                }
                return self;
            },
            getConf: function () {
                return conf;
            },
            getRoot: function () {
                return root;
            },
            getHead: function () {
                return head;
            },
            getSelect: function () {
                return select;
            },
            isOpen: function () {
                return opened;
            }
        });
 
        // callbacks
        $.each(['onBeforeShow', 'onShow', 'change', 'onHide'], function (i, name) {
 
            // configuration
            if ($.isFunction(conf[name])) {
                $(self).bind(name, conf[name]);
            }
 
            // API methods
            self[name] = function (fn) {
                if (fn) {
                    $(self).bind(name, fn);
                }
                return self;
            };
        });
    }
 
    $.fn.selectinput = function (conf) {
 
        // 单例
        if (this.data("selectinput")) {
            return this;
        }
 
        //
        conf = $.extend(true, {}, tool.conf, conf);
 
        var els;
 
        this.each(function (key) {
            var el = new Selects($(this), conf, $.now() + key);
            instances.push(el);
            var sel = el.getSelect().data("selectinput", el);
            els = els ? els.add(sel) : sel;
        });
        return els ? els : this;
    };
})(jQuery);

原文链接(336 views)|评论 (2)

javascript 序列化

类似php中的serialize方法
BTW:当数据类型是null的时候,由于使用typeof 进行验证,所以会出现问题.(typeof null == “object”) // true

function serialize(_obj)
{
   // Let Gecko browsers do this the easy way
   if (typeof _obj.toSource !== 'undefined' && typeof _obj.callee === 'undefined')
   {
      return _obj.toSource();
   }
 
   // Other browsers must do it the hard way
   switch (typeof _obj)
   {
      // numbers, booleans, and functions are trivial:
      // just return the object itself since its default .toString()
      // gives us exactly what we want
      case 'number':
      case 'boolean':
      case 'function':
         return _obj;
         break;
 
      // for JSON format, strings need to be wrapped in quotes
      case 'string':
         return '\'' + _obj + '\'';
         break;
 
      case 'object':
         var str;
         if (_obj.constructor === Array || typeof _obj.callee !== 'undefined')
         {
            str = '[';
            var i, len = _obj.length;
            for (i = 0; i < len-1; i++) { str += serialize(_obj[i]) + ','; }
            str += serialize(_obj[i]) + ']';
         }
         else
         {
            str = '{';
            var key;
            for (key in _obj) { str += key + ':' + serialize(_obj[key]) + ','; }
            str = str.replace(/\,$/, '') + '}';
         }
         return str;
         break;
 
      default:
         return 'UNKNOWN';
         break;
   }
}

来源:http://blog.stchur.com/2007/04/06/serializing-objects-in-javascript/–Serializing Objects in Javascript

原文链接(138 views)|评论 (3)

构造函数(constructor)的超类

  function test1( name ){
    this.name = name;
  }
 
  function test2( name ){
    test1.call(this,name);
    this.say = function(){}
  }
 
  test2.prototype = new test1;
 
  var t = new test2("nihao");
 
  console.log(t);
  console.log(t.constructor);

t的constructor说明了t的构造函数是test1,而不是test2。

这是因为t的constructor实际上是test2.prototype的constructor,而test2.prototype = new test1;因此test2test2.prototype的constructor属性就指向到了test1的prototype.constructor上test1.prototype的constructor上,也就是test1。

罗里吧嗦的,这标题起的还挺唬人的~呵呵

原文链接(74 views)|沙发已被占领(1)

Javascript File API for Mozilla

1. 文件读取函数
readAsBinaryString() 读取文件内容,读取结果为一个 binary string。文件每一个 byte 会被表示为一个 [0..255] 区间内的整数。函数接受一个 File 对象作为参数。
readAsText() 读取文件内容,读取结果为一串代表文件内容的文本。函数接受一个 File 对象以及文本编码名称作为参数。
readAsDataURL 读取文件内容,读取结果为一个 data: 的 URL。DataURL 由 RFC2397 定义,具体可以参考 http://www.ietf.org/rfc/rfc2397.txt。

2. 文件读取事件
Onloadstart 文件读取开始时触发。
Progress 当读取进行中时定时触发。事件参数中会含有已读取总数据量。
Abort 当读取被中止时触发。
Error 当读取出错时触发。
Load 当读取成功完成时触发。
Loadend 当读取完成时,无论成功或者失败都会触发。

<form name="demoForm" id="demoForm" method="post" enctype="multipart/form-data" 
onsubmit="uploadAndSubmit();return false;"> 
<p>Upload File: <input type="file" name="file" /></p> 
<p><input type="submit" value="Submit" /></p> 
</form> 
<div>Progessing (in Bytes): <span id="bytesRead"> 
</span> / <span id="bytesTotal"></span> 
</div>
  function uploadAndSubmit() {
    var form = document.forms["demoForm"]; 
 
     if (form["file"].files.length > 0) {
     // 寻找表单域中的 <input type="file" ... /> 标签
     var file = form["file"].files[0];
     // try sending
     var reader = new FileReader(); 
 
     C.log(reader);
     reader.onloadstart = function() {
     // 这个事件在读取开始时触发
     C.log("onloadstart");
     document.getElementById("bytesTotal").textContent = file.size;
     }
     reader.onprogress = function(p) {
     // 这个事件在读取进行中定时触发
     C.log("onprogress");
     document.getElementById("bytesRead").textContent = p.loaded;
     } 
 
     reader.onload = function() {
        // 这个事件在读取成功结束后触发
        console.log("load complete");
     } 
 
     reader.onloadend = function() {
        // 这个事件在读取结束后,无论成功或者失败都会触发
     if (reader.error) {
        C.log(reader.error);
     } else {
        document.getElementById("bytesRead").textContent = file.size;
        C.log(reader.readyState);
     }
     } 
 
        reader.readAsBinaryString(file);
     } else {
        C.log("请选择上传文件");
     }
    }
 
    var C = {
    // console wrapper
    debug: true, // global debug on|off
    quietDismiss: false, // may want to just drop, or alert instead
    log: function() {
        if (!C.debug) return false;
 
        if (typeof console == 'object' && typeof console.log != "undefined") {
            console.log.apply(this, arguments);
        }
        else {
            if (!C.quietDismiss) {
                var result = "";
                for (var i = 0, l = arguments.length; i < l; i++)
                    result += arguments[i] + " ("+typeof arguments[i]+") ";
 
                var elem = document.createElement("textarea");
                elem.innerHTML = result;
				document.body.appendChild(elem);
                }
            }
        }
    }; // end console wrapper.

fileAPI Demo:fileAPI.zip

原文链接(145 views)|暂无评论(赶紧抢沙发)

jQuery inViewport

晚上在微博上“拔赤”写了个lazyload插件,发现其中用到一个很有意思的方法”div.inViewportRegion()”,字面意思就是在可视区域内。

在网上找了找,发现这是YUI提供的一个组件,觉得很有意思。
http://gillserver.com/yui/api/dom-region.js.html

如果jQ里面也包含类似的方法,可以做很多事,于是GG了一下,发现国外的同学写过这种选择器,代码表现上更直观。

代码如下:

(function($) {
 
    $.belowthefold = function(element, settings) {
        var fold = $(window).height() + $(window).scrollTop();
        return fold < = $(element).offset().top - settings.threshold;
    };
 
    $.abovethetop = function(element, settings) {
        var top = $(window).scrollTop();
        return top >= $(element).offset().top + $(element).height() - settings.threshold;
    };
 
    $.rightofscreen = function(element, settings) {
        var fold = $(window).width() + $(window).scrollLeft();
        return fold < = $(element).offset().left - settings.threshold;
    };
 
    $.leftofscreen = function(element, settings) {
        var left = $(window).scrollLeft();
        return left >= $(element).offset().left + $(element).width() - settings.threshold;
    };
 
    $.inviewport = function(element, settings) {
        return !$.rightofscreen(element, settings) && !$.leftofscreen(element, settings) && !$.belowthefold(element, settings) && !$.abovethetop(element, settings);
    };
 
    $.extend($.expr[':'], {
        "below-the-fold": function(a, i, m) {
            return $.belowthefold(a, {threshold : 0});
        },
        "above-the-top": function(a, i, m) {
            return $.abovethetop(a, {threshold : 0});
        },
        "left-of-screen": function(a, i, m) {
            return $.leftofscreen(a, {threshold : 0});
        },
        "right-of-screen": function(a, i, m) {
            return $.rightofscreen(a, {threshold : 0});
        },
        "in-viewport": function(a, i, m) {
            return $.inviewport(a, {threshold : 0});
        }
    });
 
})(jQuery);

来源:http://www.appelsiini.net/projects/viewport

简单测了下,不错,呵呵~

Demo:http://www.zhangjingwei.com/inviewport.zip

原文链接(88 views)|暂无评论(赶紧抢沙发)