Skip to content

Instantly share code, notes, and snippets.

@kbuzyk
Created January 25, 2012 20:47
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save kbuzyk/1678621 to your computer and use it in GitHub Desktop.
Save kbuzyk/1678621 to your computer and use it in GitHub Desktop.
/**
*
*/
def([
], function () {
return Backbone.Model.extend({
/**
********* OBJECT PARAMETER'S VARIABLES *********
*/
/**
* common
*/
id: undefined,
formId: undefined,
type: undefined,
required: false,
errorMessage: "",
/**
* int
*/
minValue: undefined,
maxValue: undefined,
/**
* float & price
*/
decimalPlaces: 2,
integerPlaces: undefined,
/**
* email
*/
/**
* phone
*/
phoneMask: "(555)555-5555",
/**
* text
*/
minLength : undefined,
maxLength: undefined,
separate: false,
/**
* Word processor
*/
tinyMCE: undefined,
/**
* combobox
*/
defaultValue: undefined,
/**
* radio
*/
/**
* checkbox
*/
/**
* form
*/
items: [],
btn: {
submitId: undefined,
submitFunction: undefined
},
/**
********* UTILITY'S PARAMETERS *********
*/
/**
* List with validation's methods
*
* @return validation method according to exist type
*/
validations : function() {
return {
int : $.proxy(this.validateScope, this),
float : $.proxy(this.validateScope, this),
price : $.proxy(this.validateScope, this),
phone : $.proxy(this.validatePhoneNumber, this),
text : $.proxy(this.validateTextArea, this),
wordProcessor : $.proxy(this.validateTextArea, this),
date : $.proxy(this.validateDatePicker, this),
combobox : $.proxy(this.validateCombo, this)
}
},
/**
* List of validation tools (e.g. name of error class, etc.)
*/
validationTools : {
errorFieldClass: "errorFieldHighlight",
errorTextClass: "errorTextHighlight",
errorTextAreaClass: "errorTextAreaHighlight"
},
/**
* Render error message to UI
*
* @param model - model for validation
* @param error - text of error message
*/
showError : function (model, error) {
this.hideError();
if (this.type !== 'wordProcessor') {
$('#'+this.id).addClass(this.validationTools.errorFieldClass);
$('#'+this.id).parent().append
('<label for="'+this.id+'-warning">'+error+'</label>');
$("label[for='" + this.id + "-warning']").addClass
(this.validationTools.errorTextClass);
} else {
$('.tinymce').parent().addClass(this.validationTools.errorFieldClass);
$('.tinymce').parent().append
('<label for="'+this.type+'-warning">'+error+'</label>');
$("label[for='" + this.type + "-warning']").addClass
(this.validationTools.errorTextAreaClass);
}
},
/**
* Delete error message from UI
*/
hideError: function () {
if (this.type !== 'wordProcessor') {
$('#'+this.id).removeClass(this.validationTools.errorFieldClass);
$("label[for='" + this.id + "-warning']").remove();
} else {
$('.tinymce').parent().removeClass(this.validationTools.errorFieldClass);
$("label[for='" + this.type + "-warning']").remove();
}
},
/**
********* VALIDATION AND MASK LOGIC FOR FIELDS *********
*/
/**
* Validate logic for int field
*
* @param event - event object of current action
*/
validateInt: function (event) {
var value = $("#"+this.id).val(),
selectionStart = event.target.selectionStart,
selectionEnd = event.target.selectionEnd,
display,
position = (value.match(/^0/ig)) ? 1 : 0;
value = parseInt(value, 10);
display = _.isNaN(value) ? '' : value;
$("#"+this.id).val(display);
event.target.selectionStart = selectionStart - position;
event.target.selectionEnd = selectionEnd - position;
this.bind("error", $.proxy(this.showError, this));
this.validate = this.validations()[this.type];
this.hideError();
this.set({
minValue: this.minValue,
maxValue: this.maxValue,
currentValue: value,
required: this.required,
errorMessage: this.errorMessage
});
},
/**
* Validate logic when finishing work with current int field
*
* @param event - event object of current action
*/
finishInt: function (event) {
var value = $("#"+this.id).val();
this.bind("error", $.proxy(this.showError, this));
this.validate = this.validations()[this.type];
this.hideError();
this.set({
minValue: this.minValue,
maxValue: this.maxValue,
currentValue: parseFloat(value),
required: this.required,
errorMessage: this.errorMessage
});
},
/**
* Permit to type only allowed characters (numbers)
* @param event - event object of current action
*/
maskTypeInt : function (event) {
if ( !(event.charCode >= 48 && event.charCode <= 57 ||
event.charCode === 0) ) {
event.preventDefault();
}
},
/**
* Permit to paste only allowed characters (numbers)
* @param event - event object of current action
*/
maskPasteInt : function (event) {
var context = this;
setTimeout(function() {
var value = $("#"+context.id).val();
value = value.replace(/[^0-9]/ig, '');
value = parseInt(value, 10);
$("#"+context.id).val(value);
$("#"+context.id).blur();
$("#"+context.id).focus();
}, 0);
},
/**
*
* Validate logic for float field
*
* @param event - event object of current action
*/
validateFloat : function (event) {
var value = $("#"+this.id).val().replace(/,/, '.'),
selectionStart = event.target.selectionStart,
selectionEnd = event.target.selectionEnd,
display,
fraction = [];
if (value.match(/^0(.+)\./ig)) {
selectionStart--;
selectionEnd--;
}
value = value.split('.');
value = (value.length !== 1) ? value[0]+'.'+value[1].slice
(0, this.decimalPlaces) : value[0];
if (value.match(/^\./)) {
value = value.replace(/^\./, "0.");
selectionStart++;
selectionEnd++;
}
if (value.match(/\.$/) ) { //&& event.type !== "change") {
value = parseFloat(value)+".";
} else if (value.match(/\.(.*)0$/)) {
fraction = value.split('.');
value = parseFloat(fraction[0]) + '.' + fraction[1];
} else {
value = parseFloat(value);
}
display = _.isNaN(value) ? '' : value;
$("#"+this.id).val(display);
event.target.selectionStart = selectionStart;
event.target.selectionEnd = selectionEnd;
this.bind("error", $.proxy(this.showError, this));
this.validate = this.validations()[this.type];
this.hideError();
this.set({
minValue: this.minValue,
maxValue: this.maxValue,
currentValue: parseFloat(value),
required: this.required,
errorMessage: this.errorMessage
});
},
/**
* Validate logic when finishing work with current float field
*
* @param event - event object of current action
*/
finishFloat : function (event) {
var value = $("#"+this.id).val();
if (value !== "") {
value = value.split(".");
value = (value.length > 1 && value[1] !== "") ?
parseFloat(value[0]) + "." + value[1] : parseFloat(value[0]);
$("#"+this.id).val(value);
}
this.bind("error", $.proxy(this.showError, this));
this.validate = this.validations()[this.type];
this.hideError();
this.set({
minValue: this.minValue,
maxValue: this.maxValue,
currentValue: parseFloat(value),
required: this.required,
errorMessage: this.errorMessage
});
},
/**
* Permit to type only allowed characters (numbers and dot)
* @param event - event object of current action
*/
maskTypeFloat : function (event) {
var value = $("#"+this.id).val(),
dots = value.search(/\./ig),
commas = value.search(/,/ig);
if ( !( event.charCode >= 48 && event.charCode <= 57 ||
(event.charCode === 46 && dots === -1) ||
(event.charCode === 44 && dots === -1 && commas === -1) ||
event.charCode === 0) ) {
event.preventDefault();
}
},
/**
* Permit to paste only allowed characters (numbers and dots)
* @param event - event object of current action
*/
maskPasteFloat : function (event) {
var context = this;
setTimeout(function() {
var value = $("#"+context.id).val(),
fraction = '';
value = value.replace(/[^0-9\.,]/ig, '');
value = value.replace(/,/ig, '.');
value = value.split('.');
value.forEach(function(element, key){
if ( key > 0) {
fraction += element;
} else {
fraction = element + '.';
}
});
value = fraction.split('.');
value = (value.length !== 1) ? value[0]+'.'+value[1].slice
(0, this.decimalPlaces) : value[0];
if (value.match(/\.(.*)0$/)) {
fraction = value.split('.');
value = parseFloat(fraction[0]) + '.' + fraction[1];
} else {
value = parseFloat(value);
}
$("#"+context.id).val(value);
$("#"+context.id).blur();
$("#"+context.id).focus();
}, 0);
},
/**
* Validate logic for price field
*
* @param event - event object of current action
*/
validatePrice : function(event) {
var value = $("#"+this.id).val(),
commasBefore = (value.match(/,/ig)) ?
value.match(/,/ig).length : 0,
selectionStart = event.target.selectionStart,
selectionEnd = event.target.selectionEnd,
display,
fraction,
comma;
value = value.replace(/,/ig,'');
if (value.match(/^0(.+)\./ig)) {
selectionStart--;
selectionEnd--;
}
value = value.split('.');
if (this.integerPlaces) {
value[0] = value[0].slice(0, this.integerPlaces);
}
value = (value.length !== 1) ? value[0] +
'.'+value[1].slice(0, this.decimalPlaces) : value[0];
if (value.match(/^\./)) {
value = value.replace(/^\./, "0.");
selectionStart++;
selectionEnd++;
}
if (value.match(/\.$/)) { // && event.type !== "change") {
value = parseFloat(value)+".";
} else if (value.match(/\.(.*)0$/)) {
fraction = value.split('.');
value = parseFloat(fraction[0]) + '.' + fraction[1];
} else {
value = parseFloat(value);
}
value = value.toString().split('.');
fraction = "";
value[0] = value[0].split("").reverse().join("");
for (i = value[0].length-1; i >= 0; i--) {
comma = (i%3 === 0 && i !== 0) ? ',' : '';
fraction += value[0][i] + comma;
if (comma === ',' && selectionEnd ===
$("#"+this.id).val().length) {
selectionStart++;
selectionEnd++;
}
}
value = (value.length !== 1) ? fraction + '.' + value[1] : fraction;
display = (_.isNaN(value) || value === "NaN") ? '' : value;
$("#"+this.id).val(display);
var commasNow = (display.toString().match(/,/ig)) ?
display.toString().match(/,/ig).length : 0;
event.target.selectionStart = selectionStart +
(commasNow - commasBefore);
event.target.selectionEnd = selectionEnd +
(commasNow - commasBefore);
this.bind("error", $.proxy(this.showError, this));
this.validate = this.validations()[this.type];
this.hideError();
this.set({
minValue: this.minValue,
maxValue: this.maxValue,
currentValue: parseFloat(value.toString().replace(/,/ig, '')),
required: this.required,
errorMessage: this.errorMessage
});
},
/**
* Validate logic when finishing work with current price field
*
* @param event - event object of current action
*/
finishPrice: function(event) {
var value = $("#"+this.id).val();
if (value !== "") {
value = value.split('.')
value[1] = (value.length > 1) ? value[1] : '';
for (var i = value[1].length; i <= this.decimalPlaces - 1; i++) {
value[1] +='0';
}
value = value[0] + '.' + value[1];
$("#"+this.id).val(value);
}
this.bind("error", $.proxy(this.showError, this));
this.validate = this.validations()[this.type];
this.hideError();
this.set({
minValue: this.minValue,
maxValue: this.maxValue,
currentValue: parseFloat(value.toString().replace(/,/ig, '')),
required: this.required,
errorMessage: this.errorMessage
});
},
/**
* Permit to type only allowed characters (numbers and dot)
* @param event - event object of current action
*/
maskTypePrice : function(event) {
var value = $("#"+this.id).val(),
dots = value.search(/\./ig);
if ( !( event.charCode >= 48 && event.charCode <= 57 ||
(event.charCode === 46 && dots === -1) ||
event.charCode === 0) ) {
event.preventDefault();
}
},
/**
* Permit to paste only allowed characters (numbers and dot)
* @param event - event object of current action
*/
maskPastePrice : function(event) {
var context = this;
setTimeout(function() {
var value = $("#"+context.id).val(),
fraction = '',
i,
comma,
value = value.replace(/[^0-9\.]/ig, '');
value = value.split('.');
value.forEach(function(element, key){
if ( key > 0) {
fraction += element;
} else {
fraction = element + '.';
}
});
value = fraction.split('.');
if (context.integerPlaces) {
value[0] = value[0].slice(0, context.integerPlaces);
}
value = (value.length !== 1) ? value[0] +
'.'+value[1].slice(0, context.decimalPlaces) : value[0];
if (value.match(/\.(.*)0$/)) {
fraction = value.split('.');
value = parseFloat(fraction[0]) + '.' + fraction[1];
} else {
value = parseFloat(value);
}
value = value.toString().split('.');
fraction = "";
value[0] = value[0].split("").reverse().join("");
for (i = value[0].length-1; i >= 0; i--) {
comma = (i%3 === 0 && i !== 0) ? ',' : '';
fraction += value[0][i] + comma;
}
value = (value.length !== 1) ?
fraction + '.' + value[1] : fraction;
$("#"+context.id).val(value);
$("#"+context.id).blur();
$("#"+context.id).focus();
}, 0);
},
/**
* Validate logic for phone field
*
* @param event - event object of action
*/
validatePhone: function(event) {
var originalValue = $("#"+this.id).val(),
value = $("#"+this.id).val().replace(/[^0-9]/ig, ''),
mask = this.phoneMask.replace(/[^0-9]/ig, ''),
selectionStart = event.target.selectionStart,
selectionEnd = event.target.selectionEnd,
masked = "",
count = 0,
i = 0;
if ( (event.charCode >= 48 && event.charCode <= 57)) {
value = (value.length <= mask.length) ?
value : value.slice(0, mask.length);
for (i = 0; i < value.length; i++) {
if (!this.phoneMask[i+count].match(/\d/ig)) {
masked += this.phoneMask[i+count] + value[i];
if (originalValue.length === selectionStart) {
selectionStart++;
selectionEnd++;
} else if (selectionStart === i+count+1) {
selectionStart++;
selectionEnd++;
}
count++;
} else {
masked += value[i];
}
}
$("#"+this.id).val(masked);
event.target.selectionStart = selectionStart;
event.target.selectionEnd = selectionEnd;
}
this.bind("error", $.proxy(this.showError, this));
this.validate = this.validations()[this.type];
this.hideError();
this.set({
currentValue: value,
required: this.required,
errorMessage: this.errorMessage,
mask: mask,
phoneMask: this.phoneMask
});
},
/**
* Validate logic when finishing work with current phone field
*
* @param event - event object of current action
*/
finishPhone: function(event) {
var value = $("#"+this.id).val().replace(/[^0-9]/ig, ''),
mask = this.phoneMask.replace(/[^0-9]/ig, '');
this.bind("error", $.proxy(this.showError, this));
this.validate = this.validations()[this.type];
this.hideError();
this.set({
currentValue: value,
required: this.required,
errorMessage: this.errorMessage,
mask: mask,
phoneMask: this.phoneMask
});
},
/**
* Permit to type only allowed characters (numbers)
* @param event - event object of current action
*/
maskTypePhone : function(event) {
if ( !(event.charCode >= 48 && event.charCode <= 57 ||
event.charCode === 0)) {
event.preventDefault();
}
},
/**
* Permit to paste only allowed characters (numbers)
* @param event - event object of current action
*/
maskPastePhone : function(event) {
var context = this;
setTimeout(function() {
var value = $("#"+context.id).val().replace(/[^0-9]/ig, ''),
mask = context.phoneMask.replace(/[^0-9]/ig, ''),
masked = "",
count = 0,
i = 0;
value = (value.length <= mask.length) ?
value : value.slice(0, mask.length);
for (i = 0; i < value.length; i++) {
if (!context.phoneMask[i+count].match(/\d/ig)) {
masked += context.phoneMask[i+count] + value[i];
count++;
} else {
masked += value[i];
}
}
$("#"+context.id).val(masked);
$("#"+context.id).blur();
$("#"+context.id).focus();
}, 0);
},
/**
* Validate logic for text field
*
* @param event - event object of action
*/
validateText: function(event) {
var value = $("#"+this.id).val(),
selectionStart = event.target.selectionStart,
selectionEnd = event.target.selectionEnd;
if (this.maxLength && this.separate) {
value = value.slice(0, this.maxLength);
$("#"+this.id).val(value);
event.target.selectionStart = selectionStart,
event.target.selectionEnd = selectionEnd;
}
this.bind("error", $.proxy(this.showError, this));
this.validate = this.validations()[this.type];
this.hideError();
this.set({
currentValue: value,
required: this.required,
errorMessage: this.errorMessage,
minLength: this.minLength,
maxLength: this.maxLength
});
},
/**
* Validate logic when finishing work with current text field
*
* @param event - event object of current action
*/
finishText: function(event) {
this.validateText(event);
},
/**
* Permit to type only allowed characters
* @param event - event object of current action
*/
maskTypeText: function(event) {
this.validateText(event);
},
/**
* Permit to paste only allowed characters
* @param event - event object of current action
*/
maskPasteText: function(event) {
var context = this;
setTimeout(function() {
context.validateText(event);
}, 0);
},
validateDate: function(event) {
var value = $("#"+this.id).val();
this.bind("error", $.proxy(this.showError, this));
this.validate = this.validations()[this.type];
this.hideError();
this.set({
currentValue: value,
required: this.required,
errorMessage: this.errorMessage
});
},
/**
* Validate logic when finishing work with current date field
*
* @param event - event object of current action
*/
finishDate: function(event) {
this.validateDate(event);
},
/**
* Not permit to type
* @param event - event object of current action
*/
maskTypeDate: function(event) {
event.preventDefault();
},
/**
* Not permit to paste
* @param event - event object of current action
*/
maskPasteDate: function(event) {
event.preventDefault();
},
validateWordProcessor: function(event) {
this.bind("error", $.proxy(this.showError, this));
this.validate = this.validations()[this.type];
this.hideError();
this.set({
currentValue: this.tinyMCE.activeEditor.getContent(),
required: this.required,
errorMessage: this.errorMessage,
minLength: this.minLength,
maxLength: this.maxLength
});
},
finishWordProcessor: function(event) {
this.validateWordProcessor(event)
},
maskTypeWordProcessor: function(event) {
},
maskPasteWordProcessor: function(event) {
},
validateCombobox: function (event) {
var value = $("#"+this.id).find('option:selected').text();
this.bind("error", $.proxy(this.showError, this));
this.validate = this.validations()[this.type];
this.hideError();
this.set({
currentValue: value,
defaultValue: this.defaultValue,
required: this.required,
errorMessage: this.errorMessage
});
},
/**
* Check all the form before submit
* @param event - event object of current action
*/
validateForm: function(event) {
var errors = 0;
_.each(this.items, function(item) {
if (item.type === 'wordProcessor') {
item.tinyMCE.activeEditor.focus();
item.tinyMCE.activeEditor.addShortcut('esc');
} else {
if (item.type !== 'date') {
$("#"+item.id).focus();
$("#"+item.id).blur();
}
}
}, this);
_.each(this.items, function(item){
if ($("#"+item.id).hasClass(this.validationTools.errorFieldClass)) {
errors ++;
} else if (item.type === 'wordProcessor') {
if (item.tinyMCE.activeEditor.contentAreaContainer.parentNode.parentNode.parentNode.parentNode.parentNode.classList.length > 1) {
errors ++;
}
}
},this);
if (errors === 0) {
$("#"+this.btn.submitId).attr("disabled", "disabled");
this.btn.submitFunction();
$("#"+this.btn.submitId).removeAttr("disabled");
}
},
/**
********* BINDING LISTENERS TO FIELDS FOR MASKING AND VALIDATION *********
*/
/**
* Add listeners for int field
*/
int : function() {
$("#"+this.id).live("keypress", $.proxy(this.maskTypeInt, this));
$("#"+this.id).live("paste", $.proxy(this.maskPasteInt, this));
$("#"+this.id).live("keyup", $.proxy(this.validateInt, this));
$("#"+this.id).live("blur", $.proxy(this.finishInt, this));
},
/**
* Add listeners for float field
*/
float : function() {
$("#"+this.id).live("keypress", $.proxy(this.maskTypeFloat, this));
$("#"+this.id).live("paste", $.proxy(this.maskPasteFloat, this));
$("#"+this.id).live("keyup", $.proxy(this.validateFloat, this));
$("#"+this.id).live("blur", $.proxy(this.finishFloat, this));
},
/**
* Add listeners for price field
*/
price : function() {
$("#"+this.id).live("keypress", $.proxy(this.maskTypePrice, this));
$("#"+this.id).live("paste", $.proxy(this.maskPastePrice, this));
$("#"+this.id).live("keyup", $.proxy(this.validatePrice, this));
$("#"+this.id).live("blur", $.proxy(this.finishPrice, this));
},
/**
* Add listeners for phone field
*/
phone : function() {
$("#"+this.id).live("keypress", $.proxy(this.maskTypePhone, this));
$("#"+this.id).live("paste", $.proxy(this.maskPastePhone, this));
$("#"+this.id).live("keyup", $.proxy(this.validatePhone, this));
$("#"+this.id).live("blur", $.proxy(this.finishPhone, this));
},
/**
* Add listeners for date field
*/
date: function() {
$("#"+this.id).live("keydown", $.proxy(this.maskTypeDate, this));
$("#"+this.id).live("paste", $.proxy(this.maskPasteDate, this));
$("#"+this.id).live("keyup", $.proxy(this.validateDate, this));
$("#"+this.id).live("blur", $.proxy(this.finishDate, this));
},
/**
* Add listeners for text field
*/
text : function() {
//$("#"+this.id).live("keypress", $.proxy(this.maskTypeText, this));
$("#"+this.id).live("paste", $.proxy(this.maskPasteText, this));
$("#"+this.id).live("keyup", $.proxy(this.validateText, this));
$("#"+this.id).live("blur", $.proxy(this.finishText, this));
},
wordProcessor : function() {
/*
$("#"+this.id).live("keypress", $.proxy(this.maskTypeWordProcessor, this));
$("#"+this.id).live("paste", $.proxy(this.maskPasteWordProcessor, this));
*/
var context = this;
setTimeout(function() {
var frame = (context.tinyMCE.getInstanceById(context.tinyMCE.activeEditor.id).getWin()) ? context.tinyMCE.getInstanceById(context.tinyMCE.activeEditor.id).getWin() : context.tinyMCE.getInstanceById(context.tinyMCE.activeEditor.id).getDoc();
context.tinyMCE.activeEditor.onKeyUp.add($.proxy(context.validateWordProcessor, context));
context.tinyMCE.dom.Event.add(frame, 'blur', $.proxy(context.finishWordProcessor, context));
}, 500);
//this.tinyMCE.activeEditor.onKeyPress.add(this.validateWordProcessor)
//$("#"+this.id).live("keyup", $.proxy(this.validateWordProcessor, this));
//$("#"+this.id).live("blur", $.proxy(this.finishWordProcessor, this));
},
/**
* Add listeners for combobox
*/
combobox : function() {
$("#"+this.id).live("blur", $.proxy(this.validateCombobox, this));
$("#"+this.id).live("change", $.proxy(this.validateCombobox, this));
},
/**
* Add listeners for radio button
*/
radio : function() {
// TODO: implement it when needed (use exist template)
},
/**
* Add listeners for checkbox
*/
checkbox : function() {
// TODO: implement it when needed (use exist template)
},
/**
* Add listeners for whole form
*/
form : function () {
$("#"+this.btn.submitId).live("click", $.proxy(this.validateForm, this));
},
/**
*
********* VALIDATIONS FOR DIFFERENT TYPES *********
*
*/
/**
* Abstract method for Backbone Model's validation
* @param attrs - list of parameters for validation
*/
validate: function(attrs) {
},
/**
* Check that current number is on valid scope
*
* @param attrs - list of parameters for validation
* @return error message
*/
validateScope: function(attrs) {
var emptyMessage = "This field is required.",
minMessage = "Value should be more than "+ attrs.minValue,
maxMessage = "Value should be less than "+ attrs.maxValue,
scopeMessage = "Value should be "+ attrs.minValue+
" to "+attrs.maxValue;
if (_.isNaN(attrs.currentValue) && attrs.required) {
return (attrs.errorMessage !== "") ?
attrs.errorMessage : emptyMessage;
} else if (!_.isNaN(attrs.currentValue) && attrs.required) {
if (attrs.maxValue && attrs.minValue &&
(attrs.currentValue > attrs.maxValue ||
attrs.currentValue < attrs.minValue)) {
return (attrs.errorMessage !== "") ?
attrs.errorMessage : scopeMessage;
} else if (attrs.maxValue &&
attrs.currentValue > attrs.maxValue) {
return (attrs.errorMessage !== "") ?
attrs.errorMessage : maxMessage;
} else if (attrs.minValue &&
attrs.currentValue < attrs.minValue) {
return (attrs.errorMessage !== "") ?
attrs.errorMessage : minMessage;
}
}
},
/**
* Checks that current phone number is valid according to mask
*
* @param attrs - list of parameters for validation
* @return error message
*/
validatePhoneNumber: function(attrs) {
var emptyMessage = "Please enter valid phone number " +
"(e.g. " + attrs.phoneMask + " )";
if (attrs.currentValue.length !==
attrs.mask.length && attrs.required) {
return (attrs.errorMessage !== "") ?
attrs.errorMessage : emptyMessage;
}
},
/**
* Checks that current text is valid according to mask
*
* @param attrs - list of parameters for validation
* @return error message
*/
validateTextArea: function (attrs) {
var emptyMessage = "This field is required.",
minMessage = "Length of the text should be at least "
+ attrs.minLength + " character.",
maxMessage = "Length of the text should be less than "
+ attrs.maxLength + " characters.",
scopeMessage = "Length of the text should be "
+ attrs.minLength+ " to "+attrs.maxLength + " characters.",
filteredValue = attrs.currentValue.replace(/<\/?[^>]+>/g, '');
filteredValue = filteredValue.replace(/[^A-Za-z0-9]|nbsp| /ig, '');
if (attrs.currentValue === "" && attrs.required) {
return (attrs.errorMessage !== "") ?
attrs.errorMessage : emptyMessage;
} else if (attrs.currentValue !== "" && attrs.required) {
if (attrs.maxLength && attrs.minLength &&
(attrs.currentValue.length > attrs.maxLength ||
filteredValue.length < attrs.minLength)) {
return (attrs.errorMessage !== "") ?
attrs.errorMessage : scopeMessage;
} else if (attrs.maxLength &&
attrs.currentValue.length > attrs.maxLength) {
return (attrs.errorMessage !== "") ?
attrs.errorMessage : maxMessage;
} else if (attrs.minLength &&
filteredValue.length < attrs.minLength) {
return (attrs.errorMessage !== "") ?
attrs.errorMessage : minMessage;
}
}
},
/**
* Checks that current email is valid
*
* @param attrs - list of parameters for validation
* @return error message
*/
validateEmailAddress: function(attrs) {
// TODO: implement it when needed
},
validateCombo: function(attrs) {
var emptyMessage = "This field is required.";
if (attrs.required && attrs.defaultValue === attrs.currentValue) {
return (attrs.errorMessage !== "") ?
attrs.errorMessage : emptyMessage;
}
},
/**
* Checks that current date is valid
*
* @param attrs - list of parameters for validation
* @return error message
*/
validateDatePicker: function(attrs) {
var emptyMessage = "This field is required.";
if (attrs.currentValue === "" && attrs.required) {
return (attrs.errorMessage !== "") ?
attrs.errorMessage : emptyMessage;
}
},
/**
********* CONSTRUCTOR *********
*/
/**
* Main method
*
* @param params - list of params for validation
*/
initialize : function (params) {
_.each(params, function(param, key){
this[key] = param;
}, this);
if (this.type && this.id || (this.type === 'form') || (this.type === 'wordProcessor')) {
this[this.type]();
} else {
throw "Parameters id and type are required for validation. " +
"Please check you did not miss them.";
}
}
});
});
@vkovalskiy
Copy link

У вас модель рендерит html (при выводе данных об ошибке). Следуя концепции MVC и Backbone модель ничего не должна знать про отображение. IMHO, надо выносить в обработчик события change модели на view.

Другой вариант - для каждого варианта поля ввода создать свой view и модель. Затем использовать готовые relational frameworks для моделей, которые позволяют работать с их вложенностью.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment