- Added support for textarea and HTMLarea fields + i18n additional labels

(editor Save/Cancel,  YUI Datatable Loading/Error messages, and also column sort tooltips (new in YUI 29.0).
- Added CSS files for the existing two DataTable Templates.  Each file should be added to the corresponding
  template as a CSS Attachment.
- Avoid terminating the editor on Enter.
- Arrange for TAB to save and move editor for next cell also for HTMLarea editor.
- Define classes "wg-dt-textarea" and "wg-dt-htmlarea" + styling for the corresponding cells.
- Commented out handleTableKeyEvent() (reason in the code).
- Implemented a simple workaround to restore the "editor" field (not preserved due to an unknown reason).
This commit is contained in:
Amir Plivatsky 2011-07-12 23:34:27 +03:00
parent 1fd29bf2a1
commit 5aa0835649
5 changed files with 293 additions and 38 deletions

View file

@ -74,6 +74,18 @@ our $I18N = {
context => q{Format for a column with a date}, context => q{Format for a column with a date},
}, },
"format textarea" => {
message => q{Textarea},
lastUpdated => 0,
context => q{Format for a textarea column},
},
"format htmlarea" => {
message => q{HTMLarea},
lastUpdated => 0,
context => q{Format for an HTMLarea column},
},
"add column" => { "add column" => {
message => q{Add Column}, message => q{Add Column},
lastUpdated => 0, lastUpdated => 0,
@ -152,6 +164,23 @@ our $I18N = {
context => q{The name of a newly added value to a column}, context => q{The name of a newly added value to a column},
}, },
"data error" => {
message => q{Data error.},
lastUpdated => 0,
context => q{Message to display when DataTable has data error},
},
"sort ascending" => {
message => q{Click to sort ascending},
lastUpdated => 0,
context => q{Message to display in tooltip to sort Column in ascending order},
},
"sort descending" => {
message => q{Click to sort descending},
lastUpdated => 0,
context => q{Message to display in tooltip to sort Column in descending order},
},
}; };
1; 1;

View file

@ -0,0 +1,60 @@
/**
* wg-datatable-html.css
* CSS rules for DataTable assets
*
* Add as attachment to Default DetaTable template (HTML)
*/
/* start content at top of cells */
.dataTable table>tbody>tr>td {
vertical-align: 0;
}
.dataTable>table>tbody>tr>td>p:first-child { /* for htmlarea, but really applies to the starting p of any cell */
margin-top: 0;
}
/* padding in all data cells */
.dataTable table>tbody>tr>td {
padding-left: 10px;
padding-right: 10px;
}
/* examples of further styles */
/* limited textarea/htmlarea cells, show vertical scrollbar if needed */
/*
.dataTable table>tbody>tr>td {
height: 70px;
width: 200px;
overflow-y: auto;
}
*/
/* styling a particular DataTable in the page, by assetId */
/*
#dataTablesrvp2vk8QJqY5E0imSRQag.dataTable table>tbody>tr>td {
color:red;
height:auto;
width:150px;
overflow-y: visible
}
*/
/* minimum row height */
/*
.dataTable table>tbody>tr>td {
min-height:70px;
height:auto !important;
height:70px;
}
*/
/* styling a particular column (e.g column 2), by assetId */
/*
#dataTablesvE67R6JQfmEI__T9pIAkQ.dataTable table>tbody>tr>td:first-child+td {
color:blue;
}
*/

View file

@ -0,0 +1,59 @@
/**
* wg-datatable-yui.css
* CSS rules for DataTable assets
*
* Add as attachment to Default DetaTable template (YUI)
*/
/* start content at top of cells */
.yui-dt-editable {
vertical-align: 0;
}
.wg-dt-htmlarea>p:first-child {
margin-top: 0;
}
/* padding in all data cells */
td.yui-dt-editable .yui-dt-liner {
padding-left: 10px;
padding-right: 10px;
}
/* examples of further styles */
/* limited textarea/htmlarea cells, show vertical scrollbar if needed */
/*
.wg-dt-textarea, .wg-dt-htmlarea {
height: 70px;
width: 200px;
overflow-y: auto;
}
*/
/* styling a particular DataTable in the page */
/*
#dataTablesrvp2vk8QJqY5E0imSRQag .wg-dt-textarea, #dataTablesrvp2vk8QJqY5E0imSRQag .wg-dt-htmlarea {
color:red;
height:auto;
width:150px;
overflow:visible;
}
*/
/* minimum row height */
/*
td.yui-dt-editable .yui-dt-liner {
min-height:70px;
height:auto !important;
height:70px;
}
*/
/* styling a particular column */
/*
#dataTablesrvp2vk8QJqY5E0imSRQag .yui-dt-col-col1 .yui-dt-liner {
color:blue;
}
*/

View file

@ -7,3 +7,15 @@
.yui-dt-editable .yui-dt-liner { .yui-dt-editable .yui-dt-liner {
min-height: 10px; min-height: 10px;
} }
/* displaying the initial blank line in HTMLarea is not useful */
.wg-dt-htmlarea>p:first-child {
margin-top: 0;
}
/* size of Textarea/HTMLarea cell */
.wg-dt-textarea, .wg-dt-htmlarea {
height: 50px;
width: 150px;
overflow-y: auto;
}

View file

@ -1,4 +1,3 @@
/*global WebGUI*/ /*global WebGUI*/
// Initialize namespace // Initialize namespace
if (typeof WebGUI == "undefined") { if (typeof WebGUI == "undefined") {
@ -8,7 +7,6 @@ if (typeof WebGUI.Form == "undefined") {
WebGUI.Form = {}; WebGUI.Form = {};
} }
/** /**
* This object contains scripts for the DataTable form control * This object contains scripts for the DataTable form control
*/ */
@ -39,6 +37,21 @@ WebGUI.Form.DataTable
this.options = options; this.options = options;
this.schemaDialog = undefined; this.schemaDialog = undefined;
/************************************************************************
* editorByFormat ( event, data )
* Return the DataTable editor type that matches the given format
*/
this.editorByFormat
= function ( format ) {
switch( format ) {
case "text":
case "number":
case "link":
return "textbox";
}
return format;
};
/************************************************************************ /************************************************************************
* addRow ( event, data ) * addRow ( event, data )
* Add a row to the bottom of the table * Add a row to the bottom of the table
@ -105,16 +118,21 @@ WebGUI.Form.DataTable
/************************************************************************ /************************************************************************
* handleEditorKeyEvent ( obj ) * handleEditorKeyEvent ( obj )
* Handle a keypress when the Cell Editor is open * Handle a keypress when the Cell Editor is open
* Enter will close the editor and move down * Not implemented: Enter will close the editor and move down
* Tab will close the editor and move right. * Tab will close the editor and move right.
* Use the handleTableKeyEvent() to handle the moving
* Open a new cell editor on the newly focused cell * Open a new cell editor on the newly focused cell
*/ */
this.handleEditorKeyEvent this.handleEditorKeyEvent
= function ( obj ) { = function ( obj ) {
// 9 = tab, 13 = enter // 9 = tab, 13 = enter
var e = obj.event; var e = obj.event;
if ( e.keyCode == 9 || e.keyCode == 13 ) {
// Avoid terminating the editor on enter
if ( e.keyCode == 13) {
return false;
}
if ( e.keyCode == 9) {
var cell = this.dataTable.getCellEditor().getTdEl(); var cell = this.dataTable.getCellEditor().getTdEl();
var nextCell = this.dataTable.getNextTdEl( cell ); var nextCell = this.dataTable.getNextTdEl( cell );
this.dataTable.saveCellEditor(); this.dataTable.saveCellEditor();
@ -128,8 +146,6 @@ WebGUI.Form.DataTable
// No next cell, make a new row and open the editor for that one // No next cell, make a new row and open the editor for that one
this.dataTable.addRow( {} ); this.dataTable.addRow( {} );
} }
// BUG: If pressing Enter, editor gets hidden right away due to YUI default event
// putting e.preventDefault() and return false here makes no difference
} }
}; };
@ -159,7 +175,10 @@ WebGUI.Form.DataTable
* handleTableKeyEvent ( obj ) * handleTableKeyEvent ( obj )
* Handle a keypress inside the DataTable * Handle a keypress inside the DataTable
* Space will open the cell editor * Space will open the cell editor
* Note: it doesn't currently work: getSelectedTdEls() always returns [] when selectionMode is "standard"
* Commented out for now.
*/ */
/*
this.handleTableKeyEvent this.handleTableKeyEvent
= function ( obj ) { = function ( obj ) {
// 9 = tab, 13 = enter, 32 = space // 9 = tab, 13 = enter, 32 = space
@ -171,6 +190,7 @@ WebGUI.Form.DataTable
} }
} }
}; };
*/
/************************************************************************ /************************************************************************
* hideSchemaDialog ( ) * hideSchemaDialog ( )
@ -211,7 +231,13 @@ WebGUI.Form.DataTable
} }
var dataTableOptions = { var dataTableOptions = {
dateOptions : { format : this.options.dateFormat } dateOptions : {
format : this.options.dateFormat,
MSG_LOADING : this.i18n.get( "WebGUI", "Loading..." ),
MSG_ERROR : this.i18n.get( "Form_DataTable", "data error" ),
MSG_SORTASC : this.i18n.get( "Form_DataTable", "sort ascending" ),
MSG_SORTDESC : this.i18n.get( "Form_DataTable", "sort descending" )
}
}; };
if ( this.options.showEdit ) { if ( this.options.showEdit ) {
@ -222,6 +248,40 @@ WebGUI.Form.DataTable
dataTableOptions.initialRequest = ""; dataTableOptions.initialRequest = "";
} }
for ( var i = 0; i < this.columns.length; i++ ) {
this.columns[ i ].editor = this.editorByFormat( this.columns[ i ].formatter );
}
var widget = YAHOO.widget,
DT = widget.DataTable;
// Dynamically add HTMLarea field type
// HTMLAreaCellEditor is like TextareaCellEditor, but with an additional property "htmlarea" which is true
var HTMLAreaCellEditor = function(a) {
widget.TextareaCellEditor.superclass.constructor.call(this, a);
};
YAHOO.lang.extend( HTMLAreaCellEditor, widget.TextareaCellEditor, {
htmlarea : true
} );
// Extend the static arrays of editors and formatters
DT.Editors[ "htmlarea" ] = HTMLAreaCellEditor;
// Define classes "wg-dt-textarea" and "wg-dt-htmlarea" that can be overided by a stylesheet
// (e.g. in the extraHeadTags of the asset).
var formatter = function ( type ) {
var fmt = function( el, oRecord, oColumn, oData ) {
var value = YAHOO.lang.isValue(oData) ? oData : "";
el.innerHTML = "<div class='wg-dt-" + type + "'>" + value + "</div>";
};
return fmt;
};
DT.Formatter[ "textarea" ] = formatter( "textarea" );
DT.Formatter[ "htmlarea" ] = formatter( "htmlarea" );
// XXX need to do it with YUI API
widget.BaseCellEditor.prototype.LABEL_SAVE = this.i18n.get( "Form_DataTable", "save" );
widget.BaseCellEditor.prototype.LABEL_CANCEL = this.i18n.get( "Form_DataTable", "cancel" );
this.dataTable = new YAHOO.widget.DataTable( this.dataTable = new YAHOO.widget.DataTable(
this.containerId, this.containerId,
this.columns, this.columns,
@ -230,12 +290,52 @@ WebGUI.Form.DataTable
); );
if ( this.options.showEdit ) { if ( this.options.showEdit ) {
var tinymceEdit = "tinymce-edit";
var saveThis = this;
this.dataTable.doBeforeShowCellEditor = function( oCellEditor ) {
if ( !oCellEditor.htmlarea ) {
return true;
}
oCellEditor.getInputValue = function() {
return tinyMCE.activeEditor.getContent();
};
oCellEditor.textarea.setAttribute( 'id', tinymceEdit );
tinyMCE.execCommand( 'mceAddControl', false, tinymceEdit );
setTimeout(function(){ tinyMCE.execCommand( 'mceFocus',false, tinymceEdit ); }, 0);
// watch hitting tab, which should save the current cell and open an editor on the next
tinyMCE.activeEditor.onKeyDown.add(
function( eh, t ) {
return function(ed, e) { // ed unused
eh.call( t, { event: e } );
};
}( saveThis.handleEditorKeyEvent, saveThis )
);
return true;
};
// Remove TinyMCE on save or cancel
var mceRemoveControl = function ( oArgs ) {
var oCellEditor = oArgs.editor;
if ( oCellEditor.htmlarea ) {
tinyMCE.execCommand( 'mceRemoveControl', false, tinymceEdit );
oCellEditor.textarea.removeAttribute( 'id' );
}
};
this.dataTable.subscribe( "editorSaveEvent", mceRemoveControl );
this.dataTable.subscribe( "editorCancelEvent", mceRemoveControl );
// Add the class so our editors get the right skin // Add the class so our editors get the right skin
YAHOO.util.Dom.addClass( document.body, "yui-skin-sam" ); YAHOO.util.Dom.addClass( document.body, "yui-skin-sam" );
this.dataTable.subscribe( "cellDblclickEvent", this.dataTable.onEventShowCellEditor ); this.dataTable.subscribe( "cellDblclickEvent", this.dataTable.onEventShowCellEditor );
this.dataTable.subscribe( "rowClickEvent", this.dataTable.onEventSelectRow ); this.dataTable.subscribe( "rowClickEvent", this.dataTable.onEventSelectRow );
this.dataTable.subscribe( "tableKeyEvent", this.handleTableKeyEvent, this, true ); /* this.handleTableKeyEvent() is commented out, see there for the reason */
/* this.dataTable.subscribe( "tableKeyEvent", this.handleTableKeyEvent, this, true ); */
this.dataTable.subscribe( "editorKeydownEvent", this.handleEditorKeyEvent, this, true ); this.dataTable.subscribe( "editorKeydownEvent", this.handleEditorKeyEvent, this, true );
this.dataTable.subscribe( "editorShowEvent", this.handleEditorShowEvent, this, true ); this.dataTable.subscribe( "editorShowEvent", this.handleEditorShowEvent, this, true );
this.dataTable.subscribe( "rowAddEvent", this.handleRowAdd, this, true ); this.dataTable.subscribe( "rowAddEvent", this.handleRowAdd, this, true );
@ -288,7 +388,6 @@ WebGUI.Form.DataTable
scope : this scope : this
} }
} ); } );
// This data table will be submitted async // This data table will be submitted async
if ( this.options.ajaxSaveUrl ) { if ( this.options.ajaxSaveUrl ) {
var save = new YAHOO.widget.Button( { var save = new YAHOO.widget.Button( {
@ -340,6 +439,8 @@ WebGUI.Form.DataTable
"format link", "format link",
"format number", "format number",
"format date", "format date",
"format textarea",
"format htmlarea",
"add column", "add column",
"cancel", "cancel",
"ok", "ok",
@ -349,7 +450,13 @@ WebGUI.Form.DataTable
"help select row", "help select row",
"help add row", "help add row",
"help default sort", "help default sort",
"help reorder column" "help reorder column",
"data error",
"sort ascending",
"sort descending"
],
'WebGUI' : [
"Loading..."
] ]
}, },
onpreload : { onpreload : {
@ -372,7 +479,7 @@ WebGUI.Form.DataTable
var helpDialog = new YAHOO.widget.Panel( "helpWindow", { var helpDialog = new YAHOO.widget.Panel( "helpWindow", {
modal : false, modal : false,
draggable : true, draggable : true,
zIndex : 1000 zIndex : 10000
} ); } );
helpDialog.setHeader( "DataTable Help" ); helpDialog.setHeader( "DataTable Help" );
helpDialog.setBody( helpDialog.setBody(
@ -411,28 +518,16 @@ WebGUI.Form.DataTable
}; };
var buttonLabel = this.i18n.get( "Form_DataTable", "delete column" ); var buttonLabel = this.i18n.get( "Form_DataTable", "delete column" );
var availableFormats = [ var availableFormats = [];
{ var formatType = [ "text", "number", "email", "link", "date", "textarea", "htmlarea" ];
"value" : "text", for ( var fti = 0; fti < formatType.length; fti++) {
"label" : this.i18n.get( "Form_DataTable", "format text" ) availableFormats.push(
}, {
{ "value" : formatType[fti],
"value" : "number", "label" : this.i18n.get( "Form_DataTable", "format " + formatType[fti] )
"label" : this.i18n.get( "Form_DataTable", "format number" ) }
}, );
{ }
"value" : "email",
"label" : this.i18n.get( "Form_DataTable", "format email" )
},
{
"value" : "link",
"label" : this.i18n.get( "Form_DataTable", "format link" )
},
{
"value" : "date",
"label" : this.i18n.get( "Form_DataTable", "format date" )
}
];
// function for creating new database columns to the table schema // function for creating new database columns to the table schema
var createTableColumn = function(i,cols) { var createTableColumn = function(i,cols) {
@ -602,7 +697,7 @@ WebGUI.Form.DataTable
this.updateSchema this.updateSchema
= function () { = function () {
var data = this.schemaDialog.getData(); var data = this.schemaDialog.getData();
// First delete columns // First delete columns
var deleteCols = YAHOO.lang.JSON.parse( data[ "deleteCols" ] ); var deleteCols = YAHOO.lang.JSON.parse( data[ "deleteCols" ] );
for ( var x = 0; x < deleteCols.length; x++ ) { for ( var x = 0; x < deleteCols.length; x++ ) {
@ -630,7 +725,7 @@ WebGUI.Form.DataTable
var rows = this.dataTable.getRecordSet().getRecords(); var rows = this.dataTable.getRecordSet().getRecords();
for ( var r = 0; r < rows.length; r++ ) { for ( var r = 0; r < rows.length; r++ ) {
rows[ r ].setData( newKey, rows[ r ].getData( oldKey ) ); rows[ r ].setData( newKey, rows[ r ].getData( oldKey ) );
rows[ r ].setData( oldKey, undefined ); rows[ r ].setData( oldKey, undefined );
} }
} }
@ -640,7 +735,7 @@ WebGUI.Form.DataTable
formatter : format, formatter : format,
resizeable : ( col ? col.resizeable : 1 ), resizeable : ( col ? col.resizeable : 1 ),
sortable : ( col ? col.sortable : 1 ), sortable : ( col ? col.sortable : 1 ),
editor : ( format == "date" ? "date" : "textbox") editor : this.editorByFormat( format )
}; };
if ( format == "date" ) { if ( format == "date" ) {
newCol["dateOptions"] = { format : this.options.dateFormat }; newCol["dateOptions"] = { format : this.options.dateFormat };
@ -671,9 +766,9 @@ WebGUI.Form.DataTable
} }
} }
} }
i++; i++;
} }
this.dataTable.render(); this.dataTable.render();
this.schemaDialog.cancel(); this.schemaDialog.cancel();
}; };