img-captcha.js 6.15 KB
/**
 * Created by TaoHuang on 2016/12/12.
 */

var CODE_TYPE = require('./captcha-types');

var Captcha = function(container, options) {
    var optionDefault = {
        template: require('hbs/common/captcha.hbs'),
        refreshURI: '//www.yohobuy.com/passport/images.png',
        checkURI: '//www.yohobuy.com/passport/captcha/img'
    };

    $.extend(this, optionDefault, options);

    this.$container = $(container);
    this.$imgPics = null;
    this.$tip = null;
    this.picWidth = null;
    this.refreshCb = null;
    this.running = false;
    this.errorCode = CODE_TYPE.errorCode;
    this._isInit = false;

    // NODE: 这个是专门给自动化测试做的后门
    this.$_____trojanYohobuy = null;

    return this;
};

Captcha.prototype = {
    init: function() {
        if (this._isInit) {
            this.refresh();
            return this;
        }

        this._isInit = true;
        this.bindEvents();

        // 初始化时不自动刷新验证码
        this.refresh();

        return this;
    },

    /**
     *  method: 绑定事件
     */
    bindEvents: function() {
        this.$container
            .on('click.refresh', '.img-check-refresh', $.proxy(this.refresh, this))
            .on('click.rotate', '.img-check-pic', $.proxy(this.rotateImg, this));

        return this;
    },

    /**
     *  method: 渲染 dom
     *  @param obj data 渲染数据
     *  {
     *      imgSrc: 'src'  //图片src
     *  }
     */
    render: function(data) {
        var self = this;

        this.$container.html(this.template(data));
        this.$imgPics = this.$container.find('.img-check-pic');
        this.$tip = this.$container.find('.img-check-tip');
        this.$_____trojanYohobuy = this.$container.find('#yohobuy');
        this.picWidth = this.$imgPics.width();

        this.$imgPics.each(function(index, elem) {
            var $container = $(elem);
            var position = self.calcPosition($container);

            $container.find('img').css(position);
        });

        return this;
    },

    /**
     *  method: 计算 background-position
     *  @param num index img-check-pic 的index
     *  @param num count img-check-pic
     */
    calcPosition: function($container) {
        var positionX, positionY;
        var index = $container.index();
        var count = parseInt($container.attr('data-val'), 10);
        var unit = 'px';

        count = count % 4;

        positionX = -index * this.picWidth + unit;
        positionY = -count * this.picWidth + unit;

        return {
            'margin-left': positionX,
            'margin-top': positionY
        };
    },

    /**
     *  Handler method: 刷新验证码
     */
    refresh: function() {
        var self = this;
        var url = this.refreshURI + '?t=' + $.now();

        return $.sleep(500).then(function() {
            if (self.running) {
                return $.Deferred().reject().promise(); // eslint-disable-line
            }

            self.running = true;

            self.render({
                images: url
            });

            self.hideTip();
            self.refreshCb && self.refreshCb();
            self.running = false;
            return $.Deferred().resolve().promise(); // eslint-disable-line
        });
    },

    onRefresh: function(cb) {
        this.refreshCb = cb;
        return this;
    },

    onSuccess: function() {
        // pass
        return this;
    },

    /**
     * 检查是否正确
     */
    check: function(params) {
        var self = this;
        var uri = this.checkURI;

        if (self.getResults() === '') {
            self.showTip();
            return $.Deferred().reject().promise(); // eslint-disable-line
        }

        if (!self.checkURI) { // 跳过网络检查
            return $.Deferred().resolve().promise();  // eslint-disable-line
        }

        params = params || {};

        $.extend(params, {
            verifyCode: self.getResults()
        });

        return $.post(uri, params).then(function(result) {
            if (result.code === 200) {
                self.hideTip();
                return $.Deferred().resolve().promise(); // eslint-disable-line
            } else if (result.code === 403) {
                self.refresh();
                return $.Deferred().reject().promise(); //eslint-disable-line
            } else {
                self.showTip(result.message);
                return $.Deferred().reject().promise(); //eslint-disable-line
            }
        });
    },


    /**
     * Handler method: 旋转图片
     */
    rotateImg: function(event) {
        var $picContainer = $(event.target).parent();
        var prevRotateCount = parseInt($picContainer.attr('data-val'), 10);

        $picContainer.attr('data-val', prevRotateCount + 1);
        $picContainer.find('img').css(this.calcPosition($picContainer));

    },

    /**
     * method: 获取结果
     * @return string '0123'
     */
    getResults: function() {
        var result = [];

        this.$container.find('.img-check-pic')
            .each(function() {
                var $elem = $(this);
                var val = $elem.attr('data-val');

                val = parseInt(val, 10);

                result.push(val % 4);
            });

        if (this.$_____trojanYohobuy && this.$_____trojanYohobuy.val()) {
            result = [];
            result.push(this.$_____trojanYohobuy.val());
        }

        return result.join(',');
    },

    /**
     *  显示错误
     */
    showTip: function(msg) {
        if (msg) {
            this.$tip.find('em').html(msg);
        } else {
            this.$tip.find('em').html('请将图形验证码翻转至正确方向');
        }

        if (this.$tip) {
            this.$tip.removeClass('hide');
        }
        return this;
    },

    /**
     * 隐藏错误
     */
    hideTip: function() {
        if (this.$tip) {
            this.$tip.addClass('hide');
        }
        return this;
    },

    show: function() {
        this.$container.removeClass('hide');
        return this;
    },

    hide: function() {
        this.$container.addClass('hide');
        return this;
    }
};

Captcha.prototype.construct = Captcha;

require('../../common/promise');

module.exports = Captcha;