Categories | Question details Back To List | ||
dhtmlxTree setDragHandler I've set up setDragHandler(tondrag) - function tondrag(id,newparent, idbefore) I can drag-n-drop at the same level to a different parent (newwparent) but only if it has a child :- 1) If it has a child then parameter newparent= the new parent id. 2) but if there is no child then parameter newparent is the "parent id" of newparent! I therefore do not know where to insert the moved node - I need to know the real parent id as I am also doing the same on a server ie reflecting the tree on the server - directory tree. How can I obtain the true parent id? Also idbefore (see above) is in fact the id after the insert point and not as comment says in source: @eventparam: if node droped as sibling then contain id of item before whitch source node will be inserted. 1) same parent - mv P1-2 above P1-1 P1 -1 -2 can become P1 -2 -1 2) different parent with child - move P2-2 below P1-2 P1 -1 P2 -2 -3 can become P1 -1 -2 P2 -3 3) different parent no child - move P2-1 to P1 fails as the parent parameter contains R1 and not P1 R1 -P1 -P2 --1 --2 I think I can solve this uising if new parent parameter = parent of target parent var nextindex= getIndexById(idbefore); var realparent= getItemIdByIndex(newparent,nextindex-1); but I also need to check for null ie if target parent is last then next parent will not exist ie null Answer posted by Support on Jun 04, 2009 05:19 Which drag-behavior you are using? If you need to drop item only as child of something - you can use tree.setDragBehavior("child") Now the onDrag event will provide only ID of item, on which source item was dropped, and you need not include any other parameters in calculations. tree.setDragBehavior("child") tree.attachEvent("onDrag",function(sid,tid){ if (this._allow_next_call) return true; //allow inner calls this._allow_next_call = true; if (this.getSubItems(tid)) //item has child this.moveItem(sid,"child",tid); else this.moveItem(sid,"item_sibling",tid); //if there is no child - drop on the same level this._allow_next_call = false; return false; //block default drag processing }) Answer posted by Stephen on Jun 04, 2009 09:45 I'm using tree.setDragBehavior("sibling") Examples to illustrate required use 1) reorder node items that are at the same level eg authors eg move StephenKing above JaneAusten Its useful to see the horizonal line that appears when moving - I dont see this using tree.setDragBehavior("child") as I assume you are expected to drop eg StephenKing into Horror parent folder icon 2) move a node item to another parent eg move JaneAusten from parent Fiction to parent Classics Also then want to do copy instead of move Answer posted by Alex (support) on Jun 05, 2009 00:33 Hello, there is also complex mode tree.setDragBehavior("complex") It allows to combine both "sibling" and "child" modes. To enable copying: tree.enableMercyDrag(true) Answer posted by Stephen on Jun 05, 2009 02:35 I've tried both tree.setDragBehavior("complex") and they do not work for the specific problem I've already described, take the following:- --books ----classics ----horror -------frankenstein I want to move "frankenstein" as follows --books ----classics -------frankenstein ----horror but this is not possible as my event handler function tondrag(id, newparent, idbefore) does not give the target parent, it only supplies the target parents parent as follows id=/books/horror/frankenstein newparent=/books <<<<<<<<< I need /books/classics idbefore=/books/horror/ <<<<<<this is the 'parent' after the insertion point not before but if I have start with --books ----classics -------dracula ----horror -------frankenstein I can move as follows --books ----classics -------dracula -------frankenstein ----horror because my hander function tondrag(id, newparent, idbefore) supplies the target parent id=/books/classics/frankenstein newparent=/books/horror idbefore=/books/classics/dracula Remember I'm duplicating the tree layout and item order on my server. So I do the move both in the tree and on the server ie once the drag-n-drop takes place a reload from the server will leave the tree as is following the drag-n-drop. Answer posted by Stephen on Jun 05, 2009 02:37 Sorry above should have read as below ie frankenstein moved to above dracula "but if I have start with --books ----classics -------dracula ----horror -------frankenstein I can move as follows --books ----classics -------frankenstein -------dracula ----horror Answer posted by Stephen on Jun 05, 2009 03:04 Ok I see whats wrong, the reason I see a failure is that dhtmlxTree sees my horizontal drag line as applying to parents ie 1. if books exist then the line applies to books 2. if no books exist in a category like classics then the line applies to categories and not books For 2 to get the same behaviour as 1 you need to drag the cursor to the category icon and then drop :( Its annoying as I only want to allow drag-n-drop at the same level as per my examples. Take what works - we have --classics <-----------------drag bar--------------> ----dracula --horror ----frankenstein <<< selected then visually drag-n-drop is seen with a horizontal drag bar ie release key and frankenstein is dropped above dracula as a book --classics <-----------------drag bar--------------> --horror ----frankenstein <<< selected again visually drag-n-drop is seen with a horizontal drag bar but release the key and frankenstein is dropped above horror but not as a book instead as a new category --classics --frankenstein --horror Answer posted by Stephen on Jun 05, 2009 03:28 Question is then how do I solve this? I need to use the horizontal bar for ordering nodes. [A] Tell the user to only use the horizontal bar when another book exists and if not use the category icon? Do this via a popup? Not good. A user would expect the same behaviour. [B] still use the bar when the category is empty ie and in my code find the new parent (id) into which I am dropping my book/ As stated my event handler function tondrag(id, newparent, idbefore) does not give the target parent, it only supplies the target parents parent as follows id=/books/horror/frankenstein newparent=/books <<<<<<<<< I need /books/classics idbefore=/books/horror/ <<<<<<this is the 'parent' after the insertion point not before whereas I need newparent=/books/classics and as I stated in the first posting: maybe I can use idbefore=/books/horror/ <<<<<<this is the 'parent' after the insertion point var nextindex= getIndexById(idbefore); var realparent= getItemIdByIndex(newparent,nextindex-1); but if target parent is last then next parent will not exist ie idbefore=null in which case maybe I get all the subitems for /books and the last subitem is the new parent. Answer posted by Support on Jun 05, 2009 05:13 Working sample was sent by email. ( the info received in onDrag event is really not suitable for desired use-case - but it can be transformed to necessary one ) tree.attachEvent("onDrag",function(sid,tid,bid){ if (this._allow_next_call) return true; //allow inner calls this._allow_next_call = true; //get previous item ID if (!bid){ if (tree.hasChildren(tid)) //last child bid = tree.getItemIdByIndex(tid,tree.hasChildren(tid)-1) else bid = tid; //has not childs - drop on parent } else { var ind = tree.getIndexById(bid); if (ind) //if has previous item bid = tree.getItemIdByIndex(tid,ind-1); else bid = tid; //else drop on parent } if (bid && tree.hasChildren(bid)) tree.moveItem(sid,"item_child",bid); //drop if item already has childs else tree.moveItem(sid,"item_sibling_next",bid); this._allow_next_call = false; return false; //block default drag processing }) Answer posted by Support on Jun 05, 2009 05:15 >>it only supplies the target parents parent as follows targetID - ID of parent to the item, which is below drag-line-marker ( parent of below ) beforeID - ID of item, which is below drag-line-marker if drag item placed after last child on level - targetID will point to the parent of above item, and beforeID will have null value. Answer posted by Stephen on Jun 05, 2009 09:28 Thanks for the quick response. I pasted the handler into my code, renaming "tree" to my tree but its not working as expected eg if I drag-n-drop dracula to under classics -books --classics --horror ----dracula results in --classics --dracula --horror (and same for moving from classics to horror) Problem is classics has no children and move 'sibling' is used if (bid && tree.hasChildren(bid)) tree.moveItem(sid,"item_child",bid); //drop if item already has childs else tree.moveItem(sid,"item_sibling_next",bid); If I amend and use tree.moveItem(sid,"item_child",bid); then it works except in the drop handler where I call s=atree.getSubItems(tid) Although the handler parameter tid is correct == books/classics the call returns with s= "books/horror/dracula" and so a count of 1 not 0. Answer posted by Stephen on Jun 05, 2009 12:26 I think my real problem lies with onDrop "Event raised after drag-and-drop processed. Event also raised while programmatic moving nodes." tree.getSubItems(tid) is coming back with incorrect data If dracula has moved from books/horror to books/classics then ondrop has tid=books/classics and I'd expected tree.getSubItems(tid) to return with books/classics/dracula but instead tree.getSubItems(tid) returns with books/horror/dracula which is wrong: onDrop is meant to be after the move but I assume books/horror/dracula is a symbolic link ie the move is incomplete at this point Answer posted by Stephen on Jun 06, 2009 10:45 On second thoughts the problem lies with me and thinking in terms of a mv dir ie I thought because dracula moved from horror/ to classics/ in the tree then the itemId will change to reflect that but why should it. Its up to me to rename it : so tree.getSubItems(tid) is ok. Answer posted on Jun 08, 2009 05:50 >>I thought because dracula moved from horror/ to classics/ in the tree then >>the itemId will change to reflect that but why should it. Yep, the IDs are preserved as is. Technically they can be changed by using tree.changeItemId - it can be used after moveItem to set new ID, according to the scheme, used in your case >>I think my real problem lies with onDrop If you are using onDrag with custom logic - it better place your custom logic after calling moveItem with custom parameters , because here all necessary ids already known |