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.
Related
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).
I've been having some troubles with this javascript code and I am looking for a suggestion. I am programtically adding a row to a table with javascript but I need to add an onclick event for each row. Problem is when the row adds to the page the quotations and upper / lower case has been all converted to lower case causing issues on the web page.
here is the current code
var row = $("<tr id=" + id + " onclick=return SelectRow('Racks','" + id + "') >");
if someone could explain how to get it so that the ending result looked like this
<tr id="r1" onclick="return SelectRow('Racks','r1')">
</tr>
I'm guessing it has to do with escape characters and the order they are being placed but I can't seem to figure it out.
Don't try to generate JavaScript inside HTML inside JavaScript. It is a right pain.
Don't write 90s style code. Stop using onclick attributes. Use event handlers bound with JavaScript.
function row_click_handler(event) {
return SelectRow("Racks", this.id);
}
var row = $("<tr />").attr("id", id).on("click", row_click_handler);
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.
I have an HTML document.
It is possible to get the events associated with every Element in a particular FORM element in the document using JavaScript.
var element = document.forms[i].elements[j];
This way I can get jth element in ith form, But can I get the event associated with the element.
There can be any number of elements in a form. I am using IE 8.
**EDIT :**
Actually I was trying to serialize HTML DOM into XML.
what I did to do this was :
createXML : function() {
objSerializeDOM.msg += "";
objSerializeDOM.msg += "<?xml version='1.0' encoding='UTF-8'?>\n\n";
// Get all the forms in a document.
var forms = document.forms;
for ( var i = 0; i < forms.length; i++) {
// Get all the elements on per form basis.
elements = document.forms[i].elements;
objSerializeDOM.msg += "<FORM name=\"" + forms[i].name + "\" method=\""
+ forms[i].method + "\" action=\"" + forms[i].action + "\">\n\n";
for ( var j = 0; j < elements.length; j++) {
objSerializeDOM.msg += " <" + elements[j].tagName + " type=\""
+ elements[j].type + "\"" + " name=\""
+ elements[j].name + "\"" + " Value =\""
+ elements[j].value + "\" />\n";
}
alert(document.forms[i].elements[1].event);
}
objSerializeDOM.msg += "\n\n</FORM>\n\n";
alert(objSerializeDOM.msg);
objSerializeDOM.writeToFile(objSerializeDOM.msg);
}
What I am getting from this is an XML :
<?xml version='1.0' encoding='UTF-8'?>
<FORM name="loginForm" method="post" action="/sigma/login.do;jsessionid=E6509E7BA55573AA5386274ABB93F718">
<INPUT type="hidden" name="message" Value ="" />
<INPUT type="hidden" name="userAction" Value ="" />
<INPUT type="text" name="userId" Value ="" />
<INPUT type="password" name="passwd" Value ="" />
<INPUT type="button" name="button" Value ="Continue" />
</FORM>
Now suppose I have:
<input tabindex="7" name="button" type="button" class="button"
style="width:100;height:30" Value="Continue" onclick='login()' />
All I want to do now is to get onClick in my XML or any event associated like onBlur() etc.
As Felix said in his comment, there are several ways to register an event on an object. So how you can get the events attached to an object and serialize them somehow to your xml depends on how they are registered. I will list some thoughts of how you can get them for serialisation.
1 Handlers registered inline
1.1 Completely inline code:
<INPUT type="hidden" name="message" Value ="" onclick="alert('hello')"/>
When the code is completely inline, you can just get the attribute in your xml and save it.
2.1 Inline function call
In this case you would have to export the declaration of the function. In JavaScript Functions are objects itsself so you could actually get the declaration text of your function by invoking myFunc.toString(). The hard part on this would be to figure out, if this is a function call where the declaration hast to be exported or not.
2 Handlers registered through attributes
If you have added all your element Handlers through i.e. :
function myFunc(num){
alert("Your number is: " + num);
}
document.getElementById('myElement').onclick = myFunc;
you could just iterate your form elements like you already do and get the onlick, onmouseover, onblur, on.... properties all one by one and save them to xml. Also in this case the content of this propertys will be Function Objects as well so to save their actual content you have to do .toString() on the Function object.
In addition there are some other ways to register Event handlers depending on the different Browsers. So if you definetly know how your events are registered, you can actually serialize them. If you don't that's going to be very difficult.
I hope that helps to get you a bit further.
This probably isn't what you're looking for but may help you atleast see which part of the DOM you need to be looking at - you can get a plugin for firebug which shows any jQuery events bound to DOM elements called firequery, and I think firebug on its own can show attached events in normal JS.
Considering that firebug is written in JS, there obviously must be a way to do it.
Unfortunately I don't have time to go through the source myself (I'd like to :D ) but you can find the repo here: http://code.google.com/p/fbug/source/browse/branches/firebug1.8/content/firebug/
Sorry I can't be of more help and good luck
Though It looks weird to answer my own question but may be it will help some one :
I did some research and found that:
document.forms[i].elements[j].onclick will return
function onclick()
{
login()
}
Here is the method which I was calling onClick of the button
similarly we can check many others like:
document.forms[i].elements[j].onblur
document.forms[i].elements[j].onfocus etc. etc.
Many thanks to all for taking interest in this question.
There is a very good tool visual event that would display all the events associated with element visually.
Add the following code at the end of each page that you want to monitor.
This will make the page disable and highlight all the events with icons and also show what they are doing by taking the cursor on that icon.
(function()
{
if(typeof VisualEvent!='undefined')
{
if(document.getElementById('Event_display'))
{
VisualEvent.fnClose();
}else{
VisualEvent.fnInit();
}
}else
{
var n=document.createElement('script');
n.setAttribute('language','JavaScript');
n.setAttribute('src','http://www.sprymedia.co.uk/design/event/media/js/event-loader.js');
document.body.appendChild(n);
}
})();
Please read visual event for detail.
I have a classic table / thead / tbody structure, which I add a line at the end of the tbody. The line contains only an input element. The code works in Firefox 3.6 but not in Chrome v5 or IE8. I'm using jQuery 1.4.2.
Does not work:
$("#" + AJAX_ID).parent().find('tr:last > td:nth-child(2) > input').focus();
Does work:
$("#" + AJAX_ID).parent().find('tr:last > td:nth-child(2) > input').css('background-color', 'red');
even setting an ID on the input, and using document.getElementBuId('id').focus() doesn't work.
*** edit ***
The site is pretty complex (mix of template / static html and dynamic html), but the table
looks like this (rendered html in chrome, layout via tidy) : http://pastebin.com/PHqxAEVm
*** edit 2 ***
Even $("#lectures").find("input:last").focus(); called from the ajax callback doesn't do anything.. $("#lectures").find("input:last").css('background-color', 'red'); turns one red though, but the focus goes to the address bar.
Here's a dump of the returned object from the selector:
http://pastebin.com/Jdw1TZXf
*** edit 3 ***
Here's the JavaScript code that builds the table: http://pastebin.com/cbCfi0UY
on page load, oContainer is $("#lectures") while after the ajax call it's $("#" + AJAX_ID).parent(), which is supposed to point to the table's tbody
*** edit 4 ***
Hard problem... here's the full lectures.js file: http://pastebin.com/Jkg0DZqa
batisses and compteurs are json objects loaded via the template. the user select a batisse then a compteur then press a button that calls buildAjout(), which calls in this example buildElectric($("#lectures"), compteur);. Once the line is filled bu the user, onBlurLecture(tr_parent) is called, the data is sent to the server via AJAX and function callback_compteurs_lecture_add(AJAX_ID) is called after the ajax call is complete. The function SendCommand is a custom function which use jQuery ajax.
The creation of the first input line (and the focus) works, but not the one created in the callback of the ajax.
*** edit 5 ***
The full rendered page looks like: http://pastebin.com/UfBYcjX3
I shortened the batisses variable. The (full) page has no JavaScript errors.
In Chrome's JavaScript console, I cannot focus the inputs.
*** edit 6 ***
Wrong function name in this question for SendCommand. fixed.
Solution found:
.focus() doesn't work on an input while orher attributes works
What ID are you targeting? Because if I replace $("#" + AJAX_ID) with $('table') it works -> demo (at least in Chrome)
and if I wrap the function inside a $(document).ready(function(){...}) it works in IE -> demo
I'm still looking to see what the problem might be, but I have a few comments about your code so far.
I haven't tested this, but I creating a jQuery object then appending another object inside ends up taking a lot of time because of the number of function calls. I've found it easier to just build up a string and only use one append. This example makes it easy to read:
var table = '\
<table style="width: 100%">\
<thead>\
<tr>\
<th>Numéro</th>\
<th>litre</th>\
<th style='width: 100px;'>Status</th>\
</tr>';
// append more to the string
table += '<tbody>.....</tbody></table>';
$('body').append(table);
I found this bit of code and I just wanted to show you that you can shorten it:
$("#no_batisse").css('display', 'none');
$("#lectures").html("");
$("#lectures").css('display', '');
shortens to:
$("#no_batisse").hide();
$("#lectures").empty().hide();
Instead of calling this function after each row addition, you could try adding a live function once that works with dynamically added content:
$(oLigne).find("input").blur(function() { onBlurLecture(oLigne); });
try running this when you initialize the script (just once)
$('#lecture').find('input').live('blur', function(){
onBlurLecture( $(this).closest('tr') );
})
I'll keep looking!
EDIT:
If your code is being triggered via some element that has a default behavior (like an <a> element), try adding return false; to the end of its callback.
Alternatively, if you give a parameter to the event handler's function, like function(e) {...}, you can call e.preventDefault() from within the callback instead of return false;.
First, I don't know if this is the issue, but IDs can not start with a number.
Second, which element has the AJAX ID that are you using? You'll get different results depending on that.
To avoid any ID issues, you could do:
$("#lectures").find('tr:last > td:nth-child(2) > input').focus();
or if you want it to be relative, do:
$("#" + AJAX_ID).closest('tbody').find('tr:last > td:nth-child(2) > input').focus();
got it!
I use "tab" (tabulation) to switch to the next input while writing in them. At the last one, the focus goes out of the window so I cannot set it. I converted the last column "status" into a input so it gets the focus while onBlur is executed. When the ajax load callback is called, the new line is added and the input is focused as it should.
Chrome: works
Firefox: works
IE8: works (with fix)
spent 1½ day on that lol
thanks everyone!
Try to trigger .focusin() (this was added in jQuery's 1.4) See documentation.