Migration from jquery1 to jquery 2 : selectors - javascript

I'm having troubles with selectors and brackets :
var myInputId = $(input).attr("id")
"value-5379-32433[]"
This is an input id for a checkbox list. I want to select now all the elements having this ID :
$("#" + myInputId);
Uncaught Error: Syntax error, unrecognized expression: #value-5379-32433[]
It works if I escape the brackets but I find this solution quite ugly as I have to use it in many places :
$("#" + inputId.replace("[", "\\[").replace("]", "\\]"))
Do you have a nicer solution to this problem ?
EDIT Note : This has to returns many elements as there is many checkboxes with this ID.
EDIT 2 : The html 3 elements I want to select :
<div class="type_mlist_check ">
<input type="checkbox" id="value-5379-32433[]" value="1" >
<input type="checkbox" id="value-5379-32433[]" value="2" >
<input type="hidden" id="value-5379-32433[]" value="-1">
</div>

Since selector contains meta character use attribute equals selector instead.
$('[id="' + myInputId + '"]');
Or use a single String#replace method with character class regex and global modifier.
$('# ' + myInputId.replace(/[#;?%&,.+*~\':"!^$[\]()=>|\/#]/g,'\\$&'))

Related

jQuery each to find label for attr not working

I am getting an error and think i know why but not sure how to resolve it.... for example my for label / id is:
shipping_address[country] << i think because of the brackets []
and my JS is
$(document).ready(function() {
$("form :input").each(function(index, elem) {
var eId = $(elem).attr("id");
var label = null;
if (eId && (label = $(elem).parents("form").find("label[for="+eId+"]")).length == 1) {
$(elem).attr("placeholder", $(label).html());
$(label).remove();
}
});
});
Error:
js__jquery.js?1419646…:1468 Uncaught Error: Syntax error, unrecognized
expression: label[for=billing_address[first_name]]
Example HTML:
<div class="col-sm-6">
<div class="form-group">
<label for="card[first_name]">First Name<span> * </span></label>
<input id="card[first_name]" name="card[first_name]" type="text" class="form-control" value="" validate="true">
</div>
</div>
Wrap the attribute value within quotes or escape metacharacter since the id value contains some metacharacter which has special meaning in jQuery.
.find("label[for='" + eId + "']")
// -^-----------^-
From jQuery docs :
To use any of the meta-characters ( such as !"#$%&'()*+,./:;<=>?#[]^`{|}~ ) as a literal part of a name, it must be escaped with with two backslashes: \. For example, an element with id="foo.bar", can use the selector $("#foo\.bar"). The W3C CSS specification contains the complete set of rules regarding valid CSS selectors. Also useful is the blog entry by Mathias Bynens on CSS character escape sequences for identifiers.
FYI : Use text() method instead of html() method to get text content.
$(elem).attr("placeholder", $(label).text());
// ------^^^^^^---
Square brackets inside attribute selectors need to be escaped.
var eId = elem.id.replace(/[\[\]]/g, '\\$&');

Strange behavior with input type="hidden" and prop("checked", true)

I stumbled upon this by accident, and I'm wondering if its a bug or intended behaviour. I set a checked on an input type="hidden" which I thought was not possible. But depending on the used jQuery selector this field is then returned or not returned.
HTML:
<form>
<div>Checkbox: <input class="test" type="checkbox" name="check" value="1" /></div>
<div>Hidden: <input class="test" type="hidden" name="check" value="1" /></div>
<div><input id="button" type="button" value="run test" /></div>
<div>Results:</div>
<div id="resultA"><strong>$('.test:checked')</strong><br /></div>
<div id="resultB"><strong>$('.test:checked[value=1]')</strong><br /></div>
<div id="resultC"><strong>$('.test:checked[value="1"]')</strong><br /></div>
</form>
jQuery:
$(function() {
$('#button').click(function() {
$('.test').prop('checked', true);
$('.test:checked').each(function() {
$('#resultA').append($(this).attr('type') + ' - checked<br />');
});
$('.test:checked[value=1]').each(function() {
$('#resultB').append($(this).attr('type') + ' - checked<br />');
});
$('.test:checked[value="1"]').each(function() {
$('#resultC').append($(this).attr('type') + ' - checked<br />');
});
});
});
Above example as a JSFiddle: https://jsfiddle.net/m5fatj8q/6/
ResultA: only returns the checkbox.
ResultB: returns both the checkbox and hiddden field!
ResultC: only returns the checkbox.
My questing is:
Why does resultB return the hidden field? And is this a bug or intended behaviour?
The attribute selector [value=1] is not valid; the value you're matching against in an attribute selector either has to be a string (denoted with quotes, as per your 3rd option) or a CSS identifier which
cannot start with a digit.
That's why the behaviour differs between 2 and 3.
The reason it then differs between 1 and 2 must be down to a bug in Sizzle, the selector engine that jQuery uses internally, not correctly handling invalid selectors. If you instead use querySelectorAll, you get
'.test:checked[value=1]' is not a valid selector.
I'm by no means an expert in the Sizzle source code, but I think the issue is a combination of their definition of an attribute:
// "Attribute values must be CSS identifiers [capture 5] or strings [capture 3 or capture 4]"
and here:
// Move the given value to match[3] whether quoted or unquoted
match[3] = ( match[3] || match[4] || match[5] || "" ).replace( runescape, funescape );
which would appear to just use the value given, no matter whether it was quoted or not. This is then compounded by the check for :checked:
return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected);
Which seems to only look to make sure it's an <input> element, and not specifically a checkbox or radio button.

How can I get input tags with title attributes that contain " "?

I have the following input tag in my dom and unable to add classes and/or ids:
<input type="radio" title=" ">
When I try
$('input[title=" "]')
or
$('input[title=" "]')
it does not return anything. Can I pull this based on that title?
Your selectors didn't work because you didn't use the proper symbol. The title attribute gets any html entities decoded, so is going to get decoded to the actual symbol   (ascii code 160). So that means the text isn't going to match it, neither will a regular space (ascii code 32).
On a Windows OS you can type ALT+0160 to get the symbol. On other OS you will need to find the equivalent key combo, or copy paste from a character map.
console.log( "Number of inputs with regular space: ", $('input[title=" "]').length );
console.log( "Number of inputs with text: ", $('input[title=" "]').length );
console.log( "Number of inputs with symbol: ", $('input[title=" "]').length );
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<!-- Regular space in title -->
<input type="checkbox" title=" ">
<!-- non-break space html entity -->
<input type="checkbox" title=" ">
<!-- encoded html entity which will match -->
<input type="checkbox" title="&nbsp;">
Would it suffice to select all non-blank title attributes?
$('input:not([title=""])').click(function(){
alert('non-blank title');
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<input type="text" title=" " />
This should work:
var isFound = $('[title=" "]').length === 1;
if (isFound) console.log('Element is found.');
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div title=" "></div>
This subtle difference is to put an actual not a space character into selector.
It's a bit unwieldy can try a function to return the value of the title attribute and use that. If you are using this in a normal page, you can swap getTitle parameter below for a more specific selector like ID.
function getTitle(selector) {
return $(selector).attr('title');
}
$('input[title=' + getTitle('input[type="radio"]') + ']');
Use the following trick with JQuery's filter() function and RegExp.test function to get input tags with title attributes that contain :
var inputs = $("input[title]").filter(function(i){
return /\u00A0/.test($(this).attr('title'));
});
$("input[title*=' ']");
To get input elements with title attributes that contains a "regular" space use the following:
The [attribute*=value] selector matches every element whose attribute
value containing a specified value.

How do I retrieve text from an input checkbox with jquery?

I'm trying to retrieve the text for selected check boxes like so:
HTML:
<label class="checkbox">
<input type="checkbox" name="priority" value="2" checked="checked">2 - Critical
</label>
<label class="checkbox">
<input type="checkbox" name="priority" value="3">3 - Important
</label>
jquery:
$('#priorityContents input:checkbox:checked').each(function() {
if(priorityText.length > 0) {
priorityText = priorityText + "|";
}
priorityText = priorityText + $(this).text();
});
alert(priorityText);
I would expect to see:
2 - Critical
I don't get any errors in my console. What am I missing?
You can try:
<input id="cb" type="checkbox" name="priority" value="2" checked="checked">
<label for='cb' class="checkbox"> 2 - Critical</label>
$('#priorityContents input[type="checkbox"]:checked').each(function() {
var txt = $(this).next('label').text();
});
please note that :checkbox selector is deprecated you can use input[type="checkbox"] instead.
You want to get to the label element, which is the parent of the input:
$('#priorityContents input[type="checkbox"]:checked').parent();
Here's the fiddle: http://jsfiddle.net/Hk63N/
For increased performance, you should consider splitting up the selector:
var priorityText = '';
$('#priorityContents input[type="checkbox"]').filter(':checked').parent().each(function() {
if ( ! priorityText ) {
priorityText = priorityText + "|";
}
priorityText = priorityText + $(this).text();
});
alert(priorityText);​
From the jQuery docs:
To achieve the best performance when using these selectors, first select some elements using a pure CSS selector, then use .filter().
Here's the fiddle for this: http://jsfiddle.net/Hk63N/1/
Based on the code you posted, why would you expect to see that result? At no point in that code have you attempted to retrieve the text. I'd suggest:
$('#priorityContents input:checkbox:checked').each(function() {
var next = this.nextSibling,
text = next.nodeType == 3 ? next.nodeValue : '';
console.log(text);
});
JS Fiddle demo.
This iterates over each checked checkbox within the element of the given id, looks at the next sibling of the current node (not the jQuery object, the plain DOM node) and, if that node is a textNode (a node of nodeType equal to 3) assigns the nodeValue (the text contents of that node) to the variable.
If it's not a textNode, then it assigns an empty string instead.
There's some stuff definitely missing from your code. Like the #priorityContents elements which is pretty important if you're searching for it.
Anyway I created this demo that works for me. Basically what you have wrong I believe is this part:
priorityText = priorityText + $(this).text();
The actual checkbox element doesn't own the .text(). YOu needt to go up to the parent to get the actual value contained in there.
DEMO
Try this
var checkedTxt=$('.checkbox :checked').parent().text();
console.log(checkedTxt);
DEMO.
First, wrap the text only in the <label> tags, which is a good idea anyway for usability. Assign the for attribute to the ID of the checkbox:
<input type="checkbox" name="priority" id="priority-2" value="2" checked="checked">
<label class="checkbox" for="priority-2"> 2 - Critical</label>
Then you can target this easily with jQuery selectors:
$('#priorityContents input:checkbox:checked').each(function() {
priorityText = $('label[for="'+$(this).attr('id')+'"]').text();
...
});
That said, the easiest approach might instead be to add whatever text you want in a data-prioritytext attribute on the checkbox, and extract that with .data('prioritytext') in your code.
var name=$(this).parent().text();
you will get the text of that checkbox
In html checkbox have no attributes to take text data. so
use parent()function to take
you can retrieve text of checked checkbox this way using jquery.
var value = $(document).find('input[type="checkbox"]:checked').attr('value');

Need help with regular expression and javascript

I've following problem: I use a clone script to clone input fields which are used for cms options. Depending on the field name the option arrays are created in the db.
I have following field at the moment:
options[categories][1][3]
and want to increase the first number by using a counter variable like:
options[categories][2][3]
options[categories][3][3]
...
However I'm not familiar with regular expressions so I hoped someone could provide a str.replace code which helps me to replace the first number with my counter variable.
Thanks in advance!
.......
Code:
.......
At the moment it looks like:
if ( $(clone).attr('name') ){
newid = $(clone).attr('name');
var position = newid.lastIndexOf("[");
newid = newid.substring(0, position)+ '[' + (counter +1) + ']';
$(clone).attr('name', newid);
};
Html field:
<input type="checkbox" value="1" name="options[categories][1][3]">
3 is the category id, 1 is the option I need the category for. The clone script would produce:
<input type="checkbox" value="1" name="options[categories][1][4]">
at the moment - but I need:
<input type="checkbox" value="1" name="options[categories][2][3]">
I think it's a regex problem because the easiest solution would be to search for [categories][anyvalue] and replace it with [categories][counter]
You could use a regular expression to replace the first number in brackets. Like this:
if ( $(clone).attr('name') ) {
var newid = $(clone).attr('name');
newid = newid.replace(/\[[0-9]*\]/, '[' + (counter + 1) + ']');
$(clone).attr('name', newid);
};

Categories