lowbase / jstree
jsTree是一个jQuery插件,提供交互式树。
Requires
- components/jquery: >=1.9.1
Suggests
- robloach/component-installer: Allows installation of Components via Composer
README
jsTree是一个jQuery插件,提供交互式树。它是完全免费的,开源并且以MIT许可证分发。
jsTree易于扩展、主题化和配置,支持HTML & JSON数据源、AJAX & 异步回调加载。
jsTree在box-model(content-box或border-box)下都能正常工作,可以加载为AMD模块,并内置了用于响应式设计的移动主题,可以轻松自定义。它使用jQuery的事件系统,因此绑定树中各种事件的回调函数既熟悉又简单。
您还将获得
- 拖放支持
- 键盘导航
- 行内编辑、创建和删除
- 三态复选框
- 模糊搜索
- 可自定义节点类型
除了本README之外,您还可以在jstree.com & 讨论组上找到更多信息.
入门指南
包含所有必要的文件
要开始,您需要在页面上准备3样东西
- jQuery(任何高于1.9.1的版本都可以工作)
- jstree主题(默认提供了一个主题)
- jstree源代码文件
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script> <link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/jstree/3.0.9/themes/default/style.min.css" /> <script src="//cdnjs.cloudflare.com/ajax/libs/jstree/3.0.9/jstree.min.js"></script>
如果您决定自行托管jstree,文件位于dist文件夹中。您可以安全地忽略dist/libs文件夹。
使用HTML填充树
现在我们已准备好创建树了,行内HTML是最简单的选项(适用于菜单)。您只需选择一个节点(使用jQuery选择器)并调用.jstree()函数,让jstree知道您想在所选节点内渲染树。$.jstree.create(element)也可以使用。
<div id="container"> <ul> <li>Root node <ul> <li>Child node 1</li> <li>Child node 2</li> </ul> </li> </ul> </div> <script> $(function() { $('#container').jstree(); }); </script>
您可以在渲染节点时添加一些选项,使用data-attribute(注意引号)
<li data-jstree='{ "selected" : true, "opened" : true }'>Root node ...
使用数组(或JSON)填充树
从HTML构建树很容易,但不是很灵活,行内JS数据是一个更好的选择
<div id="container"></div> <script> $(function() { $('#container').jstree({ 'core' : { 'data' : [ { "text" : "Root node", "children" : [ { "text" : "Child node 1" }, { "text" : "Child node 2" } ] } ] } }); }); </script>
与先前的简单HTML示例不同,这次.jstree()函数接受一个配置对象。
目前重要的是要注意,jstree会尝试解析您在core.data键中指定的任何数据,并使用它来创建树。如前一个示例所示,如果此键不存在,jstree将尝试解析容器的行内HTML。
所需的JSON格式
您使用的数据必须符合特定格式,树中的每个分支由一个对象表示,该对象至少应包含一个 text 键。可以使用 children 键向分支添加子节点,它应该是一个对象数组。
请注意,如果您只需要具有特定文本的节点,可以使用简单的字符串代替对象,上面的数据可以写作:
[ { "text" : "Root node", "children" : [ "Child node 1", "Child node 2" ] } ]
每个节点还有其他可用的选项,只有需要时才设置它们,例如
id- 使节点以后可以被识别(也将用作LI节点的 DOM ID)。请确保在树实例中不要重复相同的 ID(这将违背其作为唯一标识符的目的,并可能导致 jstree 出现问题)。icon- 用于节点图标的字符串,可以是文件的路径,也可以是类名(或类名列表),您可以在 CSS 中对其进行样式化(也适用于字体图标)。data- 可以是任何您想要的内容 - 它是与节点相关联的元数据 - 您可以在以后访问和修改它 - 它对节点的视觉效果没有影响。state- 一个对象,指定有关节点的几个选项selected- 如果节点应该被初始选中opened- 如果节点应该被初始展开disabled- 如果节点应该被禁用checked- 仅限复选框插件 - 如果节点应该被选中(仅当tie_selection为false时使用,您应该只在真正了解自己在做什么时才这样做)undetermined- 仅限复选框插件 - 如果节点应该以不确定状态渲染(仅与延迟加载一起使用,并且节点尚未加载时使用,否则此状态将自动计算)。
type- 类型插件特定 - 节点的类型(应在类型配置中定义),如果未设置,则假定"default"。li_attr- 将用于向结果LIDOM 节点添加 HTML 属性的值对象。a_attr- 将用于向结果A节点添加 HTML 属性的值对象。
这里有一个带有一些这些属性设置的新演示
<div id="container"></div> <script> $(function() { $('#container').jstree({ 'core' : { 'data' : [ { "text" : "Root node", "state" : {"opened" : true }, "children" : [ { "text" : "Child node 1", "state" : { "selected" : true }, "icon" : "glyphicon glyphicon-flash" }, { "text" : "Child node 2", "state" : { "disabled" : true } } ] } ] } }); }); </script>
使用AJAX填充树
基于前面的示例,让我们看看如何让 jstree 为您执行 AJAX 请求。
<div id="container"></div> <script> $(function() { $('#container').jstree({ 'core' : { 'data' : { "url" : "//www.jstree.com/fiddle/", "dataType" : "json" // needed only if you do not supply JSON headers } } }); }); </script>
服务器响应是
[{
"id":1,"text":"Root node","children":[
{"id":2,"text":"Child node 1"},
{"id":3,"text":"Child node 2"}
]
}]
您可以将 core.data 设置为 jQuery AJAX 配置。jstree 将访问该 URL,并且如果返回格式正确的 JSON,它将被显示。
如果您无法提供正确的 JSON 头部信息,请将 core.data.dataType 设置为 "json"。
服务器响应中的 ID 可以使节点以后被识别(我们将在接下来的几个演示中看到),但它们不是必需的。
当使用 ID 时,请确保它们在特定树内部是唯一的
使用AJAX和懒加载节点填充树
延迟加载意味着节点将在需要时加载。想象一下,您想要显示大量节点,但使用单个请求加载它们会产生太多的流量。延迟加载可以使动态加载节点成为可能 - 当用户浏览树时,jstree 将执行 AJAX 请求。
这里我们使用我们之前的示例,并延迟加载 "Child node 1" 节点。
<div id="container"></div> <script> $(function() { $('#container').jstree({ 'core' : { 'data' : { "url" : "//www.jstree.com/fiddle/?lazy", "data" : function (node) { return { "id" : node.id }; } } } }); }); </script>
初始服务器响应是
[{
"id":1,"text":"Root node","children":[
{"id":2,"text":"Child node 1","children":true},
{"id":3,"text":"Child node 2"}
]
}]
现在让我们关注一下有什么不同。首先,数据对象的 "data" 配置选项。如果您用 jQuery 检查,它应该是字符串或对象。但是 jstree 使您可以设置一个函数。
每次jstree需要发起AJAX调用时,此函数将被调用,并接收一个单一参数 - 正在加载的节点。此函数的返回值将用作AJAX调用的实际"data"。为了更好地理解,请打开演示并查看控制台中的请求。
您会发现第一个请求发往:http://www.jstree.com/fiddle?lazy&id=# #是当jstree需要加载根节点时,函数接收的特殊ID。
现在打开根节点 - 将显示两个子节点,但不会发起请求 - 这是因为我们已经在第一个请求中加载了这些子节点。
接下来是另一个区别 - "子节点1"看起来是关闭的 - 这是因为在我们提供的数据中,"children"属性被设置为true(您可以在服务器响应中看到它)。这个特殊值指示jstree需要延迟加载"子节点1"节点。
打开此节点 - 您将看到发起下一个请求到:http://www.jstree.com/fiddle?lazy&id=2 ID被设置为2,因为正在加载的节点的ID是2,并且我们已经配置jstree在AJAX请求中发送节点ID(通过data函数)。
服务器响应是
["Child node 3","Child node 4"]
您还可以将"url"设置为一个函数,它的工作方式与"data"相同 - 每次需要发起请求时,jstree都会调用您的函数,请求将发送到您在此函数中返回的内容。当处理类似http://example.com/get_children/1的URL时,这非常有用。
使用回调函数填充树
有时您可能不希望jsTree为您发起AJAX调用 - 您可能想自己发起它们,或使用其他方法来填充树。在这种情况下,您可以使用回调函数。
<div id="container"></div> <script> $(function() { $('#container').jstree({ 'core' : { 'data' : function (node, cb) { if(node.id === "#") { cb([{"text" : "Root", "id" : "1", "children" : true}]); } else { cb(["Child"]); } } } }); }); </script>
如您所见,您的函数将接收两个参数 - 需要加载子节点的节点以及一个回调函数,当您得到数据时调用该回调函数。数据遵循相同的熟悉的JSON格式,延迟加载与AJAX的工作方式相同(如上例所示)。
处理事件
jstree提供了许多事件来让您知道树发生了什么。事件与您如何填充树无关。让我们使用最基本的事件changed - 它在树的选定更改时触发。
<div id="container"></div> <script> $(function() { $('#container').jstree({ 'core' : { 'data' : [ {"id" : 1, "text" : "Node 1"}, {"id" : 2, "text" : "Node 2"}, ] } }); $('#container').on("changed.jstree", function (e, data) { console.log("The selected nodes are:"); console.log(data.selected); }); }); </script>
所有jstree事件都在特殊的"$.jstree"命名空间中触发 - 这也是为什么我们监听"changed.jstree"。处理程序本身接收一个额外的参数 - 它将包含关于发生的所有您需要了解的事件信息。在这种情况下,data.selected是选定节点ID的数组(请注意,如果您没有指定ID,它们将自动生成)。
让我们扩展一下,并记录出节点的文本而不是ID。
$('#container').on("changed.jstree", function (e, data) { console.log(data.instance.get_selected(true)[0].text); console.log(data.instance.get_node(data.selected[0]).text); });
上面的两行代码达到完全相同的效果 - 获取第一个选定节点的文本。
在data参数对象中,您总是会得到一个instance键 - 这是树实例的引用,因此您可以轻松调用方法。
所有可用函数和事件均在API文档中进行了说明。
使用API与树交互
在先前的例子中,我们只是触及了与树交互的表面。让我们继续获取实例并在该实例上调用方法。
<button>Select node 1</button> <div id="container"></div> <script> $(function() { $('#container').jstree({ 'core' : { 'data' : [ {"id" : 1, "text" : "Node 1"}, {"id" : 2, "text" : "Node 2"}, ] } }); $('button').on("click", function () { var instance = $('#container').jstree(true); instance.deselect_all(); instance.select_node('1'); }); }); </script>
上面的例子展示了如何获取jstree实例的引用(再次使用选择器,但这次我们传递一个布尔值true),并调用一些方法 - 最后一个方法是按ID选择节点。
方法也可以这样调用
$('#container').jstree("select_node", "1");
所有可用函数和事件均在API文档中进行了说明。
更多配置信息
我们已经就配置对象进行了概述(当我们在指定内联和AJAX数据源时)。
$("#tree").jstree({ /* config object goes here */ });
配置对象中的每个键对应一个插件,该键的值是该插件的配置。还有两个特殊键"core"和"plugins"。
"core"存储核心配置选项。"plugins"是一个包含您希望在实例中激活的插件名称(字符串)的数组。
配置时,您只需设置与默认值不同的值。
所有配置选项和默认值均在API文档中进行了记录。
$("#tree").jstree({ "core" : { // core options go here "multiple" : false, // no multiselection "themes" : { "dots" : false // no connecting dots between dots } }, "plugins" : ["state"] // activate the state plugin on this instance });
我们将进一步介绍所有插件。
请注意,默认情况下,所有对结构的修改都被阻止 - 这意味着拖放、创建、重命名、删除将不会工作,除非您启用它们。
$("#tree").jstree({ "core" : { "check_callback" : true, // enable all modifications }, "plugins" : ["dnd","contextmenu"] });
"core.check_callback"也可以设置为函数,该函数将在每次即将发生修改时调用(或者当jstree需要检查是否可以修改时)。如果您返回true,则允许操作,false的值表示不允许。您可以期望的操作包括create_node、rename_node、delete_node、move_node和copy_node。more参数将包含调用检查的插件提供的信息。例如,DND插件将提供一个包含正在检查的移动或复制操作信息的对象 - 是否是多树操作,当前悬停的节点是哪个,插入箭头指向哪里 - 在之前、之后或内部等。
$("#tree").jstree({ "core" : { "check_callback" : function (operation, node, parent, position, more) { if(operation === "copy_node" || operation === "move_node") { if(parent.id === "#") { return false; // prevent moving a child above or below the root } }, return true; // allow everything else } }, "plugins" : ["dnd","contextmenu"] });
您收到的more参数包含与正在执行的检查相关的其他信息。
例如:在用户拖动节点时,move_node和copy_node检查将重复触发,如果检查由dnd插件触发,则more将包含一个dnd键,并将其设置为true。您可以通过检查more.dnd,并且只有当dnd触发了检查时才执行某些操作。如果您只想在节点真正即将被放下时执行操作,则检查more.core。
插件
jsTree附带了一些捆绑的插件,但它们只会修改您的树,如果您使用"plugins"配置选项激活它们。以下是每个插件的简要说明。您可以在API文档中了解有关每个插件的可用配置选项的更多信息。
checkbox
在节点前渲染一个复选框图标,使多选变得容易。它还有一个“三态”选项,这意味着某些子节点被选中时,节点将获得一个“方块”图标。
请注意,如果启用了任何类型的级联,禁用节点也可能被选中(不是它们自己,例如,当禁用节点的父节点被选中且选择配置为级联向下时)。
$("#tree").jstree({ "plugins" : ["checkbox"] });
contextmenu
使您能够在节点上右键单击并显示一个包含可配置操作的菜单。
$("#tree").jstree({ "core" : { "check_callback" : true }, // so that modifying operations work "plugins" : ["contextmenu"] });
dnd
使您能够拖放树节点并重新排列树。
$("#tree").jstree({ "core" : { "check_callback" : true }, // so that operations work "plugins" : ["dnd"] });
massload
使您能够一次加载多个节点(对于懒加载的树)。
$("#tree").jstree({ "core" : { "data" : { .. AJAX config .. } }, "massload" : { "url" : "/some/path", "data" : function (nodes) { return { "ids" : nodes.join(",") }; } }, "plugins" : [ "massload", "state" ] });
search
添加了在树中搜索项并仅显示匹配节点的可能性。它还包含AJAX / 回调钩子,因此搜索也可以在懒加载的树中工作。
<form id="s"> <input type="search" id="q" /> <button type="submit">Search</button> </form> <script> $("#container").jstree({ "plugins" : ["search"] }); $("#s").submit(function(e) { e.preventDefault(); $("#container").jstree(true).search($("#q").val()); }); </script>
sort
根据比较配置选项函数自动排列所有同级节点,默认为字母顺序。
$("#tree").jstree({ "plugins" : ["sort"] });
state
将所有打开和选择的节点保存在用户的浏览器中,因此当返回到同一树时,将恢复之前的状态。
$("#tree").jstree({ // the key is important if you have multiple trees in the same domain "state" : { "key" : "state_demo" }, "plugins" : ["state"] });
types
使您能够为节点添加“类型”,这意味着可以轻松控制节点组的嵌套规则和图标,而不是单独控制。要设置节点类型,请将类型属性添加到节点结构中。
$("#tree").jstree({ "types" : { "default" : { "icon" : "glyphicon glyphicon-flash" }, "demo" : { "icon" : "glyphicon glyphicon-ok" } }, "plugins" : ["types"] });
unique
强制规定不允许存在同名节点作为同级节点 - 防止将节点重命名和移动到已包含同名节点的父节点。
$("#tree").jstree({ "plugins" : ["unique"] });
wholerow
使每个节点呈现块级样式,从而使选择更加容易。在旧浏览器中,对于大型树可能导致性能下降。
$("#tree").jstree({ "plugins" : ["wholerow"] });
更多插件
如果您创建了自己的插件(或下载第三方插件),必须在页面上包含其源代码,并在"plugins"配置数组中列出其名称。
// conditional select (function ($, undefined) { "use strict"; $.jstree.defaults.conditionalselect = function () { return true; }; $.jstree.plugins.conditionalselect = function (options, parent) { this.activate_node = function (obj, e) { if(this.settings.conditionalselect.call(this, this.get_node(obj))) { parent.activate_node.call(this, obj, e); } }; }; })(jQuery); $("#tree").jstree({ "conditionalselect" : function (node) { return node.text === "Root node" ? false : true; }, "plugins" : ["conditionalselect"] });
如这里所见,在创建插件时,您可以定义默认配置,向jstree添加自己的函数,或覆盖现有函数,同时保持调用被覆盖函数的能力。
许可证 & 贡献
请勿编辑“dist”子目录中的文件,因为它们是通过grunt生成的。您将在“src”子目录中找到源代码!
如果您愿意,您可以随时[捐赠一小笔金额][paypal],以帮助jstree的开发。[paypal]: https://www.paypal.com/cgi-bin/webscr?cmd=_xclick&business=paypal@vakata.com¤cy_code=USD&amount=&return=http://jstree.com/donation&item_name=Buy+me+a+coffee+for+jsTree
版权所有 (c) 2014 Ivan Bozhanov (http://vakata.com)
许可协议为MIT许可协议。