/** _ _____ _ _ _ | | __ \ (_) | | | | ___ ___ | | |__) |___ ___ _ ______ _| |__ | | ___ / __/ _ \| | _ // _ \/ __| |_ / _` | '_ \| |/ _ \ | (_| (_) | | | \ \ __/\__ \ |/ / (_| | |_) | | __/ \___\___/|_|_| \_\___||___/_/___\__,_|_.__/|_|\___| 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(""); /** * 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(""); //if hoverCursor has been set, append the style t.addClass(SIGNATURE).attr(ID, id).before('
'); //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('
')[0].lastChild); //add the visual node to be used as grip g.append(dc ? "": t.opt.gripInnerHtml).append('
'); 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*{cursor:"+ t.opt.dragCursor +"!important}"); //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