SOURCE

/**
 * @modify daringuo
 * @date 2017.06.14
*/
;(function(window, document) {
    // 黑名单逻辑,对应blankListFunc
    var blankList = ['richText', 'link', 'word'];

    var blankListFunc = {
        // richText: 富文本
        richText: function () {
            var textSelection = textObj.getTextSelection(), $anchor = textSelection.anchorNode, isRichFlag = false;
            var isRich = function ($node) {
                if (isRichFlag === false && $node !== document.body) {
                    var attrContenteditable = $node.getAttribute('contenteditable');
                    if (attrContenteditable === '' || attrContenteditable === 'true') {
                        isRichFlag = true;
                    } else {
                        isRich($node.parentElement);
                    }
                }
            };
            isRich($anchor.parentElement);
            return isRichFlag;
        },
        // link: 超链接
        link: function () {
            var textSelection = textObj.getTextSelection(), $anchor = textSelection.anchorNode, isRichFlag = false;
            if ($anchor.parentElement && $anchor.parentElement.nodeName === 'A') {
                return true;
            } else {
                return false;
            }
        },
        // 纯字母,空格,字符之类的不出(避免和翻译插件的冲突)
        word: function () {
            var text = textObj.getSelectedText();
            if (/[\u4e00-\u9fa5]/.test(text)) {
                return false
            } else {
                if (!/[a-zA-Z]/.test(text)) {
                    return false;
                }
                return true;
            }
        }
    };

    function TextObj () {
        var text;
        // 获取选中的文本句柄,由于是插件,不用兼容IE
        this.getTextSelection = function() {
            var sel = window.getSelection();
            if (sel && sel.focusNode && sel.focusNode.nodeType == 3 && sel.getRangeAt(0).commonAncestorContainer) {
                return sel;
            } else {
                return null;
            }
        };
        this.getSearchEl = function() {
            var el = document.getElementById('qb-sougou-search');
            if (el) {
                return el;
            }
            el = document.createElement('div');
            el.id = 'qb-sougou-search';
            el.innerHTML = '<p>搜索</p><p class="last-btn">复制</p><iframe src=""></iframe>';
            document.getElementsByTagName('body')[0].appendChild(el);
            return el;
        };
        this.getSelectedText = function() {
            var textSelection = this.getTextSelection();
            if (textSelection) {
                return textSelection.toString();
            }
        };
        // 获取弹出坐标, gap参数为偏移值
        this.getXY = function(screenX, screenY, outerWidth, outerHeight, gap) {
            var _this = this;
            // 简易冒泡
            var sort = function (array, key) {
                var i, j, flag, temp;
                for (i = 0; i < array.length - 1 ;i++) {
                    flag = false;
                    for (j = array.length - 1 ;j > i ;j--) {
                        if (array[j][key] < array[j - 1][key]){
                            temp = array[j];
                            array[j] = array[j - 1];
                            array[j - 1] = temp;
                            flag = true;
                        }
                    }
                    if (flag == false) {
                        return;
                    }
                }
            };
            // 获取选中区域边界点
            var getAllRectPoint = function () {
                var sel = _this.getTextSelection(),
                    pointArr = [], i, rects = sel.getRangeAt(0).getClientRects(), newRect = [],
                    fontSize = window.parseFloat(window.getComputedStyle(sel.anchorNode.parentElement)['font-size']);

                var pickTop = function (item) {
                    // 取矩形上面的点
                    // 左上点
                    pointArr.push({
                        position: 'lt',
                        point: {
                            x: item.left,
                            y: item.top
                        }
                    });
                    // 右上点
                    pointArr.push({
                        position: 'rt',
                        point: {
                            x: item.right,
                            y: item.top
                        }
                    });
                };

                var pickBottom = function (item) {
                    // 取矩形下面的点
                    // 左下点
                    pointArr.push({
                        position: 'lb',
                        point: {
                            x: item.left,
                            y: item.bottom
                        }
                    });
                    // 右下点
                    pointArr.push({
                        position: 'rb',
                        point: {
                            x: item.right,
                            y: item.bottom
                        }
                    });
                };

                for (i = 0; i < rects.length; i++) {
                    // if (rects[i].width >= fontSize) {
                        newRect.push(rects[i]);
                    // }
                }


                pickTop(newRect[0]);
                pickBottom(newRect[newRect.length - 1]);

                return pointArr;
            }
            // 获取按距离鼠标松开距离排序得边界点数组
            var getSortedPoint = function () {
                var pointArr = getAllRectPoint();
                pointArr.forEach(function (item) {
                    var distance = Math.pow(item.point.x - screenX, 2) + Math.pow(item.point.y - screenY, 2);
                    distance = Math.sqrt(distance);
                    item.distance = distance;
                });
                sort(pointArr, 'distance');
                return pointArr;
            }
            // 获取弹出坐标
            var getOriginPoint = function () {
                var sortedPointArr = getSortedPoint(screenX, screenY),
                    scrollLeft = document.documentElement.scrollLeft || document.body.scrollLeft,
                    scrollTop = document.documentElement.scrollTop || document.body.scrollTop,
                    screenHeight = document.documentElement.clientHeight,
                    screenWidth = document.documentElement.clientWidth,
                    originPoint;

                sortedPointArr.forEach(function (item) {
                    if (originPoint) {
                        return;
                    }
                    var point = item.point;
                    // 判断
                    if (item.position.indexOf('t') >= 0) {
                        // 上面的点
                        if (point.y - outerHeight - gap > 0) {
                            originPoint = {
                                x: point.x + scrollLeft,
                                y: point.y + scrollTop - outerHeight - gap
                            };
                        }
                    }

                    if (item.position.indexOf('b') >= 0) {
                        // 下面的点
                        if (point.y + outerHeight + gap < screenHeight) {
                            originPoint = {
                                x: point.x + scrollLeft,
                                y: point.y + scrollTop + gap
                            };
                        }
                    }

                });

                if (originPoint.x <= 0) {
                    originPoint.x = gap;
                }

                if (originPoint.x + outerWidth >= screenWidth + scrollLeft) {
                    originPoint.x = screenWidth + scrollLeft - outerWidth - gap;
                }
                return originPoint;
            };

            return getOriginPoint();
        };
        this.pop = function(screenX, screenY) {
            text = this.getSelectedText();
            if (!text) {
                return;
            }
            var rect;
            var searchEl = this.getSearchEl();
            var len;
            text = text.replace(/[\n\r\t]/g, '');
            len = this.getTextLength(text);
            if (len && len <= 80) {
                rect = this.getXY(screenX, screenY, 107, 26, 12);
                searchEl.style.left = rect.x + 'px';
                searchEl.style.top = rect.y + 'px';
                searchEl.style.display = 'block';
                searchEl.style.opacity = '1';

                chrome.extension.sendMessage({
                    cmd: 'pop',
                    url: document.URL
                });
                // reportElt.contentWindow.postMessage({
                //   protocol: 8107,
                //   key: 200500,
                //   strV: document.URL
                // }, '*');
            }
        };
        this.close = function() {
            var searchEl = this.getSearchEl();
            searchEl.style.display = 'none';
            searchEl.style.opacity = '0';
        }
        this.getTextLength = function(str) {
            var len = str.length;
            var lenStart, lenEnd;
            str = escape(str.replace(/%/g, ''));
            lenStart = str.length;
            str = str.replace(/%/g, '');
            lenEnd = str.length;
            return len + lenStart - lenEnd;
        };
        this.getText = function() {
            return text;
        }
    }

    function initReport() {
        var elt = document.createElement('iframe');
        elt.id = 'qb-iframe-report';
        elt.src = 'http://stdl.qq.com/stdl/qb9/extension-report/report.html';
        elt.style.display = 'none';
        document.body.appendChild(elt);
        return elt;
    }

    var textObj = new TextObj();
    var originX, originY, originElt;
    // var reportElt = initReport();

    document.addEventListener('mousedown', function (e) {
        e = e || event;
        originX = e.pageX || e.clientX;
        originY = e.pageY || e.clientY;
        originElt = e.target || e.srcElement || {};
    }, false);

    document.addEventListener('mouseup', function (e) {
        var e = e || event;
        var x = e.x || e.clientX;
        var y = e.y || e.clientY;
        var target = e.target || e.srcElement || {};
        var blankTag = false;
        try {
            textObj.close();

            if (/input|textarea/i.test(target.nodeName) || /input|textarea/i.test(originElt.nodeName)) {
              return;
            }

            var textSelection = textObj.getTextSelection();

            if (!textSelection) {
                return;
            }

            var boundingClientRect = textSelection.getRangeAt(0).getBoundingClientRect();

            if (boundingClientRect.top === boundingClientRect.bottom || boundingClientRect.left === boundingClientRect.right) {
                return;
            }

            if (originX == x && originY == y) {
              return;
            }

            // 黑名单逻辑(富文本,链接,包含单词的情况)
            blankList.forEach(function (item) {
                if (blankListFunc[item]() === true) {
                    blankTag = true;
                }
            });

            if (blankTag) {
                return;
            }

            setTimeout(function () {
              textObj.pop(x, y);
            }, 50);
        } catch(e) {

        }


    }, false);

    document.addEventListener('click', function (e) {
        var target = e.srcElement || e.target;
        var text = textObj.getText();
        if (target.parentElement && target.parentElement.id == 'qb-sougou-search') {
          if (target.innerHTML == '搜索') {
            chrome.extension.sendMessage({cmd: 'search', text: text});
            // reportElt.contentWindow.postMessage({
            //   protocol: 8107,
            //   key: 200501,
            //   strV: text
            // }, '*');
          }
          else if (target.innerHTML == '复制') {
            document.execCommand( 'Copy' );
            chrome.extension.sendMessage({cmd: 'copy', text: text});
            // reportElt.contentWindow.postMessage({
            //   protocol: 8107,
            //   key: 200502,
            //   strV: text
            // }, '*');
          }
        }
    }, false);

    // 数据摸底
    (function () {
        var screenHeight = document.documentElement.clientHeight;
        var srollHeight = document.body.scrollHeight;
        var fnScroll = function (e) {
            if (window.scrollY + screenHeight >= srollHeight) {
                window.external.dataReport(8888, 313, 0, 1, 0, 0, window.location.href, '', '');
            }
        };
        window.addEventListener('scroll', fnScroll, false);
    }());

})(window, window.document);
console 命令行工具 X clear

                    
>
console