I am able to get the information from the object I am using to store the form information, when the one tries to fire the submit without filling in the fields successfully, but when I enter all the information correctly I can't seem to obtain the same upon success?
var theForm = document.getElementsByTagName('form')[0];
var firstNameInput = document.getElementById('firstNameInput');
var lastNameInput = document.getElementById('lastNameInput');
var emailInput = document.getElementById('emailInput');
var stateInput = document.getElementById('stateInput');
var theButton = document.querySelector('input[type=submit]');
// Wire the form's submit event to a callback
theForm.addEventListener('submit', validate);
function validate(e) {
// Error tracking variable
var error = false;
// Do validations
var emailPattern = /^(([^<>()\[\]\\.,;:\s#"]+(\.[^<>()\[\]\\.,;:\s#"]+)*)|(".+"))#((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
var formData = {
'firstName': null,
'lastName': null,
'email': null,
'stateInput': null
}
if ((firstNameInput.value == '') || (firstNameInput.value == null)) {
firstNameInput.classList.add('invalid-input');
firstNameInput.nextElementSibling.style.display = 'block';
firstNameInput.nextElementSibling.innerHTML = 'Not valid!';
error = true;
}
if ((lastNameInput.value == '') || (lastNameInput.value == null)) {
lastNameInput.classList.add('invalid-input');
lastNameInput.nextElementSibling.style.display = 'block';
lastNameInput.nextElementSibling.innerHTML = 'Not valid!';
error = true;
}
if (!emailPattern.test(emailInput.value)) {
emailInput.classList.add('invalid-input');
emailInput.nextElementSibling.style.display = 'block';
emailInput.nextElementSibling.innerHTML = 'Please enter valid email address!';
error = true;
}
if ((stateInput.value == 'selectstate')) {
stateInput.classList.add('invalid-input');
stateInput.nextElementSibling.style.display = 'block';
stateInput.nextElementSibling.innerHTML = 'Not valid!';
error = true;
}
// If error, stop the event
if (error) {
e.preventDefault();
e.stopPropagation();
console.log('There is no data from the form: ');
for (var prop in formData) {
console.log(prop + ' : ' + formData[prop]);
}
return false;
} else {
formData['firstName'] = firstNameInput.value;
formData['lastName'] = lastNameInput.value;
formData['email'] = emailInput.value;
formData['stateInput'] = stateInput.value;
console.log('There is now data from the form: :) ');
for (var prop in formData) {
console.log(prop + ' : ' + formData[prop]);
}
return true;
}
}
I tried this:
var result = theForm.addEventListener('submit', validate);
if (result) {
console.log(result);
}
Any help would be appreciated!
According to w3schools.com, this function, addEventListener() does not return anything.
https://www.w3schools.com/jsref/met_element_addeventlistener.asp
If you'd like to know if the event listener is installed properly, you need to check if the function exists:
if(theForm.addEventListener){
theForm.addEventListener('submit', validate);
}else{
theForm.attachEvent('onclick', validate);
}
I have a button and the button can have two labels - Activate and Deactivate. If I click on the button, then the button labels interchange, i.e. if I click on the button and the current text is Activate, then the text is switched to Deactivate and vice versa. I want to do two more things at a time on this button click -
I have a checkbox named IsMandatory. When I click on the button, if it changes from Activate to Deactivate, then the IsMandatory checkbox becomes disabled and vice versa.
Simultaneously, if the Ismandatory checkbox becomes disabled, it will be unchecked. If the checkbox becomes enabled, it becomes checked.
How can I achieve this???
So far I have done this:
<input type="hidden" id="stat" data-bind="value:IsActive" />
<input type="button" id="butt" onclick="change();" />
<input type="hidden" id="stat2" data-bind="value: IsMandatory" />
<input type="checkbox" id="chckbox" data-bind="checked: IsMandatory" />
<script type="text/javascript">
$(function () {
var stat = document.getElementById("stat").value;
var stat2 = document.getElementById("stat2").value;
//alert(stat);
if (stat == 1) {
document.getElementById("butt").value = "Activate";
document.getElementById("chckbox").disabled = false;
document.getElementById("chckbox").checked = true;
stat2 = 1;
}
else {
document.getElementById("butt").value = "Deactivate";
document.getElementById("chckbox").disabled = true;
document.getElementById("chckbox").checked = false;
stat2 = 0;
}
//if (stat2 == 1)
//{
// document.getElementById("chckbox").checked = false;
//}
//else
//{
// document.getElementById("chckbox").disabled = true;
//}
});
function activeStatus(IsActive) {
//alert(ActiveStatus);
if (IsActive == 1) {
//document.getElementById("chckbox").disabled = false;
return "Activate";
}
else {
//document.getElementById("chckbox").disabled = true;
return "Deactivate";
}
}
function change() {
var butt = document.getElementById("butt").value;
if (butt == 'Deactivate') {
document.getElementById("butt").value = "Activate";
document.getElementById("chckbox").disabled = false;
document.getElementById("chckbox").checked = true;
document.getElementById("stat").value = 1;
document.getElementById("stat2").value = 1;
}
else {
document.getElementById("butt").value = "Deactivate";
document.getElementById("chckbox").disabled = true;
document.getElementById("chckbox").checked = false;
document.getElementById("stat").value = 0;
document.getElementById("stat2").value = 0;
}
}
</script>
EDIT-1: Additional JavaScript Code:
var urlInputConfiguration = "/InputConfiguration";
var url = window.location.pathname;
var Id = url.substring(url.lastIndexOf('/') + 1);
$(function () {
$.ajaxSetup({
// Disable caching of AJAX responses
cache: false
});
var InputConfiguration = function (InputConfiguration) {
var self = this;
self.Id = ko.observable(InputConfiguration ? InputConfiguration.Id : 0).extend({ required: true });
self.SectionName = ko.observable(InputConfiguration ? InputConfiguration.SectionName : '');
self.SectionText = ko.observable(InputConfiguration ? InputConfiguration.SectionText : '');
self.IsActive = ko.observable(InputConfiguration ? InputConfiguration.IsActive : 1);
self.IsMandatory = ko.observable(InputConfiguration ? InputConfiguration.IsMandatory : 1);
};
var InputConfigurationCollection = function () {
var self = this;
//if ProfileId is 0, It means Create new Profile
if (Id == 0) {
self.InputConfiguration = ko.observable(new InputConfiguration());
}
else {
$.ajax({
url: urlInputConfiguration + '/GetInputConfigurationById/' + Id,
async: false,
dataType: 'json',
success: function (json) {
self.InputConfiguration = ko.observable(new InputConfiguration(json));
}
});
}
self.InputConfigurationErrors = ko.validation.group(self.InputConfiguration());
self.saveInputConfiguration = function () {
//self.Country = ko.observable(new Country());
var isValid = true;
if (self.InputConfigurationErrors().length != 0) {
self.InputConfigurationErrors.showAllMessages();
isValid = false;
}
// alert(JSON.stringify(ko.toJS(self.Country())));
if (isValid) {
//self.InputConfiguration().IsMandatory = document.getElementById("stat2").value;
self.InputConfiguration().IsActive = document.getElementById("stat").value;
var activevalue = self.InputConfiguration().IsActive;
if (activevalue == 1)
{
document.getElementById("chckbox").disabled = false;
//document.getElementById("chckbox").checked = true;
self.InputConfiguration().IsMandatory = document.getElementById("stat2").value;
}
else
{
document.getElementById("chckbox").disabled = true;
//document.getElementById("chckbox").checked = false;
self.InputConfiguration().IsMandatory = document.getElementById("stat2").value;
}
$.ajax({
type: (Id > 0 ? 'PUT' : 'POST'),
cache: false,
dataType: 'json',
url: urlInputConfiguration + (Id > 0 ? '/UpdateInputConfigurationInformation?id=' + Id : '/SaveInputConfigurationInformation'),
data: JSON.stringify(ko.toJS(self.InputConfiguration())),
contentType: 'application/json; charset=utf-8',
async: false,
success: function (data) {
alert("Case Input Configuration saved successfully.");
window.location.href = '/InputConfiguration';
},
error: function (err) {
var err = JSON.parse(err.responseText);
var errors = "";
for (var key in err) {
if (err.hasOwnProperty(key)) {
errors += key.replace("InputConfiguration.", "") + " : " + err[key];
}
}
$("<div></div>").html(errors).dialog({ modal: true, title: JSON.parse(err.responseText).Message, buttons: { "Ok": function () { $(this).dialog("close"); } } }).show();
},
complete: function () {
}
});
}
};
};
var InputConfigurationsViewModel = function () {
var self = this;
var url = "/InputConfiguration/GetAllInputConfiguration";
var refresh = function () {
$.getJSON(url, {}, function (data) {
self.InputConfigurations(data);
});
};
// Public data properties
self.InputConfigurations = ko.observableArray([]);
// Public operations
self.createInputConfiguration = function () {
window.location.href = '/InputConfiguration/InputConfigurationCreateEdit/0';
};
self.editInputConfiguration = function (inputConfiguration) {
//alert(country.CountryID);
window.location.href = '/InputConfiguration/InputConfigurationCreateEdit/' + inputConfiguration.Id;
};
self.removeInputConfiguration = function (inputConfiguration) {
// First remove from the server, then from the UI
if (confirm("Are you sure you want to delete this profile?")) {
var id = customerProfileConfiguration.Id;
$.ajax({ type: "DELETE", url: 'InputConfiguration/DeleteInputConfiguration/' + id })
.done(function () { self.CustomerProfileConfigurations.remove(inputConfiguration); });
}
}
refresh();
};
ko.applyBindings(new InputConfigurationsViewModel(), document.getElementById("inputconfigurationlist"));
ko.applyBindings(new InputConfigurationCollection(), document.getElementById("inputconfiguration_edit"));
});
var clone = (function () {
return function (obj) {
Clone.prototype = obj;
return new Clone()
};
function Clone() { }
}());
I can't bind the value of IsMandatory, although check/uncheck along with enable/disable is working fine when I click the button. Also, while my button text is Activate, IsActive value is bound as 1, and when my button text is Deactivate, IsActive value is bound as 0. When checkbox is checked, IsMandatory value should have been 1, when checkbox is unchecked, IsMAndatory value should have been 0.
Binding had to be used by force, I tried to use knockout but that's not actually helping.
So first of all, when I get the button value, without clicking it, by using document.getElementById and keeping it inside a variable stat, I had to make sure that if stat = 1, then another variable stat2 which has the value from the checkbox becomes 1 as well. Next, when stat2 = 1, checkbox will be checked. Similar thing was done in the else statement when stat = 0. So now stat2 = 0, and checkbox is unchecked.
if (stat == 1)
{
document.getElementById("butt").value = "Activate";
document.getElementById("chckbox").disabled = false;
stat2 = 1;
if (stat2 == 1) {
document.getElementById("chckbox").checked = true;
}
else {
document.getElementById("chckbox").disabled = false;
}
}
else
{
document.getElementById("butt").value = "Deactivate";
document.getElementById("chckbox").disabled = true;
stat2 = 0;
if (stat2 == 0) {
document.getElementById("chckbox").checked = false;
}
else {
document.getElementById("chckbox").disabled = true;
}
}
Next, the change is incorporated inside the function change(). That means when I click the button, then the change() function is called. Inside it, I had to make sure that if Deactivate becomes Activate, then document.getElementById("stat2").value becomes 1 and if 1, then checkbox should be checked. Reverse would happen if we change from Activate to Deactivate.
function change() {
var butt = document.getElementById("butt").value;
if (butt == 'Deactivate')
{
document.getElementById("butt").value = "Activate";
document.getElementById("chckbox").disabled = false;
document.getElementById("stat").value = 1;
document.getElementById("stat2").value = 1;
if ((document.getElementById("stat2").value) == 1)
{
document.getElementById("chckbox").checked = true;
}
else
{
document.getElementById("chckbox").checked = false;
}
}
else
{
document.getElementById("butt").value = "Deactivate";
document.getElementById("chckbox").disabled = true;
document.getElementById("chckbox").checked = false;
document.getElementById("stat").value = 0;
document.getElementById("stat2").value = 0;
if ((document.getElementById("stat2").value) == 0)
{
document.getElementById("chckbox").checked = false;
}
else
{
document.getElementById("chckbox").checked = true;
}
}
}
Finally, I'm force binding this value of the checkbox inside my IsMandatory property, which is inside my js file. IsMandatory property is the property that I declared in the view model for checkbox. IsActive is the property for button. Whenever IsActive is 1, then I enable the checkbox and then I take the value from my checkbox by using document.getElementById. If value of checkbox = 1, then IsMandatory becomes 1, else IsMandatory becomes 0.
self.InputConfiguration().IsActive = document.getElementById("stat").value;
self.InputConfiguration().IsMandatory = document.getElementById("stat2").value;
var activevalue = self.InputConfiguration().IsActive;
var check = self.InputConfiguration().IsMandatory;
if (activevalue == 1)
{
document.getElementById("chckbox").disabled = false;
//document.getElementById("chckbox").checked = true;
check = 1;
if (check == 1) {
self.InputConfiguration().IsMandatory = 1;
}
else
{
self.InputConfiguration().IsMandatory = 0;
}
}
else
{
document.getElementById("chckbox").disabled = true;
check = 0;
//document.getElementById("chckbox").checked = false;
if (check == 0) {
self.InputConfiguration().IsMandatory = 0;
}
else
{
self.InputConfiguration().IsMandatory = 1;
}
}
Ok, so backstory is we have a bunch of identical (in function) forms on a page to add variants to a product,
The form consists of three major parts.
The Attribute Editor
This component allows the user to add attributes to a product.
Each attribute has a visibility status, an attribute key, an attribute value and a delete button which together form one row.
The component also has an Add Attribute button, which when clicked adds a new row to the bottom of the list.
Each attribute key select list has a new attribute option, which upon selecting launches a modal dialog with a form to enter the new attribute name, this form then submits via AJAX and returns an ID, the new option is then appended to every attribute key select on the page to allow it to be selected.
When a key is selected in an instance of the component all other attribute key select's in the group get that option disabled to prevent duplicate attributes.
The attribute editor gets submitted as part of the main form below.
The Main Form
This component consists of the general description fields of the variant.
The form is submitted via AJAX and has the jQuery Validation Engine attached for form validation.
Because we are adding new input's dynamically with the attribute editor we must constantly detach, and re-attach the validation engine.
The Alert System
This component handles displaying/hiding the error/success/status messages on form by form basis.
The Issue
Now there are also a couple of forms that are very similar, but are slight variantions on a couple of the event handlers, so I wanted to create the code so I could replace bits and pieces of it at will without having to copy the entire code.
So after following the tips from this question I ended up with the code below, but I am getting the error: Uncaught TypeError: object is not a function which is on this line: var variantAlert = new VariantAlert(form); which I believe is because I am not returning anything, but I don't know what I should return to get the code to do what I want!
Short Version
$(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);
}
})();
Full Version
$(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);
});
}
})();
Yours variantAlert uses like
variantAlert.message('failed');
That means constructor must return object containing message function
var VariantAlert = function (form) {
var timer;
/*********************************
* 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);
});
}
return {
message: message
};
}
Finally got it to work using a different method, my code is below for anyone to compare and for reference.
$(function () {
/*********************************
* Loop over each variant and setup
* the attribute editor and form
*********************************/
var editors = [];
$("form.variant-form").each(function (i, form) {
var variantEditor = new VariantEditor(form);
editors.push(variantEditor);
variantEditor.attributeEditor.init();
variantEditor.form.init();
});
});
var VariantEditor = function (form) {
var that = this;
that.formElement = $(form);
/*********************************
* Sets up the attribute editor
*********************************/
that.attributeEditor = {
/*********************************
* Variables
*********************************/
template:null,
attribute:null,
modal:null,
manualHide:false,
triggerSelect:null,
oldOption:null,
/*********************************
* Sets up the attribute editor
*********************************/
init:function () {
var that = this;
//The Template row
that.template = $('.variant_demo_row', that.formElement);
//How many attributes are pre-loaded
that.attributes = $('.variant_select', that.formElement).length;
//Append the attribute editor modal to the body to avoid style corruption
that.modal = that.formElement.siblings('.newAttribute').appendTo('body');
//setup the handlers
//doing it this way allows us to overwrite the individual handlers with ease
that.addNewAttributeHandler();
that.removeAttributeHandler();
that.selectFocusHandler();
that.selectChangeHandler();
that.attributeVisibilityHandler();
that.modalFormSubmissionHandler();
that.modalShowHandler();
that.modalCancelClickHandler();
$('.variant_select', that.formElement).each(function (i, select) {
that.oldOption = null;
$(select).change();
});
},
/*********************************
* Add new attribute button handler
*********************************/
addNewAttributeHandler:function () {
var that = this;
$('.variant_attribute_add_new a', that.formElement).on('click keypress', function (e) {
//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 = that.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_' + that.attributes);
$('.variant_input', newRow).prop('name', 'attribute_value_' + that.attributes);
$('.variant_visible', newRow).prop('name', 'attribute_visible_' + that.attributes);
//insert the new attribute row at the bottom of the attributes
newRow.insertBefore($('.variant_attribute_add_new', that.formElement)).show('fast', function () {
$('select', newRow).focus();
});
//we have added new nodes so we need to reset the validationEngine
that.formElement.validationEngine('detach');
that.form.init();
that.attributes++;
});
},
/*********************************
* Remove attribute button handler
*********************************/
removeAttributeHandler:function () {
var that = this;
that.formElement.on('click keypress', '.removeAttribute', {}, function (e) {
//patched support for enter key
if (e.type === 'keypress' && e.which != 13) {
return true;
}
that.attributes--;
var val = $(this).siblings('select').val();
//re-enable whatever attribute key was in use
if (val != "") {
$('.variant_select option[value=' + val + ']', that.formElement).removeAttr('disabled');
}
//animate the removal of the attribute
$(this).closest('.controls-row').hide('fast', function () {
$(this).remove();
});
});
},
/*********************************
* Attribute key select focus handler
*********************************/
selectFocusHandler:function () {
var that = this;
that.formElement.on('focus', '.variant_select', {}, function () {
//store the old option so we know what option to
//re-enable if a change is made
that.oldOption = $('option:selected', this).val();
});
},
/*********************************
* Attribute key select change handler
*********************************/
selectChangeHandler:function () {
var that = this;
that.formElement.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 (that.oldOption !== null) {
$('.variant_select option[value=' + that.oldOption + ']', that.formElement).removeAttr('disabled');
}
if ($('option:selected', select).hasClass('newAttribute')) { //Add new attribute selected
that.triggerSelect = select;
that.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', that.formElement).not(select).children('option[value=' + select.val() + ']').prop('disabled', 'disabled');
}
that.oldOption = select.val();
});
},
/*********************************
* Toggle visibility button handler
*********************************/
attributeVisibilityHandler:function () {
var that = this;
that.formElement.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
*********************************/
modalFormSubmissionHandler:function () {
var that = this;
$('.newAttributeForm', that.modal).validationEngine('attach', {
onValidationComplete:function (form, status) {
if (status) {
var text = $('.newAttributeName', that.modal).val();
$('.newAttributeName', that.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
that.triggerSelect.val(data.id);
that.triggerSelect.trigger('change');
that.manualHide = true;
that.modal.modal('hide');
that.triggerSelect.siblings('input').focus();
form.spin(false);
},
dataType:'JSON'
});
}
}});
},
modalCancelClickHandler:function () {
var that = this;
$('.btn-danger', that.modal).on('click', function () {
if (!that.manualHide) {
that.triggerSelect[0].selectedIndex = 1;
that.triggerSelect.trigger('change');
}
that.manualHide = false;
});
},
modalShowHandler:function () {
var that = this;
that.modal.on('show shown', function () {
$('.newAttributeName', that.modal).focus();
});
}
};
/*********************************
* Sets up the variant main form
* The above function focuses on setting up the attribute editor
* This function sets up the rest of the form and handles the
* form submissions
*********************************/
that.form = {
init:function () {
var that = this;
that.nameChangeHandler();
that.submitHandler();
that.statusChangeHandler();
},
/*********************************
* Variant name change handler
* Changes the heading on the accordion if the
* name form input changes
*********************************/
nameChangeHandler:function () {
var that = this;
var accordion_heading = that.formElement.closest('.accordion-body').siblings('.accordion-heading').find('.accordion-toggle .name');
$('.name-input', that.formElement).on('change', function () {
accordion_heading.text($(this).val());
});
},
statusChangeHandler: function(){
var that = this;
console.log($('input[name=status]', that.formElement).parent());
$('input[name=status]', that.formElement).parent().on('click keypress', function(e){
//patched support for enter key
if (e.type === 'keypress' && e.which != 13) {
return true;
}
console.log('called');
var checked = $(this).prop('checked');
var label = that.formElement.closest('.accordion-body').siblings('.accordion-heading').find('.accordion-toggle .label');
label.text(checked ? 'Online' : 'Offline').toggleClass('label-important label-success');
});
},
/*********************************
* Form submit handler
*********************************/
submitHandler:function () {
var that = this;
that.formElement.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) {
that.message('failed');
} else {
switch (response.status) {
case 0:
that.message('errors', response.errors);
break;
case 1:
that.message('success');
break;
default:
that.message('failed');
break;
}
}
form.spin(false);
},
error:function () {
cfox.alert('alert-error', "An error was encountered when submitting this form. Please try again.");
form.spin(false);
cfox.enableForm(form);
}
});
}
}
});
}
};
/*********************************
* handles showing/hiding any messages
* in the variant forms
*********************************/
that.message = function (type, message) {
var that = this;
var alert;
clearTimeout(that.timer);
$('.variant_status_message', that.formElement).hide('fast');
if (type == 'success') {
alert = $('.variant_status_message.success', that.formElement);
} else if (type == 'errors') {
alert = $('.variant_status_message.errors', that.formElement);
$('.alert-message', alert).html(message);
} else if (type == 'failed') {
alert = $('.variant_status_message.failed', that.formElement);
}
alert.show('fast', function () {
$('html, body').animate({
scrollTop:alert.closest('.accordion-group').offset().top
}, 150, 'linear');
that.timer = setTimeout(function () {
alert.hide('fast')
}, 5000);
});
}
that.attributeEditor.formElement = that.formElement;
that.attributeEditor.form = that.form;
that.attributeEditor.message = that.message;
that.form.formElement = that.formElement;
that.form.attributeEditor = that.attributeEditor;
that.form.message = that.message;
that.message.formElement = that.formElement;
that.message.attributeEditor = that.attributeEditor;
that.message.form = that.form;
return that;
};
VariantEditor.prototype = {};