0

これは私を困惑させました。私はテキストボックスを持っています。何かを入力して、Enter キーを押します。Javascript は、別のフォームで読み取り専用の入力要素を作成します。テキスト入力ボックスの横には、それらを削除するためのボタンがあります。そのフォームの下部には、すべての読み取り専用テキスト入力を送信するための送信ボタンもあります。

フォーム内のボタンをクリックするとフォームが送信されるため (ボタンとそれに対応するテキスト入力の両方を含む親 div を削除したいだけです)、フォームの送信時に関数が呼び出されます。この関数は、押されたボタンのタイプ (削除または送信) を判別し、それに応じて動作します。

ここで問題が発生します。削除ボタンが押されたとき、関数destinations.enterは決して呼び出されません。これを解決するために私がしたことはsubmitDestinations、 の機能を複製する と呼ばれるグローバル関数を作成することでしたdestinations.enter。代わりにこの関数を呼び出すと、すべて問題なく終了します。

なぜdestinations.enter送信時に実行されないのか、誰にも考えがありsubmitDestinationsますか? 関数スコープが2つの関数の唯一の違いであるように見えるので、クロージャーと関係があると信じたいです。ただし、クロージャーを使用するのはこれが初めてであり、クロージャーについての理解は限られています。

Javascript:

var destinations = (function(){
    var max_destinations = 7;
    var counter = 0;

    function increment(){
        counter += 1;
        if(counter > max_destinations){
            throw 'Too many destinations. (Max 7)'
        }
    }
    function decrement(){
        counter += 0;
        if(counter < 0){
            alert('Cannot have less than 0 destinations..')
            throw 'Too few destinations. Get out of the console!'
        }
    }
    return {
        add : function(form){
            try{
                var formInput = form.elements[0];
                var destination = formInput.value;
                // Dont do anything if the input is empty
                if(destination == ""){
                    return false;
                }else{
                    // increment the destinations counter
                    increment();
                }
            }catch(err){
                alert(err);
                return false;
            }
            // add the text value to a visual element
            var elem = document.createElement('div');
            elem.setAttribute('class','destination');
            // create the input
            var input = document.createElement('input');
            input.setAttribute('id','dest'+String(counter));
            input.setAttribute('class','destinationText');
            input.setAttribute('style','border: none');
            input.setAttribute('name','destinations');
            input.setAttribute('readonly','readonly');
            input.setAttribute('value',destination);
            // create the remove button
            var button = document.createElement('button');
            button.setAttribute('onclick','this.form.submitted=this;');//'return destinations.remove(this);');
            button.setAttribute('class','removeButton')
            button.setAttribute('id','but'+String(counter))
            var buttonText = document.createTextNode('Remove');
            button.appendChild(buttonText);
            // add the elements to the div
            elem.appendChild(input);
            elem.appendChild(button);

            var parent = document.getElementById('destinationsDiv');
            parent.appendChild(elem);
            // clear the input box
            formInput.value = '';
            return false;
        },
        enter : function(form){
            alert('hi')
            var button = form.submitted;
            if(button.id != 'submitBtn'){
                return remove(button);
            }else{
                return true;
            }
            return false;
        },
        remove : function(button){
            try{
                decrement();
            }catch(err){
                // do not allow less than 0 counter
                alert(err);
                return false;
            }
            // remove the button's parent div altogether
            var toDelete = button.parentNode;
            toDelete.parentNode.removeChild(toDelete);
            return false;
        }

    }
})();

そしてhtml:

        <div>
            <form id='hi' onsubmit="return destinations.add(this);">
                <input type="text" value="" />
            </form>
            <!--form id='submitDiv' method="post" onsubmit="alert(this.submitted);return submitDestinations(this);"-->
            <form id='submitDiv' method="post" onsubmit="alert(this.submitted);return destinations.enter(this);">
                <div id='destinationsDiv'>
                    <div>
                        <input id="dest1" class="destinationText" style="border: none" name="destinations" readonly="readonly" value="aadasd" \>
                        <button onclick="this.form.submitted=this;" class="removeButton" id="but1" \></button>
                    </div>
                    <div>
                        <input id="dest2" class="destinationText" style="border: none" name="destinations" readonly="readonly" value="Hi Stackoverflow" \>
                        <button onclick="this.form.submitted=this;" class="removeButton" id="but2" \></button>
                    </div>
                </div>
                <input type="submit" id='submitBtn' onclick="this.form.submitted=this;"/>
            </form>
        </div>

次の JavaScript 関数をグローバル スコープに追加して代わりに呼び出すと、すべて正常に動作します。これは、次とまったく同じことを行いますdestinations.enter

function submitDestinations(form){
    var button = form.submitted;
    if(button.id != 'submitBtn'){
        return destinations.remove(button);
    }else{
        return true;
    }
}

HTML で変更するのは、送信時に呼び出されるメソッドだけです。

        <div>
            <form id='hi' onsubmit="return destinations.add(this);">
                <input type="text" value="" />
            </form>
            <form id='submitDiv' method="post" onsubmit="alert(this.submitted);return submitDestinations(this);">
            <!--form id='submitDiv' method="post" onsubmit="alert(this.submitted);return destinations.enter(this);"-->
                <div id='destinationsDiv'>
                    <div>
                        <input id="dest1" class="destinationText" style="border: none" name="destinations" readonly="readonly" value="aadasd" \>
                        <button onclick="this.form.submitted=this;" class="removeButton" id="but1" \></button>
                    </div>
                    <div>
                        <input id="dest2" class="destinationText" style="border: none" name="destinations" readonly="readonly" value="Hi Stackoverflow" \>
                        <button onclick="this.form.submitted=this;" class="removeButton" id="but2" \></button>
                    </div>
                </div>
                <input type="submit" id='submitBtn' onclick="this.form.submitted=this;"/>
            </form>
        </div>
4

2 に答える 2

2

名前の競合があったことが判明しました。私が作成していたテキスト入力の name 属性は、送信時に呼び出していた JavaScript オブジェクトと同じ名前の「destinations」に設定されていました。したがって、「onsubmit」の JavaScript は、私の JavaScript 関数を参照する代わりに、DOM 要素を参照して Enter を呼び出そうとしていました。

于 2013-01-03T20:03:59.033 に答える
0

destinations.enter() の実装にエラーがあります。ボタンを削除するために remove() を呼び出しますが、「remove」という名前は、destinations.enter() が定義されているスコープにバインドされていません。

あたかも destinations.remove() が他の場所で呼び出されないように見えるため、最も簡単な修正は、destinations オブジェクトのメソッドにするのではなく、destinations コンストラクターのプライベート関数に移動することです。

submitDestinations() の本体を変更して、そのスコープにバインドされている destinations.remove() を呼び出すため、変更されたバージョンが機能します。

于 2013-01-03T10:58:29.610 に答える