/**_ _____ _ _ _ | | __ \ (_) | | | | ___ ___ | | |__) |___ ___ _ ______ _| |__ | | ___ / __/ _ \| | _ // _ \/ __| |_ / _` | '_ \| |/ _ \| (_| (_) | | | \ \ __/\__ \ |/ / (_| | |_) | | __/\___\___/|_|_| \_\___||___/_/___\__,_|_.__/|_|\___|v1.6 - jQuery plugin created by Alvaro Prieto LaurobaLicences: MIT & GPLFeel 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 objectvar h =$("head");//head objectvar drag =null;//reference to the current grip that is being draggedvar 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 packingvarID="id";varPX="px";varSIGNATURE="JColResizer";varFLEX="JCLRFlex";//short-cutsvarI= parseInt;varM= Math;var ie = navigator.userAgent.indexOf('Trident/4.0')>0;varS;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*/varinit=function( tb, options){var t =$(tb);//the table object is wrappedt.opt = options;//each table has its own options available at anytimet.mode = options.resizeMode;//shortcutst.dc = t.opt.disabledColumns;if(t.opt.disable)returndestroy(t);//the user is asking to destroy a previously colResized tablevar 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 stylet.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-widtht.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 specifiedif(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*/vardestroy=function(t){var id=t.attr(ID), t=tables[id];//its table object is foundif(!t||!t.is("table"))return;//if none, then it wasn't processed t.removeClass(SIGNATURE+" "+FLEX).gc.remove();//class and grips are removeddelete tables[id];//clean up data};/*** Function to create all the grips associated with the table given by parameters * @param {jQuery ref} t - table object*/varcreateGrips=function(t){var th = t.find(">thead>tr:first>th,>thead>tr:first>td");//table headers are obtainedif(!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 waysth = th.filter(":visible");//filter invisible columnst.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 restoredth.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 gripg.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 neededif(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 classg.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 shortcutt.g.push(g); t.c.push(c);//the current grip and column are added to its table objectc.width(c.w).removeAttr("width");//the width of the column is converted into pixel-based measurementsg.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)*/varmemento=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 removedw =S[t.id].split(";");//column widths is obtainedtw = w[t.ln+1];if(!t.f && tw){//if not fixed and table width data available its size is restoredt.width(tw*=1);if(t.opt.overflow){//if overfolw flag is set, restore table width also as table min-widtht.css('min-width', tw +PX);t.w = tw;}}for(;i<t.ln;i++){//for each columnaux.push(100*w[i]/w[t.ln]+"%");//width is stored in an array since it will be required again a couple of lines aheadth.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 datafor(;i < t.c.length; i++){//iterate through columnsw = t.c[i].width();//width is obtainedS[t.id]+= w+";";//width is appended to the sessionStorage object using ID as keym+=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 deserializingif(!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*/varsyncGrips=function(t){ t.gc.width(t.w);//the grip's container width is updated for(var i=0; i<t.ln; i++){//for each columnvar c = t.c[i]; t.g[i].css({//height and position of the grip is updated according to the table layoutleft: 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 */varsyncCols=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 modec2.width(w2 +PX);t.cg.eq(i+1).width( w2 +PX);}elseif(t.opt.overflow){//if overflow is set, incriment min-width to force overflowt.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 */varapplyBounds=function(t){var w = $.map(t.c,function(c){//obtain real widthsreturn 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*/varonGripDrag=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 incrementvar mw = t.opt.minWidth, i = drag.i ;//cell's min widthvar 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 cellsvar 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 gripvar c = t.c[drag.i];//width of the last column is obtaineddrag.w = c.w + x- drag.l;}if(t.opt.liveDrag){//if liveDrag is enabledif(last){c.width(drag.w);if(!t.f && t.opt.overflow){//if overflow is set, incriment min-width to force overflowt.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 callbackif(cb){ e.currentTarget = t[0];cb(e);}//if any, it is fired }returnfalse;//prevent text selection while dragging };/*** Event handler fired when the dragging is over, updating table layout* @param {event} e - grip's drag over event*/varonGripDragOver=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-classif(!(drag.x - drag.l ==0)){var t = drag.t;var cb = t.opt.onResize;//get some values var i = drag.i;//column indexvar 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 draggedif(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 valuessyncGrips(t);//the grips are updatedif(cb){ e.currentTarget = t[0];cb(e);}//if there is a callback function, it is firedif(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*/varonGripMouseDown=function(e){var o =$(this).data(SIGNATURE);//retrieve grip's datavar t = tables[o.t], g = t.g[o.i];//shortcuts for the table and grip objectsvar oe = e.originalEvent.touches;//touch or mouse event?g.ox = oe? oe[0].pageX: e.pageX;//the initial position is keptg.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 boundh.append("<style type='text/css'>*{cursor:"+ t.opt.dragCursor +"!important}</style>");//change the mouse cursorg.addClass(t.opt.draggingClass);//add the dragging class (to allow some visual feedback) drag = g;//the current grip is stored as the current dragging objectif(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 returnfalse;//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 */varonResize=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 casesif(t.f){//in fixed modet.w = t.width();//its new width is keptfor(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 tablesapplyBounds(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 hoverdragCursor:"e-resize",//cursor to be used while draggingpostbackSafe: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 enabledonResize: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 peopleoptions.fixed =true;options.overflow =false;switch(options.resizeMode){case'flex': options.fixed =false;break;case'overflow': options.fixed =false; options.overflow =true;break;}returnthis.each(function(){init(this, options);});}});})(jQuery);
bootstrap-table-resizable.js
/*** @author: Dennis Hernández* @webSite: http://djhvscf.github.io/Blog* @version: v1.0.0*/(function($){'use strict';varinitResizable=function(that){//Deletes the plugin to re-create itthat.$el.colResizable({disable:true});//Creates the pluginthat.$el.colResizable({liveDrag: that.options.liveDrag,fixed: that.options.fixed,headerOnly: that.options.headerOnly,minWidth: that.options.minWidth,hoverCursor: that.options.hoverCursor,dragCursor: that.options.dragCursor,onResize: that.onResize,onDrag: that.options.onResizableDrag,resizeMode: that.options.resizeMode});};$.extend($.fn.bootstrapTable.defaults,{resizable:true,liveDrag:false,fixed:true,headerOnly:false,minWidth:15,hoverCursor:'e-resize',dragCursor:'e-resize',onResizableResize:function(e){returnfalse;},onResizableDrag:function(e){returnfalse;}});var BootstrapTable = $.fn.bootstrapTable.Constructor,_toggleView = BootstrapTable.prototype.toggleView,_resetView = BootstrapTable.prototype.resetView;BootstrapTable.prototype.toggleView=function(){_toggleView.apply(this, Array.prototype.slice.apply(arguments));if(this.options.resizable &&this.options.cardView){//Deletes the plugin$(this.$el).colResizable({disable:true});}};BootstrapTable.prototype.resetView=function(){var that =this;_resetView.apply(this, Array.prototype.slice.apply(arguments));if(this.options.resizable){// because in fitHeader function, we use setTimeout(func, 100);setTimeout(function(){initResizable(that);},100);}};BootstrapTable.prototype.onResize=function(e){var that =$(e.currentTarget);that.bootstrapTable('resetView');that.data('bootstrap.table').options.onResizableResize.apply(e);}})(jQuery);