It's simple validation module. Now, i can't understand why my functions (validateEmail) can't call successful. I have no js errors, but browser do postback with my form thorought validation code
<script type="text/javascript">
var Validation;
(function (Validation) {
var FormValidator = (function () {
function FormValidator(formid) {
this.emailPattern = /^[a-zA-Z0-9._-]+#[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}$/;
this.formID = formid;
}
FormValidator.prototype.Validate = function () {
var errorsSum;
$('#' + this.formID).find('input[type="text"][validate], textarea[validate]').each(function (index, item) {
var validateType = $(item).attr('validate');
switch(validateType) {
case 'text':
case 'password': {
errorsSum += FormValidator.prototype.validateText(item);
break;
}
case 'email': {
errorsSum += FormValidator.prototype.validateEmail(item);
break;
}
}
});
return errorsSum == 0;
};
FormValidator.prototype.validateGeneric = function (element, validationFunc) {
var jqElement = $(element);
alert('tested element = ' + jqElement);
if(validationFunc(jqElement.val())) {
alert('tested element error = ' + jqElement.val());
element.removeClass('error');
return 0;
} else {
element.addClass('error');
}
alert('tested element success = ' + jqElement.val());
return 1;
};
FormValidator.prototype.validateEmail = function (element) {
return FormValidator.prototype.validateGeneric(element, function (elementValue) {
return FormValidator.prototype.emailPattern.test(elementValue);
});
};
FormValidator.prototype.validateText = function (element) {
return FormValidator.prototype.validateGeneric(element, function (elementValue) {
return elementValue != '';
});
};
return FormValidator;
})();
Validation.FormValidator = FormValidator;
})(Validation || (Validation = {}));
</script>
This is my form
#using (Html.BeginForm("Register", "Account", FormMethod.Post, new { #id = "register-form", #class = "form-horizontal"}))
{
...
#Html.TextBoxFor(m => m.Email, new { #placeholder = #L("Email"), #name = "email", #validate = "email" })
...
}
This is validation code
<script type="text/javascript">
$(function () {
$('#register-form').submit(function() {
return (new Validation.FormValidator('register-form').Validate());
});
});
</script>
I don't understand js so deep
You need to catch the submit event and prevent it from firing, validate the form, then submit if it was valid. Right now you are running the javascript as soon as it's submitted, but it just keeps submitting anyway since you don't stop the http request from being made.
On a related note, this is a huge mess. You don't need anything close to that much code just to validate emails and text presence on your form. This is all you need:
var validate = function(form){
var form_valid = true;
form.find('input[validate], textarea').each(function(index, el){
var type = el.attr('validate');
if (type == 'email') {
if (!el.match(/^[a-zA-Z0-9._-]+#[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}$/)) { form_valid = false; el.addClass('error'); }
}
if (type == 'text') {
if (!el.val() == '') { form_valid = false; el.addClass('error'); }
}
});
return form_valid
}
$('#register-form').on('submit', function(){
validate($(this)) && $(this).submit()
});
Hope this helps...
Edit: made the example a bit more modular
Related
I have certain form inputs that are only displayed depending on other input's value. I am trying to control when inputs fadeOut() and fadeIn() with, I think, a promise() but it seems the call-stack still runs everything synchronously - maybe I am not configuring the promise correctly?
Here is some pseudo code. The catch here is one of my inputs, input3 needs to be removed, then re-added to correct some JQuery validation and JQuery automcomplete rules, so I am trying to create the function to do that, every time that function is called to fadeIn().
function display_input1() {
return new Promise(function (resolve) {
resolve(hide_input3())
var new_element = `...`
$(new_element)
.hide()
.insertAfter(
$("#input0")
)
$("new_element").fadeIn("fast")
})
}
function hide_input1() {
$("#input1")
.fadeOut("fast", function () {
$("#input1").remove()
})
}
function display_input2(data) {
var new_element = `...`
$(new_element)
.hide()
.insertAfter(
$("#input0")
)
$("new_element").fadeIn("fast")
}
function hide_input2() {
$("#input2")
.fadeOut("fast", function () {
$("#input2").remove()
})
}
function display_input3(search_type) {
return new Promise(function (resolve) {
resolve(hide_input1(), hide_input3())
if (search_type == "some_varible") {
var new_element = `...`
} else if (search_type == "some_variable") {
var new_element - `...`
}
$(new_element)
.hide()
.insertAfter(
$("#input2")
)
$("new_element").fadeIn("fast")
})
}
function hide_input3() {
if ($("#input3").length) {
$("#input3")
.fadeOut("fast", function () {
$("#input3").remove()
})
}
}
$(document).on("change", "#input0", function (e) {
var option = $(this).find("option:selected")
var data = AJAX response
if (data["some_attr"]) {
display_input2(data)
hide_input1()
} else {
hide_input2()
if (data["some_attr"]) {
if (!$("#input1").length) {
display_input1()
}
} else {
hide_input1()
}
}
})
$(document).on("change", "input2", function (e) {
var option = this
if (option.value === "input1") {
display_input1()
} else if (["input2", "input3"].includes(option.value)) {
if (option.value === "input2") {
var search_type = "some_varible"
} else {
var search_type = "some_varibale"
}
display_input3(search_type)
}
})
$(document).on("click", "button.cancel", function (e) {
hide_input1()
hide_input2()
hide_input3()
$(form).validate().resetForm()
})
UPDATE
Based on comments, I've reflected my code block for better understanding. I've consolidated functions in hopes to make the code more malleable.
function display_form_input(input_type, search_type = null, data = null) {
if (input_type == "input_var1") {
var new_element = `...`
$(new_element)
.hide()
.insertAfter(
$("#input1")
)
$("#input1").fadeIn("fast")
} else if (input_type == "input_var2") {
var new_element = `...`
$(new_element)
.hide()
.insertAfter(
$("#input0")
)
$("#input2").fadeIn("fast")
} else if (input_type == "input_var3") {
if (search_type == "some_var1") {
var new_element = `...`
} else if (search_type == "some_var2") {
var new_element = `...`
}
$(new_element)
.hide()
.insertAfter(
$("#input3")
)
$("#input3").fadeIn("fast")
}
}
function hide_form_input(input_type) {
return new Promise(function (resolve) {
if (input_type == "input_var1") {
$("#input1")
.fadeOut("fast", function () {
$("#input1").remove()
resolve()
})
} else if (input_type == "input_var2") {
$("#input2")
.fadeOut("fast", function () {
$("#input2").remove()
resolve()
})
} else if (input_type == "input_var3") {
$("#input3")
.fadeOut("fast", function () {
$("#input3").remove()
resolve()
})
}
})
}
$(document).on("change", "#input0", function (e) {
var option = $(this).find("option:selected")
$.ajax({
...
success: function (data) {
if (data["key1"]) {
hide_form_input("input_var1")
display_form_input(
"input_var2",
null,
(data = data["key1"]),
)
} else {
hide_form_input("input_var2")
if (data["key2"] && !$("#input1").length) {
display_form_input("input_var1")
}
}
},
})
})
$(document).on("change", "#input2", function (e) {
var option = this
if (option.value === "value1") {
var search_form = hide_form_input("input_var3")
search_form
.promise()
.done(display_form_input("input_var1"))
} else if (["value2", "value3"].includes(option.value)) {
if (option.value === "value2") {
var search_type = "value22"
} else {
var search_type = "value33"
}
hide_form_input("input_var1")
var search_form = hide_form_input("input_var3")
search_form
.promise()
.done(display_form_input("input_var3", search_type))
}
})
$(document).on("click", "button.cancel", function (e) {
var items = ["input_var1", "input_var2", "input_var3"]
items.forEach(function (item) {
hide_form_input(item)
})
$(form).validate().resetForm()
})
You are creating a promise in display_input1, but where you are calling display_input1 you are not capturing the promise or ever resolving it. So your promise isn't doing anything
if (option.value === "input1") {
var p = display_input1();
//here you can call p.then(function(resolve, reject) { ... } or
var res = await p; (if you mark the function that await is in async)
Thanks to #Bergi and #ControlAltDel for walking me through understanding .promise(). I now have a working example I was trying to achieve! Thank you guys so much for your patience.
Here is my working example in pseudo code. I made some improvements too on a function based #Bergi comments (always strive for DRY code)
function display_form_input(input_type, search_type = null, data = null) {
/*
create_form_input: Display the form input for a given input_type.
Args:
input_type (str): The type of input to create.
Optional Args:
search_type (str): The type of results expected from this search.
Returns:
None
*/
if (input_type == "input_var1") {
var new_element = `...`
$(new_element)
.hide()
.insertAfter(
$("#input0").closest("div.row").children(),
)
$("#input1").parents(":eq(1)").fadeIn("fast")
} else if (input_type == "input_var2") {
var new_element = `...`
$(new_element)
.hide()
.insertAfter($("#input0").closest("div.row"))
$("#input2").parents(":eq(2)").fadeIn("fast")
} else if (input_type == "input_var3") {
if (search_type == "some_var1") {
var new_element = `...`
} else if (search_type == "some_var2") {
var new_element = `...`
}
$(new_element)
.hide()
.insertAfter($("#input2").closest("div.row").children())
$("#input3").parents(":eq(1)").fadeIn("fast")
}
}
function hide_form_input(input_type) {
/*
hide_form_input: Hide the form input for a given input_type.
Args:
input_type (str): The type of input to hide.
Returns:
JQuery Promise.
*/
if (input_type == "input_var1") {
var form_element = $("#input1").parents(":eq(1)")
} else if (input_type == "input_var2") {
var form_element = $("#input2").parents(":eq(2)")
} else if (input_type == "input_var3") {
var form_element = $("#input3").parents(":eq(1)")
}
return form_element
.fadeOut("fast")
.promise()
.then(function () {
form_element.remove()
})
}
$(document).on("change", "#input0", function (e) {
/*
Event Handler: Trigger what form field to display when a the input0
changes.
*/
var option = $(this).find("option:selected")
$.ajax({
...
success: function (data) {
if (data["key1"]) {
hide_form_input("input_var1").then(function () {
if (!$("#input2").length) {
display_form_input(
"input_var2",
null,
data["key1"],
)
}
})
} else {
hide_form_input("input_var2")
if (data["key2"] && !$("#input1").length) {
display_form_input("input_var1")
} else if (!data["key2"]) {
hide_form_input("input_var2")
}
}
},
})
})
$(document).on("change", "#input2", function (e) {
/*
Event Handler: Trigger what form field to display when a the input2
changes.
*/
var option = this
if (option.value === "value1") {
hide_form_input("input_var3").then(function () {
display_form_input("input_var1")
})
} else if (["value2", "value3"].includes(option.value)) {
if (option.value === "value2") {
var search_type = "some_var1"
} else {
var search_type = "some_var2"
}
hide_form_input("input_var1")
hide_form_input("input_var3").then(function () {
display_form_input("input_var3", search_type)
})
}
})
$(document).on("click", "button.cancel", function (e) {
/*
Event Handler: Make form back to default state.
*/
var button = this
var form = $($(button).closest("form"))
var items = ["input_var1", "input_var2", "input_var3"]
items.forEach(function (item) {
hide_form_input(item)
})
$(form).validate().resetForm()
})
I'm using the TomTom FuzzySearch/Autocomplete API, to allow users to search for an address on a form and then the address input fields will prepopulate (with the address values), when the user selects an address.
My API call works absolutely fine and the input fields display the correct values.
The problem I have, is the input fields remain untouched, despite the fields having a value. (If I type document.getElementById("house-number-textbox").value, a value is returned).
How can I turned the input fields to be touched, when the input values are applied?
I noticed, if I type something in the input field, after my input values have been added, only then does the form register my inputs as valid/touched.
PS - The reason I am injecting my scripts is because I'm using an AB Testing tool. So despite the form/application being AngularJS, I can only manipulate the form via the AB Testing tool, (on top of the compiled codebase - hence why I'm using vanilla JS).
Here's my code:
function waitForElement(className, callBack){
window.setTimeout(function(){
var element = document.getElementById(className);
if(element) {
callBack(className, element);
} else {
waitForElement(className, callBack);
}
},2000)
};
// LOAD API SCRIPTS
function loadScript(scriptUrl) {
const script = document.createElement('script');
script.src = scriptUrl;
document.body.appendChild(script);
return new Promise((res, rej) => {
script.onload = function() {
res();
}
script.onerror = function () {
rej();
}
});
};
// RESULTS MANAGER
function appendParentSelector(parentSelector, selector) {
return parentSelector ? parentSelector + ' ' + selector : selector;
}
function ResultsManager(resultsElementSelector) {
this.resultsElement = document.querySelector(appendParentSelector(resultsElementSelector, '.js-results'));
this.resultsPlaceholder =
document.querySelector(appendParentSelector(resultsElementSelector, '.js-results-placeholder'));
this.resultsLoader = document.querySelector(appendParentSelector(resultsElementSelector, '.js-results-loader'));
}
ResultsManager.prototype.loading = function() {
this.resultsLoader.removeAttribute('hidden');
this.resultsElement.setAttribute('hidden', 'hidden');
this.resultsPlaceholder.setAttribute('hidden', 'hidden');
this.resultsElement.innerHTML = '';
};
ResultsManager.prototype.success = function() {
this.resultsLoader.setAttribute('hidden', 'hidden');
this.resultsElement.removeAttribute('hidden');
};
ResultsManager.prototype.resultsNotFound = function() {
this.resultsElement.setAttribute('hidden', 'hidden');
this.resultsLoader.setAttribute('hidden', 'hidden');
this.resultsPlaceholder.removeAttribute('hidden');
};
ResultsManager.prototype.append = function(element) {
this.resultsElement.appendChild(element);
};
ResultsManager.prototype.clear = function() {
for (var i = 0; i < this.resultsElement.children.length; i++) {
this.resultsElement.removeChild(this.resultsElement.children[i]);
}
};
waitForElement("house-number-textbox",function(){
console.log("WAIT FOR ELEMENT DONE");
window.ResultsManager = window.ResultsManager || ResultsManager;
console.log("document.getElementById(component)", document.getElementById("house-number-textbox") );
// use
loadScript('https://api.tomtom.com/maps-sdk-for-web/cdn/plugins/SearchBox/2.24.2//SearchBox-web.js')
.then(() => {
console.log('Script loaded!');
})
.catch(() => {
console.error('Script loading failed! Handle this error');
});
// use
loadScript('https://api.tomtom.com/maps-sdk-for-web/cdn/5.x/5.64.0/services/services-web.min.js')
.then(() => {
console.log('Script loaded!');
// HANDLE RESULTS
tt.setProductInfo('ABTest', '1');
// Options for the fuzzySearch service
var searchOptions = {
key: 'XXX',
language: 'en-Gb',
limit: 10,
countrySet: "GB"
};
var searchBoxOptions = {
minNumberOfCharacters: 1,
searchOptions: searchOptions
// autocompleteOptions: autocompleteOptions
};
var ttSearchBox = new tt.plugins.SearchBox(tt.services, searchBoxOptions);
document.querySelector('.tt-side-panel__header').appendChild(ttSearchBox.getSearchBoxHTML());
let componentForm = {
// streetName: "house-number-textbox",
municipalitySubdivision: "street-name-textbox",
localName: "town-city-textbox",
extendedPostalCode: "postcode-textbox"
};
function SidePanel(selector) {
// this.map = map;
this.element = document.querySelector(selector);
}
new SidePanel('.tt-side-panel');
var resultsManager = new ResultsManager();
ttSearchBox.on('tomtom.searchbox.resultscleared', handleResultsCleared);
ttSearchBox.on('tomtom.searchbox.resultsfound', handleResultsFound);
ttSearchBox.on('tomtom.searchbox.resultfocused', handleResultSelection);
ttSearchBox.on('tomtom.searchbox.resultselected', handleResultSelection);
function handleResultsCleared() {
resultsManager.clear();
}
// HANDLE RESULST
function handleResultsFound(event) {
// Display fuzzySearch results if request was triggered by pressing enter
if (event.data.results && event.data.results.fuzzySearch && event.data.metadata.triggeredBy === 'submit') {
var results = event.data.results.fuzzySearch.results;
if (results.length === 0) {
handleNoResults();
}
resultsManager.success();
console.log("results", results);
}
if (event.data.errors) {
console("event.data.errors", event.data.errors);
}
}
// RESPONSE
function handleResultSelection(event) {
if (isFuzzySearchResult(event)) {
// Display selected result on the map
var result = event.data.result;
console.log("THIS result", result);
;
resultsManager.success();
for (const component in componentForm) {
console.log("componentForm", componentForm);
document.getElementById(componentForm[component]).value = result.address[component];
document.getElementById(componentForm[component]).disabled = false;
console.log('component', componentForm[component]);
if (document.getElementById(componentForm[component]).value === 'undefined') {
document.getElementById(componentForm[component]).value = "";
}
};
if (result.address.streetNumber) {
document.getElementById("house-number-textbox").value = result.address.streetNumber + " " + result.address.streetName;
} else {
document.getElementById("house-number-textbox").value = result.address.streetName;
};
};
}
function isFuzzySearchResult(event) {
return !('matches' in event.data.result);
}
function handleNoResults() {
resultsManager.clear();
resultsManager.resultsNotFound();
searchMarkersManager.clear();
infoHint.setMessage(
'No results for "' +
ttSearchBox.getValue() +
'" found nearby. Try changing the viewport.'
);
};
document.querySelector(".tt-search-box-input").setAttribute("placeholder", "Enter your address...");
})
.catch(() => {
console.error('Script loading failed! Handle this error');
});
});
I want to learn how to write Jquery plugin.This is my normal function and convert it into jquery plugin could you suggest me how to do this.
So that I can easily understand how to convert function to the plugin.
function probe_Validity(element) {
var validate = true;
$(".required-label").remove();
var warnings = {
text: "Please enter Name"
};
element.find(".required").each(function() {
var form_Data = $(this);
if (form_Data.prop("type").toLowerCase() === 'text' && form_Data.val() === '') {
form_Data.after('<div class="required-label">' + warnings.text + '</div>').addClass('required-active');
validate = false;
}
if (validate) {
return true;
} else {
return false;
}
$(function() {
$(".required").on("focus click", function() {
$(this).removeClass('required-active');
$(this).next().remove();
});
});
});
}
Take a look at this project jQuery plugin boilerplate
Consider this as a base plugin definition, look it up, follow the steps and adjust them to your needs.
It's quite easy to do you just use
jQuery.fn.theNameOfYourFunction = function() {}
then you can get the element the function is called on like this :
var element = $(this[0])
so with your function it would be :
jQuery.fn.probe_Validity = function() {
var element = $(this[0]);
var validate = true;
$(".required-label").remove();
var warnings = {
text: "Please enter Name"
};
element.find(".required").each(function() {
var form_Data = $(this);
if (form_Data.prop("type").toLowerCase() === 'text' && form_Data.val() === '') {
form_Data.after('<div class="required-label">' + warnings.text + '</div>').addClass('required-active');
validate = false;
}
if (validate) {
return true;
} else {
return false;
}
$(function() {
$(".required").on("focus click", function() {
$(this).removeClass('required-active');
$(this).next().remove();
});
});
});
};
this can be called like so :
$('#id').probe_Validity ()
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 got following jquery tags plugin.
I want to to restrict maxmimum 5 tags, so that user can not enter more than 5 words (separated by spaces).
Can someone please help me doing it?
Thanks.. Following is original plugin code:
(function($) {
var delimiter = new Array();
jQuery.fn.addTag = function(value,options) {
var options = jQuery.extend({focus:false},options);
this.each(function() {
id = $(this).attr('id');
var tagslist = $(this).val().split(delimiter[id]);
if (tagslist[0] == '') {
tagslist = new Array();
}
value = jQuery.trim(value);
if (value !='') {
$('<span class="tag">'+value + ' x</span>').insertBefore('#'+id+'_addTag');
tagslist.push(value);
$('#'+id+'_tag').val('');
if (options.focus) {
$('#'+id+'_tag').focus();
} else {
$('#'+id+'_tag').blur();
}
}
jQuery.fn.tagsInput.updateTagsField(this,tagslist);
});
return false;
};
jQuery.fn.removeTag = function(value) {
this.each(function() {
id = $(this).attr('id');
var old = $(this).val().split(delimiter[id]);
$('#'+id+'_tagsinput .tag').remove();
str = '';
for (i=0; i< old.length; i++) {
if (escape(old[i])!=value) {
str = str + delimiter[id] +old[i];
}
}
jQuery.fn.tagsInput.importTags(this,str);
});
return false;
};
jQuery.fn.tagsInput = function(options) {
var settings = jQuery.extend({defaultText:'add a tag',width:'300px',height:'100px','hide':true,'delimiter':',',autocomplete:{selectFirst:false}},options);
this.each(function() {
if (settings.hide) {
$(this).hide();
}
id = $(this).attr('id')
data = jQuery.extend({
pid:id,
real_input: '#'+id,
holder: '#'+id+'_tagsinput',
input_wrapper: '#'+id+'_addTag',
fake_input: '#'+id+'_tag',
},settings);
delimiter[id] = data.delimiter;
$('<div id="'+id+'_tagsinput" class="tagsinput"><div id="'+id+'_addTag"><input id="'+id+'_tag" value="" default="'+settings.defaultText+'" /></div><div class="tags_clear"></div></div>').insertAfter(this);
$(data.holder).css('width',settings.width);
$(data.holder).css('height',settings.height);
if ($(data.real_input).val()!='') {
jQuery.fn.tagsInput.importTags($(data.real_input),$(data.real_input).val());
} else {
$(data.fake_input).val($(data.fake_input).attr('default'));
$(data.fake_input).css('color','#666666');
}
$(data.holder).bind('click',data,function(event) {
$(event.data.fake_input).focus();
});
// if user types a comma, create a new tag
$(data.fake_input).bind('keypress',data,function(event) {
if (event.which==event.data.delimiter.charCodeAt(0) || event.which==13) {
$(event.data.real_input).addTag($(event.data.fake_input).val(),{focus:true});
return false;
}
});
$(data.fake_input).bind('focus',data,function(event) {
if ($(event.data.fake_input).val()==$(event.data.fake_input).attr('default')) {
$(event.data.fake_input).val('');
}
$(event.data.fake_input).css('color','#000000');
});
if (settings.autocomplete_url != undefined) {
$(data.fake_input).autocomplete(settings.autocomplete_url,settings.autocomplete).bind('result',data,function(event,data,formatted) {
if (data) {
d = data + "";
$(event.data.real_input).addTag(d,{focus:true});
}
});;
$(data.fake_input).bind('blur',data,function(event) {
if ($(event.data.fake_input).val() != $(event.data.fake_input).attr('default')) {
$(event.data.real_input).addTag($(event.data.fake_input).val(),{focus:false});
}
$(event.data.fake_input).val($(event.data.fake_input).attr('default'));
$(event.data.fake_input).css('color','#666666');
return false;
});
} else {
// if a user tabs out of the field, create a new tag
// this is only available if autocomplete is not used.
$(data.fake_input).bind('blur',data,function(event) {
var d = $(this).attr('default');
if ($(event.data.fake_input).val()!='' && $(event.data.fake_input).val()!=d) {
event.preventDefault();
$(event.data.real_input).addTag($(event.data.fake_input).val(),{focus:true});
} else {
$(event.data.fake_input).val($(event.data.fake_input).attr('default'));
$(event.data.fake_input).css('color','#666666');
}
return false;
});
}
$(data.fake_input).blur();
});
return this;
};
jQuery.fn.tagsInput.updateTagsField = function(obj,tagslist) {
id = $(obj).attr('id');
$(obj).val(tagslist.join(delimiter[id]));
};
jQuery.fn.tagsInput.importTags = function(obj,val) {
$(obj).val('');
id = $(obj).attr('id');
var tags = val.split(delimiter[id]);
for (i=0; i<tags.length; i++) {
$(obj).addTag(tags[i],{focus:false});
}
};
})(jQuery);
best way is to count the number of "tag" classes already added, and then you can handle it differently, for example you can prevent showing the "add a tag" input once 5 tags inserted by defining maxTags and updating jQuery.fn.addTag and jQuery.fn.removeTag :
/*
jQuery Tags Input Plugin 1.0
Copyright (c) 2010 XOXCO, Inc
Documentation for this plugin lives here:
http://xoxco.com/clickable/jquery-tags-input
Licensed under the MIT license:
http://www.opensource.org/licenses/mit-license.php
ben#xoxco.com
*/
(function($) {
var delimiter = new Array();
var maxTags = 5;
jQuery.fn.addTag = function(value,options) {
var options = jQuery.extend({focus:false},options);
this.each(function() {
id = $(this).attr('id');
var tagslist = $(this).val().split(delimiter[id]);
if (tagslist[0] == '') {
tagslist = new Array();
}
value = jQuery.trim(value);
if (value !='') {
$('<span class="tag">'+value + ' x</span>').insertBefore('#'+id+'_addTag');
tagslist.push(value);
$('#'+id+'_tag').val('');
if (options.focus) {
$('#'+id+'_tag').focus();
} else {
$('#'+id+'_tag').blur();
}
}
jQuery.fn.tagsInput.updateTagsField(this,tagslist);
});
if($(".tag").length>maxTags-1){$('#'+id+'_addTag').hide()}
return false;
};
jQuery.fn.removeTag = function(value) {
this.each(function() {
id = $(this).attr('id');
var old = $(this).val().split(delimiter[id]);
$('#'+id+'_tagsinput .tag').remove();
str = '';
for (i=0; i< old.length; i++) {
if (escape(old[i])!=value) {
str = str + delimiter[id] +old[i];
}
}
jQuery.fn.tagsInput.importTags(this,str);
});
if($(".tag").length<maxTags){$('#'+id+'_addTag').show()}
return false;
};
jQuery.fn.tagsInput = function(options) {
var settings = jQuery.extend({defaultText:'add a tag',width:'300px',height:'100px','hide':true,'delimiter':',',autocomplete:{selectFirst:false}},options);
this.each(function() {
if (settings.hide) {
$(this).hide();
}
id = $(this).attr('id')
data = jQuery.extend({
pid:id,
real_input: '#'+id,
holder: '#'+id+'_tagsinput',
input_wrapper: '#'+id+'_addTag',
fake_input: '#'+id+'_tag',
},settings);
delimiter[id] = data.delimiter;
$('<div id="'+id+'_tagsinput" class="tagsinput"><div id="'+id+'_addTag"><input id="'+id+'_tag" value="" default="'+settings.defaultText+'" /></div><div class="tags_clear"></div></div>').insertAfter(this);
$(data.holder).css('width',settings.width);
$(data.holder).css('height',settings.height);
if ($(data.real_input).val()!='') {
jQuery.fn.tagsInput.importTags($(data.real_input),$(data.real_input).val());
} else {
$(data.fake_input).val($(data.fake_input).attr('default'));
$(data.fake_input).css('color','#666666');
}
$(data.holder).bind('click',data,function(event) {
$(event.data.fake_input).focus();
});
// if user types a comma, create a new tag
$(data.fake_input).bind('keypress',data,function(event) {
if (event.which==event.data.delimiter.charCodeAt(0) || event.which==13) {
$(event.data.real_input).addTag($(event.data.fake_input).val(),{focus:true});
return false;
}
});
$(data.fake_input).bind('focus',data,function(event) {
if ($(event.data.fake_input).val()==$(event.data.fake_input).attr('default')) {
$(event.data.fake_input).val('');
}
$(event.data.fake_input).css('color','#000000');
});
if (settings.autocomplete_url != undefined) {
$(data.fake_input).autocomplete(settings.autocomplete_url,settings.autocomplete).bind('result',data,function(event,data,formatted) {
if (data) {
d = data + "";
$(event.data.real_input).addTag(d,{focus:true});
}
});;
$(data.fake_input).bind('blur',data,function(event) {
if ($(event.data.fake_input).val() != $(event.data.fake_input).attr('default')) {
$(event.data.real_input).addTag($(event.data.fake_input).val(),{focus:false});
}
$(event.data.fake_input).val($(event.data.fake_input).attr('default'));
$(event.data.fake_input).css('color','#666666');
return false;
});
} else {
// if a user tabs out of the field, create a new tag
// this is only available if autocomplete is not used.
$(data.fake_input).bind('blur',data,function(event) {
var d = $(this).attr('default');
if ($(event.data.fake_input).val()!='' && $(event.data.fake_input).val()!=d) {
event.preventDefault();
$(event.data.real_input).addTag($(event.data.fake_input).val(),{focus:true});
} else {
$(event.data.fake_input).val($(event.data.fake_input).attr('default'));
$(event.data.fake_input).css('color','#666666');
}
return false;
});
}
$(data.fake_input).blur();
});
return this;
};
jQuery.fn.tagsInput.updateTagsField = function(obj,tagslist) {
id = $(obj).attr('id');
$(obj).val(tagslist.join(delimiter[id]));
};
jQuery.fn.tagsInput.importTags = function(obj,val) {
$(obj).val('');
id = $(obj).attr('id');
var tags = val.split(delimiter[id]);
for (i=0; i<tags.length; i++) {
$(obj).addTag(tags[i],{focus:false});
}
};
})(jQuery);
How about adding something like this:
if($('.tag').length>=5){
$('#tags_tag').attr('disabled','true');
}
I put a little more flair into my demo.
Probably the easiest solution is to change line 89 of jquery.tagsinput.js from:
var skipTag = $(tagslist).tagExist(value);
to:
var skipTag = $(tagslist).length > 5 || $(tagslist).tagExist(value);