Using Magento product chooser widget in you’re own module.

Posted by | February 19, 2012 | JavaScript, Magento, PHP | No Comments

From my personal experience Magento is in the greatest e-commerce platform when it comes to architecture and the way this is built but in the same time the it really piss me off when it comes to documentation. Well the documentation is so fuzzy and the samples are so minimal or outdated, I mean really useless. Even when you have to do a really simple task you have to do some reverse engineering and try to understand how to solve your problem (although in the old good days I love playing with decompilers and ASM to try to find out more about how the stuff are done under the hood). But when it comes to have a result in a specified amount of time this is not funny at all.
OK so one of the task that I had to figure out, was to add a product chooser widget in a custom made component. Sound easy but in reality this was frustrating because I couldn’t find anything useful and thous guys form Magento community don’t want to share anything with other (damn bastards), that is the main reason that I am sharing this with you.
Supposing that you already know how to create a module.
The product selector will be triggered by a button and will put all the product SKU in a textbox or something like.
1. create an new JS add it to js folder, this will contain something like :

getProductChooser = function (url) {
    new Ajax.Request(
    url, {
        method: "post",
        onSuccess: function (b) {
            var a = $("chosser-container");
            a.update(b.responseText);
            a.scrollTo()
        }
    })
};
var VarienRulesForm = new Class.create();
VarienRulesForm.prototype = {
    initialize: function (a) {
        this.newChildUrl = a;
        this.shownElement = null;
        this.updateElement = $("skus");
        this.chooserSelectedItems = $H({})
    },
    initParam: function (b) {
        b.rulesObject = this;
        var d = Element.down(b, ".label");
        if (d) {
            Event.observe(d, "click", this.showParamInputField.bind(this, b))
        }
        var f = Element.down(b, ".element");
        if (f) {
            var e = f.down(".rule-chooser-trigger");
            if (e) {
                Event.observe(e, "click", this.toggleChooser.bind(this, b))
            }
            var c = f.down(".rule-param-apply");
            if (c) {
                Event.observe(c, "click", this.hideParamInputField.bind(this, b))
            } else {
                f = f.down();
                if (!f.multiple) {
                    Event.observe(f, "change", this.hideParamInputField.bind(this, b))
                }
                Event.observe(f, "blur", this.hideParamInputField.bind(this, b))
            }
        }
        var a = Element.down(b, ".rule-param-remove");
        if (a) {
            Event.observe(a, "click", this.removeRuleEntry.bind(this, b))
        }
    },
    showChooserElement: function (c) {
        this.chooserSelectedItems = $H({});
        var a = this.updateElement.value.split(","),
            b = "";
        for (i = 0; i < a.length; i++) {
            b = a[i].strip();
            if (b != "") {
                this.chooserSelectedItems.set(b, 1)
            }
        }
        new Ajax.Updater(c, c.getAttribute("url"), {
            evalScripts: true,
            parameters: {
                form_key: FORM_KEY,
                "selected[]": this.chooserSelectedItems.keys()
            },
            onSuccess: this._processSuccess.bind(this) && this.showChooserLoaded.bind(this, c),
            onFailure: this._processFailure.bind(this)
        })
    },
    showChooserLoaded: function (a, b) {
        a.style.display = "block"
    },
    showChooser: function (a, c) {
        var b = a.up("li");
        if (!b) {
            return
        }
        b = b.down(".rule-chooser");
        if (!b) {
            return
        }
        this.showChooserElement(b)
    },
    hideChooser: function (a, c) {
        var b = a.up("li");
        if (!b) {
            return
        }
        b = b.down(".rule-chooser");
        if (!b) {
            return
        }
        b.style.display = "none"
    },
    toggleChooser: function (a, c) {
        var b = a.up("li").down(".rule-chooser");
        if (!b) {
            return
        }
        if (b.style.display == "block") {
            b.style.display = "none";
            this.cleanChooser(a, c)
        } else {
            this.showChooserElement(b)
        }
    },
    cleanChooser: function (a, c) {
        var b = a.up("li").down(".rule-chooser");
        if (!b) {
            return
        }
        b.innerHTML = ""
    },
    showParamInputField: function (a, c) {
        if (this.shownElement) {
            this.hideParamInputField(this.shownElement, c)
        }
        Element.addClassName(a, "rule-param-edit");
        var d = Element.down(a, ".element");
        var b = Element.down(d, "input.input-text");
        if (b) {
            b.focus();
            if (b && b.id && b.id.match(/__value$/)) {
                this.updateElement = b
            }
        }
        var b = Element.down(d, "select");
        if (b) {
            b.focus()
        }
        this.shownElement = a
    },
    hideParamInputField: function (a, d) {
        Element.removeClassName(a, "rule-param-edit");
        var b = Element.down(a, ".label"),
            c;
        if (!a.hasClassName("rule-param-new-child")) {
            c = Element.down(a, "select");
            if (c && c.options) {
                var f = [];
                for (i = 0; i < c.options.length; i++) {
                    if (c.options[i].selected) {
                        f.push(c.options[i].text)
                    }
                }
                var e = f.join(", ");
                b.innerHTML = e != "" ? e : "..."
            }
            c = Element.down(a, "input.input-text");
            if (c) {
                var e = c.value.replace(/(^\s+|\s+$)/g, "");
                c.value = e;
                if (e == "") {
                    e = "..."
                } else {
                    if (e.length > 30) {
                        e = e.substr(0, 30) + "..."
                    }
                }
                b.innerHTML = e
            }
        } else {
            c = Element.down(a, "select");
            if (c.value) {
                this.addRuleNewChild(c)
            }
            c.value = ""
        }
        if (c && c.id && c.id.match(/__value$/)) {
            this.hideChooser(a, d);
            this.updateElement = null
        }
        this.shownElement = null
    },
    addRuleNewChild: function (b) {
        var f = b.id.replace(/^.*__(.*)__.*$/, "$1");
        var h = $(b.id.replace(/__/g, ":").replace(/[^:]*$/, "children").replace(/:/g, "__"));
        var d = 0,
            c;
        var a = Selector.findChildElements(h, $A(["input.hidden"]));
        if (a.length) {
            a.each(function (k) {
                if (k.id.match(/__type$/)) {
                    c = 1 * k.id.replace(/^.*__.*?([0-9]+)__.*$/, "$1");
                    d = c > d ? c : d
                }
            })
        }
        var g = f + "--" + (d + 1);
        var j = b.value;
        var e = document.createElement("LI");
        e.className = "rule-param-wait";
        e.innerHTML = Translator.translate("Please wait, loading...");
        h.insertBefore(e, $(b).up("li"));
        new Ajax.Updater(e, this.newChildUrl, {
            evalScripts: true,
            parameters: {
                form_key: FORM_KEY,
                type: j.replace("/", "-"),
                id: g
            },
            onComplete: this.onAddNewChildComplete.bind(this, e),
            onSuccess: this._processSuccess.bind(this),
            onFailure: this._processFailure.bind(this)
        })
    },
    _processSuccess: function (b) {
        var a = b.responseText.evalJSON();
        if (a.ajaxExpired && a.ajaxRedirect) {
            alert(Translator.translate("Your session has been expired, you will be relogged in now."));
            location.href = a.ajaxRedirect
        }
        return true
    },
    _processFailure: function (a) {
        location.href = BASE_URL
    },
    onAddNewChildComplete: function (c) {
        $(c).removeClassName("rule-param-wait");
        var a = c.getElementsByClassName("rule-param");
        for (var b = 0; b < a.length; b++) {
            this.initParam(a[b])
        }
    },
    removeRuleEntry: function (b, c) {
        var a = Element.up(b, "li");
        a.parentNode.removeChild(a)
    },
    chooserGridInit: function (a) {},
    chooserGridRowInit: function (a, b) {
        if (!a.reloadParams) {
            a.reloadParams = {
                "selected[]": this.chooserSelectedItems.keys()
            }
        }
    },
    chooserGridRowClick: function (b, d) {
        var f = Event.findElement(d, "tr");
        var a = Event.element(d).tagName == "INPUT";
        if (f) {
            var e = Element.select(f, "input");
            if (e[0]) {
                var c = a ? e[0].checked : !e[0].checked;
                b.setCheckboxChecked(e[0], c)
            }
        }
    },
    chooserGridCheckboxCheck: function (b, a, c) {
        if (c) {
            if (!a.up("th")) {
                this.chooserSelectedItems.set(a.value, 1)
            }
        } else {
            this.chooserSelectedItems.remove(a.value)
        }
        b.reloadParams = {
            "selected[]": this.chooserSelectedItems.keys()
        };
        this.updateElement.value = this.chooserSelectedItems.keys().join(", ")
    }
};

2. be sure that the js file will be hooked in the header, for that add the following line to the adminhtlm layout XML (note that my module is called znuv so you would replace wit the popper name):

3. now you have a code that it will add the widget to the interface so let’s add a backend form with a button that will show the chooser, so for that add the following lines:

$action = 'getProductChooser(\'' . Mage::getUrl(
'adminhtml/promo_widget/chooser/attribute/sku/form/rule_conditions_fieldset',
array('_secure' => Mage::app()->getStore()->isAdminUrlSecure())
) . '?isAjax=true\'); return false;';
 
$productFieldset->addField('trigger', 'button', array(
'name' => 'trigger',
'label' => Mage::helper('whooparoo')->__('Choose Products'),
'value' => Mage::helper('whooparoo')->__('Choose Products'),
'class' => 'rule-chooser-trigger',
'onclick' => $action,
)
);

So that’s all, happy coding 🙂

About Andrei Tara

Andrei is a developer/geek who loves creating high quality and efficient applications, always following the best practices in software engineering. He loves the challenge of learning new, exciting things and playing with new languages, frameworks, and tools.

Leave a Reply