Why jquery validation is not working on appended elements? - javascript

I have a form and I want to add new elements as you can see in this fiddle I used append $('#cvfields').append(campos); to add this elements but the jquery validation plugin started to giving me problems. I found this in some answers related whith this question
$('#titulo_'+campo).rules('add', {'required': true});
$('#tipo_'+campo).rules('add', {'required': true});
But when I added .rules code I received this error
Uncaught TypeError: Cannot read property 'form' of undefined
$.extend.rules
(anonymous function)
x.event.dispatch
v.handle
Hope you can help!

You have some issues with your code:
1) When you use the .rules('add') method on a selector of multiple elements, you must nest it inside a jQuery .each() or it won't be applied to all the matching elements.
$('.newinput').each(function() {
$(this).rules('add', {
'required': true
});
});
However, you can probably skip .rules() entirely. See item #2 below.
2) You can totally forget about item #1 above since you're only trying to make these new fields required. Simply add a required="required" attribute (which I see you've already done) when you create them and you will not need to worry about the .rules('add') method at all. Alternatively, you could use class="required" instead, which is the method I chose for the demo below.
3) This is why nothing was working: Your newly added elements must also contain unique names. It's a requirement of the plugin that all form inputs need a name atribute. It's how the plugin keeps track of the elements, so they all need to be unique. However, as per your code, they do not. Your newly created elements all have the same exact name assigned to them as your existing elements. Fix it by adding a counter and incrementing it to the name each time you append to the form.
$(function () {
validar();
cvFields();
});
function validar() {
$(".validate").validate({
....
});
}
function cvFields() {
var count = 0;
$('#addcvfields').click(function (e) {
e.preventDefault();
count++;
var total = $()
var campos = '' +
....
'<input name="profesorcv_titulo[' + count + ']" type="text" class="form-control required" placeholder="Titulo de Estudio o Experiencia">' +
....
'<select name="profesorcv_tipo[' + count + ']" class="form-control required">' +
....
'<textarea rows="3" name="profesorcv_descripcion[' + count + ']" class="form-control" id="profesorcv_descripcion" placeholder="Describe Brevemente"></textarea>' +
....;
$('#cvfields').append(campos);
});
}

you get these problems because the added form elements where not in the DOM when your form validation plugin get initialized. you have to call your validation plugin again, after you've added new elements to the DOM.
EDIT: I just had a look at your fiddle code. your problem can be solved by first calling cvFields() and then validar();
$(function(){
cvFields();
validar();
});
If you first call validar(), the function will look in the DOM (document) if there are elements with the class ".validate". If there are elements with this class they'll get processed by the function. However all the elements that are added to the DOM after the validar() function won't get processed because they were not present in the DOM when the validar() function was called.
If you want to get the validating work after you added more items to validate you simply have to do validar(); again.

Related

Javascript Escape Character Replacement

I'm using a button to dynamically generate a new table row in my form and the lines include calling functions with parameters. I tried using JQuery on the added lines to trigger the .blur() event, as was successfully done with the hardcoded first table row, but the page completely ignored it. So I'm trying another route of triggering the onblur() event from within the row HTML. I'm getting stuck on the function parameter, as I'm either messing up the escape character order or messing up the translation. I've already spent a few hours on this and tried doing research on Stack Overflow, so I'm hoping a second set of eyes would be able to help.
Here are the relevant pieces of code. The stored html is appended to my table row, which already works.
var strVar = 'myString';
var rowCount = $("#tbodyID td").closest("tr").length;
var rowNum = rowCount + 1;
var line17 = "<td><input type='number' class='form-control' name='named_qty' onblur='function(" + strVar + ")' id='row_R" + rowNum.toString() + "' /></td> ";
There are approximately 25 lines with varying html to be inserted. I was able to get it to work previously, but realized that a value was hardcoded and I needed it to be dynamic. The function it calls is accepting a string.
When inserted into the HTML document, this line should generally read:
<td><input type="number" class="form-control" name="named_qty" onblur="function('myString')" id="row_R2" /></td>
I did some more research and realized that I was using the JQuery blur() method as :
$('#id').blur( function() { }); and trying to call those functions, not realizing that the method only works for HTML elements that had been written to the DOM on page load.
Apparently the solution is to use the JQuery on() method as follows:
$(document).on("blur", '#id', function() { <insert code> });
From W3Schools,
Note: Event handlers attached using the on() method will work for both current and FUTURE elements (like a new element created by a script).
This removes the necessity to include the event function call in the HTML line to be appended to the DOM.

changing text input to select in wordpress using jQuery

I am using a WordPress module abase to get some data from database and send them to a form. The problem is, that abase form does not allow to use select input. Because of that I am trying to convert text input to a select. I created function toSelect, to which I pass id of element and list of options (for testing I put id of element to function definition).
function toSelect(itemid,valuelist) {
var out = '';
out += '<select id="bus311mtd_2_status" style="width:50px;">';
for (i=0; i < valuelist.length; i++) {
out += '<option value="'+valuelist[i]+'">'+valuelist[i]+'</option>';
}
out += '</select>';
alert(out);
$("#bus311mtd_2_status").replaceWith(out);
//$("#bus311mtd_2_status").replaceWith('<input type="text" value="zamontowane">');
}
alert(out) gives nice select input code, but $("#bus311mtd_2_status").replaceWith(out) does not work.
Even something like: $("#bus311mtd_2_status").replaceWith('<input type="text" value="zamontowane">') doesn't work.
Element with id bus311mtd_2_status for sure exists (i.e. changing its value using document.getElementById() works fine)
Maybe jQuery doesn't work?
Your code seems to work fine for me. Perhaps it's your function call. I used:
toSelect(null, ['a', 'b', 'c']);
itemid doesn't appear to be used in the function.
Here's a fiddle with your code working:
http://jsfiddle.net/dgrundel/Lko6aftf/
Here's a slightly optimized version of the function, that uses the itemid argument:
function toSelect2(itemid,valuelist) {
var html = '<select id="' + itemid + '" style="width:50px;"><option>' +
valuelist.join('</option><option>') +
'</option></select>';
$('#' + itemid).replaceWith(html);
}
toSelect2('myInput2', ['d', 'e', 'f']);
Thank you for the answer and optimization. I used itemid initially but because of problems I temporarily replaced it with id of some existing element to make sure that the problem is somwhere else.
All the code until first alert works fine and alert(out) gives the popup window with text:
<select id="bus311mtd_2_status" style="width:50px;"><option value="ready">ready</option><option value="awaiting">awaiting</option></select>
This works as was expected. But the problem starts with the next line.
I wanted to show that even such an easy code like below doesn't work.
$("#bus311mtd_2_status").replaceWith('<input type="text" value="zamontowane">');
So it looks like the jQuery was not supported.
And I've got another observation: within script tags no empty lines are allowed (the code doesn't work if they are present).

Using variables in javascript to reference html elements dynamically

I am trying to use jQuery / javascript to remove a class from a named input element if a checkbox is ticked.
I have several checkboxes, each with a accompanying hidden (on page load) text input field.
The checkbox and text input field are named "question_X" and "question_X_description" respectively. (where X is a number 0 to 100, say)
As such I'm trying to define a variable in my code that is defined as "this element's name"+"_description", and then use that to define the suitable element to remove the class from.
Here is what I've tried:
$('input:checkbox').change(function(){
var x = $(this).attr('name').'_description';
if($(this).is(":checked")) {
$('input[name="x"]').removeClass("hidden");
} else {
$('input[name="x"]').addClass("hidden");
}
});
However, nothing happens when the any checkbox is checked. Am I referencing my variable correctly?
Use your console, It will have error messages.
First issue
var x = $(this).attr('name').'_description';
^^^
That is not how you build a string in JavaScript. JavaScript does not use . to join strings. It uses +
var x = $(this).attr('name') + '_description';
Second issue
$('input[name="x"]').
You are not looking for the string you built, you are looking for an element with the name x
Needs to be
$('input[name="' + x + '"]').
$('input[name="x"]').removeClass("hidden");
Will be looking for:
<input name="x" />
Try
$(name="'+x+'").removeClass("hidden");
Use document.getElementById('element_name')
Example of HTML element:
<input type="text" id="element_name">

Count Dynamically created html elements with jquery

I am counting the number of inputs on the current document that have value. It works fine, except for when I have dynamically added more inputs. I can't get there values.
For example I may have
<input id="participant-1"/>
<input id="participant-2"/>
...
Dynamically created after button click
<input id="participant-15" />
I'll get the value of each one in a for loop like
for(var i =1 ; i <25; i++)
{
...$('input#participant-' + i).val();
}
Now when I run a for loop to check the value of each one of these inputs it only gets the values of the inputs that weren't dynamically created. I have looked at the other questions on here and I still can't see how to apply something like .on() to what I am trying to accomplish.
NEW FOLLOW UP QUESTION
ok, now I think this is where I need more clarification concerning how to use the .on.
I have a jsfiddle here: JsFiddle example
where I create new elements and on blur of all text boxes I would like to calculate how many of the elements have value and log it. Now it currently will respond from blur event with elements who were static. It doesn't work for dynamically created elements
Give it a common class:
<input class="textbox" id="participant-1"/>
<input class="textbox" id="participant-2"/>
And get it like:
var values = [];
$('.textbox').each(function(){
values.push($(this).val());
});
console.log(values)
And to answer the edit:
The Syntax should be : $(container_selector).on(event_type, target_selector, callback)
JSFiddle Demo
$('.name').on('blur', 'input', calculate_total);
Could also consider the use of the CSS attribute selector.
http://www.w3.org/TR/CSS2/selector.html#attribute-selectors
$("input[id|=participant]").each(function(){
// something
});
Using a class selector will save time here.
<input id="participant-1" class="participant"/>
<input id="participant-2" class="participant"/>
Then use a simple count call...
var count = $('.participant').length
alert ('You have ' + count + ' Counted Inputs');
//result is 2
Hope you find this useful

Problem using dynamically added html-object from javascript

I have a problem with dynamically including an object-tag in my html.
We have a external service which we call to get some html-fragment, it includes an object-tag, a script and a simple html-form. I take that content and add it to a div in my page and then try to execute the script that uses the included object. When i debug using Firebug I can see that the code is correctly inserted in the page but the script gets an error when it tries to access the object. It seems to me that the object isn’t initialized. Let me show you some code to exemplify what I mean.
getFragment makes an ajax call using jQuery to get the content.
var htmlSnippet = RequestModule.getFragment( dto );
$('#plugin').html( htmlSnippet ).hide();
The included content in plugin-div looks like this
<div id="plugin" style="display: none; ">
Browser:
Chrome
<object name="signer" id="signer" type="application/x-personal-signer2"></object>
<form method="POST" name="signerData" action="#success">
<input name="nonce" value="ASyhs..." type="hidden">
<input name="signature" value="" type="hidden">
<input name="encodedTbs" value="U2l..." type="hidden">
<input name="provider" value="nexus-personal_4X" type="hidden">
<input type="submit" onclick="doSign()" value="Sign">
</form>
</div>
The javascript that tries to use the “signer” object looks like this:
function doSign(){
var signer2 = document.getElementById("signer");
retVal = signer2.SetParam('TextToBeSigned', 'some value...');
... and then some more
}
It’s when i call the signer2.SetParam method that I get an error saying
Object #<an HTMLObjectElement> has no method 'SetParam'
But when I use the original page where the content is loaded when the page loads the script works so I know that the ‘SetParam’ method exists on the object and that the script works. But somehow it doesn’t work when I dynamically add it to the page afterwards.
I’ve Googled this a lot the last couple of days with no luck.
Does anyone have any idea on how to get this to work?
Best regards,
Henrik
First of all Object tag is not fully supported in all browsers (Source)
Next, from my experience, jQuery (which heavily relies on document.createDocumentFragment) sometimes fails to attach/trigger events on dynamically created/cloned DOM nodes, which could explain why your object failed to initialize.
That said, to try and fix your problem, I suggest using native document.createElement and document.appendChild methods instead of jQuery.html. You can try document.innerHTML but if that fails, you can always go with the ones I mentioned earlier.
My suggestion is to either alter your service to replace:
<script type="text/javascript">
function addElement(parentid, tag, attributes) {
var el = document.createElement(tag);
// Add attributes
if (typeof attributes != 'undefined') {
for (var a in attributes) {
el.setAttribute(a, attributes[a]);
}
}
// Append element to parent
document.getElementById(parentid).appendChild(el);
}
addElement('plugin', 'object', {name:"signer",id:"signer",type:"application/x-personal-signer2"});
</script>
OR if you cannot change the content that is returned by the service, run this after you include the content onto your page:
<script type="text/javascript">
/*
* Goes through al the object tags in the element with the containerid id
* and tries to re-create them using the DOM builtin methods
*/
function reattachObjectTags(containerid) {
jQuery('#'+containerid+' object').each(function(){
var attrs = {}, el = this;
// We're insterested in preserving all the attributes
var saved_attrs = {}, attr;
for(var i=0; i < el.attributes.length; i++) {
attr = el.attributes.item(i);
if(attr.specified) {
saved_attrs[attr.nodeName]=attr.nodeValue;
}
}
this.parentNode.removeChild(this);
var new_element = document.createElement('object');
for (var a in saved_attrs) {
new_element.setAttribute(a,saved_attrs[a]);
}
document.getElementById(containerid).appendChild(new_element);
});
}
// Do your stuff
var htmlSnippet = RequestModule.getFragment( dto );
$('#plugin').html( htmlSnippet ).hide();
// reattach all the object elements in #plugin
reattachObjectTags('plugin');
</script>
THIS IS ALL UNTESTED -
I typed this off the top of my mind, since I don't have the means to fire up IE and test this.
For a jQuery solution, I think this should work:
$("input:submit").click(function(){
$("#signer").append('<param name="TextToBeSigned" value="some value ...">');
... and then some more
});
Might want to give the submit button a class or an id and use that as a selector, if you have multiple forms on that page though.
Hope this helps.
I've set up a test script here: https://dl.dropbox.com/u/74874/test_scripts/object.html
If you open up Firebug/Web Inspector, you'll see that the SetParam method is in-fact, not defined. I don't know what it's supposed to do, but it's not defined in either case. If you're trying to add <param> tags to your embed, you could use the DOM API to do that. There is some code in the test script that does that, but I'll paste it here anyway:
var obj_signer = document.getElementById('signer');
var obj_p = document.createElement('param');
obj_p.id = "myp2";
obj_p.name = "TextToBeSigned";
obj_p.value = "some value ...";
obj_p.setAttribute('valueType', 'ref');
obj_signer.appendChild(e);
Or be faster using jQuery:
$("#signer").append("<param id='myp2' name='TextToBeSigned' value='some value ...' valueType='ref'></param>");

Categories

Resources