わかりました、バックストーリーは、製品にバリエーションを追加するために、ページに同一の (機能的に) フォームがたくさんあるということです。フォームは 3 つの主要な部分で構成されています。
アトリビュート エディタ
このコンポーネントを使用すると、ユーザーは商品に属性を追加できます。各属性には 、visibility status
、attribute key
、 がattribute value
あり、delete button
これらが一緒になって 1 つの行を形成します。
コンポーネントにはAdd Attribute
ボタンもあり、クリックするとリストの一番下に新しい行が追加されます。
各attribute key
選択リストにはnew attribute
オプションがあり、選択すると、新しい属性名を入力するフォームを含むモーダル ダイアログが起動します。このフォームは AJAX 経由で送信され、ID が返されます。新しいオプションはattribute key
、ページ上のすべての選択に追加されて許可されます。選ばれる。
コンポーネントのインスタンスでキーが選択されるとattribute key
、グループ内の他のすべての選択はそのオプションを無効にして、属性の重複を防ぎます。
属性エディタは、以下のメイン フォームの一部として送信されます。
メインフォーム
このコンポーネントは、バリアントの一般的な説明フィールドで構成されています。フォームは AJAX 経由で送信され、フォーム検証用にjQuery Validation Engineが接続されています。
属性エディターを使用して新しい入力を動的に追加しているため、常に検証エンジンを切り離して再接続する必要があります。
アラートシステム
このコンポーネントは、フォームごとにエラー/成功/ステータス メッセージの表示/非表示を処理します。
問題
現在、非常によく似ていますが、いくつかのイベント ハンドラーがわずかに異なるフォームもいくつかあります。そのため、コードを作成して、コード全体をコピーすることなく、コードの一部を自由に置き換えることができるようにしたいと考えました。 .
したがって、この質問のヒントに従った後、以下のコードになりましたが、エラーが発生しています:Uncaught TypeError: object is not a function
これはこの行にあります: これはvar variantAlert = new VariantAlert(form);
、何も返していないためだと思いますが、何を返すべきかわかりません私がやりたいことをするためのコードを取得するために!
短縮版
$(function () {
$("form.variant-form").each(function (i, form) {
var variantAlert = new VariantAlert(form);
var variantForm = new VariantForm(form, variantAlert);
variantForm.init();
var attributeEditor = new AttributeEditor(form, variantForm);
attributeEditor.init();
});
});
var AttributeEditor = (function (form, formSetup) {
form = $('form');
var someVar = 123;
var init = function () {
someEventHandler();
};
var someEventHandler = function () {
$('.selector', form).on('some event', function (e) {
form.css('background-color', '#f00');
});
};
return AttributeEditor;
})();
var VariantForm = (function (form, variantAlert) {
form = $('form');
var init = function () {
anotherEventHandler();
};
var anotherEventHandler = function () {
$('.anotherSelector', form).on('another event', function () {
form.doStuff();
});
};
})();
var VariantAlert = (function (form) {
var timer;
form = $('form');
var message = function (type, message) {
doMoreStuff(type, message);
}
})();
完全版
$(function () {
/*********************************
* Loop over each variant and setup
* the attribute editor and form
*********************************/
$("form.variant-form").each(function (i, form) {
var variantAlert = new VariantAlert(form);
var variantForm = new VariantForm(form, variantAlert);
variantForm.init();
var attributeEditor = new AttributeEditor(form, variantForm);
attributeEditor.init();
});
});
var AttributeEditor = (function (form, formSetup) {
/*********************************
* Variables
*********************************/
form = $('form');
var template = $('.variant_demo_row', form);
var attributes = $('.variant_select', form).length;
var modal = form.siblings('.newAttribute').appendTo('body');
var manualHide = false;
var triggerSelect = null;
var oldOption = null;
var init = function () {
//setup the handlers
//doing it this way allows us to overwrite the individual handlers with ease
addNewAttributeHandler();
removeAttributeHandler();
selectFocusHandler();
selectChangeHandler();
attributeVisibilityHandler();
modalFormSubmissionHandler();
modalShowHandler();
modalCancelClickHandler();
};
/*********************************
* Add new attribute button handler
*********************************/
var addNewAttributeHandler = function () {
$('.variant_attribute_add_new a', form).on('click keypress', function (e) {
form.css('background-color', '#f00');
//patched support for enter key
if (e.type === 'keypress' && e.which != 13) {
return true;
}
//clone the template row so we can edit it
var newRow = template.clone().css('display', 'none').removeClass('hidden variant_demo_row').addClass('variant_row');
//give each element in the clone it's unique name
$('.variant_select', newRow).prop('name', 'attribute_key_' + attributes);
$('.variant_input', newRow).prop('name', 'attribute_value_' + attributes);
$('.variant_visible', newRow).prop('name', 'attribute_visible_' + attributes);
//insert the new attribute row at the bottom of the attributes
newRow.insertBefore($('.variant_attribute_add_new', form)).show('fast', function () {
$('select', newRow).focus();
});
//we have added new nodes so we need to reset the validationEngine
form.validationEngine('detach');
formSetup.init();
attributes++;
});
};
/*********************************
* Remove attribute button handler
*********************************/
var removeAttributeHandler = function () {
form.on('click keypress', '.removeAttribute', {}, function (e) {
//patched support for enter key
if (e.type === 'keypress' && e.which != 13) {
return true;
}
attributes--;
var val = $(this).siblings('select').val();
//re-enable whatever attribute key was in use
if (val != "") {
$('.variant_select option[value=' + val + ']', form).removeAttr('disabled');
}
//animate the removal of the attribute
$(this).closest('.controls-row').hide('fast', function () {
$(this).remove();
});
});
};
/*********************************
* Attribute key select focus handler
*********************************/
var selectFocusHandler = function () {
form.on('focus', '.variant_select', {}, function () {
//store the old option so we know what option to
//re-enable if a change is made
oldOption = $('option:selected', this).val();
});
};
/*********************************
* Attribute key select change handler
*********************************/
var selectChangeHandler = function () {
form.on('change', '.variant_select', {}, function () {
var select = $(this);
//empty class is used for "placeholder" simulation
select.removeClass('empty');
//re-enable whatever option was previously selected
if (oldOption !== null) {
$('.variant_select option[value=' + oldOption + ']', form).removeAttr('disabled');
}
if ($('option:selected', select).hasClass('newAttribute')) { //Add new attribute selected
triggerSelect = select;
modal.modal('show');
} else if ($('option:selected', select).val() == "") { //Placeholder selected
select.addClass('empty');
} else { //Value selected
//disable the selected value in other attribute key selects
$('.variant_select', form).not(select).children('option[value=' + select.val() + ']').prop('disabled', 'disabled');
}
oldOption = select.val();
});
};
/*********************************
* Toggle visibility button handler
*********************************/
var attributeVisibilityHandler = function () {
form.on('click', '.toggleVisibility', {}, function () {
//the titles of the button
var hidden = 'Hidden Attribute';
var visible = 'Visible Attribute';
var btn = $(this);
var icon = btn.children('i');
var box = btn.siblings('.variant_visible');
//toggle the state between visible and hidden
btn.toggleClass('btn-success btn-warning').attr('title', btn.attr('title') == hidden ? visible : hidden);
icon.toggleClass('icon-eye-open icon-eye-close');
box.prop("checked", !box.prop("checked"))
});
};
/*********************************
* New attribute submission handler
*********************************/
var modalFormSubmissionHandler = function () {
$('.newAttributeForm', modal).validationEngine('attach', {
onValidationComplete:function (form, status) {
if (status) {
var text = $('.newAttributeName', modal).val();
$('.newAttributeName', modal).val('');
form.spin();
$.ajax({
type:'POST',
url:'/cfox/cart/variants/addattribute',
data:{name:text},
success:function (data) {
//add new attribute key to attribute key selects everywhere
$('.variant_select').append($('<option>', { value:data.id}).text(data.name));
//set the triggering selects value to the new key
triggerSelect.val(data.id);
triggerSelect.trigger('change');
manualHide = true;
modal.modal('hide');
triggerSelect.siblings('input').focus();
form.spin(false);
},
dataType:'JSON'
});
}
}});
};
var modalCancelClickHandler = function () {
$('.btn-danger', modal).on('click', function () {
if (!manualHide) {
triggerSelect[0].selectedIndex = 1;
triggerSelect.trigger('change');
}
manualHide = false;
});
};
var modalShowHandler = function () {
modal.on('show shown', function () {
$('.newAttributeName', modal).focus();
});
}
return AttributeEditor;
})();
var VariantForm = (function (form, variantAlert) {
/*********************************
* Variables
*********************************/
form = $('form');
var init = function () {
nameChangeHandler();
submitHandler();
};
/*********************************
* Variant name change handler
* Changes the heading on the accordion if the
* name form input changes
*********************************/
var nameChangeHandler = function () {
var accordion_heading = form.closest('.accordion-body').siblings('.accordion-heading').find('.accordion-toggle');
$('.name-input', form).on('change', function () {
accordion_heading.text($(this).val());
});
};
/*********************************
* Form submit handler
*********************************/
var submitHandler = function () {
form.validationEngine('attach', {
onValidationComplete:function (form, status) {
if (status == true) {
$.ajax({
type:'POST',
url:form.attr('action'),
data:form.serialize(),
dataType:'json',
beforeSend:function () {
cfox.disableForm(form);
form.spin();
form.children('.variant_status_message').hide('fast');
},
success:function (response) {
cfox.enableForm(form);//need to do this here so browser doesn't cache disabled fields
if (typeof response != "object" || response === null) {
variantAlert.message('failed');
} else {
switch (response.status) {
case 0:
variantAlert.message('errors', response.errors);
break;
case 1:
variantAlert.message('success');
break;
default:
variantAlert.message('failed');
break;
}
}
form.spin(false);
},
error:function () {
variantAlert.message('failed');
form.spin(false);
cfox.enableForm(form);
}
});
}
}
});
}
})();
var VariantAlert = (function (form) {
/*********************************
* Variables
*********************************/
var timer;
form = $('form');
/*********************************
* handles showing/hiding any messages
* in the variant forms
*********************************/
var message = function (type, message) {
var alert;
clearTimeout(timer);
$('.variant_status_message', form).hide('fast');
if (type == 'success') {
alert = $('.variant_status_message.success', form);
} else if (type == 'errors') {
alert = $('.variant_status_message.errors', form);
$('.alert-message', alert).html(message);
} else if (type == 'failed') {
alert = $('.variant_status_message.failed', form);
}
alert.show('fast', function () {
$('html, body').animate({
scrollTop:alert.closest('.accordion-group').offset().top
}, 150, 'linear');
timer = setTimeout(function () {
alert.hide('fast')
}, 5000);
});
}
})();