Viewing File: /usr/local/cpanel/base/cjt/table2.js

/*
    #                                                 Copyright(c) 2020 cPanel, L.L.C.
    #                                                           All rights reserved.
    # copyright@cpanel.net                                         http://cpanel.net
    # This code is subject to the cPanel license. Unauthorized copying is prohibited
*/

// check to be sure the CPANEL global object already exists
if (typeof (CPANEL) === "undefined" || !CPANEL) {
    alert("You must include the CPANEL global object before including table2.js!");
} else {

    // el: string or DOM object
    // data: array of objects
    // animate_render: boolean
    //
    // columns: array of objects, e.g.:
    // {
    //  key: 'user',                    //required
    //  label: 'Username',              //optional
    //  renderer: function(row,i) {..}  //optional
    // }
    // "renderer" receives the data row and index and must return a String object
    //
    // actions: array of objects { label: "", code: function(row,i) {..} }
    // each function receives the data row and index as its parameters
    CPANEL.table2 = function(table_opts) {
        for (var i in table_opts) {
            this[i] = table_opts[i];
        }

        this.columns = this.columns.map(function(col_data) {
            var key = col_data.key;
            if (!("renderer" in col_data)) {
                col_data.renderer = function(row) {
                    return row[key];
                };
            }
            if (!("label" in col_data)) {
                col_data.label = key;
            }

            return col_data;
        });

        var need_to_render_head = true;
        if ("el" in this) {
            if (typeof this.el === "string") {
                this.id = this.el;
                this.el = DOM.get(this.el);
            } else {
                this.id = this.el.id || DOM.generateId(this.el);
            }
            this.head = this.el.tHead;
            if (!this.head) {
                this.head = document.createElement("thead");
                this.foot = document.createElement("tfoot");
                this.el.insertBefore(this.foot, this.el.firstChild);
                this.el.insertBefore(this.head, this.el.firstChild);
            } else {
                need_to_render_head = false;
            }
            var tBodies = this.el.tBodies;
            if (tBodies && tBodies.length > 0) {
                this.body = tBodies[0];
            } else {
                this.body = document.createElement("tbody");
                this.el.appendChild(this.body);
            }
        } else {
            this.el = document.createElement("table");
            this.id = DOM.generateId(this.el);
            this.head = document.createElement("thead");
            this.body = document.createElement("tbody");
        }

        DOM.addClass(this.el, "cjt-table");

        this.constructor.tables[this.id] = this;
        this._encoded_id = this.id.html_encode();

        if (!("animate_render" in this)) {
            this.animate_render = true;
        }
        this.animate_render = false; // for now, until/if I get it working

        if (need_to_render_head) {
            this.render_head();
        }

        if ("data" in this) {
            this.render();
        }
    };

    // id => JS object
    CPANEL.table2.tables = {};

    YAHOO.lang.augmentObject(CPANEL.table2.prototype, {

        // requires this.data
        render: function() {
            var that = this;

            if ("actions" in this) {
                var actions_html = this.actions.map(function(action, action_index) {
                    return YAHOO.lang.substitute(that._action_item_template, {
                        action_label: action.label.html_encode(),
                        action_index: action_index,
                        table_id: that._encoded_id
                    });
                }).join("");

                this._actions_html = "<ul class='cjt-table-action-list'>" + actions_html + "</ul>";

                this.data.forEach(function(d, i) {
                    that._cached_forms[i] = {};
                });
            }

            // this may be faster combining the reduce() and forEach()
            this.data
                .map(function(row, idx) {
                    return that._generate_row_objects.call(that, row, idx);
                })
                .reduce(function(a, b) {
                    return a.concat(b);
                }, []) // flatten the list
                .forEach(function(row) {
                    that.body.appendChild(row);
                });

            // accommodate touch screens!!
            if (!CPANEL.is_touchscreen && ("actions" in this)) {
                this._show_actions(0);
            }

            if (this.animate_render) {
                Array.prototype.filter.call(this.body.rows, function(r) {
                    return !DOM.hasClass(r, "cjt-table-form-row");
                })
                    .forEach(function(r) {
                        Array.prototype.filter.call(r, CPANEL.animate.slide_down);
                    });
            }
        },
        render_head: function() {
            var that = this;
            var column_headers = this.columns.map(function(col) {
                var th = document.createElement("th");
                th.id = that.id + "-head-cell-" + col.key;
                th.innerHTML = col.label;
                return th;
            });

            // IE can't handle injecting rows via innerHTML
            var the_row = document.createElement("tr");
            the_row.id = this.id + "-head-row";
            the_row.className = "cjt-table-head-row";
            column_headers.forEach(function(h) {
                the_row.appendChild(h);
            });
            this.head.appendChild(the_row);
        },
        render_action: function(action, data_index) {
            var form_cell = this._get_form_cell(data_index);

            // form elements are always wrapped in a div
            var existing_form_contents = form_cell.firstChild;

            if (existing_form_contents) {
                this._cached_forms[data_index][action.label] = existing_form_contents;

                CPANEL.animate.slide_up_and_remove(form_cell.firstChild);

                if ((data_index in this._open_forms) && this._open_forms[data_index] === action.label) {
                    delete this._open_forms[data_index];
                    return;
                }
            }


            var form_div = (data_index in this._cached_forms) && this._cached_forms[data_index][action.label];
            if (!form_div) {
                form_div = document.createElement("div");
                form_div.innerHTML = action.code(this.data[data_index], data_index);
                DOM.addClass(form_div, "cjt-table-form");
                DOM.setStyle(form_div, "display", "none");
            }

            form_cell.appendChild(form_div);
            CPANEL.animate.slide_down(form_div);
            this._open_forms[data_index] = action.label;
        },
        reset: function() {
            for (var open_index in this._open_forms) {
                var form_cell = _get_form_cell(open_index);
                var contents = form_cell.childNodes;
                if (contents) {
                    Array.prototype.forEach.call(contents, CPANEL.animate.slide_up_and_remove);
                }
            }
        },

        // row_index => action label => HTML
        _cached_forms: {},

        // row index => action label
        _open_forms: {},

        _get_form_cell: function(i) {
            return DOM.get(this.id + "-form-cell-" + i);
        },

        _action_item_template: "<li class=\"cjt-table-action-{action_label}\" onclick='CPANEL.table2.tables[\"{table_id}\"].render_action(CPANEL.table2.tables[\"{table_id}\"].actions[{action_index}],{d_index})'>{action_label}</li>",

        _generate_row_objects: function(row_data, row_index) {
            var data_cells = this.columns.map(function(col_data, col_index) {
                var key = col_data.key;
                var cell = document.createElement("td");
                if (this.animate_render) {
                    cell.style.height = "0";
                }
                cell.className = "cjt-table-data-cell-" + col_data.key;
                cell.innerHTML = col_data.renderer(row_data, row_index);
                return cell;
            });

            var stripe_class = row_index % 2 ? "row-odd" : "row-even";
            var row_class = ["cjt-table-data-row", stripe_class];

            var row_events = {};
            if (this._actions_html) {
                var that = this;
                if (CPANEL.is_touchscreen) {
                    row_events.ontouchstart = function() {
                        that._toggle_actions(row_index);
                    };
                } else {
                    row_events.onmouseover = function() {
                        that._show_actions(row_index);
                    };
                }
                row_class.push("cjt-table-data-row-with-actions");
            }

            var main_row = document.createElement("tr");
            main_row.id = this.id + "-data-row-" + row_index;
            main_row.className = row_class.join(" ");
            data_cells.forEach(function(c) {
                main_row.appendChild(c);
            });

            var rows = [main_row];

            if (this._actions_html) {
                var click_row = document.createElement("tr");
                click_row.id = this.id + "-click-row-" + row_index;
                click_row.className = "cjt-table-click-row " + stripe_class;
                var click_row_cell = document.createElement("td");
                click_row_cell.colSpan = 99;
                click_row_cell.innerHTML = YAHOO.lang.substitute(this._actions_html + "", {
                    "d_index": row_index
                });
                click_row.appendChild(click_row_cell);

                var form_row = document.createElement("tr");
                form_row.id = this.id + "-form-row-" + row_index;
                form_row.className = "cjt-table-form-row " + stripe_class;
                var form_row_cell = document.createElement("td");
                form_row_cell.id = this.id + "-form-cell-" + row_index;
                form_row_cell.colSpan = 99;
                form_row.appendChild(form_row_cell);

                rows.push(click_row, form_row);
            }

            // assign events as needed
            for (var ev in row_events) {
                rows.forEach(function(r) {
                    r[ev] = row_events[ev];
                });
            }

            return rows;
        },

        _shown_actions_index: null,
        _show_actions: function(row_index) {
            if (row_index !== this._shown_actions_index) {
                this._hide_actions(this._shown_actions_index);
                DOM.addClass(this.id + "-click-row-" + row_index, "actions_visible");
                this._shown_actions_index = row_index;
            }
        },
        _hide_actions: function(row_index) {
            DOM.removeClass(this.id + "-click-row-" + row_index, "actions_visible");
        },
        _toggle_actions: function(row_index) {
            if (row_index === this._shown_actions_index) {
                this._hide_actions(row_index);
                this._shown_actions_index = null;
            } else {
                this._show_actions(row_index);
            }
        },

        _: true // does nothing
    });


    (function() {
        var _stylesheet = [
            [".cjt-table-form-cell", "padding: 0px "],
            [".cjt-table-action", "float:left; cursor:pointer"],
            [".cjt-table-action-list", "visibility:hidden; list-style:none; padding:0; margin:0"],
            [".cjt-table-click-row.actions_visible ul", "visibility:visible"]
        ];
        var inserter;
        var first_stylesheet = document.styleSheets[0];
        if (!first_stylesheet) {
            var new_stylesheet = document.createElement("style");
            document.head.appendChild(new_stylesheet);
            first_stylesheet = document.styleSheets[0];
        }
        if ("insertRule" in first_stylesheet) { // W3C DOM
            _stylesheet.forEach(function(rule) {
                first_stylesheet.insertRule(rule[0] + " {" + rule[1] + "}", 0);
            });
        } else { // IE
            _stylesheet.forEach(function(rule) {
                first_stylesheet.addRule(rule[0], rule[1], 0);
            });
        }
    })();

    CPANEL.table2.Tree = function(name) {
        this.name = name;
    };

}
Back to Directory File Manager