Дерево на jquery с «drag and drop»
Для того чтобы организовать хранение дерева, массив данных должен содержать как минимум два параметра: id записи, и child — т.е. в иерархии к какой id относится эта запись. Пример child =0, если запись в «корне». Например структура в mysql в простейшем случае может быть такой: id,name,address,child
Для непосредственного отображения дерева удобно пользоваться jquery плагином dynatree. При перетаскивании элементов дерева при помощи «drag and drop», состояние ветвей записывается в БД. Ниже пример кода, какой он может быть:
HTML
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 |
<?php // Данный код создан и распространяется по лицензии GPL v3 // Изначальный автор данного кода - Грибов Павел // http://грибовы.рф include_once ("inc/lbfunc.php"); // загружаем функции LB if ($user->mode==1){ ?> <link href="js/skin/ui.dynatree.css" rel="stylesheet" type="text/css"> <script src="js/jquery.dynatree.js" type="text/javascript"></script> <div class="well"> <div class="row-fluid"> </div> <?php $period=true; $seconddate=false; $agent=false; $period=false; $fill=false; $btrep=false; //include_once("head.php"); include("controller/client/themes/bootstrap/lanbilling/reports/head.php"); ?> <input type="submit" id="reloaddevices" name="Submit" class="btn btn-primary" value="Обновить список устройств"> <div id="tree"></div> <div id="zxc"></div> </br> </div> <script> $("#blibase").change(function() {// обрабатываем выбор базы $('#tree').dynatree('destroy'); GetTree(); }); $("#reloaddevices").click(function(){ $('#tree').dynatree('destroy'); $("#tree").html("<img src=controller/client/themes/"+theme+"/img/loading.gif><br>*выполнение запроса может занять до 10 минут.Пожалуйста дождитесь окончания задания.."); $.get("controller/server/lanbilling/graf/devicesgrafjson.php?mode=update&blibase="+$("#blibase").val(), function(data) { GetTree(); $("#zxc").html(data); }); }); function SaveAllNodes(node, sourceNode){ $.post("controller/server/lanbilling/graf/devicessavejson.php", {node: node.data.key,sourceNode:sourceNode.data.key}, function(data) { $("#zxc").html(data); }); }; function GetTree(){ // --- Initialize first Dynatree ------------------------------------------- $("#tree").dynatree({ initAjax: { url: "controller/server/lanbilling/graf/devicesgrafjson.php?mode=list&blibase="+$("#blibase").val() }, onLazyRead: function(node){ // Mockup a slow reqeuest ... node.appendAjax({ url: "sample-data2.json", debugLazyDelay: 750 // don't do this in production code }); }, dnd: { onDragStart: function(node) { /** This function MUST be defined to enable dragging for the tree. * Return false to cancel dragging of node. */ logMsg("tree.onDragStart(%o)", node); return true; }, onDragStop: function(node) { // This function is optional. logMsg("tree.onDragStop(%o)", node); }, autoExpandMS: 1000, preventVoidMoves: true, // Prevent dropping nodes 'before self', etc. onDragEnter: function(node, sourceNode) { /** sourceNode may be null for non-dynatree droppables. * Return false to disallow dropping on node. In this case * onDragOver and onDragLeave are not called. * Return 'over', 'before, or 'after' to force a hitMode. * Return ['before', 'after'] to restrict available hitModes. * Any other return value will calc the hitMode from the cursor position. */ logMsg("tree.onDragEnter(%o, %o)", node, sourceNode); return true; }, onDragOver: function(node, sourceNode, hitMode) { /** Return false to disallow dropping this node. * */ logMsg("tree.onDragOver(%o, %o, %o)", node, sourceNode, hitMode); // Prevent dropping a parent below it's own child if(node.isDescendantOf(sourceNode)){ return false; } // Prohibit creating childs in non-folders (only sorting allowed) if( !node.data.isFolder && hitMode === "over" ){ return "after"; } }, onDrop: function(node, sourceNode, hitMode, ui, draggable) { /** This function MUST be defined to enable dropping of items on * the tree. */ logMsg("tree.onDrop(%o, %o, %s)", node, sourceNode, hitMode); sourceNode.move(node, hitMode); SaveAllNodes(node, sourceNode); // expand the drop target // sourceNode.expand(true); }, onDragLeave: function(node, sourceNode) { logMsg("tree.onDragLeave(%o, %o)", node, sourceNode); } } }); }; GetTree(); </script> <?php } else { ?> <div class="alert alert-error"> У вас нет доступа в данный раздел! </div> <?php } ?> |
PHP загрузка дерева
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 |
<?php // Данный код создан и распространяется по лицензии GPL v3 // Изначальный автор данного кода - Грибов Павел // http://грибовы.рф include_once ("../../../../config.php"); // загружаем первоначальные настройки // загружаем классы include_once("../../../../class/sql.php"); // загружаем классы работы с БД include_once("../../../../class/config.php"); // загружаем классы настроек include_once("../../../../class/users.php"); // загружаем классы работы с пользователями include_once("../../../../class/employees.php"); // загружаем классы работы с профилем пользователя // загружаем все что нужно для работы движка include_once("../../../../inc/connect.php"); // соеденяемся с БД, получаем $mysql_base_id include_once("../../../../inc/config.php"); // подгружаем настройки из БД, получаем заполненый класс $cfg include_once("../../../../inc/functions.php"); // загружаем функции include_once("../../../../inc/login.php"); // загружаем функции $blibase=_GET('blibase'); $mode=_GET('mode'); function getchild($oldkey){ global $sqlcn,$blibase; $sql="SELECT count(*) as cnt FROM devices WHERE child='$oldkey' and idbase='$blibase'"; $result2 = $sqlcn->ExecuteSQL($sql) or die("Не могу сделать выборку из devices (4)!".mysqli_error($sqlcn->idsqlconnection)); while($row2 = mysqli_fetch_array($result2)) {$cnt=$row2["cnt"];}; $sql="SELECT * FROM devices WHERE child='$oldkey' and idbase='$blibase'"; $result2 = $sqlcn->ExecuteSQL($sql) or die("Не могу сделать выборку из devices(5)!".mysqli_error($sqlcn->idsqlconnection)); $pz=0; while($row2 = mysqli_fetch_array($result2)) { $name=$row2["devname"]."(".$row2["address"].")"; $key=$row2["id"]; echo "{"; echo "\"title\": \"$name\",\"isFolder\": true,\"key\": \"$key\",\"children\": ["; getchild($key); echo "]}"; $pz++; if ($pz<$cnt){echo ",";}; }; }; if ($mode=="list"){ //листаю корневые сетевые устройства $sql="SELECT count(*) as cnt FROM devices WHERE child=0 and idbase='$blibase'"; $result2 = $sqlcn->ExecuteSQL($sql) or die("Не могу сделать выборку из devices (1)!".mysqli_error($sqlcn->idsqlconnection)); while($row2 = mysqli_fetch_array($result2)) {$cnt=$row2["cnt"];}; $sql="SELECT * FROM devices WHERE child=0 and idbase='$blibase'"; $result2 = $sqlcn->ExecuteSQL($sql) or die("Не могу сделать выборку из devices(2)!".mysqli_error($sqlcn->idsqlconnection)); echo "["; $pz=0; while($row2 = mysqli_fetch_array($result2)) { $name=$row2["devname"]."(".$row2["address"].")"; $key=$row2["id"]; echo "{"; echo "\"title\": \"$name\",\"isFolder\": true,\"key\": \"$key\",\"children\": ["; getchild($key); echo "]}"; $pz++; if ($pz<$cnt){echo ",";}; }; echo "]"; //echo "!$pz;$cnt!"; }; ?> |
PHP сохранение дерева
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
<?php // Данный код создан и распространяется по лицензии GPL v3 // Изначальный автор данного кода - Грибов Павел // http://грибовы.рф include_once ("../../../../config.php"); // загружаем первоначальные настройки // загружаем классы include_once("../../../../class/sql.php"); // загружаем классы работы с БД include_once("../../../../class/config.php"); // загружаем классы настроек include_once("../../../../class/users.php"); // загружаем классы работы с пользователями include_once("../../../../class/employees.php"); // загружаем классы работы с профилем пользователя // загружаем все что нужно для работы движка include_once("../../../../inc/connect.php"); // соеденяемся с БД, получаем $mysql_base_id include_once("../../../../inc/config.php"); // подгружаем настройки из БД, получаем заполненый класс $cfg include_once("../../../../inc/functions.php"); // загружаем функции include_once("../../../../inc/login.php"); // загружаем функции $blibase=_GET('blibase'); function ListChild($child,$oldkey){ global $sqlcn,$blibase; for ($i=0;$i<count($child);$i++){ var_dump($child[$i]); $key=$child[$i]["key"]; echo "</br>$oldkey,$key<hr>"; if (isset($child[$i]["children"])==true){ ListChild($child[$i]["children"],$key); }; $sql="UPDATE devices SET child='$oldkey' where id='$key'"; echo "</br>$sql</br>"; $result3 = $sqlcn->ExecuteSQL($sql) or die("Не могу обновить devices (oldkey)!".mysqli_error($sqlcn->idsqlconnection)); }; }; $node=$_POST['node']; $sourceNode=$_POST['sourceNode']; $sql="UPDATE devices SET child='$node' where id='$sourceNode'"; $result3 = $sqlcn->ExecuteSQL($sql) or die("Не могу обновить devices (oldkey)!".mysqli_error($sqlcn->idsqlconnection)); ?> |