autobind.js 3.32 KB
/**
 * TODO: 
 * 1. 移除getMecJson, 插件内部操作直接更新data
 * 2. data -> view
 * 3. 细粒度数据更新
 */
define(['autobind/utils'], function (_u) {
    function _AutoBind(cfg) { 
        this.$container = $(cfg.container);
        this.$el =  _u.getEles(cfg.container);
        this.handler = cfg.handler;
        this.defaultPropKey = cfg.defaultPropKey;
        this.render = cfg.render;
    }

    _AutoBind.prototype = {
        bindEvent: function () {
            var handler = this.handler;
            var defaultPropKey = this.defaultPropKey;
            var t = this;

            _u.event(this.$container, function (e) {
                var eventType = _u.getEvtType(this);
                var keyCode = e.keyCode || window.event.keyCode;

                // 当前事件类型是否与元素类型匹配
                if (eventType.indexOf(e.type)<0) return;

                if(e.type === 'keydown' && keyCode !== 13) return;

                var propName = _u.getPropName(this) || defaultPropKey;
                var _handler = handler[propName];
                var value = _handler ? _handler.get() : this.value;
                
                t.render(propName, value);
            });
        }
    };

    return function AutoBind(settings) {
        var defaultConfig = {
            container: document.body,
            target: {}, // eg. { name: 'x' }
            handler: {}, // eg. { name: {get: Function}}
            defaultPropKey: '', // 针对只有一个key的情况 data-prop
            render: function () { }
        };
        var cfg = $.extend(defaultConfig, settings);
        var _autobind = new _AutoBind(cfg);

        _autobind.bindEvent();

        // 手动更新
        this.update = function (propKey, value) {
            var len = arguments.length;

            if (len === 0) {
                propKey = cfg.defaultPropKey;
                value = cfg.handler[propKey].get();
            }

            cfg.target[propKey] = value;
            cfg.render(propKey, value);
        };
    };
});

define('autobind/utils', function () {
    var sign_key = '[data-autobind]';
    var prop_key = 'data-autobind';
    var namespace = '__autobind__';

    return {
        getEles: function (el) {
            var $el = $(el);

            return $el.find(sign_key);
        },
        hasPropKey: function (el) {
            return el.hasAttribute(prop_key);
        },
        getPropName: function (el) {
            return $(el).attr(prop_key);
        },
        event: function ($el, callback) {
            var evts = ['focusout', 'change', 'click', 'keydown'].map(function (evt) {
                return evt + "." + namespace;
            }).join(' ');
            
            $el.off(evts, sign_key)
                .on(evts, sign_key, callback);
        },
        getEvtType: function (el) {
            var tagName = el.tagName.toLowerCase();
            var inputType = el.type;

            switch (tagName) {
                case 'input':
                    if (inputType !== 'text' && inputType !== 'number') {
                        return 'click';
                    }
                case 'textarea':
                    return 'focusout keydown';
                case 'select':
                    return 'change';
                default:
                    return 'click';
            }
        }
    };
});