📜 ⬆️ ⬇️

Enter into the program hierarchical list

There was a task - to enter the elements of a hierarchical list (for example, KLADR) into a web application.

When working with drupal , I saw a Hierarchical Select module there that implements this functionality.
But I wanted to do it myself - in order not to become attached to systems that are completely incomprehensible to me and generally interesting.

The search for a turnkey solution, not tied to any existing system, gave something like
This , that did not suit.
')
The topic does not pretend to the novelty and special complexity of execution.
Made in 2 hours.
Wanted to share.
Perhaps someone will come in handy.
As much as possible I documented everything and the functions describing the source of data were rendered into 2 methods:
- search for children (one level) by parent
- search of all parents of the child up the hierarchy
so that anyone can use it for their needs.

Perhaps something similar somewhere was, but quickly I did not find it.
So let's get started.


Immediately reference to the working example and source codes
Example

You can quickly rewrite to your data source (just change 2 methods per class)

Formulation of the problem:


Functional by module:


The sequence of presentation:
  1. Describe the necessary and sufficient data that the application to which it connects must generate
  2. JavaScript description
  3. A class that serves ajax requests
  4. How it all works
  5. Result processing


1. What to do with the application


2. Description of javaScript
 //  $(document).ready(function() { /** *          */ $('.select_hierarhy_container').each(function() { selecHierarhyInit(this); }); }); /** *  ,     . : * id (containerId),    (initValue)     * ,    * * @param v_container * - */ function selecHierarhyInit(v_container) { var container = $(v_container); var containerId = container.attr('id'); var initValue = container.children('input').val(); container.load('ajax.php?container_id=' + containerId + '&init_id=' + initValue); } /** *          v_obj,  *      : id  * (containerId)        (level) *    (parent_id)      * ,   (  ,     *  )      * * @param v_obj *    select,   */ function selecHierarhygetChilds(v_obj) { obj = $(v_obj); var containerId = obj.parents('.select_hierarhy_container').attr('id'); var parent_id = obj.val(); obj.nextAll().remove(); $.ajax({ url : 'ajax.php?container_id=' + containerId + '&parent_id=' + parent_id, success : function(data) { $('#' + containerId).append(data); } }); } 


3. Class serving ajax requests
 /** * ,     . * *          * $_POST[$selectName]    .   - . *     (,    ) *        *     (  ) *  ,  ,    * * @author dibrovsd */ class HerarhySelect { //  select- private $selectName; /** * @param string $selectName  select-,    */ public function __construct($selectName) { $this->selectName = $selectName; } /** *    * @param int $parentId    */ public function getContent($parentId) { return $this->generateSelect($parentId); } /** *     *    ,     * ( ) *    ,   *   ( )   ,    ,  * @param int $nodeId   */ public function getInit($nodeId) { if($nodeId == '') { return $this->getContent(-1); } else { $s = null; $parents = $this->getDataParentsList($nodeId); foreach($parents as $parentId => $childId) { $s .= $this->generateSelect($parentId, $childId); } $s .= $this->generateSelect($nodeId); return $s; } } /** *     $parentId,    $childId * @param int $parentId    * @param int $childId */ private function generateSelect($parentId, $childId = null) { //    -  $childs = $this->getDataChilds($parentId); if($childs == null) { return; } $s = '<select name='.$this->selectName.'[new][] onChange="selecHierarhygetChilds(this);"> <option></option>'; foreach($childs as $id => $value) { $s .= '<option value="'.$id.'" '. ($id == $childId ? 'selected' : '').'>'. $value.'</option>'; } $s .='</select>'; return $s; } /** *  .   - *    *     * *      . *      , web- *  -  (   ) * * @param int $parentId    */ private function getDataChilds($parentId) { $dataSource = $this->getDataArray(); if(!isset($dataSource[$parentId])) { return null; } else { return $dataSource[$parentId]; } } /** *       , *     $childId *    -      *    ,   -    * *  (   )      *       *       : *  Oracle  , *  PostgreSQL   *     ,     * (       ) * * @param int $child * @return int:int id  : id , *       , *   */ private function getDataParentsList($childId) { $dataSource = $this->getDataArray(); $result = array(); $currentChild = $childId; //      . //    ,     do { $isParentFind = false; foreach($dataSource as $idParent => $childs) { if(isset($childs[$currentChild])) { $result[$idParent] = $currentChild; $isParentFind = true; $currentChild = $idParent; break; } } } while($isParentFind); return array_reverse($result, true); } /** *  -    . *    ,  ,  , *     , *     */ private function getDataArray() { return array( -1 => array(1 => 'test1', 2 => 'test2', 3 => 'test3'), 1 => array(4 => 'test1_1', 5 => 'test1_2', 6 => 'test1_3'), 4 => array(7 => 'test2_1', 8 => 'test2_2', 9 => 'test2_3'), 9 => array(10 => 'test2_1_1', 11 => 'test2_1_2', 12 => 'test2_1_3') ); } } 


4. How it all works

When the page loads, when the document model is fully formed,
initialization javascript code is triggered
and for each container loads initialization data
using the selecHierarhyInit function (container_object)

This feature requests content by passing
- identifier of the container, which is equal to the name of the input element
- initializing node identifier of the hierarchy

The PHP class, receiving this identifier in the getInit ($ id) function, processes it.
If it is empty, it loads one level with a list of nodes subordinate to the root of the hierarchy (I use the “stub” -1)
If not, it scans the hierarchy up from the initializing node, and then inverts the resulting dictionary,
getting the "drop down" and passes the array to print
Next, this content (a list of lists or one list) is returned by javaScript, which writes it into a container,
removing the initial value that we no longer need

If the statement has changed select, then the function selecHierarhygetChilds is called, which receives as a parameter
the object of the changed list selects parameters from it:
Deletes all lists that are after the changed,
because when you change the parent, his children need to be rebuilt again
queries PHP for getContent (id) list of children, in relation to this, nodes and adds what was received after (all children have been deleted)
changed list

5. Processing the result
I will do without comments

 if(isset($_POST['sendForm'])) { $data1 = array_reverse($_POST['field_1']['new']); $data2 = array_reverse($_POST['field_2']['new']); $val1 = $data1[0] == '' ? $data1[1] : $data1[0]; $val2 = $data2[0] == '' ? $data2[1] : $data2[0]; } else { $val1 = null; $val2 = 12; } 

Source: https://habr.com/ru/post/132594/


All Articles