Mega Code Archive

 
Categories / JavaScript DHTML / GUI Components
 

Editable Grid Table cell

<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html> <head>   <title>OS3 Grid Example 4 - Editable Grid</title>   <!-- examples.css -->   <style type="text/css" rel="stylesheet"> html, body {   height: 100%;   width:  100%;   font-family: Arial, Verdana, sans-serif;   color: #cccc99;   font-size: 1em;   /* overflow: auto; */   margin-left: 0px;   margin-top:  0px;   margin-bottom: 0px;   margin-right: 0px; } #block_top {   margin: 5px;   background-color: #d0d0d0;   border: 1px solid #000; } #block_left {   margin-left: 5px;   left: 0px;   background-color: #76808b;   border: 1px solid #000;   float: left;   width: 15%; } #block_middle {   margin-left: 18%;   margin-right: 5%;   padding: 5px;   background-color: #959595;   border: 1px solid #000; } .block {   margin: 5px;   border: 1px solid #000; } a {    text-decoration: none;   margin-left: 5px;   } a:hover {     text-decoration: underline overline ;        }    h1,h2,h3,h4,h5,h6.center { text-align: center; } body {   color: #000000;   background: #666666; } /* Menu */ .menu_title {    margin:  4px;   padding: 5px;   border: 1px solid #000;   background-color: #454545;   color: white;   font-weight: bold; } /* Description Menu */ .descr_menu { border: 1px solid black; background-color: #353535; } .descr_menu th { width:150px; background:#8080ff; } .descr_menu th a { text-decoration:none; color:#000000; } .descr_menu td {        font-weight: bold;        background:  #add8e6;        padding: 5px;     } /* Form 1 */ .form1   {      border: 1px solid black;      padding: 5px;     margin: 5px;     background-color: #a5a5cc;     display: none;   } .field_descr   {       text-align: right;       font-weight: bold;       margin-right: 5px;     } .code {     padding: 5px;     margin: 5px;     font-family: courier;     background: #ccccff;     white-space: pre;   } .result {     padding: 3px;     margin: 2px;     background: #eee;   } .note {     padding: 5px;     margin: 2px;     background: #ffaaaa;     border: solid;     border-width: 1px;   }      </style>   <!-- os3grid.css -->   <style type="text/css" rel="stylesheet"> .g_table {     margin: 0;     padding: 0;     border: 0;     border-collapse: separate;     border-spacing: 0px;    } .g_header {        border: 2px solid;     border-color: #fff #333 #333 #fff;     background-color: #eeeeee;      padding-right: 9px;     padding-left: 9px;     padding-bottom: 2px;     cursor: pointer;      text-align: center;     color: black;      font-size: 12px;        } .g_resize {     cursor: e-resize;   } .g_header_down {       border: solid;       border-color: #333 #555 #555 #333;       border-width: 2px;       background-color: #eeeeee;        padding-top: 2px;       padding-left: 10px;       padding-right: 8px;       text-align: center;       color: black;        cursor: pointer;       font-size: 12px;       } .g_cell {     border: solid;     border-width: 1px 1px 1px 1px;     border-color: #ccc;     padding: 4px;     font-size: 10px;   } .g_cell_hl {       border: dashed;       border-width: 1px;       border-color: #f00;       background-color: #ddd;      } .g_edit_box {       border: solid;       border-width: 1px;       border-color: #999;       padding: 3px;       background: white;       }      </style>      <!-- os3grid.js -->   <script type="text/javascript"> /*   OS3Grid v0.5   by Fabio Rotondo - fsoft ( at ) sourceforge.net   0.5:   - ATTR: start_counter     - resize_cols     - set_col_render () */ // =================================================================== // GLOBAL STUFF - Init global data class // =================================================================== function os3_grid_global_data () {   this.grid_arr = new Array ();   this.sort_field = 0;   this.sort_inverted = 0; } var _os3_grid_global_data = new os3_grid_global_data (); var _os3g_resize_cell; var _os3g_resize_start_x = -1; // Flag T/F to know if the current browser is the almighty bugged Internet Exploder. var _os3g_is_ie = ( document.all != null ); // =================================================================== // Grid Resize Functions // =================================================================== function grid_resize_cell_down ( id ) {   _os3g_resize_cell = document.getElementById ( id );   document.onmousemove = grid_resize_callback;   if ( ! _os3g_is_ie )    {     document.captureEvents(Event.MOUSEMOVE);   } else {     while ( ! _os3g_resize_cell )     {       _os3g_resize_cell = document.getElementById ( id );       if ( confirm ( "The buggy Internet Explorer cannot get the ID: " + id + ". Try again?\nBTW: You should really consider to switch to Mozilla Firefox (www.getfirefox.com)" ) == false ) break;     }   } } function grid_resize_cell_up () {   if ( ! _os3g_resize_cell ) return;   document.onmousemove = null;   // later   if ( ! _os3g_is_ie )   {     document.releaseEvents(Event.MOUSEMOVE);   }   if ( _os3g_resize_cell.old_className ) _os3g_resize_cell.className = _os3g_resize_cell.old_className;   _os3g_resize_start_x = -1;   // Save the new column width inside _column_width array;   var res = _os3g_resize_cell.id.split ( "_th" );   var name = res [ 0 ];   var num  = res [ 1 ];   var grid = _os3_grid_global_data.grid_arr [ name ];   grid._column_width [ num ] = _os3g_resize_cell.width;   _os3g_resize_cell = null; } function grid_resize_callback ( e ) {   var cur_x, cur_y;   if ( ( ! _os3g_is_ie ) && ( e.pageX ) )     cur_x = e.pageX;   else      cur_x = event.x;   if ( _os3g_resize_start_x == -1 )    {     _os3g_resize_start_x = 1;     _os3g_resize_start_x = cur_x - _os3g_resize_cell.offsetWidth;   }   if ( cur_x <= _os3g_resize_start_x ) cur_x = _os3g_resize_start_x +1;   _os3g_resize_cell.width = ( cur_x - _os3g_resize_start_x ); } // =================================================================== // Grid Edit Functions // =================================================================== function grid_edit_abort_or_blur ( input, cell_id, evt ) {         evt = (evt) ? evt : event;   var ccode = ( evt.charCode ) ? evt.charCode : ( ( evt.which ) ? evt.which : evt.keyCode );         var ch = String.fromCharCode ( ccode );   // User confirmed input by pressing "enter key"   if ( ccode == 13 ) return input.blur ();   // User aborted input   if ( ccode == 27 )   {     var v = cell_id.split ( ":" );     var grid = _os3_grid_global_data.grid_arr [ v [ 0 ] ];     input.value = grid.rows [ v [ 2 ] ] [ "data" ] [ v [ 1 ] ];     input.blur ();   }   return true; } function grid_edit_end ( input, cell_id ) {   var v = cell_id.split ( ":" );   var grid = _os3_grid_global_data.grid_arr [ v [ 0 ] ];   var oldv = grid.rows [ v [ 2 ] ] [ "data" ] [ v [ 1 ] ];   if ( oldv != input.value )   {     if ( grid._column_validator [ v [ 1 ] ] )       if ( grid._column_validator [ v [ 1 ] ] ( input.value ) == false )       {         alert ( "Invalid input: " + input.value );         return input.focus ();       }     grid.rows [ v [ 2 ] ] [ "data" ] [ v [ 1 ] ] = input.value;     if ( grid.onchange ) grid.onchange ( grid, v [ 1 ], v [ 2 ], input.value );     if ( grid.sort_on_edit ) grid.sort ();   }   return grid.render (); } function grid_cell_txt_edit ( cell ) {   var v = cell.id.split ( ":" );   var grid = _os3_grid_global_data.grid_arr [ v [ 0 ] ];   var val;   var s, el, size;   var type = grid._column_type [ v [ 2 ] ];   if ( ! type ) type = 'str';   val = String ( grid.rows [ v [ 2 ] ] [ "data" ] [ v [ 1 ] ] );   s  = '<input type="text" id="grid_edit_cell" value="' + val + '" ';   s += ' onblur="grid_edit_end ( this, \'' + cell.id + '\' )" ';   s += ' onfocus="this.select()" ';   if ( grid._column_chars [ v [ 1 ] ] )      s += 'onkeypress="return grid_edit_filter_chars ( event, \'' + grid._column_chars [ v [ 1 ] ] + '\' )" ';   s += ' onkeydown="grid_edit_abort_or_blur(this, \'' + cell.id + '\', event)" ';   s += ' size="'+ val.length + '" ';   s += ' class="g_edit_box" ';   if ( type == 'int' ) s += ' style="text-align: right;" ';   s += '/>';   cell.innerHTML = s;   el = document.getElementById ( "grid_edit_cell" );   el.focus (); } function grid_edit_filter_chars ( evt, valids ) {         evt = (evt) ? evt : event;         if ( evt.charCode < 32 ) return true;                                                                                                                                                             var ccode = ( evt.charcode ) ? evt.charcode : ( ( evt.which ) ? evt.which : evt.keycode );         var ch = String.fromCharCode ( ccode ).toLowerCase ();   valids = valids.toLowerCase ();         if ( valids.indexOf ( ch ) == -1 ) return false;         return true; } function grid_header_mdown ( header ) {   if ( header.className == 'g_header_down' ) return;   header.old_className = header.className;   header.className = 'g_header_down';    } function grid_header_mup ( header ) {   if ( header.old_className ) header.className = header.old_className; } function grid_header_click ( header ) {   var name, num, res, grid;      res = header.id.split ( "_gh" );   name = res [ 0 ];   num  = res [ 1 ];   grid = _os3_grid_global_data.grid_arr [ name ];   grid.set_sort_field ( num );   grid.sort () } function grid_row_over ( row ) {   var old_col = row.style.backgroundColor;   var hover_col = _os3_grid_global_data.grid_arr [ row.firstChild.id.split ( ":" ) [ 0 ] ].cols [ "hover" ];   if ( _os3g_resize_cell ) grid_resize_cell_up ();   if ( ( row.selected ) || ( old_col == hover_col ) ) return;   row.old_color = old_col;   row.style.backgroundColor = hover_col; } function grid_row_out ( row ) {   if ( ! row.selected ) row.style.backgroundColor = row.old_color; } function grid_cell_click ( cell ) {   var v = cell.id.split ( ":" );   var grid = _os3_grid_global_data.grid_arr [ v [ 0 ] ];   var val;   val = grid.rows [ v [ 2 ] ] [ "data" ] [ v [ 1 ] ];   sel = grid._cell_click ( grid, cell, v [ 2 ], v [ 1 ], val );      if ( sel )   {     cell.old_border = cell.style.borderColor;     cell.style.borderColor = grid.cols [ "rowsel" + ( v [ 2 ] % 2 ) ];   } else     cell.style.borderColor = cell.old_border;   cell.selected = sel; } // =================================================================== // Row selection function // =================================================================== function grid_row_click ( cell, grid_id, row_num ) {   var grid = _os3_grid_global_data.grid_arr [ grid_id ];   var row = cell.parentNode;   if ( row.selected )   {     row.selected = false;     grid_row_out ( row );   } else {     row.selected = true;     row.style.backgroundColor = grid.cols [ "rowsel" + ( row_num % 2 ) ];   }   grid.rows_selected [ row_num ] = row.selected;   if ( grid.onrowselect ) grid.onrowselect ( grid, row_num, row.selected ); } // =================================================================== // Internal Functions // =================================================================== function os3_grid_int_sort ( a, b ) {   var res = 0;   var v1, v2;   v1 = parseInt ( a [ "data" ][ _os3_grid_global_data.sort_field ] );   v2 = parseInt ( b [ "data" ][ _os3_grid_global_data.sort_field ] );   if  ( v1 < v2 ) res = -1;   else if ( v1 > v2 ) res = 1;   if ( _os3_grid_global_data.sort_inverted ) res *= -1;   return res; } function os3_grid_str_sort ( a, b ) {   var res = 0;   var v1, v2;   v1 = a [ "data" ][ _os3_grid_global_data.sort_field ];   v2 = b [ "data" ][ _os3_grid_global_data.sort_field ];   if ( v1 < v2 ) res = -1;   else if ( v1 > v2 ) res = 1;   if ( _os3_grid_global_data.sort_inverted ) res *= -1;   return res; } function _os3g_set_headers () {   this.headers = arguments; } function _os3g_set_sort_field ( num ) {   if ( num == this.sort_field )      this.sort_inverted = ! this.sort_inverted;   else   {     this.sort_field = num;     this.sort_inverted = false;   } } function _os3g_set_cell_click ( fname ) {   this._cell_click = fname;   if ( this.id && this.autorender ) this.render (); } function _os3g_set_size ( w, h ) {   this._width = w;   this._height = h;   if ( this.id && this.autorender ) this.render (); } function _os3g_set_scrollbars ( sbars ) {   this._scrollbars = sbars;   if ( this.id && this.autorender ) this.render (); } function _os3g_set_border ( bsize, style, color ) {   this._border = bsize;   if ( style ) this._border_style = style;   if ( color ) this._border_color = color;   if ( this.id && this.autorender ) this.render (); } function _os3g_set_sortable ( sortable ) {   this._sortable = sortable ;   if ( this.id && this.autorender ) this.render (); } function _os3g_set_highlight ( hl ) {   this._row_hl = hl ;   if ( this.id && this.autorender ) this.render (); } function _os3g_sort () {   if ( this.sort_field == -1 ) return;   var ctype = this._column_type [ this.sort_field ];   var sfunc;   if ( ! ctype ) ctype = "str";   sfunc = { "str" : os3_grid_str_sort,         "int" : os3_grid_int_sort,         "date": os3_grid_str_sort } [ ctype ];   _os3_grid_global_data.sort_field = this.sort_field;   _os3_grid_global_data.sort_inverted = this.sort_inverted;   this.rows.sort ( sfunc );   this.render ( this.id ); } function _os3g_add_row () {   var arr;   arr = { "data" : arguments, "style" : this.current_style };   this.rows.push ( arr ); } function _os3g_get_str () {   var t, len;   var s = '<table class="g_table">';   var id, td_id;   // Row selections are discarted on rendering   this.rows_selected = new Array ();   if ( this.headers )   {     s += '<tr>';     if ( this._show_row_num ) s+= '<td><div class="g_header">&nbsp</div></td>';     len = this.headers.length;     for ( t = 0; t < len; t ++ )     {            td_id = this.id + "_th" + t;       id = this.id + "_gh" + t;       s += '<td id="' + td_id + '" ';       if ( this._column_width [ t ] ) s += 'style="width: ' + this._column_width [ t ] + 'px;" ';       s +='><div id="' + id + '" class="g_header"';       if ( this._click_cb [ t ] )       {         if ( this._click_cb [ t ] != -1 )          {           s += ' onclick="' + this._click_cb [ t ] +  '"';           s += ' onmousedown="grid_header_mdown(this)"';           s += ' onmouseup="grid_header_mup(this)"';           // s += ' onmouseout="grid_header_mup(this)" ';         }       } else if ( this._sortable ) {           s += ' onclick="grid_header_click(this)"';           s += ' onmousedown="grid_header_mdown(this)"';           s += ' onmouseup="grid_header_mup(this)"';           //s += ' onmouseout="grid_header_mup(this)" ';       }       s += '>'+ this.headers [ t ] + "</div></td>";        if ( this.resize_cols )         s += '<td class="g_resize" onmousedown="grid_resize_cell_down(\'' + td_id + '\')" onmouseup="grid_resize_cell_up()"></td>';     }     s += '</tr>';   }   var r, i, rlen, bgc, align, hl, style, rowcol, fullrow, v;   len = this.rows.length;   rlen = this.rows[0]['data'].length;  // All rows must be equal size   for ( t = 0; t < len; t ++ )   {     fullrow = this.rows [ t ];     r   = fullrow [ 'data' ];     style  = fullrow [ 'style' ];     rowcol  = fullrow [ 'color' ];     if ( rowcol )       bgc = ' bgcolor="' + rowcol + '"';     else        bgc = ' bgcolor="' + this.cols [ style + ( t % 2 ) ] + '"';     if ( this._row_hl )       hl = ' onmouseover="grid_row_over(this)" onmouseout="grid_row_out(this)" ';     else       hl = '';            s += '<tr ' + hl + bgc + '>';     if ( this._show_row_num )      {       s+= '<td class="g_header"';       if ( this._row_sel )       {         s += ' onmousedown="grid_header_mdown(this)"';         s += ' onmouseup="grid_header_mup(this)"';         s += ' onclick="grid_row_click(this,\'' + this.id + '\',' + t + ')"';       }       s += ' id="' + this.id + ':' + t + '"';       s+= '>' + ( this.start_counter + t ) + '</td>';     }     for ( i = 0; i < rlen; i ++ )     {       if ( this._column_align [ i ] )         align = 'align="' + this._column_align [ i ] + '"';       else if ( ( this._column_type [ i ] ) && ( this._column_type [ i ] != 'str' ) )         align = 'align="right"';       else         align = "";              s += '<td class="g_cell" valign="top" ' + align;       if ( this.resize_cols ) s += ' colspan="2"';       if ( this._column_edit [ i ] ) s += ' ondblclick="grid_cell_' + this._column_edit [ i ] + '_edit(this)" ';       if ( this._cell_click ) s += ' onclick="grid_cell_click(this)" ';       s += ' id="' + this.id + ':' + i + ':' + t + '"';       s += '>';        if ( this._column_render [ i ] )         v = this._column_render [ i ] ( r [ i ] );       else         v = r [ i ];       s += v;       s += '</td>';     }     s += '</tr>';   }   s += "</table>";      return s; } function _os3g_render ( objId ) {   if ( objId == undefined ) objId = this.id;   this.id = objId;   var obj = document.getElementById ( objId );   obj.innerHTML = this.get_str ();   if ( this._scrollbars )     obj.style.overflow = "auto";   else     obj.style.overflow = "visible";  // was "none"   if ( this._width )  obj.style.width = this._width;   if ( this._height ) obj.style.height = this._height;   if ( this._border )    {     if ( this._border_style ) obj.style.border = this._border_style;     if ( this._border_color ) obj.style.borderColor = this._border_color;     obj.style.borderWidth = this._border + "px";   }      // Bind element to the os3_grid_array   _os3_grid_global_data.grid_arr [ objId ] = this;   if ( this.onrender ) this.onrender ( this ); } function _os3g_set_row_color ( col, row_num ) {   if ( ( row_num == undefined ) || ( row_num == -1 )  ) row_num = this.rows.length -1;   this.rows [ row_num ] [ 'color' ] = col; } function _os3g_set_row_style ( style, row_num ) {   if ( ( row_num == undefined ) || ( row_num == -1 )  ) row_num = this.rows.length -1;      this.rows [ row_num ] [ 'style' ] = style; } function _os3g_set_col_align ( col, align ) {   this._column_align [ col ] = align; } function _os3g_set_col_editable ( col, edit ) {   this._column_edit [ col ] = edit; } function _os3g_get_value ( x, y ) {   return this.rows [ y ] [ x ]; } function _os3g_set_col_valid_chars ( col, chars ) {   this._column_chars [ col ] = chars; } function _os3g_set_col_validation ( col, func ) {   this._column_validator [ col ] = func; } function _os3g_set_row_select ( rsel ) {   this._row_sel = rsel;   if ( this._row_sel ) this._show_row_num = true;   if ( this.id && this.autorender ) this.render (); } function _os3g_show_row_num ( show ) {   this._show_row_num = true;   if ( this.id && this.autorender ) this.render (); } function _os3g_set_col_type ( col, type ) {   this._column_type [ col ] = type; } function _os3g_set_col_render ( col, render ) {   this._column_render [ col ] = render; } function _os3g_get_row ( row ) {   return this.rows [ row ] [ "data" ]; } function _os3g_set_click_cb ( col, callback ) {   this._click_cb [ col ] = callback;   if ( this.id && this.autorender ) this.render (); } function _os3g_set_style ( style ) {   this.current_style = style;   if ( this.id && this.autorender ) this.render (); } function OS3Grid ( auto_render ) {   // ===========================================   // Public attribs   // ===========================================   this.id = 0;   this.start_counter = 0;   // ===========================================   // PUBLIC FLAGS   // ===========================================   // Flag T/F. If True, any modification (done with set_* funcs) will immediately renderd on grid   this.autorender = auto_render;     // Flag T/F. If True, grid will be re-sorted on value changes   this.sort_on_edit = false;   // ===========================================   // PUBLIC CALLBACKS   // ===========================================   // Function to be called when data in grid changes   this.onchange = false;   // Function to be called after the grid redraws   this.onrender = false;   // Callback to be called when the user selects / deselects a row   this.onrowselect = false;   // Flag T/F. If True, user can resize column at runtime   this.resize_cols = false;      // ===========================================   // PUBLIC ATTRIBUTES   // ===========================================   // Array rows_selected   this.rows_selected = false;  // This array keeps track of selected rows   // Colors   this.cols = { "hover"   : "#8ec4cf",          "rowsel0"  : "#ffa07f",          "rowsel1"  : "#df8c6f",          "normal0"  : "#ffffff",          "normal1"  : "#dfdfdf",          "error0"  : "#ff0033",          "error1"  : "#cc0033",          "warn0"  : "#ffff99",          "warn1"  : "#ffff66",          "note0"  : "#9aff9a",          "note1"  : "#4eee94"         };   // Default style   this.current_style = "normal";   // =============================================================================================   // Private Stuff - Do not directly modify these values!   // =============================================================================================   this.headers = 0;   this.rows = new Array ();   this.sort_field = -1;   this.sort_inverted = false;        this._row_style = new Array ();   this._column_align = new Array ();   this._column_edit  = new Array ();   this._column_chars  = new Array ();   this._column_validator = new Array ();   this._column_width = new Array ();   this._column_render = new Array ();   // This array stores the custom click callbacks   this._click_cb = new Array ();      // This array contains the column type. By default it is "str"   // Valid values are: "str", "int", "date"   this._column_type = new Array ();   // Flag T/F. If True, the grid is sortable (by clicking on the headers)   this._sortable = false;   // Flag T/F. If True, scrollbars are used.   this._scrollbars = false;   // Force grid container width   this._width = 0;   // Force grid container height   this._height = 0;   // Grid container border size (in pixels)   this._border = 0;   // Grid container border style (solid, dashed, dotted...)   this._border_style = 0;   // Grid container block color   this._border_color = 0;   // Function callback for every cell click   this._cell_click = 0;   // Function callback for every row click   this._row_click = 0;   // Flag T/F. If True rows will be highlighted when the mouse scrolls over them.   this._row_hl = false;   // Flag T/F. If True rows number are shown and rows are selectable by clicking on them.   this._show_row_num = false;   // Flag T/F. If True rows number are shown and rows are selectable by clicking on them.   this._row_sel = false;   // Public methods   this.add_row     = _os3g_add_row;   this.get_row     = _os3g_get_row;   this.get_str     = _os3g_get_str;   this.getv    = _os3g_get_value;   this.render     = _os3g_render;   this.set_border   = _os3g_set_border;   this.set_cell_click   = _os3g_set_cell_click;   this.set_click_cb  = _os3g_set_click_cb;   this.set_col_align  = _os3g_set_col_align;   this.set_col_editable  = _os3g_set_col_editable;   this.set_col_render  = _os3g_set_col_render;   this.set_col_type  = _os3g_set_col_type;   this.set_col_valid_chars = _os3g_set_col_valid_chars;   this.set_col_validation = _os3g_set_col_validation;   this.set_headers      = _os3g_set_headers;   this.set_highlight  = _os3g_set_highlight;   this.set_row_color  = _os3g_set_row_color;   this.set_row_select  = _os3g_set_row_select;   this.set_row_style  = _os3g_set_row_style;   this.set_scrollbars   = _os3g_set_scrollbars;   this.set_size     = _os3g_set_size;   this.set_sort_field   = _os3g_set_sort_field;   this.set_sortable  = _os3g_set_sortable;   this.set_style    = _os3g_set_style;   this.show_row_num  = _os3g_show_row_num;   this.sort     = _os3g_sort; }      </script>      <!-- form_validators.js -->   <script type="text/javascript"> function check_integer ( n ) { return RegExp ( "^[-+]?[0-9]+$" ).test( n ); } function check_string ( s ) { return RegExp ( "^[a-zA-Z]+$" ).test( s ); } function check_alfanum_string ( s ) { return RegExp ( "^[a-zA-Z0-9]+$" ).test( s ); }  function check_date ( s ) { return RegExp ( "^[0-9]{4,4}.[0-9]{2,2}.[0-9]{2,2}$" ).test( s ); } function check_time ( s ) { return RegExp ( "^[012][0-9]:[0-5][0-9]$" ).test( s ); } function check_email ( s ) { return RegExp ( "^[a-zA-Z0-9-_.]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,4}$" ).test( s ); } function check_float ( n ) {   if (n.length == 0) return false;   var first_char = n.charAt(0);   if (first_char != '-' && first_char != '.' &&       (first_char < '0' || first_char > '9')) return false;   var dot = false;   var digit_expected = false;   if (first_char == '.') {     dot = true;     digit_expected = true;   } else if (first_char == '-')     digit_expected = true;   if (digit_expected && n.length < 2) return false;   for (var count = 1; count < n.length; count++) {     var c = n.charAt(count);     if (c == '.') {       if (dot) return false;       dot = true;     } else if (c < '0' || c > '9')       return false;   }   return true; }      </script> </head> <body> <div id="block_top">   <h2 class="center">OS3Grid Example 4 - Editable Grid</h2>   <h4 class="center">By Fabio Rotondo - fsoft (@) sourceforge ( dot ) net</h4> </div> <div id="block_middle">   <div>     how to edit the grid.<br />     First to set the editable columns:     <div class="code"><pre>         g.set_col_editable ( 1, "txt" );         g.set_col_editable ( 2, "txt" );         g.set_col_editable ( 3, "txt" );     </pre></div>     force the user to insert a valid e-mail by     filtering his/her typing against the given string and by adding a field validator:     <div class="code"><pre>         g.set_col_valid_chars ( 3, "abcdefghijklmnopqrstuvwxyz@.-0123456789_" );         g.set_col_validation ( 3, check_email );     </pre></div>     The <tt>check_email</tt> is a form validation function defined inside <tt>form_validators.js</tt>.     <div class="code"><pre>       &lt;script src="form_validators.js" type="text/javascript"&gt;&lt;/script&gt;     </pre></div>     grid rows to be automatically resorted when the user changes grid contents, simply     set this flag to true:          <div class="code"><pre>         g.sort_on_edit = true;     </pre></div>          <div class="result">       <div id="grid"></div>       <script type="text/javascript">         function val_changed ( grid, x, y, new_val )         {           alert ( "On grid: " + grid.id + " x: " + x + " y: " + y + " - value changed to: " + new_val );         }         // Create an OS3Grid instance         var g = new OS3Grid ();         // Grid Headers are the grid column names         g.set_headers ( 'nick', 'Name', 'Surname', 'E-Mail Address' );         // If contents is bigger than container, Grid will automatically show scrollbars         g.set_scrollbars ( true );         // The grid will have a solid border (these are CSS attributes)         g.set_border ( 1, "solid", "#cccccc" );         // Now, we add some rows to the grid         g.add_row ( 'fsoft', 'Fabio', 'Rotondo', 'fsoft (@) sourceforge (dot) net' );         g.add_row ( 'john', 'John', 'Bustone', 'jbust (@) somewhere (dot) net' );         g.add_row ( 'mkey', 'Mark', 'Key', 'mkey (@) okay (dot) net' );         g.add_row ( 'jdoe', 'John', 'Doe', 'redbull (@) batman (dot) net' );         // Enable sortable rows         g.set_sortable ( true );         // Enable highlight of rows with the mouse         g.set_highlight ( true );         g.set_col_editable ( 1, "txt" );         g.set_col_editable ( 2, "txt" );         g.set_col_editable ( 3, "txt" );         g.onchange = val_changed;         g.set_col_valid_chars ( 3, "abcdefghijklmnopqrstuvwxyz@.-0123456789_" );         g.set_col_validation ( 3, check_email );         g.set_row_select ( true );         g.sort_on_edit = true;                  // Show the grid replacing the original HTML object with the "grid" ID.         g.render ( 'grid' );       </script>     </div>   </div> </div> </body> </html>