Unobtrusive table column resize with jquery, as plugin [and google code]

Hi all,

Thanks for all the feedback on my previous post on simple resizable columns in jQuery. I took some time to learn how to build a jQuery plugin, and I am proud to present the result :)

Please see here: http://www.audenaerde.org/example2.html for the demo. You can also download the source code for the plugin here: http://www.audenaerde.org/simpleresizabletables.js

Feel free to use (just leave me some credit ;) ) and comments are welcome too.

Update!

the code is also available on google code: http://code.google.com/p/simple-jquery-resizable-table-plugin/ . If you like to contribute, drop me a note :)

Unobtrusive table column resize with jquery

With this piece of code, simple add the class  ‘resizabletable’ to your table and the columns can be easily resized by drag and drop!

I was inspired by the flexigrid, but wanted a simpler solution. This one also nicely integrates into Wicket DataTable, for example.

Update: fixed the multi table on a page bug, kindly pointed out by Nick (see comments)

To see it working: http://www.audenaerde.org/example.html

<!DOCTYPE HTML>
<html>
<head>
<script type="text/javascript"
        src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
<script type="text/javascript"
        src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.7.2/jquery-ui.js"></script>
    <script type="text/javascript">
    function resetTableSizes (table, change, columnIndex)
    {
        //calculate new width;
        var tableId = table.attr('id');
        var myWidth = $('#'+tableId+' TR TH').get(columnIndex).offsetWidth;
        var newWidth = (myWidth+change)+'px';

        $('#'+tableId+' TR').each(function()
        {
            $(this).find('TD').eq(columnIndex).css('width',newWidth);
            $(this).find('TH').eq(columnIndex).css('width',newWidth);
        });
        resetSliderPositions(table);
    };

    function resetSliderPositions(table)
    {
        var tableId = table.attr('id');
        //put all sliders on the correct position
        table.find(' TR:first TH').each(function(index)
        {
            var td = $(this);
            var newSliderPosition = td.offset().left+td.outerWidth() ;
            $("#"+tableId+"_id"+(index+1)).css({  left:   newSliderPosition , height: table.height() + 'px'}  );
        });
    }

    function makeResizable(table)
    {        
        //get number of columns
        var numberOfColumns = table.find('TR:first TH').size();

        //id is needed to create id's for the draghandles
        var tableId = table.attr('id');
        for (var i=0; i<=numberOfColumns; i++)
        {
            //enjoy this nice chain :)
            $('<div id="'+tableId+'_id'+i+'"></div>').insertBefore(table).data('tableid', tableId).data('myindex',i).draggable(
            { axis: "x",
              start: function ()
              {
                var tableId = ($(this).data('tableid'));
                $(this).toggleClass( "dragged" );
                //set the height of the draghandle to the current height of the table, to get the vertical ruler
                $(this).css({ height: $('#'+tableId).height() + 'px'} );
              },
              stop: function (event, ui)
              {
                var tableId = ($(this).data('tableid'));
                $( this ).toggleClass( "dragged" );
                var oldPos  = ($( this ).data("draggable").originalPosition.left);
                var newPos = ui.position.left;
                var index =  $(this).data("myindex");
                resetTableSizes($('#'+tableId), newPos-oldPos, index-1);
              }          
            }
            );;
        };

        resetSliderPositions(table);

    }
    $(document).ready(function()
    {
        $(".resizabletable").each(function(index)
        {
            makeResizable($(this));
        });

    });

    </script>
    <style>
        .draghandle.dragged
        {
            border-left: 1px solid #333;
        }

        .draghandle
        {
            position: absolute;
            z-index:5;
            width:5px;
            cursor:e-resize;
        }
        TH
        {
            border-left: 1px solid #333;
            border-bottom: 1px solid #333;
        }
    </style>
</head>
<body>
<div id="container" style="border: 1px solid blue;">
    <table id="mytable" style="width:100%; border: 1px solid red;" border="0" cellspacing="0" cellpadding="0" >
    <thead>
        <tr>
            <th style="">Dit is een interessante zin!</th>
            <th style="">b</th>
            <th style="">b</th>
            <th style="">b</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td style="">Dit is een interessante zin!</td>
            <td style="">b</td>
            <td style="">b</td>
            <td style="">b</td>
        </tr>
        <tr>
            <td style="">b</td>
            <td style="">a</td>
            <td style="">b</td>
            <td style="">b</td>
            </tr>
        <tr>
            <td style="">b</td>
            <td style="">a</td>
            <td style="">b</td>
            <td style="">b</td>
        </tr>
    </tbody>
    </table>
</div>
</body>
</html>

Enjoy :) 

Master Thesis!

I couldn’t find my master thesis fast enough in my gmail, so I post it here, for the world to see! (yeah it’s version 12..)

Final_report_00012

Align Two DIVS on vertical middle

Ha,

Today I found an elegant CSS way of aligning two DIVs vertically on their centers. After spending some search on Google and not finding a satisfactionary solution, I treid to create my own. Here it is:

<span>
 <div style="display:inline-block; vertical-align:middle">
 RobAu's <br>Vertically aligned DIVS
 </div>
 <div style="display:inline-block; vertical-align:middle;width:100px;">
 <div style="width:100px; height:150px; background-color:red"></div>
 <div style="width:100px; height:150px; background-color:blue"></div>
 </div>
</span>

The span is used to have an normal line. The divs are converted to inline-blocks, like images. That way, they can be aligned in the middle.By simply putting two container DIVs in the span, they are alinged vertically, without giving any pre-set heights, percentages, positioning etc.

Feel free to use!

RobAu’s
Vertically aligned DIVS

Lenovo SL500 and Ubuntu.. fixing the loose ends

Half a year ago I started working for a new company and they provided me with a Lenovo SL 500. I started using Ubuntu a year ago, so I was eager to try it out on my new laptop. I wanted to keep the pre-installed Windows intact, so I went the wubi way  (http://wubi-installer.org/).

After installing most things seem to work fine. Except for a few things. The extra keys, the birghtness and wifi where working non optimal. So i started my search on the internet and found solutions to all of my problems!

Setting the brightness

Ok. So setting the brightness was not easy. It requires a installation of extra drivers, and of the 2.6.30 kernel.

Installation of the new kernel (and new nVidia drivers)

http://law-and-tech.blogspot.com/2009/06/thinkpad-sl500-and-linux.html

Installation of the SL500 acpi driver

http://ubuntuforums.org/showpost.php?p=7483027&postcount=4

Installation of the Wifi firmware

Well. I’m not sure if it really fixes the drop-outs of the connections, but there is no more error in the kernel.log

http://intellinuxwireless.org/?n=downloads

Look fot the 5100 agn. Unzip the zip and copy the .ucode file to the /lib/firmware/<your_kernel>

Installing a Documentum Lifecycle

There is no option to do this in DA. But it is really, really simple :)

#1 Find the id of the lifecycle with DQL:

SELECT r_object_id FROM dm_policy WHERE object_name=’<your_lifecycle>’

This returns the CURRENT version of the lifecycle

# Use API to validate, install:

validate,c,<dm_policy_id>
install,c,,<dm_policy_id>

Removing Seconds, Minutes and Hours from a WDK Date-Time DocbaseAttribute Value Control

So, you are building a wdk application using docbaseobjects. Good :) But now you want more control on how your datetime attribute is rendered. That what I wanted anyway. So after doing some googling I found a javascript that actually hides the fields after they are rendered.  This seemed so ugly to me that I decided to create a custom DateValueTag implementation.

 

How is this accomplished?

I created my own DocbaseAttributeValueTag extension. See below

package my.package;
import java.io.IOException;
import java.util.ArrayList;
import javax.servlet.jsp.JspTagException;
import javax.servlet.jsp.JspWriter;
import com.documentum.fc.common.IDfProperties;
import com.documentum.web.common.WrapperRuntimeException;
import com.documentum.web.form.control.DateInput;
import com.documentum.web.form.control.DateInputTag;
import com.documentum.web.form.control.DateTime;
import com.documentum.web.formext.Trace;
import com.documentum.web.formext.control.docbase.DocbaseAttributeCache;
import com.documentum.web.formext.control.docbase.DocbaseAttributeValue;
import com.documentum.web.formext.control.docbase.DocbaseAttributeValueTag;
/**
 */
public class ShortDateTag
    extends DocbaseAttributeValueTag
{
    protected void renderSingleAttribute( String strFormattedValue, String strValue, boolean bReadonly,
                                          boolean bHasCompleteList, JspWriter out )
        throws IOException, JspTagException
    {
        if ( bReadonly )
        {
            super.renderSingleAttribute( strFormattedValue, strValue, bReadonly, bHasCompleteList, out );
        }
        else
        {
            // render custom date control here
            renderCustomDateTime( strValue, out );
        }
    }
    private void renderCustomDateTime( String strValue, JspWriter out )
    {
        DocbaseAttributeValue value = (DocbaseAttributeValue) getControl();
        String strClass = value.getCssClass();
        String strStyle = value.getCssStyle();
        String strSize = "32";
        DateInputTag tag = new DateInputTag();
        tag.setPageContext( pageContext );
        tag.setParent( this );
        tag.setName( value.getElementName( "value" ) );
        tag.setId( getId() );
        tag.setTooltip( value.getToolTip() );
        if ( strClass != null )
        {
            tag.setCssclass( strClass );
        }
        if ( strSize != null )
        {
            tag.setWidth( strSize );
        }
        if ( strStyle != null )
        {
            tag.setStyle( strStyle );
        }
        DateInput dateTimeObj = (DateInput) tag.getControl();
        if ( !value.isEnabled() )
        {
            dateTimeObj.setEnabled( false );
        }
        else
        {
            dateTimeObj.setEnabled( true );
        }
        java.util.Date date = DateTime.toDate( strValue );
        if ( date != null )
        {
            dateTimeObj.setValue( date );
        }
        dateTimeObj.setIsRemovable( false );
        renderSetEvents( null, value.getVaDependenciesProperties(), out );
        DocbaseAttributeCache
            .updateAttributeAndDependentList( value.getAttribute(), dateTimeObj.getElementName(), null );
        try
        {
            tag.doStartTag();
            tag.doEndTag();
        }
        catch ( JspTagException e )
        {
            throw new WrapperRuntimeException( e );
        }
    }
    /**
     * see com.documentum.web.formext.control.docbase.DocbaseAttributeValueTag
     */
    private void renderSetEvents( String strControlName, IDfProperties dependenciesList, JspWriter out )
    {
        DocbaseAttributeValue value = (DocbaseAttributeValue) getControl();
        ArrayList lisControls = DocbaseAttributeCache.getPostServerEventControls( value.getAttribute(), strControlName,
                                                                                  dependenciesList );
        StringBuffer buf = new StringBuffer( 256 );
        if ( lisControls.size() > 0 )
        {
            buf.append( "<script>" );
            buf.append( "setPostServerEventControls(\"" );
            for ( int i = 0; i < lisControls.size(); i++ )
            {
                if ( i > 0 )
                {
                    buf.append( ",\"" );
                }
                buf.append( (String) lisControls.get( i ) );
                buf.append( "\"" );
            }
            buf.append( ");" );
            buf.append( "</script>" );

        }
    }
}

Now you only have to get the WDK to use the new tag. This is accomplished in a xml file. I created a docbaseattributes.xml and added the lines:

<config version='1.0'>
   <scope type="my_document_type">
      <docbaseobjectconfiguration id='attributes'>
         <names>
            <!-- apply to attribute -->
            <attribute name='senddate'>
               <valuetagclass>my.package.ShortDateTag</valuetagclass>
            </attribute> 
 

That’s it!

Inside WDK DocbaseObject

Last days I’ve been struggling with the dmfx:docbaseobject in the wdk 5.3.

Because I wanted more control on the layout of the attributes, I choose to create the attributes one by one in the jsp, instead of using the attributelist.

Snippet:

<dmfx:docbaseobject name='current_document' />                        
<tr><td>
<dmfx:docbaseattribute name='attr_obj_id' object='current_document' attribute='r_object_id'  col1="</td><td>" />
</td></tr>
<tr><td>
<dmfx:docbaseattribute name='attr_medewerkercode' object='current_document' attribute='medewerkercode' size='12' col1="</td><td>" />
</td></tr>

This piece of code resides in a component-page. I have created a button that refreshes the page and changes the docbaseobject’s id. When re-rendering, the old values of the attributes remain on the page. This has to do with the internal workings of the DocbaseAttributeValueTag.

The problem lies in the renderEnd code, which does something like this:           

DocbaseAttributeValue value = (DocbaseAttributeValue) getControl();
 
if(obj.isADocbaseObjectInstance())
{
  strValue = value.getValue();
  if(strValue == null)
  {
    IObjectAdapter objectAdapter = obj.getObjectAdapter();
    if(objectAdapter != null)
    {
      strValue = getValueFromObjectAdapter(objectAdapter);
    } else
    {
      strValue = getValueFromDocbaseObject();
    }
    value.setValue(strValue);
    bGotDisplayValuesForRepeatingAttr = true;
  }
}

It acutally reads the value directly from it’s control class. But once the value inside the control class gets set to somethinh other than null, the object is no longer updated.

This is how I worked around it.

I created a extra boolean value “m_reloadFromDocbase” in the control class and in the DocbaseAttribute class, and added these lines in the renderEnd

   if (value.getReloadFromDocbase())
      strValue = null;

This ensures the value of the attribute will get reloaded from the docbase.

In the behaviour class that handles thes jsp, the render-code is a little extended:

                DocbaseAttribute dat = (DocbaseAttribute) getControl( "attr_" + attribute, DocbaseAttribute.class );
                dat.setReloadFromDocbase( true );

The attribute comes form analyzing the page, using a FindValidAttribute visitor. If the boolean is set to false, the filled-in value will remain.

If you are interested in more detail, please dorp me a line [still figuring out howto]

Hello world!

Welcome to WordPress.com. This is your first post. Edit or delete it and start blogging!

Follow

Get every new post delivered to your Inbox.