Gaurang Tandon
Gaurang Tandon

Reputation: 6761

Grouped context menu items in a Chrome extension

I have the following data structure (sample):

Folder1
  - Folder2
    - Snip1
    - Snip2
  - Folder3
    - Snip3
  - Snip4
  - Folder4
    - Snip5

There is no limit on nesting of folders inside one another

I need to allow the user to insert a particular snip whenever he/she right-clicks on a textarea. Now, I can either flatten the above data to:

- Snip1
- Snip2
- Snip3
- Snip4
- Snip5

to simply create context menu entries. But, I want better user experience so I will prefer something like:

enter image description here

to simulate the folder structure in the actual data.

Question: Is it possible to generate such type of context menu items' structure though Chrome extensions?

I have looked at the docs, but found nothing useful.

UPDATE: For anyone interested in the code, here's it:

    // this is the top most folder
    this.createCtxMenuEntry = function(parentId){
        this.list.forEach(function(object, index){
            var id = chrome.contextMenus.create({
                contexts: ["editable"],
                id: // generateUniqueIDYourself
                title: object.name,
                parentId: parentId
            });
            
            if(object is folder) object.createCtxMenuEntry(id);
        });
    };

The trick is to use the parentId property.

Upvotes: 3

Views: 1485

Answers (1)

Wolf War
Wolf War

Reputation: 1563

yes, it's possible to create dynamically (based on user data and changes) nested context menu with chrome extension
I created exactly the same thing with my [V7 Notes][1] extension (inserting notes in text fields)
example: Alt

first you need to create main item and then recursively (I guess you have folder structure) create sub-folders appended to that main item

var OriginalArrayData = [....]; //or whatever you have

chrome.contextMenus.create({
    title : "MAIN title",
    id: "main_ID", //call it whatever you like, but it needs to be unique
    type : "normal",
    contexts : ["editable"],
},function() {
    buildTree(OriginalArrayData, 'main_ID'); //pass original array and main_ID in first call
});

function buildTree(a, b) {
    for (var i=0, l=a.length; i<l; i++) { //loop trough passed data
        var notId = a[i].id, //create random unique ID for new items, I'm using id's from my notes
        notText = a[i].text; //create item title, I'm using text from my notes

        chrome.contextMenus.create({ //create CTX item
            id: notId,//for ID use previously created
            parentId: b,//for parent ID use second passed argument in function
            title: notText,//for title use previously creted text (or whatever)
            type: "normal",
            contexts: ["editable"]
        });
        if (a[i].list) buildTree(a[i].list, notId);//if folder, recursively call the same function
    }
}

on the last line, whenever your loop runs into a folder, you need to call your buildTree function, but this time you need to pass data/array from within that folder, and that folder ID so that it can be used as parent ID for further children

When function finishes traversing trough sub folders, it returns one step UP where it was entering those sub-loops

So, to summ up:

  • create main item
  • in callback create recursive function to loop all your data and create/append those new items to main item
  • if you have folder, that folder now becomes main item and all it's children will be append to it...and so on
  • this way context menu will follow folders structure of your data as deep as they are

I think this is the easiest and lightest way to create dynamic folder structure on context menus
When some of the data changes, you need to clean context menu and create it all over again... (or update it if you know which to target) [1]: https://addons.opera.com/extensions/details/v7-notes/

Upvotes: 6

Related Questions