Javascript - необходимо предложение Designpattern - PullRequest
3 голосов
/ 25 октября 2010

Hallo,

У меня есть 3 различных функции в Javascript, первая заменяет настраиваемую панель выбора ширины HTML Selectboxs, созданную с помощью UL.

, а другие 2 заменяют кнопки «Флажок» и «Радио» соответственно.1005 *

Теперь я хочу вывести классы из этих функций и нуждаюсь в ваших предложениях, как лучше организовать эти функции в классе, возможно ли наследование?

Я действительно ценю вашу помощь.

Спасибо.

Вот пример кода.

function replaceSelect(formid) {

    var form = $(formid);
    if (!form) return;

    invisibleSelectboes = document.getElementsByClassName("optionsDivInvisible");
    if (invisibleSelectboes.length > 0) {
        for (var i = 0; i < invisibleSelectboes.length; i++) {
            document.body.removeChild(invisibleSelectboes[i]);
        }
    }

    var selects = [];
    var selectboxes = form.getElementsByTagName('select');

    var selectText = "Bitte auswählen";
    var selectRightSideWidth = 21;
    var selectLeftSideWidth = 8;
    selectAreaHeight = 21;
    selectAreaOptionsOverlap = 2;

    // Access all Selectboxes in Search mask.
    for (var cfs = 0; cfs < selectboxes.length; cfs++) {
        selects.push(selectboxes[cfs]);
    }

    // Replace the select boxes
    for (var q = 0; q < selects.length; q++) {
        if (selects[q].className == "") continue;

        var onchangeEvent = selects[q].onchange;

        //create and build div structure
        var selectArea = document.createElement('div');
        var left = document.createElement('div');
        var right = document.createElement('div');
        var center = document.createElement('div');
        var button = document.createElement('a');
        //        var text = document.createTextNode(selectText);
        var text = document.createTextNode('');
        center.id = "mySelectText" + q;

        if ( !! selects[q].getAttribute("selectWidth")) {
            var selectWidth = parseInt(selects[q].getAttribute("selectWidth"));
        } else {
            var selectWidth = parseInt(selects[q].className.replace(/width_/g, ""));
        }

        center.style.width = selectWidth + 'px';
        selectArea.style.width = selectWidth + selectRightSideWidth + selectLeftSideWidth + 'px';

        if (selects[q].style.display == 'none' || selects[q].style.visibility == 'hidden') {
            selectArea.style.display = 'none';
        }

        button.style.width = selectWidth + selectRightSideWidth + selectLeftSideWidth + 'px';
        button.style.marginLeft = -selectWidth - selectLeftSideWidth + 'px';
        //  button.href = "javascript:toggleOptions( + q + ")";
        Event.observe(button, 'click', function (q) {
            return function (event) {
                clickObserver(event, q)
            }
        }(q));

        button.onkeydown = this.selectListener;
        button.className = "selectButton"; //class used to check for mouseover
        selectArea.className = "selectArea";

        selectArea.id = "sarea" + q;
        left.className = "left";
        right.className = "right";
        center.className = "center";
        right.appendChild(button);
        center.appendChild(text);
        selectArea.appendChild(left);
        selectArea.appendChild(right);
        selectArea.appendChild(center);
        //hide the select field
        selects[q].style.display = 'none';
        //insert select div
        selects[q].parentNode.insertBefore(selectArea, selects[q]);

        //build & place options div
        var optionsDiv = document.createElement('div');

        if (selects[q].getAttribute('width')) optionsDiv.style.width = selects[q].getAttribute('width') + 'px';
        else optionsDiv.style.width = selectWidth + 8 + 'px';

        optionsDiv.className = "optionsDivInvisible";
        optionsDiv.id = "optionsDiv" + q;
        optionsDiv.style.left = findPosX(selectArea) + 'px';
        optionsDiv.style.top = findPosY(selectArea) + selectAreaHeight - selectAreaOptionsOverlap + 'px';

        //get select's options and add to options div
        for (var w = 0; w < selects[q].options.length; w++) {
            var optionHolder = document.createElement('p');

            if (selects[q].options[w].className == "informal") {
                var optionLink = document.createElement('a');
                var optionTxt = document.createTextNode(selects[q].options[w].getAttribute('text'));
                optionLink.innerHTML = selects[q].options[w].getAttribute('text');
                optionLink.className = "informal";
                cic.addEvent(optionLink, 'click', function (event) {
                    Event.stop(event);
                });

                Event.observe(optionLink, 'mouseover', function (event) {
                    Event.stop(event);
                });

                Event.observe(optionLink, 'mouseout', function (event) {
                    Event.stop(event);
                });
            }
            else {
                var optionLink = document.createElement('a');
                var optionTxt = document.createTextNode(selects[q].options[w].text);
                optionLink.appendChild(optionTxt);
                cic.addEvent(optionLink, 'click', function (id, w, q, onchangeEvent) {
                    return function () {
                        showOptions(q);
                        selectMe(selects[q].id, w, q, onchangeEvent);
                    }
                }(selects[q].id, w, q, onchangeEvent));
            }

            //optionLink.href = "javascript:showOptions(" + q + "); selectMe('" + selects[q].id + "'," + w + "," + q + ");";

            optionHolder.appendChild(optionLink);
            optionsDiv.appendChild(optionHolder);

            if (selects[q].options[w].selected) {
                selectMe(selects[q].id, w, q);
            }
        }
        document.getElementsByTagName("body")[0].appendChild(optionsDiv);
        Event.observe(optionsDiv, 'mouseleave', function (submenuid) {
            optionsDiv.className = 'optionsDivInvisible'
        });

        cic.addEvent(optionsDiv, 'click', function (event) {
            if (event.stopPropagation) event.stopPropagation();
            else event.cancelBubble = true;
        });

    }
    form.setStyle({
        visibility: 'visible'
    });
}​

Ответы [ 4 ]

3 голосов
/ 25 октября 2010

Я бы пошел с

var Library = (function()
{
    function _selectBox()
    {
        // stuff
    }

    function _checkBox()
    {
        // stuff
    }

    function _radioButton()
    {
        // stuff
    }

    return {
        SelectBox : _selectBox,
        CheckBox : _checkBox,
        RadioButton : _radioButton
    };
})();

или

var Library = (function()
{
    return {
        SelectBox : function()
        {
            // stuff
        },

        CheckBox : function()
        {
            // stuff
        },

        RadioButton : function()
        {
            // stuff
        }
    };
})();

[Редактировать]
Таким образом, вы можете объявить «частные» переменные, которые могут быть доступны только изсама библиотека, просто объявляя var foo="bar"; внутри объявления Library, создает переменную foo, к которой нельзя получить доступ извне, но к которой может получить доступ любой объект из библиотеки, поэтому функции, подобные _selectBox в моем примере, остаются закрытыми, но все еще может быть доступен через Library.SelectBox, который также будет "public getter"
[/ Edit]

, вместо

var Library = (function(){})();

вы можете сделать что-то вродеэто:

var Library = Library || {};

Library.UI = (function(){})();

таким образом, вы можете хранить отдельные части вашей библиотеки кодов, вы можете хранить их в отдельных файлах , которые не заботятся о порядке, в котором они находятсязагруженные, если они имеют

var Library = Library || {};

поверх них

, функции будут вызываться так:

Library.SelectBox();

или в выбранном вами случаеперейти с «подклассами»

Library.UI.SelectBox();
3 голосов
/ 25 октября 2010

Судя по всему, вы хотите создать унифицированный API для инкапсуляции всей этой функциональности, улучшающей форму.Возможно что-то вроде этого:

var formEnhancement = {
    SelectBox: function(){ /* ... */ },
    CheckBox: function(){ /* ... */ },
    RadioButton: function(){ /* ... */ }
};

formEnhancement.SelectBox.prototype = { /* ... define methods ... */ };
// etc. (other prototypes)

// Call something:
var myEnhancedSelectBox = new formEnhancement.SelectBox(
    document.getElementById('id-of-a-select-box')
);

Это отвечает на ваш запрос?

1 голос
/ 25 октября 2010

Все ответы являются общими закономерностями. Думаю, ни один из них не очень полезен. Тот факт, что вы помещаете свои 3 огромные функции в объект, не делает ваш код модульным, многократно используемым и обслуживаемым.

Итак, мое первое предложение - использовать декомпозицию функции . Вы упомянули наследство. Теперь, если ваш код в основном состоит из этих трех гигантских функций, ничто не может быть унаследовано или разделено. Вы должны разделить функциональную логику по назначению на более мелкие, более простые.

Хорошим примером является то, что вы упомянули слово , которое заменяет , имеет отношение ко всем вашим случаям. Возможно, вы можете настроить функцию, которая отвечает за замену DOM независимо от типа элемента. Такая функция может быть разделена между вашими модулями, делая ваш код более надежным и позволяя вам DRY .

Лучший способ организовать этот процесс называется желаемое за действительное , когда вы решаете свою проблему с помощью интуитивно понятных и полезных функций, даже если они могут даже не существовать. Это связано с тем, как вы можете создавать эффективные взаимодействия.

1 голос
/ 25 октября 2010

Поместите функции в пространство имен:

Объявите это так:

FormUtils = {};

и добавьте его свойства, которые будут вашими функциями

FormUtils.replaceSelect = function () {/*your code*/};
FormUtils.replaceCheckbox = function () {/*your code*/};
FormUtils.replaceRadio = function () {/*your code*/};

затем вы вызываете эти функции с их пространством имен:

FormUtils.replaceSelect();

Это простой и очень приемлемый шаблон дизайна для JavaScript

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...