jQuery Finding Element By Id With Space And Via Variable - javascript

I am able to locate an element of an element through an id and add a class when the ID is hard coded, e.g:
var tableId = el.id;
$('#' + tableId).find("[id='Checkout On']").addClass('highlight');
However, I want to pass 'Checkout On' as a variable, e.g:
var tableId = el.id;
var childEl = col.id;
$('#' + tableId).find("[id=" + childEl + "]").addClass('highlight');
However this doesn't seem to work.
Update:
Completely understand IDs should not have spaces however this is not something I am able to resolve.

You've left out the quotes in the version using the variable:
$('#' + tableId).find("[id='" + childEl + "']").addClass('highlight');
// ------------------------^---------------^
But note that an id with a space in it is invalid. From the spec:
3.2.5.1 The id attribute
The id attribute specifies its element's unique identifier (ID). [DOM]
The value must be unique amongst all the IDs in the element's home subtree and must contain at least one character. The value must not contain any space characters.
(my emphasis)
That means that even if this works on one browser, there's no guarantee it'll work in another, or even in the next minor release of the one where it worked. (I bet it will, but there's no reason to tempt things like that...)

You should never use whitespaces for any id or class names. Go with snake_case or camelCase: checkout_on or checkoutOn

If you want to select an element with ID use the #... selector. It's better. Like this:
var tableId = el.id;
var childEl = col.id;
$('#' + tableId).find("#" + childEl ).addClass('highlight');
NOTE: IDs can not have spaces. Check this for more info.

Related

Universal String selector for Javascript?

I have something like
x.getElementById("foo" + rowIndex);
There are a couple of cases that have some other string before the "foo" in the ID, and my question is if there are any replacements (like the "%" in SQL) that I could use to add something else to the "foo" like
x.getElementById("%foo" + rowIndex);
If you use querySelector instead of getElementById, you can pass a selector string that selects an ID which ends with the substring you want, for example:
x.querySelector('[id$="foo' + rowIndex + '"]');
const rowIndex = 3;
console.log(document.querySelector('[id$="foo' + rowIndex + '"]'));
<div id="barfoo3">text</div>
(of course, if you want to select all elements whose ID ends with that, use querySelectorAll instead of querySelector)
That said, note that such dynamic IDs are somewhat of a code smell - you might consider if there are more elegant alternative methods.

Why does jQuery not seem to add text to nested spans?

I have tried this in a couple of different orders, and neither works. I start off like this:
var messageHtml = "<span class='message-bundle' id='" + randomId + "'></span>";
$(".visualizer").append(messageHtml);
randomId is a random number. Then I set the top and left positioning for the element (it is set to position: absolute).
Then I .append() the following empty spans to this span:
$(".message-bundle#" + randomId).append("<span class='usertag' id='" + randomId + "'></span><br/>" +
"<span class='message' id='" + randomId + "'></span>");
I keep them empty initially because I want to sanitize their contents against XSS exploits. So far, everything is fine. Then I add sanitized text to these nested spans.
$(".message-bundle .usertag#" + randomId).text(msgObj.usertag);
$(".message-bundle .message#" + randomId).text(msgObj.message);
This never works. I have tried printing out the .text() of these two elements, but they contain empty strings. Why is this? Can I somehow sanitize the strings and add them inline when creating the .usertag and .message spans above (instead of using .text())?
ids need to be unique throughout the entire document, and you’re duplicating them. It’s an inappropriate use of them anyway, though; you should work with elements more and HTML less.
var message =
$('<span>', { class: 'message-bundle' })
.append($('<span>', { class: 'usertag', text: msgObj.usertag }))
.append($('<span>', { class: 'message', text: msgObj.message }));
$('.visualizer').append(message);
This appends elements that you can manipulate as proper objects from the moment they’re created, rather than by re-selecting them after adding HTML.
IDs must be unique within the document - you're assigning the same ID to multiple elements. (Or is that just over-simplified code?)

Select text string before comma, set it to uppercase

JS Fiddle Example
OK--I have a field that is a full name (last name, first name). The data that is returning isn't last and first name, it is full name. It is then printed last, first. I want to select just the last name (everything before comma), and set it to uppercase.
I may be mixing jQuery and javascript in my example, I'm not positive--still a newb. However, what I've done in the example is to:
function splitLastName(){
var splitNameArray = $('[data-dojo-attach-point|="physcianNameNode"]').split(",");
var lastName = splitNameArray[0];
var firstName = splitNameArray[1];
lastName.wrap('<span class="isUppercase" />');
}​
Basically, I'm setting a variable of the field--I've tested that it accurately grabs the element I want it to grab. I'm turning the string into an array, split by the comma field. Then setting the two parts of the array as their own variables. Finally, attempting to wrap the lastName string in a span that adds the 'isUppercase' class. I know I'm doing something wrong, what is it?
function splitLastName(){
$('[data-dojo-attach-point|="physcianNameNode"]').html(function(i, v) {
var names = v.split(',');
return '<span class="isUppercase">' +names[0] + '</span>,' + names[1];
});
}
Fiddle
.html() docs
The above is a quick solution setting a new innerHTML to the element. If you want to use proper DOM manipulation, it'd be like:
function splitLastName() {
$('[data-dojo-attach-point|="physcianNameNode"]').each(function() {
var names = $(this).text().split(',');
$(this).empty().append($('<span>', {
'class': 'isUppercase',
text: names[0]
}), ',' + names[1]);
});
}
Fiddle
Note that I'm using .each() so the code above will work regardless of $('[data-dojo-attach-point|="physcianNameNode"]') matching multiple elements or just a single one.
The problem is you are trying to split a JQuery object.
I have updated your example: See here
function splitLastName(){
var element = $('[data-dojo-attach-point|="physcianNameNode"]');//find the element
var html = element.html();//get the contents of the DIV element
var splitNameArray = html.split(",");//Split the value with comma
var lastName = splitNameArray[0];//store the last name
var firstName = splitNameArray[1];//store the first name
var newHtml = '<span class="isUppercase">' + lastName + '</span>, ' + firstName;//create the new html using the parsed values
element.html(newHtml);//assign the new html to the original DIV element (overwriting the old)
}
The problem occurs with this line:
var splitNameArray = $('[data-dojo-attach-point|="physcianNameNode"]').split(",");
The notation:
$('< some name >')
is a jQuery selector that selects an element. If you type this into your console (replacing < some name > with your selector) in your browser you'll see that it returns an object not a string. So your code is trying to split an object. I don't know where the string is located (div, span, input box etc.) but you need to pull the string to do the split. If your string is text in a div or span use:
var splitNameArray = ($('[data-dojo-attach-point|="physcianNameNode"]').text()).split(",");
as this will grab the string contained in that selector and then perform the split on it. Likewise, if it is in an input you will need to use the proper handler to get the value:
var splitNameArray = ($('[data-dojo-attach-point|="physcianNameNode"]').val()).split(",");
This will pull the value from an input and then perform the split. If your string is in html then you could alternatively grab it using the following notation:
var splitNameArray = ($('[data-dojo-attach-point|="physcianNameNode"]').html()).split(",");
This will pull the html and perform the respective split operation.
Hope this helps.

Loop through .each(function) properly and format number string to phone number

How to loop through my results and format each number string. The first result is formated correctly, but not the second result or any result after the first.
$('#phoneResults').each(function(){
//Only the first result is being altered! Ugh.
var string = $(this).html();
$(this).html(string.substring(0,3) + '.' + string.substring(3,6) + '.' + string.substring(6,10))
});
Likely because the # refers to an element ID, which by convention is unique. jQuery will treat this as a single item, so iteration will yield only a single result.
Maybe try something like:
$('.phoneResults').each(function() {
// your code here
});
The problem is that you are using a duplicated id #phoneresults. Id's must e unique. When your selector operates, it is finding the first element with the ID and then stopping as there should not be any other elements with the ID. So your each() function is not operating on multiple elements.
Make this a class and change your selector to .phoneresults and you should be good to go.

jQuery bind click event to id that has increasing number on every page refresh

Here's what I have. A SharePoint 2010 custom view in a list web part. I have 6 categories and 4 sub-categories. Items do not have to have sub-category but do have to have a category.
The view shows the a blank sub-category witha number next to it. I'm trying to bind a click event to all of them but the ID increases on every page refresh. The base ID is titl[0-9]*[0-9]. Then there is another ID underneath that I want to check as well, it is titl[0-9]*_[0-9]1.
So I've tried using the regex selector for jQuery and it doesn't bind correctly. It finds the object but doesn't bind correctly.
I need it to bind to the id and then be able to trigger the onclick event of the next tbody which is the 1_. Then check if the text of it is " " and if so hide the tbody.
My code:
$(":regex(id,titl[0-9]*-[0-9]_) td a").bind('click', function(){
var parent = $(this);
var child = $(this).next("tbody");
var grandchild = $(this).next("tbody td a");
//alert(parent + " | " + child + " | " + grandchild ); //always return undefined??
// Everything below works if I can get the IDs correct for child and grandchild
if($(grandchild).css('display')!='none'){
$(grandchild).click();
if($(grandchild).text()==" "){
$(child).hide();
};
};
});
I'd strongly suggest you need to re-think your IDs - they should be consistent, really.
If you absolutely must work with a variable ID, you can use the "id" attribute in a selector as with any other attribute:
// Any element, ID starts with "titl"
$('[id^="titl"]')
To capture that and re-use it, I'd really suggest you're doing something wrong with your IDs. However, for completeness (although I can't stress enough how much you should try to avoid having to use this), something based on this should be a good (haha, yeah right) starting point
// Long-winded messy hideous foul code
var $title = $('[id^="titl"]'),
title = $title.length && $title.eq(0).attr('id');
if (title !== 0)
{
$('#' + title + ' #' + title + '1 td a').html('Ow.');
}
I'm not sure I get this, but you can target any ID starting with titl, and then filter based on the ID in many other ways inside the function:
$('[id^="titl["]').on('click', function() {
var check = this.id.charAt(10) == '_', //tenth character is underscore ?
parent = $(this),
child = $(this).next("tbody"),
grandchild = $(this).next("tbody td a");
if (check) {
//element matching second selectortype clicked
}else{
if (grandchild.is(':visible')){
grandchild.trigger('click');
if (grandchild.text()==" ") child.hide();
}
}
});
I agree about rethinking your ids if you have control over them. Even if you don't, the StartsWith selector will get you all of the higher level elements, and you can traverse to the lower level ones. Remember that chaining the selectors means that you can match on similar patterns in ids, not paying any attention to the actual values.
One other note: I've never needed to resort to a regex match with jQuery. The CSS3-like selectors are just far too powerful for that.

Categories