How to use StartsWith selector on a variable? - javascript

According to jQuery's API StartsWith selector is intended to be used on the entire document.
For example,
var $elements = $( "span[id^='MJXc']" );
will find all <span>s in the DOM that have IDs starting with 'MJXc'.
But what if I have an array of elements stored in a variable and I want to select only those elements that start with ... out of that array? Can I still use the StartsWith selector?
The following doesn't seem to work and gives out Uncaught SyntaxError: Unexpected token (
var $elements = $arrayofelements.( "span[id^='MJXc']" );
I did not add or remove any brackets, I just stuck a variable in front of the selector.
$arrayofelements looks like this in console:
0:span#MJXc-Node-7.mjx-mrow
1:span#MJXc-Node-28.mjx-mi
2:span.mjx-base
3:span#MJXc-Node-34.mjx-mi
Ideally, I would like to get elements 0, 1, and 3 reuturned, skipping element 2 as it doesn't have ID starting with 'MJXc'.

Use the .filter() method in JQuery.
$arrayOfElements.filter('span[id^=MJXc]');
Like most JQuery methods, it takes a selector. It returns a new JQuery object containing only the elements that matched the selector (in this case, a span with an ID starting with MJXc).
// get only the spans inside #parent div
$spansToFilter = $('#parent').children();
$filteredSpans = $spansToFilter.filter('[id^=MJXc]');
// prove we've filtered out the span with no matching ID
$filteredSpans.each(function(i, item) {
console.log(item);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<span id="MJXc-Node-7.mjx-mrow">(external skip)</span>
<div id="parent">
<span id="MJXc-Node-7.mjx-mrow">A</span>
<span id="MJXc-Node-28.mjx-mi">B</span>
<span class=".mjx-base">(skip C)</span>
<span id="MJXc-Node-34.mjx-mi">D</span>
</div>
What you tried didn't work because in Javascript whatever.() would be invalid; You'd be trying to call a function with no name. In JQuery and javascript, you are always calling methods on the previous object in the chain obj.method(). Those methods are returning new JQuery objects which have the same set of methods, which is what allows the chaining to be possible. All the methods JQuery objects have are listed in the JQuery documentation, including .filter(), .find(), .children(), etc.

javascript specific answer:
from your $elements array, you can simply check whether the id of your element startsWith() a particular prefix or not. It it does, then you can simply push it into new array.
var $selectedElements = [];
for(var i=0; i<$elements.length; i++)
if($elements[i].id.startsWith("MJXc"))
$selectedElements.push($elements[i]);

Related

Correct jQuery Syntax for accessing text of array in one line

I am trying to access the text of the first "th" element of the first element of "rows" with jQuery and would like to do so in one line
var currentStation = $(rows[0]).find("th")[0].text();
What would be the correct syntax to do so?
I am able to get the "th" element, but as soon as I try to access the text I get error messages.
I already tried numerous variations of different brackets combinations, but each one threw me errors.
The issue is that your [0] on find("th") takes the HTML element out of the jQuery object. The easiest way to do this is to either use innerText instead of text:
var currentStation = $(rows[0]).find("th")[0].innerText;
Or don't use [0], rather first:
var currentStation = $(rows[0]).find("th:first").text();
(Or another first):
var currentStation = $(rows[0]).find("th").first().text();
text() is a method on jQuery objects.
You are extracting the DOM element object from the jQuery object and then trying to call text() on the DOM element object.
Use the :first selector instead (note this is a jQuery selector and not a CSS selector)
const $firstRow = $(rows[0]);
const $firstTh = $firstRow.find("th:first");
var currentStation = $firstTh.text();

How can I log the number of a specific DOM element into the console?

I'm trying to log the number of elements in a html document that have the id "para" here is the code so far
window.addEventListener("load",init);
function init(){
var b = document.getElementById("para");
console.log(b);
}
so far it will only log the element itself and not the number of them in the html document
var b = document.getElementById("para");
Note the singular in this class, it only returns a single element (or null).
If your document is well-formed, there will only be ONE element with the ID of para. That is one of the things that separates IDs from classes.
You have two solutions.
Get away from using ID and use either class or data-* attributes
use document.querySelectorAll("#para")
Of the two, I recommend fixing your HTML.
Demo code in reference to a comment
var list = document.querySelectorAll("#test-span");
console.log(list.length);
<span id="test-span">1</span>
<span id="test-span">1</span>
<span id="test-span">1</span>

jQuery.find() returns an object even when there's no matching child element in the DOM

I am trying to find an element with the ID '' that is within the element '', and therefore is its child.
I am using the $.find method to perform the search.
If the child object is found, I'd like to perform some actions, and if the child object isn't found, I'd like to do different things.
However, even though I know that there is no such child element existing, the jQuery.find method reports an object that I am not sure, from inspecting in the Watches window, what it is.
Here's the relevant code snippet:
function CreateResourceKeyTextBox(resourceKeyId, editMode) {
var resourceKeyTableCell = $("#tdKeyResourceKeyId" + resourceKeyId);
var resourceKeyNameTextBox = null;
var alreadyExistingResourceKeyNameTextBox = resourceKeyTableCell.find('#txtResourceKeyName' + resourceKeyId);
if (alreadyExistingResourceKeyNameTextBox != null && typeof alreadyExistingResourceKeyNameTextBox != "undefined") {
resourceKeyTableCell.html('');
resourceKeyNameTextBox = alreadyExistingResourceKeyNameTextBox;
resourceKeyNameTextBox.css('display', 'block');
resourceKeyNameTextBox.appendTo('#tdKeyResourceKeyId' + resourceKeyId);
resourceKeyNameTextBox.css('width', '96%');
}
jQuery query functions always return an object, even if there's no matching DOM elements.
Check the length, it will be 0 if there's no element in the set :
if (alreadyExistingResourceKeyNameTextBox.length ...
jquery's find method returns a jquery object whose internal matched elements are the corresponding elements to your css selector.
If css selector fails to match any elements, then, jquery's find method's return object's internal matched elements is an empty array. You can get internal matched elements with .get method as follows:
var elems = $.find(css_selector).get()
this method returns array of DOM elements not jquery object instances, and you can check empty array using following syntax
var elems = $.find(css_selector).get()
if(elems.length === 0){
//array is empty
}else{
//array is not empty
}
This behaviour of jquery minimizes any syntax errors you might get otherwise, jquery will work without errors, no matter your css selector matches any DOM elements or not. This is beneficial in most cases, where you simply apply some changes on matched elements regardless of there are any. If existence of such elements is critical to your business logic, you should check it manually.
You should use alreadyExistingResourceKeyNameTextBox.length != 0 instead I think
if an object is not found using jquery .find() method, it always return an empty array. if you are getting anything other than that, you need to check your DOM. You can always check the length of the result i.e. result.length > 0 || result.length === 1, depending on your need

Mootools Selector issue

Right now I have a dynamic string that assigns it's values to a particular div class.
Output looks like this
<div class="12923"></div>
I want to find that 'randNumber' div, then check if it has another class 'x'
Currently what I have now doesn't work:
var randNumber = 12923
var lookingForYou = $$('.'+randNumber);
if (lookingForYou.hasClass('XCLASS')){alert('XCLASS FOUND!');}
$$ returns an Elements instance, Elements is an array-like Class
anyway since you are basically filtering, you can tell Slick that you need an element with both class:
var randNumber = 12923;
if($$('.' + randNumber +'.XCLASS').length>0){
alert('XCLASS FOUND');
}else{
//dostuff
}
or you could just use one of the Elements methods, I think .some will be your best choice here:
var randNumber = 12923
var lookingForYou = $$('.' + randNumber);
alert(lookingForYou.some(function(el){
return el.hasClass('XCLASS');
}))
EDIT:
adding some links:
A better way to use Elements on MooTools blog
in my second example I used the some method, which, by looking at the source is not overloaded, but is just the one in Array.prototype.some:
Element.js source reference
Array.some on MDN
$$ returns an array of all matching elems. Not sure if you can do a hasclass on an array. Might have to do a .each() then do it. Try $('body').getElement('.'+randNumber).hasClass('XCLASS') this way you grab 1 elem if you don't want to mess with the array.
Here:
if (lookingForYou.hasClass('XCLASS')){alert('XCLASS FOUND!');}
$$() returns an array, and hasClass() performs the check on each element of the array, returning an array of booleans. Unfortunately, when you check if (...), then the return array, even if all of the values are false, is evaluated as true because it's non-empty.

Retrieving an element by array index in jQuery vs the each() function

I was writing a "pluginable" function when I noticed the following behavior (tested in FF 3.5.9 with Firebug 1.5.3).
$.fn.computerMove = function () {
var board = $(this);
var emptySquares = board.find('div.clickable');
var randPosition = Math.floor(Math.random() * emptySquares.length);
emptySquares.each(function (index) {
if (index === randPosition) {
// logs a jQuery object
console.log($(this));
}
});
target = emptySquares[randPosition];
// logs a non-jQuery object
console.log(target);
// throws error: attr() not a function for target
board.placeMark({'position' : target.attr('id')});
}
I noticed the problem when the script threw an error at target.attr('id') (attr not a function). When I checked the log, I noticed that the output (in Firebug) for target was:
<div style="width: 97px; height: 97px;" class="square clickable" id="8"></div>
If I output $(target), or $(this) from the each() function, I get a nice jQuery object:
[ div#8.square ]
Now here comes my question: why does this happen, considering that find() seems to return an array of jQuery objects? Why do I have to do $() to target all over again?
[div#0.square, div#1.square, div#2.square, div#3.square, div#4.square, div#5.square, div#6.square, div#7.square, div#8.square]
Just a curiosity :).
.find() returns not an array of jQuery objects, but one jQuery object containing an array of DOM elements (a jQuery object, at it's core, is a wrapper around a DOM element array).
When you're iterating through, each element you're on is a DOM element. So, it needs to be wrapped in $(this) to become jQuery object and have access to those methods.
Also as a side note: The id attribute can't begin with a number, since it's invalid HTML you may or may not experience strange behavior, especially cross-browser (this rule applies for any invalid HTML).
No, the find method doesn't return an array of jQuery objects. You are creating a jQuery object for each element here:
console.log($(this));
If you log the value without creating a jQuery object from it:
console.log(this);
you will see that it's an element, not a jQuery object.
When you access the jQuery object as an array, you get an element. If you want a jQuery object you have to create one from the element.

Categories

Resources