AEM 61 - Classic UI Limit Components Added in Parsys

Goal


Limit the number of Components added in a Parsys of Classic UI

For configuring the limit in design dialog, check this post

For Touch UI check this post

Demo | Package Install

For simplicity, lets assume user admin can only configure the component limit on a parsys; In the demo user admin (logged in Firefox) configures the component limit and user author (logged in Chrome) adds components to the limit parsys


Set Component Limit Menu Item




Set Component Limit Dialog



Component Limit on Parsys in CRX



Limit Exceeded - New Menu Item Disabled



Limit Exceeded - Error on Component Drop




Solution


1) Login to CRXDE Lite, create folder (nt:folder) /apps/classicui-limit-parsys

2) Create clientlib (type cq:ClientLibraryFolder/apps/classicui-limit-parsys/clientlib and set property categories of String type to cq.widgets and dependencies to underscore

3) Create file ( type nt:file ) /apps/classicui-limit-parsys/clientlib/js.txt, add the following

                         limit-parsys.js

4) Create file ( type nt:file ) /apps/classicui-limit-parsys/clientlib/limit-parsys.js, add the following code

(function(){
    var pathName = window.location.pathname;

    if( ( pathName !== "/cf" ) && ( pathName.indexOf("/content") !== 0)){
        return;
    }

    var EAEM_COMPONENT_LIMIT = "eaemComponentLimit";

    CQ.Ext.onReady(function() {
        CQ.WCM.on("editablesready", applyLimitAndExtendDrop, this);
    });

    function isParsysNew(editable){
        return _.isObject(editable.params)
                    && (editable.params["./sling:resourceType"] == CQ.wcm.EditBase.PARSYS_NEW);
    }

    function addMenuItem(){
        var component = this.element.linkedEditComponent;

        if (!component || !component.menuComponent) {
            return;
        }

        var menu = component.menuComponent;

        if (menu.eaemLimitSet) {
            return;
        }

        menu.eaemLimitSet = true;

        var path = this.getParentPath(),
            limit = isWithinLimit(path);

        var newItem = menu.findBy(function(comp){
            return comp.text === "New...";
        })[0];

        if(!limit.isWithin){
            newItem.setDisabled(true);
        }

        //for simplicity lets assume only "admin" has set limit access
        if(CQ.User.getCurrentUser().getUserID() === "admin"){
            menu.addSeparator();

            menu.add({
                text: "Set Component Limit",
                handler: function () {
                    var dialog = getSetLimitDialog(path, limit.currentLimit);
                    dialog.show();
                }
            });
        }
    }

    function extendDrop(dropFn){
        return function(dragSource, e, data){
            var limit = isWithinLimit(this.editComponent.getParentPath());

            if(!limit.isWithin){
                this.editComponent.hideTarget();
                CQ.Ext.Msg.alert('Error', 'More than ' + limit.currentLimit + ' components not allowed');
                return false;
            }

            return dropFn.call(this, dragSource, e, data);
        }
    }

    function applyLimitAndExtendDrop() {
        var editables = CQ.utils.WCM.getEditables();

        _.each(editables, function (editable) {
            if (isParsysNew(editable)) {
                editable.emptyComponent.el.on("contextmenu", addMenuItem, editable);
            }

            var dropTargets = editable.getDropTargets();

            if(_.isEmpty(dropTargets)){
                return;
            }

            dropTargets[0].notifyDrop = extendDrop(dropTargets[0].notifyDrop);
        });
    }

    function isWithinLimit(path){
        var isWithin = true, currentLimit = "";

        $.ajax( { url: path + ".2.json", async: false } ).done(function(data){
            if(_.isEmpty(data) || !data[EAEM_COMPONENT_LIMIT]){
                return;
            }

            currentLimit = data[EAEM_COMPONENT_LIMIT];

            var compObjects = [], limit = parseInt(data[EAEM_COMPONENT_LIMIT]);

            _.each(data, function(value, key){
                if(!_.isObject(value)){
                    return;
                }

                if(!value["sling:resourceType"]){
                    return;
                }

                compObjects.push(value);
            });

            isWithin = compObjects.length < limit;
        });

        return {
            isWithin: isWithin,
            currentLimit: currentLimit
        };
    }

    function getSetLimitDialog(path, currentLimit){
        var dialogConfig = {
            "jcr:primaryType": "cq:Dialog",
            title: "Components Limit",
            modal: true,
            width: 400,
            height: 150,
            items: [{
                xtype: "panel",
                layout: "form",
                bodyStyle :"padding: 20px",
                items: [{
                    value: currentLimit,
                    xtype: "textfield",
                    fieldLabel: "Limit to "
                }]
            }],
            ok: function () {
                var limitField = this.findByType("textfield")[0],
                    data = {};

                data[EAEM_COMPONENT_LIMIT] = limitField.getValue();

                $.ajax({
                    url: path,
                    data: data,
                    type: 'POST'
                });

                this.close();
            }
        };

        return CQ.WCM.getDialog(dialogConfig);
    }
})();

No comments:

Post a Comment