diff -r 322d0feea350 -r 89ef5ed3c48b src/cm/media/js/lib/yui/yui_3.10.3/docs/datatable/datatable-chkboxselect.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/cm/media/js/lib/yui/yui_3.10.3/docs/datatable/datatable-chkboxselect.html Tue Jul 16 14:29:46 2013 +0200 @@ -0,0 +1,664 @@ + + + + + Example: Checkbox select column + + + + + + + + + + +
+
+

+
+ + +

Example: Checkbox select column

+
+
+
+
+ +
+

+ This example shows one method for managing a selection checkbox column + in a DataTable. +

+
+ +
+
+ + + +

Processed:

+
    +
  • (None)
  • +
+
+ + +

Sample Data

+ +

+ This example will use a local Javascript array of data that includes some + common Internet port socket numbers and protocol names: +

+ +
var ports = [
+    { port:20,  pname:'FTP_data',ptitle:'File Transfer Process Data' },
+    { port:21,  pname:'FTP',     ptitle:'File Transfer Process' },
+    { port:22,  pname:'SSH',     ptitle:'Secure Shell' },
+    { port:23,  pname:'TELNET',  ptitle:'Telnet remote communications' },
+    ... // data continues
+];
+ + +

The DataTable

+ +

+ Our DataTable for this example will utilize a custom formatter as the first + column, to display a standard HTML INPUT[type=checkbox] element as an + indication that the record is desired to be "selected" for additional + processing. But that checkbox won't work on its own, because if a "sort" + action happens after the checkbox is clicked the "check" status is lost! +

+ +

+ A way to get around this is to create a binding of the checkbox to an + attribute of each record which will remain with the record even upon + sorts, edits, or other modifications to the record. This is accomplished + by defining a custom recordType for the DataTable that incorporates all + of our standard data for our table but also defines a new Attribute + (called select here) that is a boolean value to track whether the record + is selected. +

+ +

+ The implementation of these methods is shown below, where we have defined a + custom formatter and emptyCellValue for the "select" column that + creates a checked or unchecked checkbox depending on the state of the + attribute, and defines a custom recordType with our new attribute added. + Additionally, we incorporate (a) scrolling and (b) sorting to demonstrate + that this technique works. +

+ +
var table = new Y.DataTable({
+    columns : [
+        {   key:        'select',
+            allowHTML:  true, // to avoid HTML escaping
+            label:      '<input type="checkbox" class="protocol-select-all" title="Toggle ALL records"/>',
+            formatter:      '<input type="checkbox" checked/>',
+            emptyCellValue: '<input type="checkbox"/>'
+        },
+        {   key: 'port',   label: 'Port No.' },
+        {   key: 'pname',  label: 'Protocol' },
+        {   key: 'ptitle', label: 'Common Name' }
+    ],
+    data      : ports,
+    scrollable: 'y',
+    height    : '250px',
+    sortable  : ['port','pname'],
+    sortBy    : 'port',
+    recordType: ['select', 'port', 'pname', 'ptitle']
+}).render("#dtable");
+ + +

The Checkbox Listeners

+ +

+ Having a DataTable with a bunch of checkboxes in it may look cool (or + not!), but we also need to define what to do when they are checked. Since + the column formatter for the first column creates the checkboxes, we + delegate "click" listeners from the DataTable for the two types of + checkboxes—the "check all" checkbox in the header and the individual + checkboxes on each data row. +

+ +

+ Be sure to avoid subscribing to events + directly on elements in each row of a DataTable. +

+ +
// Define a listener on the DT first column for each record's checkbox,
+//   to set the value of `select` to the checkbox setting
+table.delegate("click", function(e){
+    // undefined to trigger the emptyCellValue
+    var checked = e.target.get('checked') || undefined;
+
+    this.getRecord(e.target).set('select', checked);
+
+    // Uncheck the header checkbox
+    this.get('contentBox')
+        .one('.protocol-select-all').set('checked', false);
+}, ".yui3-datatable-data .yui3-datatable-col-select input", table);
+
+
+// Also define a listener on the single TH checkbox to
+//   toggle all of the checkboxes
+table.delegate('click', function (e) {
+    // undefined to trigger the emptyCellValue
+    var checked = e.target.get('checked') || undefined;
+
+    // Set the selected attribute in all records in the ModelList silently
+    // to avoid each update triggering a table update
+    this.data.invoke('set', 'select', checked, { silent: true });
+
+    // Update the table now that all records have been updated
+    this.syncUI();
+}, '.protocol-select-all', table);
+ + +

Button Click Handlers

+ +

+ The bulk of the nitty-gritty is done now. We'll just wire up a button to + process the checked records and another to clear the selection. +

+ +
function process() {
+    var ml  = table.data,
+        msg = '',
+        template = '<li>Record index = {index} Data = {port} : {pname}</li>';
+
+    ml.each(function (item, i) {
+        var data = item.getAttrs(['select', 'port', 'pname']);
+
+        if (data.select) {
+            data.index = i;
+            msg += Y.Lang.sub(template, data);
+        }
+    });
+
+    Y.one("#processed").setHTML(msg || '<li>(None)</li>');
+}
+
+Y.one("#btnSelected").on("click", process);
+
+Y.one("#btnClearSelected").on("click",function () {
+    table.data.invoke('set', 'select', undefined);
+
+    // Uncheck the header checkbox
+    table.get('contentBox')
+        .one('.protocol-select-all').set('checked', false);
+
+    process();
+});
+ + +

+ Note that another option for capturing all the checked checkboxes would be + table.get('contentBox').all('.yui3-datatable-col-select input:checked'). + To make sure that was supported across all browsers, we'd then need to + include the selector-css3 module in our use() statement. +

+ +

+ Another improvement that could be made for HTML5 compliant clients would be + to add in localStorage access to save the checked record data to the + browser environment. You can see how to do this in the + App Framework's Todo List example. +

+ + +

Full Code Listing

+ +

CSS

+ +
.yui3-skin-sam .yui3-datatable-col-select {
+    text-align: center;
+}
+
+#processed {
+   margin-top: 2em;
+   border: 2px inset;
+   border-radius: 5px;
+   padding: 1em;
+   list-style: none;
+}
+ + +

HTML Markup

+

+Note: be sure to add the yui3-skin-sam classname to the +page's <body> element or to a parent element of the widget in order to apply +the default CSS skin. See Understanding Skinning. +

+
<div class="example yui3-skin-sam"> <!-- You need this skin class -->
+    <div id="dtable"></div>
+    <button id="btnSelected" class="yui3-button">Process Selections</button>
+    <button id="btnClearSelected" class="yui3-button">Clear Selections</button>
+
+    <h4>Processed:</h4>
+    <ul id="processed">
+        <li>(None)</li>
+    </ul>
+</div>
+ + +

Javascript

+ +
YUI({ filter: 'raw' }).use( "datatable-sort", "datatable-scroll", "cssbutton", function (Y) {
+
+    var ports = [
+        { port:20,  pname:'FTP_data',ptitle:'File Transfer Process Data' },
+        { port:21,  pname:'FTP',     ptitle:'File Transfer Process' },
+        { port:22,  pname:'SSH',     ptitle:'Secure Shell' },
+        { port:23,  pname:'TELNET',  ptitle:'Telnet remote communications' },
+        { port:25,  pname:'SMTP',    ptitle:'Simple Mail Transfer Protocol' },
+        { port:43,  pname:'WHOIS',   ptitle:'whois Identification' },
+        { port:53,  pname:'DNS',     ptitle:'Domain Name Service' },
+        { port:68,  pname:'DHCP',    ptitle:'Dynamic Host Control Protocol' },
+        { port:79,  pname:'FINGER',  ptitle:'Finger Identification' },
+        { port:80,  pname:'HTTP',    ptitle:'HyperText Transfer Protocol' },
+        { port:110, pname:'POP3',   ptitle:'Post Office Protocol v3' },
+        { port:115, pname:'SFTP',   ptitle:'Secure File Transfer Protocol' },
+        { port:119, pname:'NNTP',   ptitle:'Network New Transfer Protocol' },
+        { port:123, pname:'NTP',    ptitle:'Network Time Protocol' },
+        { port:139, pname:'NetBIOS',ptitle:'NetBIOS Communication' },
+        { port:143, pname:'IMAP',   ptitle:'Internet Message Access Protocol' },
+        { port:161, pname:'SNMP',   ptitle:'Simple Network Management Protocol' },
+        { port:194, pname:'IRC',    ptitle:'Internet Relay Chat' },
+        { port:220, pname:'IMAP3',  ptitle:'Internet Message Access Protocol v3' },
+        { port:389, pname:'LDAP',   ptitle:'Lightweight Directory Access Protocol' },
+        { port:443, pname:'SSL',    ptitle:'Secure Socket Layer' },
+        { port:445, pname:'SMB',    ptitle:'NetBIOS over TCP' },
+        { port:993, pname:'SIMAP',  ptitle:'Secure IMAP Mail' },
+        { port:995, pname:'SPOP',   ptitle:'Secure POP Mail' }
+    ];
+
+    var table = new Y.DataTable({
+        columns : [
+            {   key:        'select',
+                allowHTML:  true, // to avoid HTML escaping
+                label:      '<input type="checkbox" class="protocol-select-all" title="Toggle ALL records"/>',
+                formatter:      '<input type="checkbox" checked/>',
+                emptyCellValue: '<input type="checkbox"/>'
+            },
+            {   key: 'port',   label: 'Port No.' },
+            {   key: 'pname',  label: 'Protocol' },
+            {   key: 'ptitle', label: 'Common Name' }
+        ],
+        data      : ports,
+        scrollable: 'y',
+        height    : '250px',
+        sortable  : ['port','pname'],
+        sortBy    : 'port',
+        recordType: ['select', 'port', 'pname', 'ptitle']
+    }).render("#dtable");
+
+    // To avoid checkbox click causing harmless error in sorting
+    // Workaround for bug #2532244
+    table.detach('*:change');
+
+    //----------------
+    //   "checkbox" Click listeners ...
+    //----------------
+
+    // Define a listener on the DT first column for each record's "checkbox",
+    //   to set the value of `select` to the checkbox setting
+    table.delegate("click", function(e){
+        // undefined to trigger the emptyCellValue
+        var checked = e.target.get('checked') || undefined;
+
+        this.getRecord(e.target).set('select', checked);
+
+        // Uncheck the header checkbox
+        this.get('contentBox')
+            .one('.protocol-select-all').set('checked', false);
+    }, ".yui3-datatable-data .yui3-datatable-col-select input", table);
+
+
+    // Also define a listener on the single TH "checkbox" to
+    //   toggle all of the checkboxes
+    table.delegate('click', function (e) {
+        // undefined to trigger the emptyCellValue
+        var checked = e.target.get('checked') || undefined;
+
+        // Set the selected attribute in all records in the ModelList silently
+        // to avoid each update triggering a table update
+        this.data.invoke('set', 'select', checked, { silent: true });
+
+        // Update the table now that all records have been updated
+        this.syncUI();
+    }, '.protocol-select-all', table);
+
+    //----------------
+    //  CSS-Button click handlers ....
+    //----------------
+    function process() {
+        var ml  = table.data,
+            msg = '',
+            template = '<li>Record index = {index} Data = {port} : {pname}</li>';
+
+        ml.each(function (item, i) {
+            var data = item.getAttrs(['select', 'port', 'pname']);
+
+            if (data.select) {
+                data.index = i;
+                msg += Y.Lang.sub(template, data);
+            }
+        });
+
+        Y.one("#processed").setHTML(msg || '<li>(None)</li>');
+    }
+
+    Y.one("#btnSelected").on("click", process);
+
+    Y.one("#btnClearSelected").on("click",function () {
+        table.data.invoke('set', 'select', undefined);
+
+        // Uncheck the header checkbox
+        table.get('contentBox')
+            .one('.protocol-select-all').set('checked', false);
+
+        process();
+    });
+
+});
+ +
+
+
+ +
+ +
+
+
+ + + + + + + + + + +