JavaScript工具之客户端调试用JS

开发背景

有些产品在开发中会涉及到客户端,而在客户端中开发调试中,一些调试工具不能发挥作用。特别是在遇上与JS相关问题之后,却不知道哪里出问题,调试手段也仅剩alert这种方式。并且因为无法查看控制台,console.log也不能使用,而alert也只能查看简单类型的数据,类似对象之类的便无法查看了。所以,遇上问题之后,常常会卡在那里,不知道该从何下手,通常一个小问题都会卡很久,但是最后发现错误的时候,获取只是因为多一个或者少一个符号。在缺乏一个有效的调试手段时,开发过程变艰难很多。所以便想要整理出一个JS组件,该组件能帮助捕获程序异常,并能有效打印复杂变量。当然,如果你有其他更有效的调试工具(手段),望不吝赐教,感激不尽。

修改日志

2016-01-21 –基本上重写该组件。提供更多的用法。
2016-01-22 –重写调试信息生成部分代码,能更加灵活方便的生成语句,且提供了更详细的参数显示。
2016-01-25 –新增多种格式输出,例如GE.log(data, ‘json’), GE.log(data, ‘html’)
2016-01-26 –剔除之前的jquery依赖,纯JS实现。并修复IE兼容问题。下载地址资源:http://download.csdn.net/detail/a7326012009/9418647
2016-01-27 –添加队列机制,新增翻页,便于调试,修复部分样式及功能错误

使用说明

组件介绍:目前版本的debug.js比较简陋,只提供两个功能,1、捕获异常 2、调试输出复杂变量。如果日后在工作中有新的需求,会进行及时更新。

使用方式
1、于页面中引入debug.js即可如

< scritp id=”hq-jquery-client”
data-pop-width=”300” data-pop-height=”400” data-debug-switch=”on”
s rc=”jquery-client-debug.js”>

2、关于捕获异常功能:调试功能可以通过参数配置进行开关。通过在script引入的时候对data-debug-switch进行on/off。
3、关于输出变量:在需要输出的变量名称后使用GE.log即可,如GE.log(thsInfo)。

参数说明

data-pop-width : 调试窗口的宽度,默认200px;
data-pop-height : 调试窗口的高度,默认400px;
data-debug-switch : on/off 开启/关闭错误提示
data-wrap-sptor-num : 1 换行间距,默认一个换行距离
data-level-sptor-num : 2 行里间距,默认两个制表符距离

GE.log参数说明
GE.log(data, type);
—- data[必选],想要打印的变量
—- type[可选],选择欲输出的类型,目前可提供json,html形式输出

// @charset "utf-8";
/**
 * 客户端调试用JS(jQuery版)
 * author   : yinggaozhen(yinggaozhen@myhexin.com)
 * create   : 2015-9-10
 * version  : 0.0.4
 * @demo :
 * <script type="text/javascript" id="hq-jquery-client" data-pop-width="300" data-pop-height="400" data-debug-switch="on" src="jquery-client-debug.js" ></script>
 * var std = {name : 'jack'} 
 * GE.log(std);  
 */
+function($, window) {
    var JQUERY_TAG_ID        = '#hq-jquery-client';
    var RECUR_WRAP_SPTOR     = '<br>';
    var RECUR_LEVEL_SPTOR    = '&emsp;';
    var OBJECT_SENTENCE      = '';

    var COMPLEX_RENDER_TEMPLATE = "__LEVELSP____KEY__ __ARROW__ __TYPE__(__SIZE__)__WRAPSP__";
    var SINGLE_RENDER_TEMPLATE  = "__LEVELSP____KEY__ __ARROW__ __VALUE__(__TYPE__)__WRAPSP__";

    var DEFAULT_OPTIONS = {
        popMask    : 'off',
        popWidth   : 200,
        popHeight  : 400,
        wrapSptorNum  : 1,
        levelSptorNum : 2,
        debugOnlyClient : 'on'
    }

    if (typeof jQuery === 'undefined') {
        throw new Error('No Detected Jquery Plz To Load It~');
        return;
    }

    if (typeof GE !== 'undefined') {
        throw new Error('The Variable `GE` is Already Exist!');
        return;
    }

    GE = {};

    GE.init = function(printType) {
        this.isInit        = true;
        this.isShown       = false;
        this.isClient      = false;
        this.loadCssStatus = false;

        this.printType     = (printType || 'normal').toUpperCase();

        this.options       = $.extend({}, DEFAULT_OPTIONS, $(JQUERY_TAG_ID).data());

        this.recurWrapSptor  = this._repeatSptor(this.options.wrapSptorNum, RECUR_WRAP_SPTOR);
        this.recurLevelSptor = this._repeatSptor(this.options.levelSptorNum, RECUR_LEVEL_SPTOR);

        try {
            external.createObject('Quote');
            this.isClient = true;
        } catch (e) {
        }
    }

    GE.log = function(data, type) {
        if (!this.isInit) this.init(type);

        if (this.options.debugOnlyClient === 'off' || (this.options.debugOnlyClient === 'on' && this.isClient)) {
            var rsivDta = null;
            dataType = this._typeJudge(data);

            switch (this.printType) {
                case 'JSON' : 
                    break;
                case 'HTML' : 
                    break;
                default :
                    break;
            }

            rsivDta = rsivDta === null ? this._rsiv(data) : rsivDta;
            this._pop(rsivDta); 
        } else {
            console.log(data);
        }
    }

    GE._rsiv = function (data, level) {
        var me = this,
            rsivTxt = '';

        level = level ? parseInt(level) : 0;

        var renderDta     = {};

        renderDta.type    = me._typeJudge(data);
        renderDta.wrapSp  = me.recurWrapSptor;
        renderDta.levelSp = me._repeatSptor(level, me.recurLevelSptor)

        if ('Array' === renderDta.type || 'Object' === renderDta.type) {
            for (var key in data) {
                renderDta.type = me._typeJudge(data[key]);
                renderDta.key  = key;

                if (data[key] && ('Array' === renderDta.type || 'Object' === renderDta.type)) {
                    renderDta.size = me._calObjectSize(data[key]);
                    rsivTxt += me._renderTemplate(renderDta, 'complex');
                    rsivTxt += me._rsiv(data[key], level + 1);
                } else {
                    renderDta.value = data[key];
                    rsivTxt += me._renderTemplate(renderDta);
                }
            }
        } else {
            renderDta.key   = '';
            renderDta.value = data;
            rsivTxt += me._renderTemplate(renderDta);
        }

        return rsivTxt;
    }

    GE._renderTemplate = function(renderDta, renderType) {
        renderType = renderType || 'single';
        var _renderTemplate = renderType == 'single' ? SINGLE_RENDER_TEMPLATE : COMPLEX_RENDER_TEMPLATE;
        renderDta.arrow = renderDta.key ? '=>' : '';

        for (var renderKey in renderDta) {
            _renderTemplate = _renderTemplate.replace('__' + renderKey.toUpperCase() + '__', renderDta[renderKey]);
        }

        return '<pre>' + _renderTemplate + '</pre>';
    }

    GE._pop = function(rsivDta, width, height) {
        width   = parseFloat(width)  || this.options.popWidth;
        height  = parseFloat(height) || this.options.popHeight;

        this._loadStyle();
        var builedPop = this._buildPop(rsivDta)

        $('body').append(builedPop.popBody);
        if (this.options.popMask == 'on') $('body').append(builedPop.popMask);

        var $cPopBox   = $("#c_pop_box"),
            $cMask 	   = $("#mark");

        var adjustHeight = ($(window).height() - height) / 2;

        $cPopBox.show().css({
            'width'       :   width,
            'height'      :   height,
            'margin-left' :   -(width  / 2) + 'px',
            'margin-top'  :   -(height / 2) + 'px',
            '_top'        :   'expression(eval(document.documentElement.scrollTop)+' + adjustHeight + ')'
        })

        $(window).scroll(function() {
            if (navigator.userAgent.indexOf("MSIE 6.0") > 0) {
                $cPopBox.css('_top', 'expression(eval(document.documentElement.scrollTop)+' + adjustHeight + ')');
                $cPopBox.css('_position', 'absolute');
            }
        });

        $cPopBox.on('click', '#c_hd_close', function() {
            $cPopBox.remove();
            $cMask.remove();
        });
    }

    GE._loadStyle = function () {
        if (!this.loadCssStatus) {
            var cssFileLink  = document.createElement('link'),
                headDom      = document.getElementsByTagName('head')[0];

            cssFileLink.href = 'http://s.thsi.cn/css/test/debug.css';
            cssFileLink.type = 'text/css';
            cssFileLink.rel  = 'stylesheet';
            headDom.insertBefore(cssFileLink, headDom.firstChild);
            GE.loadCssSta = true;
        }
    }

    GE._buildPop = function(rsivDta) {
        rsivDta = rsivDta || '无调试信息...';

        return {
            popBody : '<div class="c_pop" id="c_pop_box"><div class="pop_hd"><span class="hd_title" id="c_hd_title">调试信息</span><a href="###" class="hd_close" id="c_hd_close">x</a></div><div class="pop_content" id="c_pop_content">' + rsivDta +'</div></div>',
            popMask : '<div class="mark" id="mark"></div>'
        }
    }

    GE._typeJudge = function(value) {
        return Object.prototype.toString.call(value).replace(/\[object \s |\]/g, '');
    }

    GE._repeatSptor = function(reNum, reVal) {
        reNum = typeof reNum == 'number' ? reNum : (parseInt(reNum) || 1);
        return new Array(reNum + 1).join(reVal);
    }

    GE._calObjectSize = function(d) {
        return $.map(d || {}, function(o) {
            if (typeof o != 'undefined') return 1;
        }).length;
    }

    GE._htmlspecialchars = function(html) {
        return html;

        //发现IE6下读取文本错误=_=
        return html.replace(/&/g, '&amp;')
                   .replace(/"/g, '&quot;').replace(/'/g, '&#039;')
                   .replace(/</g, '&lt;').replace(/>/g, '&gt;')
                   .replace(/\n/g, '<br>').replace(/\t/g, '&emsp;');
    }

    //The Function For Debug
    var debugSwitch = $(JQUERY_TAG_ID).data().debugSwitch || 'on';
    if ('on' === debugSwitch) {
        window.onerror = function(errorMsg, errorUrl, errorLine) {
            var errorInfo = [];
            errorInfo.push('错误信息: ' + errorMsg + "\n");
            errorInfo.push('错误页面: ' + errorUrl + "\n");
            errorInfo.push('错误位置: ' + errorLine + "行\n");
            alert(errorInfo.join(''));
            return false;
        }
    }

}(jQuery, window)
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值