jstree contextmenu CLONE ( as copy , paste , and rename ) in one action - contextmenu

I am working on contextmenu for jstree, and apparently needed a clone functionality in right click menu which will actually be simulation of copy , paste and rename, so that once user right clicks on an item and then clicks on clone, a node is copied (copied and pasted in the tree , and focused with rename highlight so that user could rename it right there.
I tried code below for custom clone menu item, but it doesn't work
cloneItem: { // The "clone" menu item
label: "Clone",
action: function (obj)
{
this.copy(obj);
this.paste(obj);
}
}
Any help is very much appreciated.

After research I figured out how this clone could be implemented, the key to do this was as paste goes on parent node of copied node. here is code.
cloneItem: {
label: "Clone",
action: function (obj)
{
var currentId = this._get_node(obj).attr("id");
var parentId = this._get_node(obj)[0].firstChild.parentElement.parentNode.parentElement.id;
$("#TreeDiv").jstree("copy");
$("#TreeDiv").jstree("select_node","#"+parentId);
$("#TreeDiv").jstree("paste");
$("#TreeDiv").jstree("deselect_node","#"+parentId)
$("#TreeDiv").jstree("deselect_node", "#"+currentId)
$("#TreeDiv").jstree("select_node","#copy_"+currentId);
$("#TreeDiv").jstree("rename");
}
},
steps to do this are
copy the current item using .jstree("copy");
select the parent node of copied item using .jstree("select_node","#"+parentId);
paste the copied item ( its copied over selected item , means parent ) using .jstree("paste");
now deselect both parent and copied element using .jstree("deselect_node","#"+parentId) and .jstree("deselect_node", "#"+currentId)
Before renaming select the copied node, the copied items gets id as copy_, so do this by .jstree("select_node","#copy_"+currentId);
and the final step to do is by .jstree("rename");
I hope it will help someone, who needs clone in jstree.

Related

Testing-library unable to find rc-menu

I'm trying to implement integration tests on our React frontend which uses Ant design. Whenever we create a table, we add an action column in which we have a Menu and Menu Items to perform certain actions.
However, I seem unable to find the correct button in the menu item when using react-testing-library. The menu Ant design uses is rc-menu and I believe it renders outside of the rendered component.
Reading the testing-library documentation, I've tried using baseElement and queryByRole to get the correct DOM element, but it doesn't find anything.
Here's an example of what I'm trying to do. It's all async since the table has to wait on certain data before it gets filled in, just an FYI.
Tried it on codesandbox
const row = await screen.findByRole('row', {
name: /test/i
})
const menu = await within(row).findByRole('menu')
fireEvent.mouseDown(menu)
expect(queryByRole('button', { name: /delete/i })).toBeDisabled()
the menu being opened with the delete action as menu item
I had a same issue testing antd + rc-menu component. Looks like the issue is related to delayed popup rendering. Here is an example how I solved it:
jest.useFakeTimers();
const { queryByTestId, getByText } = renderMyComponent();
const nav = await waitFor(() => getByText("My Menu item text"));
act(() => {
fireEvent.mouseEnter(nav);
jest.runAllTimers(); // ! <- this was a trick !
});
jest.useRealTimers();
expect(queryByTestId("submenu-item-test-id")).toBeTruthy();

React Table - open in new tab?

I am using React Table any I'm trying to open each row in a new tab (each row has an id associated and should lead to /path/:id) but only when I right click -> open in new tab. I don't want to use _target='blank' Basically I want to make each cell into a link. Currently I am using getTdProps like this:
getTdProps={(state, rowInfo, column, instance) => {
return {
onClick: (e) => {
if (rowInfo) {
History.push(`/vehicle/${rowInfo?.original?._id}`);
}
},
className: `${rowInfo && "cursor-pointer"}`,
};
}}
This basically turns my cells into buttons and this is not what I want.
The only solution I came up with is something like this:
Cell: ({ original }) => (
<Link to={{pathname:`/vehicle/${original?._id}`}}>
<Battery percent={original?.battery_level}
</Link>
),
The issue is I have to use this for every column. The project is quite big and I have a lot of tables. Is there a better way to target all the cells and make them into links so I can right click -> open in new tab?

Umbraco 7 - Custom Menu Items & Trees, How does navigation work?

I have a custom section, with a custom tree.
I'm having a bit of trouble understanding how you set the correct behavior when:
You click a node in your tree to edit it.
You click a menu item on a node like "Create"
In my solution I'm using the same view to edit and create a record.
In my tree this is how a node is generated.
var routeToView = "rewards/rewardsTree/editcampaign/campaign-" + campaign.Id.ToString();
var campaignNode = CreateTreeNode("campaign-" + campaign.Id.ToString(), id.Split('-')[1], queryStrings, campaign.CampaignName, "icon-folder color-yellow", true, routeToView);
This is producing the route I want: (the name of my html file is editcampaign.html) and it is also passing "campaign-6"
/umbraco#/rewards/rewardsTree/editcampaign/campaign-6
When a user clicks the create 'menu Item' on the node - I want to send them to the same URL but just with a diffrent Id for example:
umbraco#/rewards/rewardsTree/editcampaign/brand-1
and I don't want it to pop up out of the side
This is what I have tried so far:
//This finds the view, but it comes up in a dialog also how do I pass the Id (brand-1)
MenuItem mi = new MenuItem("editcampaign", "Create Campaign");
menuItemCollection.Items.Add(mi);
//Also Tried this finds puts a whole another umbraco UI inside a dialog
mi.LaunchDialogView("#rewards/rewardsTree/editcampaign/brand-1", "TITLE GOES HERE");
Can anyone point me to the fullest documentation for Menu's trees and navigation around the back office in general?
I believe there is an option to set view path on the "Create" menu item, which makes it open normally? Also, wouldn't it make more sense to have your path like /view/path/here/id ? Then when you create a new item just send 0 as id. Umbrangular on Github is a project with great examples of custom sections and views.
EDIT: Here's an example
protected override MenuItemCollection GetMenuForNode(string id, FormDataCollection queryStrings)
{
var menu = new MenuItemCollection();
MenuItem createCategory = new MenuItem("createcategory", "Create Category");
createCategory.AdditionalData.Add("ParentCategoryId", id);
createCategory.NavigateToRoute("/path/to/view/category/0");
createCategory.Icon = "add";
menu.Items.Add(createCategory);
return menu;
}

Drag and drop in AngularJS

I am trying to implement Drag and Drop using c0deformer's jQuery UI implementation (see here: http://codef0rmer.github.io/angular-dragdrop/#/) The dragging part works fine, but I can't seem to get the functionality I am after in terms of the drop. In this application, I want to be able to drop the draggable items anywhere within a target div, i.e., I don't want the destination scope to be limited to a list-type structure (or a set of repeated divs). Mainly this is because the user will be dragging items on the fly and there will be no way of knowing how many items the user will drag and drop in advance.
I have scoured the web and cannot find an example in Angular that uses drag and drop without effectively dragging from one list to another list. Can this be done? If so, I am not sure how I would appropriately update the scope after an item has been dragged. In this example code below, the dropped items are pushed into the scope of a second list and the new scope is applied. Ideally, the scope of the dropped items is the target div I mentioned above. I'm really new to Angular, so any advice is immensely appreciated.
Snippet from c0deformer:
app.directive('droppable', function($compile) {
return {
restrict: 'A',
link: function(scope,element,attrs){
//This makes an element Droppable
element.droppable({
drop:function(event,ui) {
var dragIndex = angular.element(ui.draggable).data('index'),
dragEl = angular.element(ui.draggable).parent(),
dropEl = angular.element(this);
console.log(dropEl);
if (dragEl.hasClass('list1') && !dropEl.hasClass('list1') && reject !== true) {
scope.list2.push(scope.list1[dragIndex]);
scope.list1.splice(dragIndex, 1);
} else if (dragEl.hasClass('list2') && !dropEl.hasClass('list2') && reject !== true) {
scope.list1.push(scope.list2[dragIndex]);
scope.list2.splice(dragIndex, 1);
}
scope.$apply();
}
});
}
};
});
I recently created an angular directive for drag and drop that doesn't rely on jquery-ui. It uses the html5 drag and drop api. It also doesn't have any requirements on the format of the data to be dragged or dropped, it simply sets up a hook for you to be notified when one element is dragged onto another.
Post here: http://jasonturim.wordpress.com/2013/09/01/angularjs-drag-and-drop/
Demo here: http://logicbomb.github.io/ng-directives/drag-drop.html

jQueryUI and problem with sortable events

I'm working with the 'Connect list trough tabs' demo. I modified the code a little bit. I added the 'foo' class to the tabs-1 and tabs-2 elements.
I also added the following script:
$(".foo ul").sortable({
stop: function (event, ui) {
var tabId = $(this).attr('id');
var elementIndex = ui.item.index();
alert('tab id: ' + tabId + ' | element index: ' + elementIndex);
}});
It works super fine when I change the sort order of elements inside same tab, but I have the problem when I drop the element from the first tab to the second tab (or vice versa), because the element is firstly placed on the first position in tab1 (tab id = sortable1, element index = 0), and after that it is dropped to the second tab on the last position. The problem is because the sortable event is not fired for the second time.
I'm missing something but don't know what :)
Any help would be greatly appreciated.
Thank you!
EDIT:
Demo can be found on the following link: http://jqueryui.com/demos/sortable/#connect-lists-through-tabs
Did you ever find an answer to this? Because I'm currently having the same problem - trying a range of ways around it, but so far to no success.
EDIT
Scratch that, just found what I think is the most efficient way to resolve. Bind the event "DOMNodeInserted" to the <ul> list class you're using, and you can test the list item by searching its current DOM position:
$(".connectedSortable").bind("DOMNodeInserted", function() {
$('#tabs').find('li#staff-'+currentStaffId).each(function() {
listDeptID = $(this).parent().parent().attr('id');
listDeptID = listDeptID.split('-');
listDeptID = listDeptID[1];
....
In this example of mine, I have my list items with the id of staff-x with the id of that staff member, so the find returns one array element, and runs quite efficiently.
HTH
Jester.

Resources