0

私の基本的な設定は、「メンバー、非メンバー、スタッフなど」をクリックして選択するまで、非表示のフォームを用意することです。選択がクリックされると、フォームの合計が$ 0を超えるまで、フォームに表示され、内部の請求領域も非表示になります。

今私が抱えている問題は、5つの選択肢のうち4つがクリックされるとすぐに、合計が$0より大きくなるはずだということです。そのため、請求部分は自動的にトリガーされますが、onclickイベントまたはonchangeイベントの最初の関数をリッスンする2番目の関数(計算を実行する関数)を取得できません。それぞれの「if」ステートメントの中に、「 executecalculatefunction」のようなコードを入れる方法はありますか?

このようなもの:

if(section == 'Member') {
            var base_cost = 150;

            $("#commentTable,#ClinicStaff,#IMSNonMember,#Resident,#Student").fadeOut('slow', function() {
                // Animation complete.
            });
            $("#commentTable, #IMSMember").fadeIn('slow', function() {
                // Animation complete
            });
            $("input[name=SectionChosen]").val('Member');// Section selected, pass as hidden field for processing
                    ***$runNextFunction();***

        }

私はやってみました:$(" 'input[name^=PROD]', 'base_cost ").change(function() {

関数に入力フィールドと基本コストフィールドの両方の変更を監視させることができるかどうかを確認します。しかし、それはトリガーしたくありません。これが私の完全なセットアップです:

jQuery(function(ready){

    jQuery('.showForm').click(function(){

        var section = $(this).attr('target');
        var base_cost = ''; // reset base cost
        $("input[name=TOTAL]").val('');// Reset the Total field to 0 to hide the billing form again
        $("input[name^=PROD]").val('');// matches those that begin with 'PROD' and clears them
        $("input[name=SectionChosen]").val('');// Reset the section choice


        if(section == 'Member') {
            var base_cost = 150;

            $("#commentTable,#ClinicStaff,#IMSNonMember,#Resident,#Student").fadeOut('slow', function() {
                // Animation complete.
            });
            $("#commentTable, #IMSMember").fadeIn('slow', function() {
                // Animation complete
            });
            $("input[name=SectionChosen]").val('Member');// Section selected, pass as hidden field for processing

        }
        else if(section == 'Clinic') {
            var base_cost = 150;

            $("#commentTable,#IMSMember,#IMSNonMember,#Resident,#Student").fadeOut('slow', function() {
                // Animation complete.
            });
            $("#commentTable, #ClinicStaff").fadeIn('slow', function() {
                // Animation complete
            });
            $("input[name=SectionChosen]").val('Clinic');// Section selected, pass as hidden field for processing
        }
        else if(section == 'Nonmember') {
            var base_cost = 250;

            $("#commentTable,#IMSMember,#ClinicStaff,#Resident,#Student").fadeOut('slow', function() {
                // Animation complete.
            });
            $("#commentTable, #IMSNonMember").fadeIn('slow', function() {
                // Animation complete
            });
            $("input[name=SectionChosen]").val('Nonmember');// Section selected, pass as hidden field for processing
        }
        else if(section == 'Resident') {
            var base_cost = 75;

            $("#commentTable, #IMSMember,#ClinicStaff,#IMSNonMember,#Student").fadeOut('slow', function() {
                // Animation complete.
            });
            $("#commentTable, #Resident").fadeIn('slow', function() {
                // Animation complete
            });
            $("input[name=SectionChosen]").val('Resident');// Section selected, pass as hidden field for processing
        }
        else if(section == 'Student') {
            var base_cost = 0;

            $("#commentTable,#IMSMember,#ClinicStaff,#IMSNonMember,#Resident").fadeOut('slow', function() {
                // Animation complete.
            });
            $("#commentTable, #Student").fadeIn('slow', function() {
                // Animation complete
            });
            $("input[name=SectionChosen]").val('Student');// Section selected, pass as hidden field for processing
        }


        // Calculate order Total
        $('input[name^=PROD]').change(function() { 

            // Total cost of order, is equal to base cost + any additional selectoins made below
            var order_total = base_cost;

            // Run through all the form fields
            $('input[name^=PROD]').each(function(i) {

                // Get the current field and its name
                var form_name = $(this).attr('name');

                // If so, extract the price from the name
                var item_price = parseFloat(form_name.substring(form_name.lastIndexOf("_") + 1));

                // Get the quantity
                var item_quantity = parseInt($(this).val(), 10);

                // Update the order total
                if (item_quantity >= 0) {
                    order_total += item_quantity * item_price
                }

            });

            // Display the total rounded to two decimal places
            $('input[name=TOTAL]').val((Math.round(order_total*100)/100).toFixed(2));

            // Show the billing portion if total is not 0
            if (order_total > 1) {
                // show the section with the billing portion
                $("#BillingPortion").show();
            }
            else {
                // hide billing portion if total is 0
                $("#BillingPortion").hide();
            }
        });


    });
});

ここのjsFiddleからわかるように、フォームは機能します。選択項目をクリックしてから、ゲストに番号を挿入して「コスト」を追加すると、請求部分が表示されます。しかし、それだけでは十分ではありません。ゲストが必要ない場合でも、基本コストが0ドルを超えているかどうかを請求部分に表示する必要があるためです。

誰かが私を正しい方向に向けることができれば、それは素晴らしいことです。

また、jQueryに関してはかなり経験が浅いので、コードをもっとDRYにすることができ、おそらく一部の人にとってはひどいように見えると思いますが、少なくともそれは始まりです。

4

2 に答える 2

3

了解しました。先に進み、コードに対していくつかのリファクタリングを行いました。結果は次のとおりです。

セクションリンクのマークアップ

リンクを使用してフォームを切り替えていました。ただし、リンク自体は間接的に(JavaScriptコードを介して)、と呼ばれる非表示の入力を設定しますSectionChosen。リンクをクリックすることは選択肢を表し、その選択肢もフォームデータの一部であることをより明確にすることができます。したがって、意味的に関連のないリンクのセットではなく、ラジオボックスのセットを使用して1つのオプションを選択する方がはるかに適切です。ラジオボックスはaとainputを持つ適切な要素であるため、これらは元の非表示の入力を置き換えることができます。ボーナス:選択したラジオボックスの値が送信されるため、値を設定するためにJavaScriptも必要ありません!namevalueSectionChosen

<label><input type="radio" name="SectionChosen" value="Member" /> I am an IMS Member Physician</label>
<label><input type="radio" name="SectionChosen" value="Clinic" /> I am a Clinic/Hospital Administrators or Clinic Staff</label>
...

基本コストの取得

clickハンドラーで、クリックしたリンクに応じて呼び出されるローカル変数を設定して、合計を計算しようとしbase_costていました。問題は、新しいハンドラーをinput'changeイベントにバインドし、以前に選択したリンクから以前にバインドされたハンドラーをスタックしていたことです。動作しているように見えますが、実際には、最後にバインドされたハンドラーのみが最終的な出力値を生成する状態で、多数の合計を計算しています。

実際には、基本コストは選択したセクションのプロパティであり、フォーム入力を変更する場合とセクションを切り替える場合の両方で簡単にアクセスできる必要があります。これを行う良い方法は、各選択肢の基本コストを属性としてラジオボックスに保存することです。data-*属性は、このようなカスタムデータのニーズに合わせて特別に導入されました。

<input type="radio" name="SectionChosen" value="Member" data-base-cost="150" />

基本コストは、次の方法で取得できます。

var base_cost = $(...).data('base-cost');

現在選択されているセクションから基本コストを取得するには、現在選択されているラジオボックスを探します。

var base_cost = $('input[name=SectionChosen]:checked').data('base-cost');

これですべてです。マークアップ自体に基本コストを見つけることができるため、ハンドラーchange内からハンドラーをバインドする必要がなくなりました。つまり、必要に応じて、DOMの準備ができたときにハンドラーclickをバインドする必要があるのは1回だけです。change

さらなる改善

さらなる改善の余地は常にあります。たとえば、実際のフォームセクションに、のdata-section代わりにセクション名と一致する属性を指定できますid。このようにして、非表示にする必要のあるセクションと表示する必要のあるセクションをより簡単に選択できます。IDセレクターの同じリストを書き留める代わりに、とのようなものを選択することができ.section[data-section="Member"]ます.section:not([data-section="Member"])。ちなみに、その値は選択したラジオボックス自体からも得られる可能性があり、長い木はもうdata-section必要ありません!if...else if

于 2013-02-11T14:55:20.707 に答える
1

いくつかのこと。ハンドラー内に$('input[name^=PROD]').changeバインディングを設定することで、clickハンドラーを起動するたびに同じハンドラーを追加しますclick。つまり、2回目のクリックで入力を変更すると、2回起動します。これはおそらくあなたが望んでいたものではありません。

click次に、合計を計算する部分を、ハンドラーで呼び出すことができる別の関数に抽象化してみませんか。

function calculateTotal() {
    // your code to calculate the total and make part of the UI visible if more than
    // $0.
}

change次に、ハンドラーにそれを呼び出させることもできます。

 $('input[name^=PROD]').change(function() { 
     calculateTotal();
 }
于 2013-02-11T14:16:09.267 に答える