同源页面预览: jQuery.Preview.js插件

这是子游拜托我做的一个jQuery插件, 提供类似于SwiftPreview扩展程序的功能, 需要CSS3支持.

Gist: https://gist.github.com/BlackGlory/956a6eae2f39ff442c9a

如有更新会放在Gist.

已知缺陷: 受浏览器同源策略限制, 只能预览同源页面(代码内置了同源检查, 避免产生额外请求). 不支持响应式设计的页面, 缩放功能会在响应式站点失效.

使用方法:

/*
 * jQuery bindPreview([width = 400[, height = width * 0.618[, offsetX = 20[, offsetY = 10]]]])
 * width, height, offsetX, offsetY分别对应预览窗口的宽, 高, 与界面边缘的水平偏移量, 与界面边缘的垂直偏移量.
 */
$('a').bindPreview()

/*
 * jQuery unbindPreview()
 * 取消bindPreview()的绑定
 */
$('a').unbindPreview()

插件源代码:

/*
 * jQuery.Preview v1.1
 * Author: BlackGlory
 * Homepage: http://www.blackglory.me
 * Date: 2014-06-07
 */

(function($) {
    'use strict'

    var div = $('<div/>'),
        iframe = $('<iframe/>'),
        originCheck = function(url) {
            var parser = document.createElement('a');
            parser.href = url
            return parser.host === location.host
        },
        iframeLoadHandle = function(e) {
            var fullWidth = iframe[0].contentDocument.body.scrollWidth,
                scale = (scale = e.data.width / fullWidth) > 1 ? 1 : scale
            iframe.css({
                'transform': 'scale(' + scale + ')',
                'height': e.data.height / scale,
                'width': e.data.width / scale,
            })
        },
        mouseleaveHandle = function(e) {
            div.hide()
            iframe.attr('src', '')
        },
        mousemoveHandle = function(e) {
            var height = e.data.height,
                width = e.data.width,
                offsetX = e.data.offsetX,
                offsetY = e.data.offsetY,
                top = e.pageY - (height / 2),
                left = e.pageX + offsetX

            if (e.clientY - height / 2 + height > $(window).height()) {
                top = $(window).height() - offsetY - height + (e.pageY - e.clientY)
            } else if (top - e.pageY < 0) {
                top = (e.pageY - e.clientY) + offsetY
            }

            if ((e.clientX + offsetX + width) > $(window).width()) {
                left -= offsetX * 2 + width
            } else if (left - e.pageX < 0) {
                left = (e.pageX - e.clientX) + offsetX
            }

            div.css({
                'top': top,
                'left': left,
            })
        },
        mouseenterHandle = function(e) {
            var href = $(this).attr('href')
            if (href && originCheck(href)) {
                iframe.one('load', e.data, iframeLoadHandle)
                iframe.attr('src', href)

                div.css({
                    'height': e.data.height,
                    'width': e.data.width,
                })

                div.show()
            }
        }

    div.append(iframe)

    div.css({
        'position': 'absolute',
        'top': 0,
        'left': 0,
        'display': 'none',
        'border': '1px solid black',
        'z-index': '99999',
    })

    iframe.css({
        'border': 'none',
        'transform-origin': '0 0',
    })

    $(function() {
        $('body').append(div)
    })

    $.fn.bindPreview = function(width, height, offsetX, offsetY) {
        width = width || 400
        height = height || width * 0.618
        offsetX = offsetX || 20
        offsetY = offsetY || 10

        var data = {
            'width': width,
            'height': height,
            'offsetX': offsetX,
            'offsetY': offsetY,
        }

        this.on('mouseenter', data, mouseenterHandle)
        this.on('mousemove', data, mousemoveHandle)
        this.on('mouseleave', data, mouseleaveHandle)

        return this
    }

    $.fn.unbindPreview = function() {
        this.off('mouseenter', mouseenterHandle)
        this.off('mousemove', mousemoveHandle)
        this.off('mouseleave', mouseleaveHandle)

        return this
    }

})(jQuery)