0
  • 画像(li)を選択できるようにしたいのですが、選択項目の数は(メインdiv)のdata-maxとdata-minに依存します

問題は選択した機能にありますリスト内のアイテムのチェック済みステータスと選択済みクラスを削除しています

そのため、一番上のものを選択するまで機能し、混乱します。検証を変更して、trueまたはfalseを返すだけにする必要があります

デモ http://jsfiddle.net/XeELs/346/

JS

(function () {

    var mobileForms = (function () {

        return {

            model: {
                selection: {
                    validate: {
                        test: function (e) {
                            var that = this,
                                modelSelector = $('.divModelOptions'),
                                chosen = $('input:checked', modelSelector),
                                messages = $('.message', modelSelector),
                                minMessage = $('.min', modelSelector),
                                maxMessage = $('.max', modelSelector);


                            if (typeof (that.messageDisplayTime) !== 'undefined') clearTimeout(that.messageDisplayTime);
                            if (chosen.length >= that.min && chosen.length <= that.max) {
                                messages.slideUp(200);
                                return true;
                            } else if (chosen.length > that.max) {

                                if (that.max > 1) {
                                    maxMessage.slideDown(400, function () {
                                        that.messageDisplayTime = setTimeout(function () {
                                            maxMessage.slideUp(200);
                                        }, 3000);
                                    });

                                    if (typeof (e) !== 'undefined') e.preventDefault();
                                    return false;
                                } else {
                                    chosen[0].checked = false;
                                    chosen.parents('li').removeClass('selected');
                                    return true;
                                }

                            } else {
                                minMessage.slideDown(400);

                                return 'fail';
                            }
                        },
                        init: function () {
                            var modelSelector = $('.divModelOptions'),
                                html = '';

                            this.min = parseInt(modelSelector.attr('data-min'), 10);
                            this.max = parseInt(modelSelector.attr('data-max'), 10);

                            html = '\
                                <ul class="validation">\
                                    <li class="message min">' + modelSelector.attr('data-min-msg') + '</li>\
                                    <li class="message max">' + modelSelector.attr('data-max-msg') + '</li>\
                                </ul>';

                            modelSelector.prepend(html);
                        }
                    },
                    bindHandlers: function () {
                        var that = this,
                            modelSelector = $('.divModelOptions'),
                            chosen = $('input:checked', modelSelector);
                        var max = parseInt(modelSelector.attr('data-max'), 2);

                        $('input', modelSelector).click(function (e) {
                            var parent = $(this).parents('li');

                            if (that.validate.test(e)) {
                                if (parent.hasClass('selected')) {
                                    parent.removeClass('selected');
                                } else {
                                    parent.addClass('selected');
                                }
                            }
                        });

                        if (chosen.length) {
                            chosen.parents('li').addClass('selected');
                            that.validate.test();
                        }

                        $('form').submit(function (e) {
                            if (!that.validate.test() || that.validate.test() === 'fail') e.preventDefault();
                        });
                    },
                    init: function () {
                        this.validate.init();
                        this.bindHandlers();
                    }
                },
                nextButton: {
                    bindHandlers: function (button) {
                        button.one('click', function () {
                            mobileForms.showNextStep();
                        });
                    },
                    create: function () {
                        var nextCommandText = $('.divModelOptions').data('nextcommand');

                        // TODO: Next button should start off grey and become blue once a model is selected.
                        var button = $('<input type="button" value="' + nextCommandText + '" class="next-button">');

                        $('.divModelOptions').append(button);
                        this.bindHandlers(button);
                    },
                    init: function () {
                        this.create();
                    }
                },
                init: function () {
                    this.selection.init();
                    this.nextButton.init();
                }
            },
            validation: {
                focusOnError: function (messages) {
                    var message = $(messages[0]);
                    $('html, body').animate({
                        scrollTop: message.offset().top - 100
                    }, 500);
                },
                init: function () {
                    var visibleMessages;
                    $('form').submit(function () {
                        visibleMessages = $('.validation-message:visible, .validation .message:visible');
                        if (visibleMessages.length) {
                            mobileForms.validation.focusOnError(visibleMessages);
                        }
                    });
                }
            },
            init: function () {
                this.model.init();
                this.validation.init();
            }
        };

    })();

    $(function () {
        mobileForms.init();
    });

})();
4

1 に答える 1

0

問題のコードは、実際には問題の一部ではない関数がたくさんあったため、理解するのがかなり困難でした。また、エラー メッセージ要素が自動的に非表示になることもわかりにくく、特にsetTimeout()何度もクリックすることで複数の機能を追加できるためです。

CSS を次のように設定すると、何が起こっているかを確認するのに役立ちます。

.divModelOptions input {
    display: block;
}

この問題は、次の場合data-min="1"にのみ発生します。data-max="1"else

if (that.max > 1) {
} else {
    chosen[0].checked = false;
    chosen.parents('li').removeClass('selected');
    return true;
}

そのthat.max === 1ため、2番目にクリックされた項目は、どの項目がクリックされ、クラスが削除されたすべての親に関係なく、常に最初 <input>checked属性が false に設定されます。ただし、呼び出し元のコードのロジック条件が満たされているためです。 <li>selectedreturn true;if

if (that.validate.test(e)) {
    if (parent.hasClass('selected')) {
        parent.removeClass('selected');
            //remove check status to input
    } else {
        parent.addClass('selected');
        //add check status to input
    }
}

selected新しく選択した にクラスを追加します<li>

最初に選択されたものが<li>最初に選択されたものであるかどうかに応じて、異なる一貫性のない動作が得られることに注意してください。最初に 2番目、3番目、または 4番目を選択した場合。

選択したアイテムの数が定義された範囲を下回ったり超えたりした場合にメッセージを表示するという問題に対処するために、回答のコードを削減しようとしました。したがって、それはあなたが求めているものではないかもしれませんが、(できれば) より単純化された場所から始める必要があります.

jsFiddle デモ

JavaScript

(function () {
    var mobileForms = (function () {
        return {
            model: {
                selection: {
                    validate: {
                        inRange: function (e) {
                            var self = this,
                                chosen = $('input:checked', self.modelSelector),
                                minMessage = $('.min', self.modelSelector),
                                maxMessage = $('.max', self.modelSelector);

                            if (chosen.length === 0 || (chosen.length >= self.min && chosen.length <= self.max)) {
                                self.validation.slideUp(200);
                            } else {
                                maxMessage.toggle(chosen.length > self.max);
                                minMessage.toggle(chosen.length < self.min);
                                self.validation.slideDown(400);
                            }

                            return chosen.length <= self.max;
                        },
                        init: function () {
                            this.modelSelector = $('.divModelOptions');
                            this.validation = $('.validation', this.modelSelector);
                            this.min = parseInt(this.modelSelector.data('min'), 10);
                            this.max = parseInt(this.modelSelector.data('max'), 10);
                            this.validation.slideUp();

                            $('.min span').text(this.min);
                            $('.max span').text(this.max);
                        }
                    },
                    bindHandlers: function () {
                        var self = this;

                        $('input', this.modelSelector).click(function (e) {
                            var parent = $(this).closest('li');
                            parent.toggleClass('selected');
                            if (!self.validate.inRange()) {
                                parent.removeClass('selected');
                                return false; // stop checkbox receiving event
                            }
                        });
                    },
                    init: function () {
                        this.validate.init();
                        this.bindHandlers();
                    }
                },
                init: function () {
                    this.selection.init();
                }
            },
            init: function () {
                this.model.init();
            }
        };

    })();

    $(function () {
        mobileForms.init();
    });
})();

完全を期すために…

CSS (質問と同じ)

.divModelOptions input {
    cursor: pointer;
    display: none;
    float: left;
}
.divModelOptions label {
    cursor: pointer;
}
.divModelOptions li.selected {
    border:1px solid red
}
.divModelOptions .validation li {
    display: none;
}

HTML (data-max と data-min を試して、さまざまな例を確認してください)

<div data-max="2" data-min="2" class="divModelOptions">
    <ul class="validation">
        <li class="message min">At least <span></span> should be selected</li>
        <li class="message max">No more than <span></span> should be selected</li>
    </ul>
    <ul>
        <li>
            <label>
                <img alt="" src="http://placehold.it/30x30" />
                <input type="checkbox" id="Model" value="Model" name="Model" /><span rel="Model">Model</span>
            </label>
        </li>
        <li>
            <label>
                <img alt="" src="http://placehold.it/30x30" />
                <input type="checkbox" id="Model2" value="Model2" name="Model2" /><span rel="Model2">Model2</span>
            </label>
        </li>
        <li>
            <label>
                <img alt="" src="http://placehold.it/30x30" />
                <input type="checkbox" id="Model3" value="Model3" name="Model3" /><span rel="Model3">Model3</span>
            </label>
        </li>
        <li>
            <label>
                <img alt="" src="http://placehold.it/30x30" />
                <input type="checkbox" id="Model4" value="Model4" name="Model4" /><span rel="Model3">Model4</span>
            </label>
        </li>
    </ul>
</div>
于 2013-04-10T16:33:45.480 に答える