$(this).attr("id") not working - javascript

as the title says, I keep getting "undefined" when I try to get the id attribute of an element, basically what I want to do is replace an element with an input box when the value is "other".
Here is the code:
function showHideOther(obj) {
var sel = obj.options[obj.selectedIndex].value;
var ID = $(this).attr("id");
alert(ID);
if (sel == 'other') {
$(this).html("<input type='text' name='" + ID + "' id='" + ID + "' />");
} else {
$(this).css({
'display': 'none'
});
}
}
The HTML:
<span class='left'><label for='race'>Race: </label></span>
<span class='right'><select name='race' id='race' onchange='showHideOther(this);'>
<option>Select one</option>
<option>one</option>
<option>two</option>
<option>three</option>
<option value="other">Other</option>
</select>
</span>
It is probably something small that I am not noticing, what am I doing wrong?

Change
var ID = $(this).attr("id");
to
var ID = $(obj).attr("id");
Also you can change it to use jQuery event handler:
$('#race').change(function() {
var select = $(this);
var id = select.attr('id');
if(select.val() == 'other') {
select.replaceWith("<input type='text' name='" + id + "' id='" + id + "' />");
} else {
select.hide();
}
});

your using this in a function, when you should be using the parameter.
You only use $(this) in callbacks... from selections like
$('a').click(function() {
alert($(this).href);
})
In closing, the proper way (using your code example) would be to do this
obj.attr('id');

Because of the way the function is called (i.e. as a simple call to a function variable), this is the global object (for which window is an alias in browsers). Use the obj parameter instead.
Also, creating a jQuery object and the using its attr() method for obtaining an element ID is inefficient and unnecessary. Just use the element's id property, which works in all browsers.
function showHideOther(obj){
var sel = obj.options[obj.selectedIndex].value;
var ID = obj.id;
if (sel == 'other') {
$(obj).html("<input type='text' name='" + ID + "' id='" + ID + "' />");
} else {
$(obj).css({'display' : 'none'});
}
}

You could also write your entire function as a jQuery extension, so you could do something along the lines of `$('#element').showHideOther();
(function($) {
$.extend($.fn, {
showHideOther: function() {
$.each(this, function() {
var Id = $(this).attr('id');
alert(Id);
...
return this;
});
}
});
})(jQuery);
Not that it answers your question... Just food for thought.

What are you expecting $(this) to refer to?
Do you mean sel.attr("id"); perhaps?

Remove the inline event handler and do it completly unobtrusive, like
​$('​​​​#race').bind('change', function(){
var $this = $(this),
id = $this[0].id;
if(/^other$/.test($(this).val())){
$this.replaceWith($('<input/>', {
type: 'text',
name: id,
id: id
}));
}
});​​​

I had a similar issue.
`var ID = $(this).attr("id");`
sometimes using this method with arrow function (`
$('div).click(()=>{
console.log($(this).attr("id"))
}
`)
)Could result in undefined output so instead better using the keyword 'function'

In the function context "this" its not referring to the select element, but to the page itself
Change var ID = $(this).attr("id");
to var ID = $(obj).attr("id");
If obj is already a jQuery Object, just remove the $() around it.

I recommend you to read more about the this keyword.
You cannot expect "this" to select the "select" tag in this case.
What you want to do in this case is use obj.id to get the id of select tag.

You can do
onchange='showHideOther.call(this);'
instead of
onchange='showHideOther(this);'
But then you also need to replace obj with this in the function.

Related

How to get the value from dynamically created checkbox using Jquery with class

I am trying to get the value from checkbox when checked which is created dynamically with jquery associated with html table am using class to get the value but am unable to get it
My code is like this
Input created with Jquery
"<td><div class=" + "checkbox checkbox-primary" + "><input type=" + "checkbox" + " class=" + "cbCheck" + " value=" + "" + data.d[i].Rowname + "" + "" + data.d[i].one + "" + "></div></td>"
Jquery to get the value
$("#table").on(":checked", ".cbCheck", function () {
var id = $(this).attr("value");
alert(id);
});
Please help me how to fix this.
Thanks in advance
Working Fiddle
Try:
$('table tr td').on('click','.cbCheck',function() {
if ($(this).is(':checked')) {
alert($(this).attr('id'))
}
else
alert('unchecked');
});
Use 'change' event:
$("#table").on("change", ".cbCheck", function () {
var id = $(this).attr("value");
alert(id);
});
Instead of creating it like that
use Create element and add id dynamically then use your function I guess it will work, actually worked in my case
var newCheckBox = document.createElement('input');
newCheckBox.type = 'checkbox';
newCheckBox.id = 'ptworkinfo';
You can do using following for dynamically created elements:
$(document).on("click", ".cbCheck", function () {
var value=$(this).attr("value");
alert(value);
});

Is it possible to bind events during element concatenation in a loop?

Fiddle Example
The following is an example where several buttons are rendered via a loop. I was wondering if it is possible to bind events to each button as well during the loop before the buttons are appended to a container. My example doesn't work.
Jquery
function render(){
var input = '',
array = [{'name':'Confirm','title':'This'},{'name':'Cancel','title':'That'}]
$.each(array,function(k,obj){
var name = obj.name;
input += '<h3>'+obj.title+'</h3>';
input += '<input type="submit" name="'+name+'" value="'+name+'"/>';
$(input).find('[name="'+name+'"]').click(function(){
alert(name)
/*** do some ajax things etc ***/
})
})
return input;
}
$('#box').append(render())
Yes but I wouldn't do it the way you are:
function render(target){
var array = [{'name':'Confirm','title':'This'},{'name':'Cancel','title':'That'}]
$.each(array,function(k,obj){
var name = obj.name;
var h3 = $('<h3/>').text(obj.title);
var input = $('<input/>')
.attr('type', 'submit')
.attr('name',name)
.val(name);
input.click(function() {alert('test');});
target.append(h3);
target.append(input);
})
}
$(document).ready(function(){
render($('#box'));
});
So create jquery objects that will be rendered, then attach the event to these objects. Then once the object is built ask jquery to render them.
This way jquery can keep track of the DOM elements, in your example your stringfying everything. Jquery hasn't built the DOM element at the point where your attempting to bind to them.
Fiddle
You need to use filter() to find the element by the name as there is no parent selector to find() within:
$(input).filter('[name="' + name + '"]').click(function(){
alert(this.name)
/*** do some ajax things etc ***/
})
No, you can't bind event handlers to strings. You will need to create HTML elements first. I would recommend to bind single delegated event handler after your HTML string is appended, it's also going to be much better in terms of performance:
function render() {
var input = '',
array = [{'name': 'Confirm','title': 'This'}, {'name': 'Cancel','title': 'That'}]
$.each(array, function (k, obj) {
var name = obj.name;
input += '<h3>' + obj.title + '</h3>';
input += '<input type="submit" name="' + name + '" value="' + name + '"/>';
});
return input;
}
$('#box').append(render()).on('click', 'input[name]', function() {
alert(this.name);
/** do some ajax things etc **/
});
Demo: http://jsfiddle.net/KHeZY/200/
This can be done properly by using event-delegation, But since you concerned, I just written a solution by using .add() and .filter()
function render() {
var input = '',
array = [{
'name': 'Confirm',
'title': 'This'
}, {
'name': 'Cancel',
'title': 'That'
}],
elem = $();
$.each(array, function (k, obj) {
var name = obj.name;
input += '<h3>' + obj.title + '</h3>';
input += '<input type="submit" name="' + name + '" value="' + name + '"/>';
elem = elem.add($(input));
input = "";
});
elem.filter("[name]").click(function () {
alert(this.name);
})
return elem;
}
$('#box').append(render())
DEMO

Get values and ids of all span elements inside form

I am trying to get all span elements inside the form. The span elements are turning into input text fields and become editable. When you click away they are turning back into span elements. I will attached fiddle live example.
I gave it a go but the problem is that I am getting both ids but only value of the first span element.
Here is my html:
<span name="inputEditableTest" class="pztest" id="inputEditableTest" data-editable="">First Element</span>
<span name="inputEditableTest2" class="pztest" id="inputEditableTest2" data-editable="">Second Element</span>
<input id="test" type="submit" class="btn btn-primary" value="Submit">
And here is JavaScript with jQuery:
$('body').on('click', '[data-editable]', function () {
var $el = $(this);
var name = $($el).attr('name');
var value = $($el).text();
console.log(name);
var $input = $('<input name="' + name + '" id="' + name + '" value="' + value + '"/>').val($el.text());
$el.replaceWith($input);
var save = function () {
var $p = $('<span data-editable class="pztest" name="' + name + '" id="' + name + '" />').text($input.val());
$input.replaceWith($p);
};
$input.one('blur', save).focus();
});
$("#test").on('click', function(){
var ok = $("span")
.map(function () {
return this.id;
})
.get()
.join();
var ok2 = $("#" + ok).text();
alert(ok);
alert(ok2);
//return [ok, ok2];
});
Here is the fiddle https://jsfiddle.net/v427zbo1/3/
I would like to return the results as an array example:
{element id : element value}
How can I read ids and values only inside specific form so something like:
<form id = "editableForm">
<span id="test1">Need these details</span>
<span id="test2">Need these details</span>
<input type="submit">
</form>
<span id="test3">Don't need details of this span</span>
Lets say I have got more than 1 form on the page and I want JavaScript to detect which form has been submitted and grab values of these span elements inside the form
I will be grateful for any help
$("#test").on('click', function(){
var result = {};
$("span").each(function (k, v) {
result[v.id] = v.innerHTML;
});
alert(JSON.stringify(result));
//return [ok, ok2];
});
Here is an example: https://jsfiddle.net/v427zbo1/4/
Container issue:
You should use this selector: #editableForm span if you want to get all the divs inside this container.
$("#editableForm span").each(function (k, v) {
result[v.id] = v.innerHTML;
});
But if you want to get only first-level children elements then you should use this selector: #editableForm > span
Example with getting all the spans inside #editableForm container: https://jsfiddle.net/v427zbo1/9/
If you want to have several forms, then you can do like this:
$('form').on('submit', function(e){
e.preventDefault();
var result = {};
$(this).find('span').each(function (k, v) {
result[v.id] = v.innerHTML;
});
alert(JSON.stringify(result));
//return [ok, ok2];
});
Example with two forms: https://jsfiddle.net/v427zbo1/10/
You can't use .text to return the value of multiple elements. It doesn't matter how many elements are selected, .text will only return the value of the first one.
Virtually all jQuery methods that return a value behave this way.
If you want to get an array of values for an array of matched elements, you need another map. You also need to join the strings with , # as you're producing something along the lines of #id1id2id3 instead of #id1, #id2, #id3:
var ok = $("span").map(function () {
return this.id;
}).join(', #')
var ok2 = $("#" + ok).map(function () {
return $(this).text();
});
That said, you're already selecting the right set of elements in your first map. You pass over each element to get its ID, you already have the element. There is no reason to throw it away and reselect the same thing by its ID.
If I got you right following code will do the job
var ok = $("span")
.map(function () {
return {id: $(this).attr('id') , value: $(this).text()};
}).get();
Check this fiddle.

Javascript to get the div info

I have 4 <div> tag and <a> tag for each <div> tags.
In each and every div tag i have inserted 2 span tag and a a tag.
When the a tag is clicked i need to get the product name and the price of that div
Here is the demo http://jsfiddle.net/8VCWU/
I get the below warning message when i use the codes in the answer ...
Try this:
$(".get").click(function(e) {
e.preventDefault();
var $parent = $(this).closest(".item");
var itemName = $(".postname", $parent).text();
var itemPrice = $(".price", $parent).text();
alert(itemName + " / " + itemPrice);
});
Example fiddle
Note that you had a lot of repeated id attributes which is invalid code and will cause you problems. I've converted the #item elements and their children to use classes instead.
jQuery
$(".get").click(function(event){
event.preventDefault(); /*To Prevent the anchors to take the browser to a new URL */
var item = $(this).parent().find('#postname').text();
var price = $(this).parent().find('#price').text();
var result = item + " " + price;
alert(result)
});
DEMO
A Quick Note about id:
The id attribute specifies a unique id for an HTML element (the value must be unique within the HTML document).
A unique identifier so that you can identify the element with. You can use this as a parameter to getElementById() and other DOM functions and to reference the element in style sheets.
solution is below
use the blow code and try it
<a data-role="link" href="javascript:linkHandler('<%= obj.productname %>', '<%= obj.price %>')" class="get" >Add <a>
function linkHandler(name, price)
{
alert(name);
alert(price);
var name = name;
var price = price;
var cartItem = new item(name, parseFloat(price));
// check duplicate
var match = ko.utils.arrayFirst(viewModel.cartItems(), function(item){ return item.name == name; });
if(match){
match.qty(match.qty() + 1);
} else {
viewModel.cartItems.push(cartItem);
var rowCount = document.getElementById("cartcontent1").getElementsByTagName("TR").length;
document.getElementById("Totala").innerHTML = rowCount;
}
}
with jQuery
​$('a.get').on('click',function(){
var parent = $(this).parent();
var name = $(parent+' #postname').text();
var price = $(parent+' #price').text();
});​​​​​​​​
Or again:
$('a').click(function(e){
e.preventDefault();
var $price = $(this).siblings('#price').text();
var $postname = $(this).siblings('#postname').text();
alert($price);
alert($postname);
});
Try
function getPrice(currentClickObject)
{
var priceSpan = $(currentClickObject).parent("div:first").children("#price");
alert($(priceSpan).html());
}
and add to your a tag:
...
I'd suggest to use classed instead of id if you have more than one in your code.
The function you're looking for is siblings() http://api.jquery.com/siblings/
Here's your updated fiddle:
http://jsfiddle.net/8VCWU/14/
Hi I cleaned up the HTML as mentioned using the same Id more than once is a problem.
Using jQuery and the markup I provided the solution is trivial.
Make a note of the CSS on the below fiddle
http://jsfiddle.net/8VCWU/27/
$(document).ready(function(){
$("#itmLst a.get").click(function(){
var $lstItm = $(this).parents("li:first");
var pName = $lstItm.find("span.postname").html();
var price = $lstItm.find("span.price").html();
alert("Product Name: " + pName + " ; Price: " + price);
});
});
I have made some changes in your html tags and replace all repeated Ids with class, because you have repeated many ids in your html and it causes trouble so it is wrong structure. In HTML, you have to give unique id to each and every tag. it will not be conflicted with any other tag.
Here i have done complete bins demo. i have also specified all alternative ways to find tag content using proper jQuery selector. the demo link is as below:
Demo: http://codebins.com/bin/4ldqp8v
jQuery
$(function() {
$("a.get").click(function() {
var itemName = $(this).parent().find(".postname").text().trim();
var itemPrice = $(this).parent().find(".price").text().trim();
//OR another Alternate
// var itemName=$(this).parents(".item").find(".postname").text().trim();
// var itemPrice=$(this).parents(".item").find(".price").text().trim();
//OR another Alternate
//var itemName=$(this).closest(".item").find(".postname").text().trim();
// var itemPrice=$(this).closest(".item").find(".price").text().trim();
//OR another Alternate
//var itemName=$(this).siblings(".postname").text().trim();
//var itemPrice=$(this).siblings(".price").text().trim();
alert(itemName + " / " + itemPrice);
});
});
Demo: http://codebins.com/bin/4ldqp8v
You can check above all alternatives by un-commenting one by one. all are working fine.

How get object from each function

I have a <div> with rabioboxs:
<div id='RB-01'>
<span>Item_1</span><input type='radio' name='RB01' value='1'><br />
<span>Item_2</span><input type='radio' name='RB01' value='2'><br />
<span>Item_3</span><input type='radio' name='RB01' value='3'><br />
</div>
Then with jquery I want to get a radiobox that was checked:
var obj = null;
var tempId = "RB-01";
if ($('div[id=' + tempId + ']')) {
$('div[id=' + tempId + '] input').each(function() {
if ($(this).checked == true) { obj = $(this); }
});
}
but in the end obj = null.
You should do:
if ($(this).is(':checked') == true)
or
if (this.checked == true)
Of course rember to have at least on of the checkbox checked. Fiddle here http://jsfiddle.net/nicolapeluchetti/Ky6q2/ and here http://jsfiddle.net/nicolapeluchetti/TEw53/
var radio = $('#RB-01 input:radio:checked');
console.log(radio);
you can use the :checked selector like this:
var selectedRadios = $('#RB-01 input:checked');
The jQuery object doesn't have any checked property. Just don't create a jQuery object from the element.
Notes: You can use the # operator in the selector instead of [id=...]. You don't need to check if a selector returns anything before looping, it's perfectly valid to loop an empty jQuery object. You don't have to compare a boolean value to true to check if it's true.
var obj = null;
var tempId = "RB-01";
$('div#' + tempId + ' input').each(function() {
if (this.checked) obj = $(this);
});
You could even use a selector to find the checked element:
var tempId = "RB-01";
var ch = $('div#' + tempId + ' input:checked');
var obj = ch.length > 0 ? ch.last() : null;
(Note: I used the last method to get the last matched element so that it works the same as the code with the loop. If you know that there is only one checked element, you can just as well use the first method instead.)

Categories

Resources