Site Navigation
Comment has been reported, thanks for helping to improve the quality of this website
VegUI Tutorial - The Dataset Widget
written by vegu on 18 Apr, 2007 02:58:07
Before we get started let me state that it is very beneficial if you have read the
contentbox tutorial and the
list tutorial as a lot of code can be simply copied over from those tutorials to this one :).
There is also a live example of this tutorial that can be observed by following
this link and any graphics that may be used in this tutorial can be downloaded
here.
Okay, let's go...
As usually we start by defining and building or manager node.
Manager = new VegUIManager('Manager');
Manager.set(800,600,0,0);
Manager.T.Css.backgroundColor = '#b2b2b2';
Manager.build(document.body);
Manager.init_fx(50);
Now we need to create a list template that we will both use as a template for the actual dataset and the list control element that will be used for list selection within the dataset. Before we do so though let's create the css classes we will need. I will comment them so you know what they are for.
Warning, huge style sheet incoming!
.btn_scroll_left_0 { background-image: url(btn_arrow_left_0.gif); }
.btn_scroll_left_1 { background-image: url(btn_arrow_left_1.gif); }
.btn_scroll_right_0 { background-image: url(btn_arrow_right_0.gif); }
.btn_scroll_right_1 { background-image: url(btn_arrow_right_1.gif); }
.btn_scroll_down_0 { background-image: url(btn_arrow_down_0.gif); }
.btn_scroll_down_1 { background-image: url(btn_arrow_down_1.gif); }
.btn_scroll_up_0 { background-image: url(btn_arrow_up_0.gif); }
.btn_scroll_up_1 { background-image: url(btn_arrow_up_1.gif); }
.btn_scroll_drag { background-color: #c8c8c8; }
.scroll_bar { background-color: #838383; }
.blank {}
.cbox_cholder {
border: 1px #838383 solid;
background-color: #fff;
}
.cbox_content {
font: bold 10px Verdana, Arial, Helvetica;
color: #838383;
}
.list_normal {
font: bold 10px Verdana, Arial, Helvetica;
color: #000;
background-color: #fff;
}
.list_selected {
font: bold 10px Verdana, Arial, Helvetica;
color: #000;
background-color: #f0ead8;
}
.list_hover_selected {
font: bold 10px Verdana, Arial, Helvetica;
color: #fff;
background-color: #dfbe70;
}
.list_hover {
font: bold 10px Verdana, Arial, Helvetica;
color: #000;
background-color: #fcf9ee;
}
.list_header {
background-color: #000;
font: bold 10px Verdana, Arial, Helvetica;
color: #fff;
}
.dset_normal {
font: bold 10px Verdana, Arial, Helvetica;
color: #000;
border-top: 1px #dfbe70 solid;
background-color: #fff;
border-bottom: none;
}
.dset_selected {
font: bold 10px Verdana, Arial, Helvetica;
color: #000;
border-top: 1px #dfbe70 solid;
background-color: #f0ead8;
border-bottom: none;
}
.dset_hover_selected {
font: bold 10px Verdana, Arial, Helvetica;
color: #fff;
border-top: 1px #cbaa5c solid;
background-color: #dfbe70;
border-bottom: none;
}
.dset_hover {
font: bold 10px Verdana, Arial, Helvetica;
color: #000;
border-top: 1px #dfbe70 solid;
background-color: #fcf9ee;
border-bottom: none;
}
.dset_header {
background-color: #000;
font: bold 10px Verdana, Arial, Helvetica;
color: #fff;
}
.column_hover {
border: 1px #dfbe70 solid;
background-color: #fff;
color: #000;
}
.column_normal {
border: 1px transparent solid;
border-right: 1px #dfbe70 solid;
}
.dset_detailed {
padding: 20px;
margin: 5px;
background-color: #fdfbf4;
border: 1px #f9e4b2 solid;
color: #000;
}
.dset_list_panel {
background-color: #fdfbf4;
border: 1px #dfbe70 solid;
color: #000;
}
.dset_scaler {
background-color: #fdfbf4;
border: 1px #dfbe70 solid;
}
input {
font: bold 10px Verdana, Arial;
}
Now let's define the list template, straight from the list tutorial copied to this tutorial :)
List = Manager.get_new(VUI_LIST);
List.set(500,500,100,100,16,0);
List.CHolder.T.className = 'cbox_cholder';
List.Content.T.className = 'cbox_content';
List.ScrollY.T.className = 'scroll_bar';
List.ScrollX.T.className = 'scroll_bar';
List.ScrollY.set('y',null,null,18);
List.ScrollX.set('x',null,null,null,18);
List.ScrollY.T.rmarg_nr = -5;
List.ScrollY.T.bmarg -= 2;
List.ScrollX.T.bmarg_nr = -5;
List.ScrollY.Btn1.set(0,0,18,18,'btn_scroll_up_0','btn_scroll_up_1');
List.ScrollY.Btn2.set(0,0,18,18,'btn_scroll_down_0','btn_scroll_down_1');
List.ScrollY.Btn3.set(0,0,18,18,'btn_scroll_drag','btn_scroll_drag');
List.ScrollY.Btn3.add_skin('t',18,4,0,0,0,null,null,null,null,'img','btn_drag_y_top.gif');
List.ScrollY.Btn3.add_skin('f',18,1,0,4,0,null,3,null,null,'img','btn_drag_y_fill.gif');
List.ScrollY.Btn3.add_skin('b',18,4,0,0,0,null,null,null,-1,'img','btn_drag_y_bottom.gif');
List.ScrollY.Btn3.add_skin('p',1,1,0,0,'blank',0,0,null,null);
List.ScrollX.Btn1.set(0,0,18,18,'btn_scroll_left_0','btn_scroll_left_1');
List.ScrollX.Btn2.set(0,0,18,18,'btn_scroll_right_0','btn_scroll_right_1');
List.ScrollX.Btn3.set(0,0,18,18,'btn_scroll_drag','btn_scroll_drag');
List.set_style(
'list_hover', 'list_normal', 'list_selected', 'list_header', 'list_hover_selected'
);
List.flags |= VUI_HIDE_SCROLLX;
The Dataset
Okay, now that we have the boring re-hashed stuff out of the way lets move on to dataset goodness.
We start by creating a new dataset element using the manager's get_new method.
DSet = Manager.get_new(VUI_DATASET);
DSet.clone(List);
We clone the dataset from our list template right after, however we do not want our dataset to use the same styles as our list template so we call it's set_styles() method to set new css classes.
The method if fairly similar to the set_styles() and is used the same way.
DSet.set_style(
'dset_hover','dset_normal','dset_selected','dset_header',
'dset_hover_selected','column_normal','column_hover',
'dset_detailed'
);
arg 1: css class to use when a row is 'toched' by the mouse pointer
arg 2: css class to use when a row is in default state
arg 3: css class to use when a row is selected
arg 4: css class to use for the header row
arg 5: css class to use when a selected row is 'touched' by the mouse pointer
arg 6: css class to use on a column in default state
arg 7: css class to use on a column when it is 'touched' by the mouse pointer
arg 8: css class to use on the detailed field of a row
Before we go on lets talk about the field types quickly. When setting up the dataset (we will get to that) you can define the field type of each column. The field type defines how a field in the column can be edited by the user.
There are currently four different field types that you should be familiar with from the property-set widget:
VUI_DSET_INPUT_TEXT - text input
VUI_DSET_INPUT_LIST - list input (item is chosen from a list)
VUI_DSET_INPUT_BOOL - user can select true or false for field
VUI_DSET_INPUT_CUSTOM - a custom function is used to obtain value
The user can go into edit mode on a field by double clicking the field. If text input is the field type an editable input box will be shown to the user and when the user hits the enter key the edited value will be transfered to the field.
If boolean field type is selected then double clicking the field will simply change its value from true to false or vice versa.
If list input field type is selected then a panel will brought into view that will hold a list with values and when the user selects a value from that list it is transfered to the field and the panel is hidden again.
Now, when it comes to list input there are several elements involved to make it work.
The ListTpl property of the dataset should point to the list template object that the list with the values will be cloned from. So we do that now by pointing it to our List object we defined earlier.
The ListPanel property points to a child element of the dataset. It is the panel that will hold the value list. It is the panel that will be brought into view when a field with list input field type is
double clicked.
It is a normal
and should be set up as a div element. You can also set up its position, proportions and margins to define where it will be displayed in the dataset.
DSet.ListPanel.T.className = 'dset_list_panel';
DSet.ListPanel.set('div', 50, 50, 100, 100);
DSet.ListPanel.set_marg(100,100);
DSet.ListPanel.T.z = 100;
And finally - this only matters if the effect engine has been initialized - we set up the Scaler element. The scaler element will be used to display a growing or shrinking effect when the list panel is brought into view.
In our example we simply make sure it is a div element and that it is using the right css class.
DSet.Scaler.set('div');
DSet.Scaler.T.className = 'dset_scaler';
Setting up the dataset
In order to set up the columns and field types of our dataset we do so by editing the columns template property of the dataset. Each column should be a property of the columns object and each column can have several properties as well that define it's behavior.
DSet.T.columns = {
column_1 : {
caption : 'boolean',
width : 25,
editType : VUI_DSET_INPUT_BOOL
},
column_2 : {
caption : 'text',
width : 25,
editType : VUI_DSET_INPUT_TEXT
},
column_3 : {
caption : 'list',
width: 25,
editType : VUI_DSET_INPUT_LIST,
fill_list : function(List) {
List.flush();
for(i = 0; i < 100; i++)
List.add_item_txt('Some Item '+i, i, true);
List.adjust();
}
},
column_4 : {
caption : 'custom',
width : 25,
fetch : function() { return vui_rand(1,2500); },
editType : VUI_DSET_INPUT_CUSTOM
},
detailed : {
hidden : true,
editType : VUI_DSET_INPUT_TEXT
}
};
The comments should explain most of it, but i will go into detail on some of the stuff. In the third column there is a fill_list property. The column has had its field type set to list input and the fill_list property should point to a function that will fill the columns value list with values.
Again, the value list is the list that will be shown to the user to select a value for the field they double clicked.
In our example the value list is simply filled with 100 entries.
In the fourth column the field type (editType) is set to the custom and the function that will provide the value is set in the fetch property of the column. In this example it returns a random value between 1 and 2500.
If the editType property is not set on a column then the fields in the column will not be editable at all.
The last 'column' definition is for the detailed field. The hidden property assures that it will not be added as a normal column and the editType is set to text, meaning the user can also edit the detailed field by double clicking on it.
Filling the dataset
If you want to fill your dataset with data before it is built you do so by setting up the rows template property of the dataset.
Each row is an object that should provide values for each column in the dataset.
Row object example:
row = {
column_1 : true,
column_2 : 'Col 2, Row '+1,
column_3 : 1,
column_4 : 0,
detailed : 'This is some rather long text that will be displayed in the detailed field!',
id : 1
};
Note that we are using the names of the columns that we defined earlier to assign values to their fields in the row.
The detailed property set's the value of the detailed field of the row and the id property can be used to give the row a unique id. So knowing this lets fill our dataset with 10 rows.
As you see the detailed field can and is supposed to hold lots of data that wouldnt fit in any of the normal columns without being cut off. For example i use the dataset in my website control panel to manage comments to the blog. The dataset displays the posters information in the normal column and the comment in the detailed field.
var i;
for(i = 0; i < 10; i++) {
DSet.T.rows[i] = {
column_1 : true,
column_2 : 'Col 2, Row '+i,
column_3 : i,
column_4 : 0,
detailed : 'This is some rather long text that will be displayed in the detailed field!',
id : i
}
}
Alright, before we build the dataset, there are two more template properties you should know about.
The multiselect property allows you define whether more than one row can be selected at a time.
DSet.T.multiSelect = true;
The forceExpand property allows you define whether the detailed field of a row should start out expanded or collapse. By default this false and the detailed field for a row will only be shown to the user when touches the row with mouse pointer and hits the space bar on his keyboard.
DSet.T.forceExpand = true;
Now! we can build the dataset :)
Manager.build_element(DSet);
Rebuilding the dataset with changed row data
Once the dataset is built the columns and rows properties become direct properties of the dataset and are no longer template properties.
You can then change them as you need and once done you can rebuild the dataset by calling it's rebuild() method.
DSet.rows[5].column_2 = 'Hello world!';
Letting the user delete entries
When the user has selected one or more rows and hits the DEL key on their keyboard then the delete_req() or delete_req_m() (if multiple entries are selected) are called.
In their unedited state those methods simply call the delete_item() / delete_items() method which removes the selected rows from the dataset instantly.
If you are creating network reliant application that fills the dataset with data from a database for example then you will want to send a query to the server to delete those rows and once the rows are removed successfully on the server, then and only then you want them to be removed on the client side.
The way to accomplish that is to redefine the delete_req() and delete_req_m() functions to send a query to server using the vegUI bridge and have them call the delete_item() method only when the server has given a success response.
Remember that in order to use the vegUI bridge it must have been initialized in the manager using the manager's init_bridge() method.
Untested Example:
/* the argument submitted to the function is the value (id)
* of the currently selected row
*/
DSet.delete_req = function(value) {
var d = this;
this.Manager.Bridge.send('delete.php?v='+value,'','GET',
function() {
if(this.request.responseText == '1')
d.delete_item(value);
}
);
};
DSet.delete_req_m = function(sItems) {
var d = this, i, values = [];
for(i in sItems)
values.push(sItems[i].itemValue);
var vStr = values.join(',');
this.Manager.Bridge.send('delete.php?v='+vStr,'','POST',
function() {
if(this.request.responseText == '1')
d.delete_items(sItems);
}
);
};
Let me know if there is anything that should be further explained, as i wrote this tutorial in one big session chances are i probably missed something :).
Related Posts
Your Comment
Comments to this post: (1)
RSS Feed for comments
hongnk
I like the grid for its speed. However the custom scrollbar is not so natural (can't do page scroll). Is it possible to use windows scrollbar instead?
Report this comment