Bootstrap Table 列宽自由调整(最新可用)

今天有个新需求,需要列宽自由调整,教程都不全,还什么具体可见bootstrap-table的官方文档,链接都404了,我是去Bootstrap官网找到的js,既然都出教程了,js不能发出来?

还什么插件还依赖于colResizable v1.6?根本是直接用colResizable.js就可以实现了好吗。。。

 我的Bootstrap Table是js加载数据的,如果你们的也是,那么可以直接参考。

 

问题事实上只引入colResizable-1.6.js即可实现自由拖拽

f12看到引入bootstrap-table-resizable.js变黑了,根本不需要好吗,一样实现可自由拖拽,当然引入了也不会报错,自己斟酌要不要吧

 

 

1.colResizable-1.6.js代码和bootstrap-table-resizable.js代码

/**
               _ _____           _          _     _      
              | |  __ \         (_)        | |   | |     
      ___ ___ | | |__) |___  ___ _ ______ _| |__ | | ___ 
     / __/ _ \| |  _  // _ \/ __| |_  / _` | '_ \| |/ _ \
    | (_| (_) | | | \ \  __/\__ \ |/ / (_| | |_) | |  __/
     \___\___/|_|_|  \_\___||___/_/___\__,_|_.__/|_|\___|
     
    v1.6 - jQuery plugin created by Alvaro Prieto Lauroba
    
    Licences: MIT & GPL
    Feel free to use or modify this plugin as far as my full name is kept    
    
    If you are going to use this plug-in in production environments it is 
    strongly recommended to use its minified version: colResizable.min.js

*/

(function($){     
    
    var d = $(document);         //window object
    var h = $("head");            //head object
    var drag = null;            //reference to the current grip that is being dragged
    var tables = {};            //object of the already processed tables (table.id as key)
    var    count = 0;                //internal count to create unique IDs when needed.    
    
    //common strings for packing
    var ID = "id";    
    var PX = "px";
    var SIGNATURE ="JColResizer";
    var FLEX = "JCLRFlex";
    
    //short-cuts
    var I = parseInt;
    var M = Math;
    var ie = navigator.userAgent.indexOf('Trident/4.0')>0;
    var S;
    try{S = sessionStorage;}catch(e){}    //Firefox crashes when executed as local file system
    
    //append required CSS rules  
    h.append("<style type='text/css'>  .JColResizer{table-layout:fixed;} .JColResizer > tbody > tr > td, .JColResizer > tbody > tr > th{overflow:hidden;padding-left:0!important; padding-right:0!important;}  .JCLRgrips{ height:0px; position:relative;} .JCLRgrip{margin-left:-5px; position:absolute; z-index:5; } .JCLRgrip .JColResizer{position:absolute;background-color:red;filter:alpha(opacity=1);opacity:0;width:10px;height:100%;cursor: e-resize;top:0px} .JCLRLastGrip{position:absolute; width:1px; } .JCLRgripDrag{ border-left:1px dotted black;    } .JCLRFlex{width:auto!important;} .JCLRgrip.JCLRdisabledGrip .JColResizer{cursor:default; display:none;}</style>");

    
    /**
     * Function to allow column resizing for table objects. It is the starting point to apply the plugin.
     * @param {DOM node} tb - reference to the DOM table object to be enhanced
     * @param {Object} options    - some customization values
     */
    var init = function( tb, options){    
        var t = $(tb);                    //the table object is wrapped
        t.opt = options;                //each table has its own options available at anytime
        t.mode = options.resizeMode;    //shortcuts
        t.dc = t.opt.disabledColumns;
        if(t.opt.disable) return destroy(t);                //the user is asking to destroy a previously colResized table
        var    id = t.id = t.attr(ID) || SIGNATURE+count++;    //its id is obtained, if null new one is generated        
        t.p = t.opt.postbackSafe;                             //short-cut to detect postback safe         
        if(!t.is("table") || tables[id] && !t.opt.partialRefresh) return;         //if the object is not a table or if it was already processed then it is ignored.
        if (t.opt.hoverCursor !== 'e-resize') h.append("<style type='text/css'>.JCLRgrip .JColResizer:hover{cursor:"+ t.opt.hoverCursor +"!important}</style>");  //if hoverCursor has been set, append the style
        t.addClass(SIGNATURE).attr(ID, id).before('<div class="JCLRgrips"/>');    //the grips container object is added. Signature class forces table rendering in fixed-layout mode to prevent column's min-width
        t.g = []; t.c = []; t.w = t.width(); t.gc = t.prev(); t.f=t.opt.fixed;    //t.c and t.g are arrays of columns and grips respectively                
        if(options.marginLeft) t.gc.css("marginLeft", options.marginLeft);      //if the table contains margins, it must be specified
        if(options.marginRight) t.gc.css("marginRight", options.marginRight);      //since there is no (direct) way to obtain margin values in its original units (%, em, ...)
        t.cs = I(ie? tb.cellSpacing || tb.currentStyle.borderSpacing :t.css('border-spacing'))||2;    //table cellspacing (not even jQuery is fully cross-browser)
        t.b  = I(ie? tb.border || tb.currentStyle.borderLeftWidth :t.css('border-left-width'))||1;    //outer border width (again cross-browser issues)
        // if(!(tb.style.width || tb.width)) t.width(t.width()); //I am not an IE fan at all, but it is a pity that only IE has the currentStyle attribute working as expected. For this reason I can not check easily if the table has an explicit width or if it is rendered as "auto"
        tables[id] = t;     //the table object is stored using its id as key    
        createGrips(t);        //grips are created 
    
    };


    /**
     * This function allows to remove any enhancements performed by this plugin on a previously processed table.
     * @param {jQuery ref} t - table object
     */
    var destroy = function(t){
        var id=t.attr(ID), t=tables[id];        //its table object is found
        if(!t||!t.is("table")) return;            //if none, then it wasn't processed     
        t.removeClass(SIGNATURE+" "+FLEX).gc.remove();    //class and grips are removed
        delete tables[id];                        //clean up data
    };


    /**
     * Function to create all the grips associated with the table given by parameters 
     * @param {jQuery ref} t - table object
     */
    var createGrips = function(t){    
    
        var th = t.find(">thead>tr:first>th,>thead>tr:first>td"); //table headers are obtained
        if(!th.length) th = t.find(">tbody>tr:first>th,>tr:first>th,>tbody>tr:first>td, >tr:first>td");     //but headers can also be included in different ways
        th = th.filter(":visible");                    //filter invisible columns
        t.cg = t.find("col");                         //a table can also contain a colgroup with col elements        
        t.ln = th.length;                            //table length is stored    
        if(t.p && S && S[t.id])memento(t,th);        //if 'postbackSafe' is enabled and there is data for the current table, its coloumn layout is restored
        th.each(function(i){                        //iterate through the table column headers            
            var c = $(this);                         //jquery wrap for the current column        
            var dc = t.dc.indexOf(i)!=-1;           //is this a disabled column?
            var g = $(t.gc.append('<div class="JCLRgrip"></div>')[0].lastChild); //add the visual node to be used as grip
            g.append(dc ? "": t.opt.gripInnerHtml).append('<div class="'+SIGNATURE+'"></div>');
            if(i == t.ln-1){                        //if the current grip is the las one 
                g.addClass("JCLRLastGrip");         //add a different css class to stlye it in a different way if needed
                if(t.f) g.html("");                 //if the table resizing mode is set to fixed, the last grip is removed since table with can not change
            }
            g.bind('touchstart mousedown', onGripMouseDown); //bind the mousedown event to start dragging 
            
            if (!dc){ 
                //if normal column bind the mousedown event to start dragging, if disabled then apply its css class
                g.removeClass('JCLRdisabledGrip').bind('touchstart mousedown', onGripMouseDown);      
            }else{
                g.addClass('JCLRdisabledGrip'); 
            }

            g.t = t; g.i = i; g.c = c;    c.w =c.width();        //some values are stored in the grip's node data as shortcut
            t.g.push(g); t.c.push(c);                        //the current grip and column are added to its table object
            c.width(c.w).removeAttr("width");                //the width of the column is converted into pixel-based measurements
            g.data(SIGNATURE, {i:i, t:t.attr(ID), last: i == t.ln-1});     //grip index and its table name are stored in the HTML                                                 
        });     
        t.cg.removeAttr("width");    //remove the width attribute from elements in the colgroup 

        t.find('td, th').not(th).not('table th, table td').each(function(){  
            $(this).removeAttr('width');    //the width attribute is removed from all table cells which are not nested in other tables and dont belong to the header
        });        
        if(!t.f){
            t.removeAttr('width').addClass(FLEX); //if not fixed, let the table grow as needed
        }
        syncGrips(t);                 //the grips are positioned according to the current table layout            
        //there is a small problem, some cells in the table could contain dimension values interfering with the 
        //width value set by this plugin. Those values are removed
        
    };
    
    
    /**
     * Function to allow the persistence of columns dimensions after a browser postback. It is based in
     * the HTML5 sessionStorage object, which can be emulated for older browsers using sessionstorage.js
     * @param {jQuery ref} t - table object
     * @param {jQuery ref} th - reference to the first row elements (only set in deserialization)
     */
    var memento = function(t, th){ 
        var w,m=0,i=0,aux =[],tw;
        if(th){                                        //in deserialization mode (after a postback)
            t.cg.removeAttr("width");
            if(t.opt.flush){ S[t.id] =""; return;}     //if flush is activated, stored data is removed
            w = S[t.id].split(";");                    //column widths is obtained
            tw = w[t.ln+1];
            if(!t.f && tw){                            //if not fixed and table width data available its size is restored
                t.width(tw*=1);
                if(t.opt.overflow) {                //if overfolw flag is set, restore table width also as table min-width
                    t.css('min-width', tw + PX);
                    t.w = tw;
                }
            }
            for(;i<t.ln;i++){                        //for each column
                aux.push(100*w[i]/w[t.ln]+"%");     //width is stored in an array since it will be required again a couple of lines ahead
                th.eq(i).css("width", aux[i] );     //each column width in % is restored
            }            
            for(i=0;i<t.ln;i++)
                t.cg.eq(i).css("width", aux[i]);    //this code is required in order to create an inline CSS rule with higher precedence than an existing CSS class in the "col" elements
        }else{                            //in serialization mode (after resizing a column)
            S[t.id] ="";                //clean up previous data
            for(;i < t.c.length; i++){    //iterate through columns
                w = t.c[i].width();        //width is obtained
                S[t.id] += w+";";        //width is appended to the sessionStorage object using ID as key
                m+=w;                    //carriage is updated to obtain the full size used by columns
            }
            S[t.id]+=m;                            //the last item of the serialized string is the table's active area (width), 
                                                //to be able to obtain % width value of each columns while deserializing
            if(!t.f) S[t.id] += ";"+t.width();     //if not fixed, table width is stored
        }    
    };
    
    
    /**
     * Function that places each grip in the correct position according to the current table layout     
     * @param {jQuery ref} t - table object
     */
    var syncGrips = function (t){    
        t.gc.width(t.w);            //the grip's container width is updated                
        for(var i=0; i<t.ln; i++){    //for each column
            var c = t.c[i];             
            t.g[i].css({            //height and position of the grip is updated according to the table layout
                left: c.offset().left - t.offset().left + c.outerWidth(false) + t.cs / 2 + PX,
                height: t.opt.headerOnly? t.c[0].outerHeight(false) : t.outerHeight(false)                
            });            
        }     
    };
    
    
    
    /**
    * This function updates column's width according to the horizontal position increment of the grip being
    * dragged. The function can be called while dragging if liveDragging is enabled and also from the onGripDragOver
    * event handler to synchronize grip's position with their related columns.
    * @param {jQuery ref} t - table object
    * @param {number} i - index of the grip being dragged
    * @param {bool} isOver - to identify when the function is being called from the onGripDragOver event    
    */
    var syncCols = function(t,i,isOver){
        var inc = drag.x-drag.l, c = t.c[i], c2 = t.c[i+1];             
        var w = c.w + inc;    var w2= c2.w- inc;    //their new width is obtained                    
        c.width( w + PX);            
        t.cg.eq(i).width( w + PX); 
        if(t.f){ //if fixed mode
            c2.width(w2 + PX);
            t.cg.eq(i+1).width( w2 + PX);
        }else if(t.opt.overflow) {                //if overflow is set, incriment min-width to force overflow
            t.css('min-width', t.w + inc);
        }
        if(isOver){
            c.w=w; 
            c2.w= t.f ? w2 : c2.w;
        }
    };

    
    /**
    * This function updates all columns width according to its real width. It must be taken into account that the 
    * sum of all columns can exceed the table width in some cases (if fixed is set to false and table has some kind 
    * of max-width).
    * @param {jQuery ref} t - table object    
    */
    var applyBounds = function(t){
        var w = $.map(t.c, function(c){            //obtain real widths
            return c.width();
        });
        t.width(t.w = t.width()).removeClass(FLEX);    //prevent table width changes
        $.each(t.c, function(i,c){
            c.width(w[i]).w = w[i];                //set column widths applying bounds (table's max-width)
        });
        t.addClass(FLEX);                        //allow table width changes
    };
    
    
    /**
     * Event handler used while dragging a grip. It checks if the next grip's position is valid and updates it. 
     * @param {event} e - mousemove event binded to the window object
     */
    var onGripDrag = function(e){    
        if(!drag) return; 
        var t = drag.t;        //table object reference 
        var oe = e.originalEvent.touches;
        var ox = oe ? oe[0].pageX : e.pageX;    //original position (touch or mouse)
        var x =  ox - drag.ox + drag.l;            //next position according to horizontal mouse position increment
        var mw = t.opt.minWidth, i = drag.i ;    //cell's min width
        var l = t.cs*1.5 + mw + t.b;
        var last = i == t.ln-1;                             //check if it is the last column's grip (usually hidden)
        var min = i? t.g[i-1].position().left+t.cs+mw: l;    //min position according to the contiguous cells
        var max = t.f ?     //fixed mode?
            i == t.ln-1? 
                t.w-l: 
                t.g[i+1].position().left-t.cs-mw:
            Infinity;                                 //max position according to the contiguous cells 
        x = M.max(min, M.min(max, x));                //apply bounding        
        drag.x = x;     drag.css("left",  x + PX);     //apply position increment    
        if(last){                                    //if it is the last grip
            var c = t.c[drag.i];                    //width of the last column is obtained
            drag.w = c.w + x- drag.l;         
        }              
        if(t.opt.liveDrag){             //if liveDrag is enabled
            if(last){
                c.width(drag.w);
                if(!t.f && t.opt.overflow){            //if overflow is set, incriment min-width to force overflow
                   t.css('min-width', t.w + x - drag.l);
                }else {
                    t.w = t.width();
                }
            }else{
                syncCols(t,i);             //columns are synchronized
            }
            syncGrips(t);
            var cb = t.opt.onDrag;                            //check if there is an onDrag callback
            if (cb) { e.currentTarget = t[0]; cb(e); }        //if any, it is fired            
        }
        return false;     //prevent text selection while dragging                
    };
    

    /**
     * Event handler fired when the dragging is over, updating table layout
     * @param {event} e - grip's drag over event
     */
    var onGripDragOver = function(e){    
        
        d.unbind('touchend.'+SIGNATURE+' mouseup.'+SIGNATURE).unbind('touchmove.'+SIGNATURE+' mousemove.'+SIGNATURE);
        $("head :last-child").remove();                 //remove the dragging cursor style    
        if(!drag) return;
        drag.removeClass(drag.t.opt.draggingClass);        //remove the grip's dragging css-class
        if (!(drag.x - drag.l == 0)) {
            var t = drag.t;
            var cb = t.opt.onResize;         //get some values    
            var i = drag.i;                 //column index
            var last = i == t.ln-1;         //check if it is the last column's grip (usually hidden)
            var c = t.g[i].c;               //the column being dragged
            if(last){
                c.width(drag.w);
                c.w = drag.w;
            }else{
                syncCols(t, i, true);    //the columns are updated
            }
            if(!t.f) applyBounds(t);    //if not fixed mode, then apply bounds to obtain real width values
            syncGrips(t);                //the grips are updated
            if (cb) { e.currentTarget = t[0]; cb(e); }    //if there is a callback function, it is fired
            if(t.p && S) memento(t);     //if postbackSafe is enabled and there is sessionStorage support, the new layout is serialized and stored
        }
        drag = null;   //since the grip's dragging is over                                    
    };    
    
    
    /**
     * Event handler fired when the grip's dragging is about to start. Its main goal is to set up events 
     * and store some values used while dragging.
     * @param {event} e - grip's mousedown event
     */
    var onGripMouseDown = function(e){
        var o = $(this).data(SIGNATURE);            //retrieve grip's data
        var t = tables[o.t],  g = t.g[o.i];            //shortcuts for the table and grip objects
        var oe = e.originalEvent.touches;           //touch or mouse event?
        g.ox = oe? oe[0].pageX: e.pageX;            //the initial position is kept
        g.l = g.position().left;
        g.x = g.l;
        
        d.bind('touchmove.'+SIGNATURE+' mousemove.'+SIGNATURE, onGripDrag ).bind('touchend.'+SIGNATURE+' mouseup.'+SIGNATURE, onGripDragOver);    //mousemove and mouseup events are bound
        h.append("<style type='text/css'>*{cursor:"+ t.opt.dragCursor +"!important}</style>");     //change the mouse cursor
        g.addClass(t.opt.draggingClass);     //add the dragging class (to allow some visual feedback)                
        drag = g;                            //the current grip is stored as the current dragging object
        if(t.c[o.i].l) for(var i=0,c; i<t.ln; i++){ c=t.c[i]; c.l = false; c.w= c.width(); }     //if the colum is locked (after browser resize), then c.w must be updated        
        return false;     //prevent text selection
    };
    
    
    /**
     * Event handler fired when the browser is resized. The main purpose of this function is to update
     * table layout according to the browser's size synchronizing related grips 
     */
    var onResize = function(){
        for(var t in tables){
            if( tables.hasOwnProperty( t ) ) {
                t = tables[t];
                var i, mw=0;
                t.removeClass(SIGNATURE);   //firefox doesn't like layout-fixed in some cases
                if (t.f) {                  //in fixed mode
                    t.w = t.width();        //its new width is kept
                    for(i=0; i<t.ln; i++) mw+= t.c[i].w;        
                    //cell rendering is not as trivial as it might seem, and it is slightly different for
                    //each browser. In the beginning i had a big switch for each browser, but since the code
                    //was extremely ugly now I use a different approach with several re-flows. This works 
                    //pretty well but it's a bit slower. For now, lets keep things simple...   
                    for(i=0; i<t.ln; i++) t.c[i].css("width", M.round(1000*t.c[i].w/mw)/10 + "%").l=true; 
                    //c.l locks the column, telling us that its c.w is outdated                                    
                }else{     //in non fixed-sized tables
                    applyBounds(t);         //apply the new bounds 
                    if(t.mode == 'flex' && t.p && S){   //if postbackSafe is enabled and there is sessionStorage support,
                        memento(t);                     //the new layout is serialized and stored for 'flex' tables
                    }
                }
                syncGrips(t.addClass(SIGNATURE));
            }
        } 
        
    };        


    //bind resize event, to update grips position 
    $(window).bind('resize.'+SIGNATURE, onResize); 


    /**
     * The plugin is added to the jQuery library
     * @param {Object} options -  an object that holds some basic customization values 
     */
    $.fn.extend({  
        colResizable: function(options) {           
            var defaults = {
            
                //attributes:
                
                resizeMode: 'fit',                    //mode can be 'fit', 'flex' or 'overflow'
                draggingClass: 'JCLRgripDrag',    //css-class used when a grip is being dragged (for visual feedback purposes)
                gripInnerHtml: '',                //if it is required to use a custom grip it can be done using some custom HTML                
                liveDrag: false,                //enables table-layout updating while dragging    
                minWidth: 15,                     //minimum width value in pixels allowed for a column 
                headerOnly: false,                //specifies that the size of the the column resizing anchors will be bounded to the size of the first row 
                hoverCursor: "e-resize",          //cursor to be used on grip hover
                dragCursor: "e-resize",          //cursor to be used while dragging
                postbackSafe: false,             //when it is enabled, table layout can persist after postback or page refresh. It requires browsers with sessionStorage support (it can be emulated with sessionStorage.js). 
                flush: false,                     //when postbakSafe is enabled, and it is required to prevent layout restoration after postback, 'flush' will remove its associated layout data 
                marginLeft: null,                //in case the table contains any margins, colResizable needs to know the values used, e.g. "10%", "15em", "5px" ...
                marginRight: null,                 //in case the table contains any margins, colResizable needs to know the values used, e.g. "10%", "15em", "5px" ...
                disable: false,                    //disables all the enhancements performed in a previously colResized table    
                partialRefresh: false,            //can be used in combination with postbackSafe when the table is inside of an updatePanel,
                disabledColumns: [],            //column indexes to be excluded

                //events:
                onDrag: null,                     //callback function to be fired during the column resizing process if liveDrag is enabled
                onResize: null                    //callback function fired when the dragging process is over
            }            
            var options =  $.extend(defaults, options);        
            
            //since now there are 3 different ways of resizing columns, I changed the external interface to make it clear
            //calling it 'resizeMode' but also to remove the "fixed" attribute which was confusing for many people
            options.fixed = true;
            options.overflow = false;
            switch(options.resizeMode){
                case 'flex': options.fixed = false; break;
                case 'overflow': options.fixed = false; options.overflow = true; break;
            }

            return this.each(function() {                
                 init( this, options);             
            });
        }
    });
})(jQuery);
colResizable-1.6.js代码
/**
 * @author: Dennis Hernández
 * @webSite: http://djhvscf.github.io/Blog
 * @version: v2.0.0
 */

const isInit = that => that.$el.data('resizableColumns') !== undefined

const initResizable = that => {
  if (that.options.resizable && !that.options.cardView && !isInit(that)) {
    that.$el.resizableColumns({
      store: window.store
    })
  }
}

const destroy = that => {
  if (isInit(that)) {
    that.$el.data('resizableColumns').destroy()
  }
}

const reInitResizable = that => {
  destroy(that)
  initResizable(that)
}

$.extend($.fn.bootstrapTable.defaults, {
  resizable: false
})

const BootstrapTable = $.fn.bootstrapTable.Constructor
const _initBody = BootstrapTable.prototype.initBody
const _toggleView = BootstrapTable.prototype.toggleView
const _resetView = BootstrapTable.prototype.resetView

BootstrapTable.prototype.initBody = function (...args) {
  const that = this
  _initBody.apply(this, Array.prototype.slice.apply(args))

  that.$el
    .off('column-switch.bs.table page-change.bs.table')
    .on('column-switch.bs.table page-change.bs.table', () => {
      reInitResizable(that)
    })
}

BootstrapTable.prototype.toggleView = function (...args) {
  _toggleView.apply(this, Array.prototype.slice.apply(args))

  if (this.options.resizable && this.options.cardView) {
    // Destroy the plugin
    destroy(this)
  }
}

BootstrapTable.prototype.resetView = function (...args) {
  const that = this

  _resetView.apply(this, Array.prototype.slice.apply(args))

  if (this.options.resizable) {
    // because in fitHeader function, we use setTimeout(func, 100);
    setTimeout(() => {
      initResizable(that)
    }, 100)
  }
}
bootstrap-table-resizable.js代码

2.需要拖拽的表页面底部引入js并且调用代码

<script src="/js/colResizable-1.6.js"/>
<script src="/ajax/libs/bootstrap-table/extensions/resizable/bootstrap-table-resizable.js"></script>
     <script type="text/javascript">
         $(function(){
             $("#bootstrap-table").colResizable({
                 liveDrag:true,
                 gripInnerHtml:"<div class='grip'></div>",
                 draggingClass:"dragging",
                 resizeMode:'fit'
             });
         });
     </script>

 

posted @ 2020-09-30 14:12  千夜大魔王  阅读(3099)  评论(0编辑  收藏  举报