fuelux tree简单配置使用(动态数据+字体图标)
发布日期:2021-10-10 12:33:28 浏览次数:1 分类:技术文章

本文共 33712 字,大约阅读时间需要 112 分钟。

目录


 fuelux tree配置项(动态数据+字体图标)

在web项目开发中,我们不免会遇到各种树的信息展示,我也遇到同样的 问题,不过目前的前端树展示千奇百怪,其中 `ztree(功能最强,样式騒丑)` 还有`bootstrap 的 Treeview也不错`,今天,讲的是 ` fuelux tree` 中的 树 插件,这个插件的好处 就是树的节点图标可自定义(需要改代码,后面会展示),什么`bootstrap 的glyphicon字体`、`font-awesome的 fa 字体`,话不多说,直接上代码

 fuelux tree 的HTML:

配置 非无穷树(实际开发中):

$(function() {    var treeDataSource = new StaticTreeDataSource(folders);    $('#MyTree').tree({        dataSource: treeDataSource.getData,        multiSelect: false,     //能否多选节点        folderSelect: false,    //根节点能否选中        //注:配置 节点  首先 必须HTML 中的图标和 自定义的图标统一        //否则 不统一可能 节点 能展开 但图标没有切换 或者 不能展开        iconFolderOpen: "glyphicon-minus-sign",     //节点展开图标        iconFolderClose: "glyphicon-plus-sign"      //节点关闭图标    });})//初始化树的信息function StaticTreeDataSource(treeData) {    var nodes = treeData;    this.getData = function(options, callback) {        console.log(JSON.stringify(options))        //数据第一次初始化时 此时的 options 没有信息        if($.isEmptyObject(options)) {            nodes = nodes;        } else {            //获取当前点击节点的 options            if(options.children == null || options.children == undefined) {                nodes = {};            } else {                nodes = options.children;            }        }        //方法回调  添加当前选中节点的子节点        callback({            data: nodes        });    }}var folders = [{        "name": "Aquire",        "type": "item"    },    {        "name": "Onboard",        "type": "item"    },    {        "name": "Engage",        "type": "folder",        "attr": {            "id": "Engage",            "data-icon": "glyphicon glyphicon-folder-open",            "style": "color: rebeccapurple;"        },        "children": [{                "name": "Abandoned Cart",                "type": "folder",                "children": [{                    "name": "Archive",                    "type": "item"                }]            },            {                "name": "Birthday",                "type": "item"            },            {                "name": "Browse Retargeting",                "type": "item"            },            {                "name": "Loyalty",                "type": "item"            },            {                "name": "Newsletter",                "type": "item"            },            {                "name": "Post-Purchase",                "type": "item"            },            {                "name": "Promotional",                "type": "item"            },            {                "name": "Transactional",                "type": "folder",                "children": [{                    "name": "Archive",                    "type": "item"                }]            },            {                "name": "Wish List",                "type": "item"            }        ]    },    {        "name": "Retain",        "type": "item",        "attr": {            "id": "sky-and-water-i",            "style": "color: rebeccapurple;" //自定义节点颜色        }    }];

配置 循环树(官网API):

function staticDataSource(parentData, callback) {    childNodesArray = [{            "name": "Ascending and Descending",            "type": "folder",            "attr": {                "id": "ascending-and-descending"            }        },        {            "name": "Sky and Water I",            "type": "item",            "attr": {                "id": "sky-and-water-i",                "data-icon": "glyphicon glyphicon-file",                "style": "color: rebeccapurple;"            }        },        {            "name": "Drawing Hands",            "type": "folder",            "attr": {                "id": "drawing-hands"            }        },        {            "name": "Waterfall",            "type": "item",            "attr": {                "id": "waterfall",                "data-icon": "glyphicon glyphicon-cloud",                "style": "color: rebeccapurple;"            }        },        {            "name": "Belvedere",            "type": "folder",            "attr": {                "id": "belvedere"            }        },        {            "name": "Relativity",            "type": "item",            "attr": {                "id": "relativity",                "data-icon": "glyphicon glyphicon-picture",                "style": "color: rebeccapurple;"            }        },        {            "name": "House of Stairs",            "type": "folder",            "attr": {                "id": "house-of-stairs"            }        },        {            "name": "Convex and Concave",            "type": "item",            "attr": {                "id": "convex-and-concave",                "data-icon": "glyphicon glyphicon-tags",                "style": "color: rebeccapurple;"            }        }    ];    callback({        data: childNodesArray    });}//初始化 树信息$('#MyTree').tree({    dataSource: staticDataSource,    multiSelect: false,    folderSelect: false,    iconFolderOpen: "glyphicon-minus-sign",    iconFolderClose: "glyphicon-plus-sign"});

Fuel UX Tree 树的js (动过手脚使其能自定义图标)

这里用的的是 FuelUX 3.0

tree-custom.js 文件,这里处理实现Font Awesome字体图标和bootstrap的图标都能兼容,改过的地方都有DIY注释的

/* * Fuel UX Tree 3.0 * https://github.com/ExactTarget/fuelux * * Copyright (c) 2014 ExactTarget * Licensed under the BSD New license. */// -- BEGIN UMD WRAPPER PREFACE --// For more information on UMD visit:// https://github.com/umdjs/umd/blob/master/jqueryPlugin.js(function (factory) {    if (typeof define === 'function' && define.amd) {        // if AMD loader is available, register as an anonymous module.        define(['jquery'], factory);    } else if (typeof exports === 'object') {        // Node/CommonJS        module.exports = factory(require('jquery'));    } else {        // OR use browser globals if AMD is not present        factory(jQuery);    }}(function ($) {    // -- END UMD WRAPPER PREFACE --    // -- BEGIN MODULE CODE HERE --    var old = $.fn.tree;    // TREE CONSTRUCTOR AND PROTOTYPE    var Tree = function Tree(element, options) {        this.$element = $(element);        this.options = $.extend({}, $.fn.tree.defaults, options);        if (this.options.itemSelect) {            this.$element.on('click.fu.tree', '.tree-item', $.proxy(function (ev) {                this.selectItem(ev.currentTarget);            }, this));        }        this.$element.on('click.fu.tree', '.tree-branch-name', $.proxy(function (ev) {            this.toggleFolder(ev.currentTarget);        }, this));        // folderSelect default is true        if (this.options.folderSelect) {            this.$element.addClass('tree-folder-select');            this.$element.off('click.fu.tree', '.tree-branch-name');            this.$element.on('click.fu.tree', '.icon-caret', $.proxy(function (ev) {                this.toggleFolder($(ev.currentTarget).parent());            }, this));            this.$element.on('click.fu.tree', '.tree-branch-name', $.proxy(function (ev) {                this.selectFolder($(ev.currentTarget));            }, this));        }        this.render();    };    Tree.prototype = {        constructor: Tree,        deselectAll: function deselectAll(nodes) {            // clear all child tree nodes and style as deselected            nodes = nodes || this.$element;            var $selectedElements = $(nodes).find('.tree-selected');            $selectedElements.each(function (index, element) {                styleNodeDeselected( $(element), $(element).find( '.glyphicon' ) );            });            return $selectedElements;        },        destroy: function destroy() {            // any external bindings [none]            // empty elements to return to original markup            this.$element.find("li:not([data-template])").remove();            this.$element.remove();            // returns string of markup            return this.$element[0].outerHTML;        },        render: function render() {            this.populate(this.$element);        },        populate: function populate($el, isBackgroundProcess) {            var self = this;            var $parent = ($el.hasClass('tree')) ? $el : $el.parent();            var loader = $parent.find('.tree-loader:eq(0)');            var treeData = $parent.data();            isBackgroundProcess = isBackgroundProcess || false; // no user affordance needed (ex.- "loading")            if (isBackgroundProcess === false) {                loader.removeClass('hide hidden'); // hide is deprecated            }            this.options.dataSource(treeData ? treeData : {}, function (items) {                loader.addClass('hidden');                $.each(items.data, function (index, value) {                    var $entity;                    if (value.type === 'folder') {                        $entity = self.$element.find('[data-template=treebranch]:eq(0)').clone().removeClass('hide hidden').removeData('template'); // hide is deprecated                        $entity.data(value);                        $entity.find('.tree-branch-name > .tree-label').html(value.text || value.name);                    } else if (value.type === 'item') {                        $entity = self.$element.find('[data-template=treeitem]:eq(0)').clone().removeClass('hide hidden').removeData('template'); // hide is deprecated                        $entity.find('.tree-item-name > .tree-label').html(value.text || value.name);                        $entity.data(value);                    }                    // Decorate $entity with data or other attributes making the                    // element easily accessable with libraries like jQuery.                    //                    // Values are contained within the object returned                    // for folders and items as attr:                    //                    // {                    //     text: "An Item",                    //     type: 'item',                    //     attr = {                    //         'classes': 'required-item red-text',                    //         'data-parent': parentId,                    //         'guid': guid,                    //         'id': guid                    //     }                    // };                    //                    // the "name" attribute is also supported but is deprecated for "text".                    // add attributes to tree-branch or tree-item                    var attr = value.attr || value.dataAttributes || [];                    $.each(attr, function (key, value) {                        switch (key) {                            case 'cssClass':                            case 'class':                            case 'className':                                $entity.addClass(value);                                break;                            // allow custom icons                            case 'data-icon':                                $entity.find('.icon-item').removeClass().addClass('icon-item ' + value);                                $entity.attr(key, value);                                break;                            // ARIA support                            case 'id':                                $entity.attr(key, value);                                $entity.attr('aria-labelledby', value + '-label');                                $entity.find('.tree-branch-name > .tree-label').attr('id', value + '-label');                                break;                            // style, data-*                            default:                                $entity.attr(key, value);                                break;                        }                    });                    // add child nodes                    if ($el.hasClass('tree-branch-header')) {                        $parent.find('.tree-branch-children:eq(0)').append($entity);                    } else {                        $el.append($entity);                    }                });                // return newly populated folder                self.$element.trigger('loaded.fu.tree', $parent);            });        },        selectTreeNode: function selectItem(clickedElement, nodeType) {            var clicked = {};   // object for clicked element            clicked.$element = $(clickedElement);            var selected = {}; // object for selected elements            selected.$elements = this.$element.find('.tree-selected');            selected.dataForEvent = [];            // determine clicked element and it's icon            if (nodeType === 'folder') {                // make the clicked.$element the container branch                clicked.$element = clicked.$element.closest('.tree-branch');                clicked.$icon = clicked.$element.find('.icon-folder');            }            else {                clicked.$icon = clicked.$element.find('.icon-item');            }            clicked.elementData = clicked.$element.data();            // the below functions pass objects by copy/reference and use modified object in this function            if ( this.options.multiSelect ) {                multiSelectSyncNodes(this, clicked, selected);            }            else {                singleSelectSyncNodes(this, clicked, selected);            }            // all done with the DOM, now fire events            this.$element.trigger(selected.eventType + '.fu.tree', {                target: clicked.elementData,                selected: selected.dataForEvent            });            clicked.$element.trigger('updated.fu.tree', {                selected: selected.dataForEvent,                item: clicked.$element,                eventType: selected.eventType            });        },        discloseFolder: function discloseFolder(el) {            var $el = $(el);            var $branch = $el.closest('.tree-branch');            var $treeFolderContent = $branch.find('.tree-branch-children');            var $treeFolderContentFirstChild = $treeFolderContent.eq(0);            //take care of the styles            $branch.addClass('tree-open');            $branch.attr('aria-expanded', 'true');            $treeFolderContentFirstChild.removeClass('hide hidden'); // hide is deprecated            //DIY  配置 节点展开图标  首先 必须HTML 中的图标和 自定义的图标统一            $branch.find('> .tree-branch-header .icon-folder').eq(0)                .removeClass(this.options.iconFolderClose)                .addClass(this.options.iconFolderOpen);            /*//原本的 节点 关闭 切换                $branch.find('> .tree-branch-header .icon-folder').eq(0)                .removeClass('glyphicon-folder-close')                .addClass('glyphicon-folder-open'); */            //add the children to the folder            if (!$treeFolderContent.children().length) {                this.populate($treeFolderContent);            }            this.$element.trigger('disclosedFolder.fu.tree', $branch.data());        },        closeFolder: function closeFolder(el) {            var $el = $(el);            var $branch = $el.closest('.tree-branch');            var $treeFolderContent = $branch.find('.tree-branch-children');            var $treeFolderContentFirstChild = $treeFolderContent.eq(0);            //take care of the styles            $branch.removeClass('tree-open');            $branch.attr('aria-expanded', 'false');            $treeFolderContentFirstChild.addClass('hidden');            // DIY 配置 节点 关闭 切换图标            $branch.find('> .tree-branch-header .icon-folder').eq(0)                .removeClass(this.options.iconFolderOpen)                .addClass(this.options.iconFolderClose);            /*  //原本的 节点关闭切换              * $branch.find('> .tree-branch-header .icon-folder').eq(0)                .removeClass('glyphicon-folder-open')                .addClass('glyphicon-folder-close');*/            // remove chidren if no cache            if (!this.options.cacheItems) {                $treeFolderContentFirstChild.empty();            }            this.$element.trigger('closed.fu.tree', $branch.data());        },        toggleFolder: function toggleFolder(el) {            var $el = $(el);            /**             * DIY 修改 判断节点 是否展开             */            if ($el.parent(".tree-branch-header").parent(".tree-branch").hasClass("tree-open")) {                this.closeFolder(el);            } else{                this.discloseFolder(el);            }            /**  //原本的  节点展开判断            if ($el.find('.glyphicon-folder-close').length) {                this.discloseFolder(el);            } else if ($el.find('.glyphicon-folder-open').length) {                this.closeFolder(el);            } */        },        selectFolder: function selectFolder(el) {            if (this.options.folderSelect) {                this.selectTreeNode(el, 'folder');            }        },        selectItem: function selectItem(el) {            if (this.options.itemSelect) {                this.selectTreeNode(el, 'item');            }        },        selectedItems: function selectedItems() {            var $sel = this.$element.find('.tree-selected');            var data = [];            $.each($sel, function (index, value) {                data.push($(value).data());            });            return data;        },        // collapses open folders        collapse: function collapse() {            var self = this;            var reportedClosed = [];            var closedReported = function closedReported(event, closed) {                reportedClosed.push(closed);                // hide is deprecated                if (self.$element.find(".tree-branch.tree-open:not('.hidden, .hide')").length === 0) {                    self.$element.trigger('closedAll.fu.tree', {                        tree: self.$element,                        reportedClosed: reportedClosed                    });                    self.$element.off('loaded.fu.tree', self.$element, closedReported);                }            };            //trigger callback when all folders have reported closed            self.$element.on('closed.fu.tree', closedReported);            self.$element.find(".tree-branch.tree-open:not('.hidden, .hide')").each(function () {                self.closeFolder(this);            });        },        //disclose visible will only disclose visible tree folders        discloseVisible: function discloseVisible() {            var self = this;            var $openableFolders = self.$element.find(".tree-branch:not('.tree-open, .hidden, .hide')");            var reportedOpened = [];            var openReported = function openReported(event, opened) {                reportedOpened.push(opened);                if (reportedOpened.length === $openableFolders.length) {                    self.$element.trigger('disclosedVisible.fu.tree', {                        tree: self.$element,                        reportedOpened: reportedOpened                    });                    /*                    * Unbind the `openReported` event. `discloseAll` may be running and we want to reset this                    * method for the next iteration.                    */                    self.$element.off('loaded.fu.tree', self.$element, openReported);                }            };            //trigger callback when all folders have reported opened            self.$element.on('loaded.fu.tree', openReported);            // open all visible folders            self.$element.find(".tree-branch:not('.tree-open, .hidden, .hide')").each(function triggerOpen() {                self.discloseFolder($(this).find('.tree-branch-header'));            });        },        /**        * Disclose all will keep listening for `loaded.fu.tree` and if `$(tree-el).data('ignore-disclosures-limit')`        * is `true` (defaults to `true`) it will attempt to disclose any new closed folders than were        * loaded in during the last disclosure.        */        discloseAll: function discloseAll() {            var self = this;            //first time            if (typeof self.$element.data('disclosures') === 'undefined') {                self.$element.data('disclosures', 0);            }            var isExceededLimit = (self.options.disclosuresUpperLimit >= 1 && self.$element.data('disclosures') >= self.options.disclosuresUpperLimit);            var isAllDisclosed = self.$element.find(".tree-branch:not('.tree-open, .hidden, .hide')").length === 0;            if (!isAllDisclosed) {                if (isExceededLimit) {                    self.$element.trigger('exceededDisclosuresLimit.fu.tree', {                        tree: self.$element,                        disclosures: self.$element.data('disclosures')                    });                    /*                    * If you've exceeded the limit, the loop will be killed unless you                    * explicitly ignore the limit and start the loop again:                    *                    *    $tree.one('exceededDisclosuresLimit.fu.tree', function () {                    *        $tree.data('ignore-disclosures-limit', true);                    *        $tree.tree('discloseAll');                    *    });                    */                    if (!self.$element.data('ignore-disclosures-limit')) {                        return;                    }                }                self.$element.data('disclosures', self.$element.data('disclosures') + 1);                /*                * A new branch that is closed might be loaded in, make sure those get handled too.                * This attachment needs to occur before calling `discloseVisible` to make sure that                * if the execution of `discloseVisible` happens _super fast_ (as it does in our QUnit tests                * this will still be called. However, make sure this only gets called _once_, because                * otherwise, every single time we go through this loop, _another_ event will be bound                * and then when the trigger happens, this will fire N times, where N equals the number                * of recursive `discloseAll` executions (instead of just one)                */                self.$element.one('disclosedVisible.fu.tree', function () {                    self.discloseAll();                });                /*                * If the page is very fast, calling this first will cause `disclosedVisible.fu.tree` to not                * be bound in time to be called, so, we need to call this last so that the things bound                * and triggered above can have time to take place before the next execution of the                * `discloseAll` method.                */                self.discloseVisible();            } else {                self.$element.trigger('disclosedAll.fu.tree', {                    tree: self.$element,                    disclosures: self.$element.data('disclosures')                });                //if `cacheItems` is false, and they call closeAll, the data is trashed and therefore                //disclosures needs to accurately reflect that                if (!self.options.cacheItems) {                    self.$element.one('closeAll.fu.tree', function () {                        self.$element.data('disclosures', 0);                    });                }            }        },        // This refreshes the children of a folder. Please destroy and re-initilize for "root level" refresh.        // The data of the refreshed folder is not updated. This control's architecture only allows updating of children.        // Folder renames should probably be handled directly on the node.        refreshFolder: function refreshFolder($el) {            var $treeFolder = $el.closest('.tree-branch');            var $treeFolderChildren = $treeFolder.find('.tree-branch-children');            $treeFolderChildren.eq(0).empty();            if ($treeFolder.hasClass('tree-open')) {                this.populate($treeFolderChildren, false);            }            else {                this.populate($treeFolderChildren, true);            }            this.$element.trigger('refreshedFolder.fu.tree', $treeFolder.data());        }    };    // ALIASES    //alias for collapse for consistency. "Collapse" is an ambiguous term (collapse what? All? One specific branch?)    Tree.prototype.closeAll = Tree.prototype.collapse;    //alias for backwards compatibility because there's no reason not to.    Tree.prototype.openFolder = Tree.prototype.discloseFolder;    //For library consistency    Tree.prototype.getValue = Tree.prototype.selectedItems;    // PRIVATE FUNCTIONS    function styleNodeSelected ($element, $icon) {        $element.addClass('tree-selected');        if ( $element.data('type') === 'item' && $icon.hasClass('fueluxicon-bullet') ) {            $icon.removeClass('fueluxicon-bullet').addClass('glyphicon-ok'); // make checkmark        }    }    function styleNodeDeselected ($element, $icon) {        $element.removeClass('tree-selected');        if ( $element.data('type') === 'item' && $icon.hasClass('glyphicon-ok') ) {            $icon.removeClass('glyphicon-ok').addClass('fueluxicon-bullet'); // make bullet        }    }    function multiSelectSyncNodes (self, clicked, selected) {        // search for currently selected and add to selected data list if needed        $.each(selected.$elements, function (index, element) {            var $element = $(element);            if ($element[0] !== clicked.$element[0]) {                selected.dataForEvent.push( $($element).data() );            }        });        if (clicked.$element.hasClass('tree-selected')) {            styleNodeDeselected (clicked.$element, clicked.$icon);            // set event data            selected.eventType = 'deselected';        }        else {            styleNodeSelected(clicked.$element, clicked.$icon);            // set event data            selected.eventType = 'selected';            selected.dataForEvent.push(clicked.elementData);        }    }    function singleSelectSyncNodes(self, clicked, selected) {        // element is not currently selected        if (selected.$elements[0] !== clicked.$element[0]) {            var clearedElements = self.deselectAll(self.$element);            styleNodeSelected(clicked.$element, clicked.$icon);            // set event data            selected.eventType = 'selected';            selected.dataForEvent = [clicked.elementData];        }        else {            styleNodeDeselected(clicked.$element, clicked.$icon);            // set event data            selected.eventType = 'deselected';            selected.dataForEvent = [];        }    }    // TREE PLUGIN DEFINITION    $.fn.tree = function tree(option) {        var args = Array.prototype.slice.call(arguments, 1);        var methodReturn;        var $set = this.each(function () {            var $this = $(this);            var data = $this.data('fu.tree');            var options = typeof option === 'object' && option;            if (!data) {                $this.data('fu.tree', (data = new Tree(this, options)));            }            if (typeof option === 'string') {                methodReturn = data[option].apply(data, args);            }        });        return (methodReturn === undefined) ? $set : methodReturn;    };    $.fn.tree.defaults = {        dataSource: function dataSource(options, callback) {},        multiSelect: false,        cacheItems: true,        folderSelect: true,        itemSelect: true,        // DIY   配置 节点 默认 展开 关闭 图标        //打开图标        iconFolderOpen:"glyphicon-minus-sign",        //关闭图标        iconFolderClose:"glyphicon-plus-sign",        /*        * How many times `discloseAll` should be called before a stopping and firing        * an `exceededDisclosuresLimit` event. You can force it to continue by        * listening for this event, setting `ignore-disclosures-limit` to `true` and        * starting `discloseAll` back up again. This lets you make more decisions        * about if/when/how/why/how many times `discloseAll` will be started back        * up after it exceeds the limit.        *        *    $tree.one('exceededDisclosuresLimit.fu.tree', function () {        *        $tree.data('ignore-disclosures-limit', true);        *        $tree.tree('discloseAll');        *    });        *        * `disclusuresUpperLimit` defaults to `0`, so by default this trigger        * will never fire. The true hard the upper limit is the browser's        * ability to load new items (i.e. it will keep loading until the browser        * falls over and dies). On the Fuel UX `index.html` page, the point at        * which the page became super slow (enough to seem almost unresponsive)        * was `4`, meaning 256 folders had been opened, and 1024 were attempting to open.        */        disclosuresUpperLimit: 0    };    $.fn.tree.Constructor = Tree;    $.fn.tree.noConflict = function () {        $.fn.tree = old;        return this;    };    // NO DATA-API DUE TO NEED OF DATA-SOURCE    // -- BEGIN UMD WRAPPER AFTERWORD --}));// -- END UMD WRAPPER AFTERWORD --

配置 树的 样式

.content {    margin: 0px auto;    width: 400px;    height: 400px;    overflow: auto;    padding: 10px;    border: 1px solid #CCCCCC;}.tree {    padding-left: 14px;    overflow: auto;    position: relative}.tree:before {    width: 1px;    z-index: 1;    display: block;    content: "";    position: absolute;    top: -21px;    bottom: 16px;    left: 0;    border-left: 1px dotted #666}.tree.tree-solid-line {    padding-left: 12px}.tree.tree-solid-line:before {    border-left: 1px solid #999}.tree.tree-solid-line .tree-folder .tree-folder-content:before {    border-left: 1px solid #999}.tree.tree-no-line {    padding-left: 0}.tree.tree-no-line:before {    display: none}.tree.tree-no-line .tree-folder .tree-folder-content:before {    display: none}.tree .tree-folder {    width: auto;    min-height: 20px;    cursor: pointer}.tree .tree-folder .tree-folder-header {    position: relative;    min-height: 20px;    line-height: 20px;    min-width: 100px}.tree .tree-folder .tree-folder-header:hover {    background-color: #eee}.tree .tree-folder .tree-folder-header .tree-folder-name {    margin-left: 2px}.tree .tree-folder img {    margin-left: 4px}.tree .tree-folder .tree-folder-content {    margin-left: 23px;    position: relative}.tree .tree-folder .tree-folder-content:before {    display: inline-block;    content: "";    position: absolute;    width: 1px;    z-index: 1;    top: -9px;    bottom: 16px;    left: -12px;    border-left: 1px dotted #666}.tree .tree-item {    position: relative;    min-height: 20px;    line-height: 20px;    min-width: 100px;    cursor: pointer}.tree .tree-item:hover {    background-color: #eee}.tree .tree-item .tree-item-name {    margin-left: 2px}.tree .tree-folder,.tree .tree-item {    position: relative}.tree .tree-folder:before,.tree .tree-item:before {    display: inline-block;    content: "";    position: absolute;    top: 14px;    left: -13px;    width: 18px;    height: 0;    border-top: 1px dotted #666;    z-index: 1}.tree .tree-selected {    background-color: #eee;    color: #262626}.tree .tree-selected:hover {    background-color: #e5e5e5}.tree .tree-folder .tree-folder-header .tree-folder-name,.tree .tree-item .tree-item-name {    display: inline;    z-index: 2}.tree.tree-solid-line .tree-folder:before,.tree.tree-solid-line .tree-item:before {    border-top: 1px solid #999}.tree.tree-no-line .tree-folder:before,.tree.tree-no-line .tree-item:before {    display: none}.tree .tree-item,.tree .tree-folder {    border: 1px solid transparent}.tree .tree-item,.tree .tree-folder .tree-folder-header {    margin: 0;    padding: 4px 5px 6px 5px;    color: #333;    -webkit-box-sizing: content-box;    -moz-box-sizing: content-box;    box-sizing: content-box}.tree .tree-item .tree-item-name>i,.tree .tree-folder .tree-folder-header>i {    color: #666;    display: inline-block;    font-family: FontAwesome;    font-style: normal;    font-weight: normal;    line-height: 1;    -webkit-font-smoothing: antialiased;    -moz-osx-font-smoothing: grayscale}.tree .tree-item.tree-selected i,.tree .tree-item .tree-item-name i {    margin-left: 2px;    width: 14px;    display: inline-block;    text-align: center;    margin-right: 1px;    color: #262626}.tree.tree-plus-minus .tree-folder-header .fa-folder-open:before {    height: 16px;    width: 16px;    line-height: 16px;    vertical-align: middle;    display: inline-block;    background-position: 0 -21px;    content: ""}.tree.tree-plus-minus .tree-folder-header .fa-folder:before {    height: 16px;    width: 16px;    line-height: 16px;    vertical-align: middle;    display: inline-block;    background-position: 0 2px;    content: ""}.tree.tree-plus-minus .tree-folder-name {    margin-left: 0 !important}.tree .tree-actions {    display: none;    position: absolute;    margin-top: 1px;    right: 4px}.tree .tree-item:hover .tree-actions,.tree .tree-folder-header:hover .tree-actions {    display: inline-block}.tree .tree-actions>i {    font-weight: 300;    padding: 1px 3px;    text-align: center;    font-size: 14px;    color: #333;    margin-right: 6px;    margin-top: 0;    display: inline-block}.tree .tree-actions>i:hover {    font-weight: bold}.tree-loading {    color: #2dc3e8;    margin-left: 30px}

以下是完整案例

    
demo

 

转载地址:https://blog.csdn.net/qq_26848943/article/details/82743755 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:编程 整理 (对编程上面的一些知识整理,好记性不如烂笔头)
下一篇:Hadoop2.8+HBase2.0+ZooKeeper3.4分布式集群环境搭建

发表评论

最新留言

哈哈,博客排版真的漂亮呢~
[***.90.31.176]2024年04月22日 10时04分48秒

关于作者

    喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!

推荐文章

PyQt5 技术篇-调用字体对话框(QFontDialog)获取字体,控件设置字体。 2021-06-30
Python 技术篇-将python项目打包成exe独立运行程序,pyinstaller库打包python代码实例演示 2021-06-30
Geany 权限问题:"Error opening file ... : permission denied.",原因及解决办法。 2021-06-30
CSDN博客主页增加赞赏码收钱模块,高端大气上档次! 2021-06-30
PyQt5 技术篇-调用文件对话框获取文件、文件夹路径。文件对话框返回选中的多个文件路径 2021-06-30
SSM 整合实现 增删改查、PageHelper 实现分页 2021-06-30
[增删改查] Lucene 5 索引 CRUD 2021-06-30
使用 SpringBoot 写增删改查接口 2021-06-30
初步使用 JFreeChart 生成报表与感受 2021-06-30
前端使用 BootStrap 写一些后台常用的界面 2021-06-30
使用 SpringBoot + Ckeditor 富文本编辑器、图片上传 2021-06-30
全栈式使用 SpringBoot + SpringSecurity 做登录认证 2021-06-30
[Java爬虫] 使用 Jsoup + HttpClient 爬取网页图片 2021-06-30
使用 Git 并借助 Eclipse + Coding 合作开发项目 2021-06-30
[Java爬虫] 使用 Xpath + HtmlUnit 爬取网页基本信息 2021-06-30
[人工智能] 使用百度 API 读取身份证照片的文字 2021-06-30
在SpringBoot中使用【阿里云OSS对象存储】存取图片 2021-06-30
[Java爬虫] 使用 HtmlUnit + Xpath 模拟点击、动态获取信息 2021-06-30
使用 SpringBoot 之 JPA 整合 Redis 实现缓存 2021-06-30
SpringBoot 结合 JSR303 对前端数据进行校验 2021-06-30