轻量级jQuery拖拽插件和弹窗插件

[5/13更新]
1,增加对bootstrap的支持,(仅仅是用了bootstrap的样式,行为还是由本插件接管)

2,添加了bootstrap的示例页面

现在这种东西网上一抓一大把,而且也都很成熟,自己做一个一是轻量级,完全自定义,二也就一些人问我要一些轻量级插件的时候我推荐给他们用吧,毕竟出了问题我可以直接改,也不需要读别人的代码了,基本需求:

1,拖拽插件
    可对任意元素生效
    允许设置元素能否超出窗体可见范围
    如果不可拖出窗体外,同时可设置元素距离窗体四周的边距 (考虑到有些元素有投影等,需要留出边距显示投影)
    允许设置拖拽手柄(必须是该元素DOM树的子级)
2,弹窗插件
    初始设置标题/宽高/遮罩等基本功能
    可设置拖拽窗体位置
    可设置拖拽窗体大小
    支持最大化/还原,支持标题栏双击最大化/还原,与windows使用习惯一致,可禁用最大化
    单页面可无限弹窗
    多个弹窗初始位置会自动层叠,留出每个窗体的标题栏,与windows窗体行为一致
    同个页面多个弹窗之间点击,会自动激活点击的窗体,并将其带到最顶层
    激活的窗体关闭,会自动激活下一个窗体
    支持传入加载html,同域页面,以及跨域页面,加载完成前只有自定义的加载动画

其中,弹窗插件把css留给了外部,可完全自定义,插件内部只保留了部分必要css。窗体的拖动,就顺便用了拖拽插件的实现,不再另合并代码,

开发和测试版本为jQuery1.8.3,并且绑定事件的方法在拖拽插件用的是live/die, 弹窗插件是on/off,总之你用1.7以前,最好 是1.8,应该是没有问题的。

拖拽源码:

//----------------------------------------------------------------------------------------------------
// [作    者] walkerwang
// [邮    箱] walkerwzy@gmail.com
// [作者博客] http://walkerwang.cnblogs.com
// [更新日期] 2013-3-11
// [版 本 号] ver0.1.0
// [使用说明]
// $(element).dragable(options)
// options.namespace(string):命名空间,有默认值
// options.outer(boolean):是否允许弹窗超出屏幕范围,默认不允许
// options.offset({left:0,right:0,top:0,bottom:0}):元素与窗体四边的边距,outer=true时才生效
// options.handler(string/dom/jQuery object):拖动手柄,即元素内的某个元素点击才会触发拖动事件,默认为null,支持css选择器、DOM元素,jQuery对象
//=====================================================================================
(function ($) {
    $.fn.dragable = function (conf) {
        var options = $.extend({}, $.fn.dragable.defaults, conf),
		el = options.namespace + "_onmove",
        outer = options.namespace + "_outer";
        $(this).each(function (i, m) {
            var t = $(this), o = $(this);
            if (options.handler) o = $(options.handler, this);
            o.die('mousedown').live('mousedown', function (e) {
                t.data('position', { offset: o.offset(), eventx: e.pageX, eventy: e.pageY }).addClass(el);
                if (options.outer) t.addClass(outer);
            }).css('cursor', 'move');;
        });
        $("*").die("mousemove").die("mouseup")
		.live('mousemove', function (e) {
		    var m = $("." + el);
		    if (m.length == 0) return;
		    var mdata = m.data('position'), x, y;
		    if (m.is('.' + outer)) {
		        x = e.pageX - (mdata.eventx - mdata.offset.left);
		        y = e.pageY - (mdata.eventy - mdata.offset.top);
		    }
		    else {
		        x = Math.max(0 + (options.offset.left || 0), e.pageX - (mdata.eventx - mdata.offset.left)),
                y = Math.max(0 + (options.offset.top || 0), e.pageY - (mdata.eventy - mdata.offset.top)),
                wx = $(window).width() - m.width() - (options.offset.right || 0),
                wy = $(window).height() - m.height() - (options.offset.bottom || 0);
		        if (x > wx) x = wx;
		        if (y > wy) y = wy;
		    }
		    m.css({ position: 'absolute', left: x, top: y, margin: 0 });
		})
		.live('mouseup', function (e) {
		    $("." + el).removeClass(el);
		});
    };
    $.fn.dragable.defaults = {
        namespace: "mydragableplug",
        offset: { top: 0, bottom: 0, left: 0, right: 0 },
        handler: null,
        outer: false
    };
})(jQuery);

弹窗源码:

//----------------------------------------------------------------------------------------------------
// [作    者] walkerwang
// [邮    箱] walkerwzy@gmail.com
// [作者博客] http://walkerwang.cnblogs.com
// [更新日期] 2013-4-26
// [版 本 号] v 0.1.1
// [使用方法]
// var d=new dialog(options).show();
//=====================================================================================
var dialog = function (conf) {
    var self = this,
        defaults = {
            namespace: "mydialogplug_",//命名空间、ID前缀
            cover: false,//显示遮罩
            dragable: true,//可拖拽
            resizable: false,//可更改大小
            html: '',//加载html字符串
            ajax: '',//加载同域页面
            iframe: '',//iframe方式加载本域或跨域页面
            title: 'Title',//弹窗标题
            width: 600,//弹窗宽度
            height: 320,//弹窗高度
            outer: false,//允许弹窗被拖到窗体可见区域外
            dragMargin: {},//如果outer=false,设定弹窗与窗体四周的边距
            maximum: true,//允许最大化
            loading: ''//加载页面时的提示//可以传入文字,也可以外部用css来定义.dlg-loading的样式
        };

    //apply options
    self.options = $.extend({}, defaults, conf);
    self.options.dragMargin.top = self.options.dragMargin.top || 0;
    self.options.dragMargin.bottom = self.options.dragMargin.bottom || 0;
    self.options.dragMargin.left = self.options.dragMargin.left || 0;
    self.options.dragMargin.right = self.options.dragMargin.right || 0;

    //variable
    var str_dlg = '<div class="dlg-container dlg-zindex">' +
        '<div class="dlg-header">' +
            '<div class="dlg-op"><span class="dlg-max" style="display:none;"></span><span class="dlg-restore" style="display:none;"></span><span class="dlg-close"></span></div>' +
            '<div class="dlg-icon"></div>' +
            '<div class="dlg-title"></div>' +
        '</div>' +
        '<div class="dlg-body"></div>' +
        '<div class="dlg-footer"><div class="dlg-resize"></div></div>' +
    '</div>',
    str_cover = '<div class="dlg-cover dlg-zindex"></div>',
    zindex_start = 100000,
    maxed = false,
    resizeObj = self.options.namespace + "_onresize",
    css = {
        cover: { height: '100%', width: '100%', opacity: 0.5, backgroundColor: '#fff', position: 'fixed', top: 0, left: 0, display: 'none', zIndex: 99999 },
        container: { position: 'absolute', top: '50%', left: '50%' },
        close: { cursor: 'pointer' },
        body: { backgroundColor: '#fff', overflow: 'hidden' },
        loading: {},
        resize: { position: 'absolute', right: 0, bottom: 0, width: 15, height: 15, cursor: 'nw-resize' }
    },
    getActiveDialog = function () {
        return $($('.dlg-container').get().sort(function (a, b) { return parseInt($(b).css('z-index'), 10) - parseInt($(a).css('z-index'), 10); })[0]);
    },
    getMaxZindex = function () {
        var exists = $('.dlg-zindex');
        if (!exists) return zindex_start;
        var ids = exists.map(function () { return parseInt($(this).css('z-index'), 10); }).get();
        return Math.max.apply(Math, ids);
    },
    getStackedMargin = function () {
        var exists = $('.dlg-container');
        return 24 * exists.length;
    },
    getDialogBody = function () {
        return self.dialog.find('.dlg-body');
    },
    setDialogCentral = function () {
        self.dialog.css({ top: '50%', left: '50%', marginLeft: function () { return 0 - parseInt($(this).width() / 2, 10) + getStackedMargin(); }, marginTop: function () { return 0 - parseInt($(this).height() / 2, 10) + getStackedMargin() - 80; } });
    },
    setIFrameWH = function () {
        var body = getDialogBody();
        body.find('iframe').css({ width: body.width(), height: body.height() });
    },
    showLoading = function () {
        getDialogBody().html('<span class="dlg-loading">' + self.options.loading + '</span>');
    },
    hideLoading = function () {
        getDialogBody().find('.dlg-loading').remove();
    };

    //create cover
    self.cover = null;
    if (self.options.cover) {
        if (!self.cover) {
            self.cover = $(str_cover).hide().css(css.cover).css({ zIndex: getMaxZindex() + 1 }).appendTo($('body'));
        }
    };

    //create dialog
    self.dialog = $(str_dlg).hide().appendTo($('body'));
    self.id = self.options.namespace + $('.dlg-container').length;
    self.dialog.attr('id', self.id)
        .css({ zIndex: function () { return getMaxZindex() + 1; } })
        .find('.dlg-title').text(self.options.title);
    self.dialog = $("#" + self.id);

    //apply style
    self.dialog.css(css.container)
        .find('.dlg-close').css(css.close)
        .end().find('.dlg-body').css(css.body).css({ width: self.options.width, height: self.options.height })
        .end().find('.dlg-resize').css(css.resize)
        .end().find('.dlg-loading').css(css.loading)

    //attatch event
    self.dialog.on('mousedown', function () {
        var o = $(this),
            thisindexid = parseInt(o.css('z-index'), 10) || zindex_start,
            maxid = getMaxZindex();
        if (o.is('.dlg-close')) return;
        if (thisindexid == maxid) return;
        $('.dlg-active').removeClass('dlg-active');
        o.addClass('dlg-active').css('zIndex', maxid + 1);
    })
        .find('.dlg-close').on('click', function () { self.close(); });
    if (self.options.maximum) {
        self.dialog.find('.dlg-header').on('dblclick', function () {
            if (maxed) self.restoreWindow();
            else self.maxWindow();
        })
        .find('.dlg-max').on('click', function () {
            self.maxWindow();
        })
        .css('display', 'inline-block')
        .next('.dlg-restore').on('click', function () {
            self.restoreWindow();
        })
    };
    $(window).resize(function () {
        if (maxed) { maxed = false; self.maxWindow(true); return; }
    });

    //dragable
    if (self.options.dragable) self.dialog.dragable({ handler: '.dlg-header', offset: self.options.dragMargin, outer: self.options.outer });

    //resizable
    if (self.options.resizable) {
        self.dialog.find('.dlg-resize')
        .off('mousedown').on('mousedown', function (e) {
            var body = getDialogBody();
            $("." + resizeObj).removeClass(resizeObj);
            $(this).data({
                startx: e.pageX,
                starty: e.pageY,
                width: body.width(),
                height: body.height()
            }).addClass(resizeObj);
        });
        $('*').off('mousemove').off('mouseup')
        .on('mousemove', function (e) {
            var o = $('.' + resizeObj);
            if (o.length == 0) return;
            var x = e.pageX - parseInt(o.data('startx'), 10),
            y = e.pageY - parseInt(o.data('starty'), 10),
            body = o.parents('.dlg-container').eq(0).find('.dlg-body').eq(0);
            body.css({
                width: function () { return parseInt(o.data('width'), 10) + x; },
                height: function () { return parseInt(o.data('height'), 10) + y; }
            });
            setIFrameWH();
        })
        .on('mouseup', function () {
            $('.' + resizeObj).removeClass(resizeObj);
        });
    } else {
        self.dialog.find('.dlg-resize').css({ cursor: 'default', backgroundImage: 'none' });
    };

    //methods
    //load contents and show dialog
    self.show = function () {
        var body = getDialogBody();
        if (self.options.html) {
            body.html(self.options.html);
        } else if (self.options.ajax) {
            showLoading();
            body.load('page1.html', function () { hideLoading(); });
        } else if (self.options.iframe) {
            showLoading();
            var iframe = $('<iframe/>', { width: body.width(), height: body.height(), src: self.options.iframe }).css({ border: 'none', opacity: 0 })
            .appendTo(body)
            .load(function () { hideLoading(); iframe.animate({ opacity: 1 }) });
        } else body.html('content here');

        //position          
        setDialogCentral();

        //set active
        $(".dlg-active").removeClass('dlg-active');
        self.dialog.addClass('dlg-active').show();
        if (self.options.cover) self.cover.show();
        return self;
    };
    //close the dialog
    self.close = function () {
        if (self.cover) self.cover.remove();
        self.dialog.remove();
        $('.dlg-active').removeClass('dlg-active');
        getActiveDialog().addClass('dlg-active');
        return self;
    };
    //add buttons to the footer
    self.addBtn = function (name, callback) {
        if (typeof callback !== 'function') callback = null;
        $("<a/>", { text: name, click: callback, href: '#', class: 'dlg-btn' }).appendTo(self.dialog.find('.dlg-footer'));
        return self;
    };
    //maximum
    //@nocache:是否不缓存调整前窗体的大小
    self.maxWindow = function (nocache) {
        if (!self.options.maximum || maxed) return;
        self.dialog.find('.dlg-max').hide();
        var body = getDialogBody(),
            width = body.width(),
            height = body.height();
        if (!nocache) body.data('before', { width: width, height: height });
        body.css({
            width: function () { return $(window).width() - 15; },
            height: function () { return $(window).height() - self.dialog.find('.dlg-header').height() - self.dialog.find('.dlg-footer').height() - 15; }
        });
        self.dialog.css({ top: 3, left: 5, margin: 0 })
        .find('.dlg-restore').css({ display: 'inline-block' });
        setIFrameWH();
        maxed = true;
    };
    //restore
    self.restoreWindow = function () {
        if (!maxed) return;
        self.dialog.find('.dlg-restore').hide();
        var body = getDialogBody(),
            original = body.data('before');
        if (!original) original = { width: 600, height: 320 };
        body.css({ width: original.width, height: original.height });
        setDialogCentral();
        self.dialog.find('.dlg-max').css({ display: 'inline-block' });
        setIFrameWH();
        maxed = false;
    }

    return self;
}

演示(略),要想跑起来直接把源码从svn签下来吧,一直用的googlecode,就不发到github了,

【注1】css文件没有打包,直接写到演示页面了,如果觉得还行,想用到项目中去,自己专门建个文件夹存放:js/css/img,其次,主要是为了实现功能,样式没有做过多的要求,都是一次成型的,图标也是用everything在本机上用关键字,如restore.gif之类的搜出来的,一用也不觉得违和,就没继续深入了,总之默认风格比较极简,不满意只有自定义css了

【注2】代码持续有小改动,以上源码是第一次发布的版本,仅作示例,所以最好是到下面地址签出最新代码来

地址:http://jq-intellisense-autocomplete.googlecode.com/svn/trunk/

image

你会看到两个项目,第一个是我以前做的智能提示插件,前段时间做过一次代码重写,当然量不大,版本已经更新到0.5.1,第二个是今天介绍的,里面有一个演示页面,介绍了基本使用方式,就不再赘述了,如下截图:

image

调用方式截图:

image

posted @ 2013-04-26 22:58  $walker  阅读(1468)  评论(0编辑  收藏  举报