I want to change order of the menu items of menu in a button. For example, I have a menu like following:
menu1
menu2
menu3
menuA
I add them in this order (menuA, menu3, menu2, menu1). Now i want to move menuA to top (before menu 1) like following:
menuA
menu1
menu2
menu3
Any idea/suggestion on how to do this?
Thanks for help in advance.
I am writing an HTA which uses extjs3 and I wanted to implement a recent files menu where if you choose a file from this menu, the chosen file should be moved to the top of the menu. I got it to work by removing all items and then adding new items in the new order
ResktopDeporter.getRecentFilesMenuItems = function() {
var a = [];
Ext.each(ResktopDeporter.recentfiles, function(item, index) {
a.push(new Ext.menu.Item({
text: item,
handler: function() {
ResktopDeporter.recentfiles.remove(this.text);
ResktopDeporter.recentfiles.unshift(this.text);
ResktopDeporter.saveRecentFiles();
var parent = this.parentMenu;
parent.hide(true);
parent.removeAll(true);
var items = ResktopDeporter.getRecentFilesMenuItems();
Ext.each(items, function(item, index) {
parent.addItem(item);
});
ResktopDeporter.openDocument(this.text);
}
}));
});
return a;
}
ResktopDeporter.recentfiles is just an array of file paths and saveRecentFiles() writes the list to a cookie.
I guess there is no way to reorder the menu items so for now i just add the menu items in my required order instead of reordering them later.
Related
I want to have a Menu with active items on my website. It should be added a class to activate the item. Since the project has cryptic URLs, URL-based solutions are not possible. The text of the respective menu item is shown in the respective page title.
My idea was to compare the pagetitle id="navtopheader" with the text in the menu item. If it is equal, add the menuactive class to the respective menu item.
My HTML looks basically like this:
<div id="navtopheader" class="navtopheader">menu item 1</div>
...
<div class="nav_ebene_2">
<p>menu item 1</p>
</div>
<div class="nav_ebene_2">
<p>menu item 2</p>
</div>
...
I can do it actually in an inefficient way:
var headertext = document.getElementById("navtopheader").innerText
var menutext0 = document.getElementsByClassName("nav_ebene_2")[0].innerText
var navlist = document.getElementsByClassName("nav_ebene_2");
if (headertext == menutext0) {
navlist[0].classList.add("activemenu");
}
var menuitem1 = document.getElementsByClassName("nav_ebene_2")[1].innerText
if (headertext == menuitem1) {
navlist[1].classList.add("activemenu");
}
...
But since the number of menu items varies across the website, i would get an error message if i include too much/too few menu items.
Is there an appropriate solution? I tried the whole day but didn't solve the problem. Thank you!
Iterate over the collection of <p>s that are children of nav_ebene_2. When a match is found, add the class to its parent.
const headerText = document.querySelector('#navtopheader').textContent;
for (const p of document.querySelectorAll('.nav_ebene_2 p')) {
if (p.textContent === headerText) {
p.parentElement.classList.add('activemenu');
}
}
I am using Summernote editor v0.8.9 for quite a long time. I have created a custom dropdown button for Ordered List and Unordered List by using below code
let orderedList = function (context)
{
let ui = $.summernote.ui;
// create button
let button = ui.buttonGroup([
ui.button({
className: 'dropdown-toggle',
contents: '<i class="fa fa-list-ol"/><span class="note-icon-caret"></span>',
container: false,
tooltip: 'Ordered List',
data: {
toggle: 'dropdown'
}
}),
ui.dropdown({
className: 'dropdown-style',
contents: "<ol style='list-style-type:none' class='ordered-list'><li data-value='1'>1</li><li data-value='1' style='display: none;'>1)</li><li data-value='I'>I</li><li data-value='A'>A</li><li data-value='a)' style='display: none;'>a)</li><li data-value='a'>a</li><li data-value='i'>i</li></ol>",
callback: function ($dropdown) {
$dropdown.find('li').each(function () {
$(this).click(function() {
selectedListType = orderedListMap[$(this).attr('data-value')];
$(context).summernote('editor.insertOrderedList');
});
});
}
})
]);
return button.render(); // return button as jquery object
};
And also I get the dropdown attached to the toolbar as shown in the image
I have changed some code in the summernote.js to change the list style type after clicking on the dropdown item.
I am adding following code in the Bullet.prototype.wrapList method as follows
//for bullets and numbering style
if (selectedListType != 'NA') {
listNode.setAttribute('style', 'list-style-type:' + selectedListType);
}
I have also added the following code in the method "function replace(node, nodeName)" of "dom" object.
//for bullets and numbering style
if ((nodeName == 'OL' || nodeName == 'UL' ) && selectedListType != 'NA') {
$(newNode).css('list-style-type', selectedListType);
}
When I click on the dropdown item I am calling below code.
$(context).summernote('editor.insertOrderedList');
At first instance everything is working fine. I can change ordered list to unordered list as well as to other types of lists. But the problem arises when I am trying to create a new list. When I try to create a new list below the existing list (note : after double entering new line, existing list closes, hence a new list is created after double entering new line),
the focus does not stay on the current line. Instead it goes to the old list and old list style (Ordered/unordered) is getting changed.
I have also kept the default UL/OL in the toolbar for deugging and I can see that the document.selection() in the method WrappedRange.prototype.nativeRange is giving proper selection for default UL/OL but is giving wrong selection for my dropdown UL/OL.
Please help.
Let me know if any info is needed from my side
I solved this problem.
The problem was with the custom dropdown I created.
The dropdown needs to be in the following structure in the 'contents' attribute inside 'ui.dropdown'
<li>
</li>
<li>
</li>
'a' tag inside 'li' tag
This code is executed when clicking on menu item:
var objectTabPanel = Ext.create('App.view.ObjectTabPanel');
var tab = Ext.getCmp('mainTabPanel').add(objectTabPanel);
But if I click on the menu item again, the tabpanel is created again.
How to create a condition? If the tabpanel is created and opened, then switch to it. If the tabpanel is not created and is not open, then create and switch to it.
I want the behavior such as, for example, in SublimeText:
You can use Ext.getCmp('componentID').show():
...
onObjectsClick: function(item, e, eOpts) {
if(!Ext.getCmp('objectsPanel')) {
var objectsPanel = Ext.create('AMS.view.ObjectsPanel');
Ext.getCmp('mainTabPanel').add(objectsPanel);
}
Ext.getCmp('objectsPanel').show();
},
...
I am using angular-drag-and-drop-lists (https://github.com/marceljuenemann/angular-drag-and-drop-lists) for my AngularJS project to create two lists that allow me to do the following:
Drag items from list A to list B
Drag items from list B to list A
Reorder items in list A
Reorder items in list B
Using a simple example on the library's site (http://marceljuenemann.github.io/angular-drag-and-drop-lists/demo/#/simple) I can see that these four conditions are easily achievable. However, things start to get hairy when I want to introduce slightly more complex behaviour:
When dragging items from list A to list B, I want something to occur (easily achieved with the dnd-drop callback. This currently works for me
When dragging items from list B to list A, I don't want anything to happen other than a regular drop (i.e. the item winds up in list A and nothing fancy happens). This currently works for me
When reordering items in list A, nothing should happen when an item is re-dropped into it's new position in the list (even if it is being dropped back into it's original position) This is where I am having issues - see below for further explanation
When reordering items in list B, nothing should happen when an item is re-dropped into it's new position in the list (even if it is being dropped back into it's original position). This currently works for me
I am largely adapting the sample code used in the example link provided above. The problem I am having is that the action I want to take place when moving items from list A to list B is also occurring when I reorder things in list A.
The current setup/pseudocode I have is the following:
My lists:
$scope.models.lists = {
"A": [],
"B": []
}
I populate these lists with information pulled from a database. Each item in the list also has a property that tracks how many children the item has.
My markup looks like the following:
<ul dnd-list="list"
dnd-allowed-types="['itemType']"
dnd-drop="myCallback(event, index, item, external, type, 'itemType')">
<li ng-repeat="item in list | filter:searchText"
dnd-draggable="item"
dnd-moved="list.splice($index, 1)"
dnd-effect-allowed="move"
dnd-selected="models.selected = item"
dnd-type="'itemType'"
ng-class="{'selected': models.selected === item}"
ng-dblclick="editProperties();">
{{item.label + ' - ' + item.description}}
</li>
</ul>
My callback looks like the following:
$scope.myCallback= function(event, index, item, external, type, allowedType) {
// If the item in question has no children then we don't need to do anything special other than move the item.
if (item.children.length == 0) {
return item;
}
// If moving items around list B then just move them.
for (var i = 0; i < $scope.models.lists.B.length; i++) {
if (item.label === $scope.models.lists.B.[i].label) {
return item;
}
}
// I only want this code to execute if we know we are moving from list A to list B and the item in question has > 0 children.
if (item.children.length > 0) {
// Code that I want to execute only when moving from list A to list B goes here
}
If anyone is able to assist me with this I will be very grateful.
Thanks!
If you're not totally committed to that library (which, btw, doesn't work with a touchscreen) RubaXa's Sortable is the truth: Sortable
The documentation is strong, it's quite performant, and I wish I hadn't wasted my time on other DnD libraries before this one.
Looking at the README, the dnd-drop event fires for any drop - regardless of whether it was within the same list or not.
Going by the script as you have it now, you need to check the event (or pass some additional information into your callback) to determine what list the event is firing on.
hi i have add a dragstartCallback that set variable in event.dataTransfer
for the information of the origin/source of my dragged obj:
$scope.dragstartCallback = function(event){
var id = event.target.id;
var parent = $('#' + event.target.id).closest('ul')[0].id;
var group = $('#' + event.target.id).closest('div')[0].id;
event.dataTransfer.setData("id", id);
event.dataTransfer.setData("parent", parent);
event.dataTransfer.setData("group", group);
return true;
}
And in the dropCallback i just check if is List A or List B
$scope.dropCallback = function(event, index, item, external, type, allowedType) {
$scope.logListEvent('dropped at', event, index, external, type);
var idDivSource = event.dataTransfer.getData("parent");
var idDivDestination = $(event.target).closest('ul')[0].id;
var groupSource = event.dataTransfer.getData("group");
var groupDestination = $('#' + event.target.id).closest('div')[0].id;
if(groupSource == groupDestination){
if(idDivSource != idDivDestination){
if(idDivDestination == 'IDLISTB'){
return item?
}
if(idDivDestination == 'IDLISTA'){
DO Something else
}
DO Something else
}
}
}
Html code:
<div class="associated-drag-and-drop DnD" id="GROUP-MyD&D1" ng-repeat="(listName, list) in models.lists" flex="">
<ul dnd-list="list" id="{{listName}}" dnd-drop="dropCallback(event, index, item, external, type, 'containerType')" flex="">
<md-list-item class="associated-list__item" ng-repeat="item in list | filter:searchFilter" id="{{item.id}}"
dnd-dragover="dragoverCallback(event, index, external, type)"
dnd-dragstart="dragstartCallback(event)"
dnd-draggable="item"
dnd-moved="list.splice($index, 1)"
dnd-effect-allowed="move"
dnd-selected="models.selected = item"
ng-class="{'selected': models.selected === item}"
class="noright associated-list__item"
>
CONTENT
</md-list-item>
</ul>
</div>
Do not use this type of filter "| filter:searchFilter"
But use ng-show="And put here the condition"
Alternative change the reference to $index in dnd-moved="list.splice($index, 1)"
If you dont make this change you will have a problem with the filtered list when drag and drop
Exemple
NOT FILTERED LIST
you will have 2 array in 2 ng-repeat
ListA ListB
index1 of value index2 of value
ng-repeat of list ng-repeat of list
0 aaa 0 ppp
1 bbb 1 qqq
2 ccc 2 www
3 dddaaa 3 eeerrr
4 eeeccc 4 mmmwww
ecc... ecc...
The drag and drop lists work on the index of ng-repeat
FILTERED LIST
Now if we make a filter for 'a' with "| filter:searchFilter" code
angular will make this list
List A List B
0 aaa
1 dddaaa
the index when you drag "dddaaa" will be 1 and not 3
so it will not be removed from listA when dropped in listB
becouse the index is not the same as the non filtered list
instead if you use the ng-show="condition"
it will keep the original index of list not filtered
<md-list-item ng-repeat="item in list"
ng-show="condition">
</md-list-item>
My item list:
$scope.models = {
lists: {
"LISTA": [{1},{2},{3}],
"LISTB": [{1},{2},{3}]
}
};
I am looking for an example of a dojo enhanced grid that contains a context menu on either a cell or row menu where the cell or row data is accessed. I have managed to create an enhanced grid with a row context menu. I can create a function that captures the event of clicking on the row menu item. However, I am not sure how to access the row data in the context of the menu item handler. I have not seen any example in the tests of the nightly build. Is there an example of this available online?
I had a similar question. I wanted to create a context menu which allowed the user to remove the item that they right clicked on from the datagrid and delete the item from the datastore. Thought it should be pretty simple and with your help and some other sites, I came up with the following code.
var selectedItem; // This has to be declared "globally" outside of any functions
function onRowContextMenuFunc(e) {
grid5_rowMenu.bindDomNode(e.grid.domNode);
selectedItem = e.grid.getItem(e.rowIndex);
}
function gridRowContextMenu_onClick(e) {
store3.deleteItem(selectedItem);
}
.
<div dojoType="dijit.Menu" id="grid5_rowMenu" jsId="grid5_rowMenu" style="display: none;">
<div dojoType="dijit.MenuItem" onClick="gridRowContextMenu_onClick">Delete</div>
<div dojoType="dijit.MenuItem">Cancel</div>
</div>
.
<div id="grid" dojoType="dojox.grid.DataGrid" jsId="grid5" store="store3" structure="layoutStructure" rowsPerPage="40" onRowContextMenu="onRowContextMenuFunc"></div>
Of course, if you were programatically creating your DataGrid, you would just add onRowContextMenu: onRowContextMenuFunc to your declaration.
I figured it out. On the row context menu even, capture the row number into a global. On a click even on the menu item, retrieve the row from the global and then use it to lookup the contents of the row in the grid. I have been using this method and it has worked perfect.
Here's how to access the selected row from the context menu:
// First create a menu object to hold the various menus
var menusObject = {
// headerMenu: new dijit.Menu(),
rowMenu: new dijit.Menu()//,
// cellMenu: new dijit.Menu(),
// selectedRegionMenu: new dijit.Menu()
};
Add a menu item
menusObject.rowMenu.addChild(new dijit.MenuItem({
label: "Show me data",
onClick: function(e){
console.log(this.selectedRow)
}
}));
menusObject.rowMenu.startup();
Create the grid
var grid = new dojox.grid.EnhancedGrid({
store : store,
structure : layout,
rowsPerPage: 10,
escapeHTMLInData: false,
plugins: {
menus: menusObject
}
}, 'some are to place');
// Activate message sending from data grid row to menu items
dojo.connect(grid, 'onRowContextMenu', function(e)
{
// Set the "selectedItem" property of all of the menu items of a menu. This lets you reference the row data!!
var menuChildren = menusObject.rowMenu.getChildren();
for(var i = 0; i<menuChildren.length; i++){
menuChildren[i].selectedRow = this.getItem(e.rowIndex);
}
});