Search code examples
google-chromegoogle-chrome-extension

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.


Solution

  • 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/