Search code examples
javascriptchaining

Is this kind of chaining possible in JavaScript?


I'm working on a file manager framework similar to elFinder. My current code works fine but now I want to make it look better and add chaining (I'm not sure if it's chaining or decorator pattern).

Here is a sample of what I want to do:

function UI() {}

UI.prototype.folders = function(){
    return [];
}

UI.prototype.folders.prototype.getSelectedFolder = function(){
   return {};
}

Calling UI.folders() should return an array of folder objects. So if you call UI.folders() you would get something similar to this:

[
    Object { name="folder1", selected=false }, 
    Object { name="folder2", selected=false }, 
    Object { name="folder3", selected=true }
]

And calling UI.folders().getSelectedFolder() would filter the results from UI.folders() and will return:

Object { name="folder3", selected=true }

Is this possible? Is it right to say "chaining" in this case or it's "decorative pattern"?
If it's not - is there another more appropriate way to do it?

Any help wold be really appreciated!


Solution

  • The are a few different ways to solve this. The primary goal is that when you call a function you get an object/function back that is the same type of object with different properties. I'm not a fan of the prototype usage so I would do it like this (this is one way to solve it):

    var FolderList = function ()
    {
        var _folders = [];
        folders.pop({ name: "folder1", selected: false });
        folders.pop({ name: "folder2", selected: true });
        folders.pop({ name: "folder3", selected: false });
    
        // prevent other programers from changing _folders
        // which would break this, so just use a function
        this.folders = function ()
        {
            return _folders;
        }
    
        this.selectedFolders = function ()
        {
            var tmpFolders = [];
            for (var folderIndex = 0; 
                 folderIndex < this._folders.length; 
                 folderIndex++)
            {
                if (this._folders[folderIndex].selected)
                {
                    tmpFolders.pop(_folders[folderIndex]);
                }
            }
            _folders = tmpFolders;
            return this;
        }
    
        this.addFolder = function (folder)
        {
            _folders.pop(folder);
            return this;
        }
    };
    
    var folderList = new FolderList();
    folderList.selectedFolders()
              .addFolder({ name: "folder1", selected: false })
              .addFolder({ name: "folder3", selected: true })
              .selectedFolders();
    
    // array of 2 objects, folder2 and folder3
    var arrayOfSelectedFolder = folderList.folders();