The context:
I need to get some dynamic ids that are inside a TD element, to pass it as a parameter and call an specific function.
I added a class (.calcStartPrice) to the TD, so that it helps me iterating inside its elements:
var inputEl, eventStartPrice, exchangeRate, convertedStartPriceEl, currSymbol, decimalPlaces;
jQuery(".calcStartPrice").each(function (i,e) {
jQuery(e).find('span, input').each(function (a,b) {
console.info(b.id);
});
});
When I run this code, I have the following ids:
eventStartPrice_S20_L10140
S20_L10140_startPrice
exchangeRate_S20_L10140
curSymbol_S20_L10140
decPlaces_S20_L10140
converted_StartPrice_S20_L10140
Now, what I want to do is to check whether the id starts with eventStartPrice, for example, so that I'll attribute the id to a variable.
What I tried:
var eventStartPrice;
jQuery(".calcStartPrice").each(function (i,e) {
jQuery(e).find('span, input').each(function (a,b) {
//console.info(b.id);
if (jQuery(b[id^="eventStartPrice"])) { //this is wrong!!!
eventStartPrice = b.id;
console.info(eventStartPrice);
}
});
});
But it didn't work...
How can I check inside that second iteration if the id starts with some string?
Replace :
if (jQuery(b[id^="eventStartPrice"])) { //this is wrong!!!
With :
if (/^eventStartPrice/.test(b.id)) {
You can use regexp :
if (b.id.match(/^eventStartPrice/)))
Try this:
$(b).is("[id^='eventStartPrice']")
basically, b is not a normal object, you need to wrap it into a jQuery object so that you can perform operations on it. Or, more accurately, you're trying to access b as a jQuery object when it isn't.
Use the jquery split method
id_val = b.id
name = id_val.split('_');
Now name[0] will contain characters before '_'.
You can easily compare it using if statement
if(name[0] == "eventStartPrice")
{
......
}
When u use jQuery each u get the dom element as this. If u then create a jQuery object of that u can apply all the magic to it. Thats what ur missing in ur code. So here is my sugestion how to rewrite ur function.
var eventStartPrice;
jQuery(".calcStartPrice").each(function (i,e) {
jQuery(e).find('span, input').each(function (a,b) {
var $this = jQuery(this);
if ($this.is("[id^=eventStartPrice]")) {
eventStartPrice = $this.attr("id");
console.info(eventStartPrice);
}
});
});
U can test it out in this fiddle
Related
I'm trying to access the class that was matched by a jQuery selector in a callback function. For example, if I have the following HTML,
<p class="someclass sorted-1 anotherclass">test</p>
I'd like to match this element and get the sorted-1 class name. The value 1 is arbitrary. Something like the following. getMatchedClass() is pseudo code. I thought I could get the value from $(this), but I'm not seeing it.
$('[class*=sorted-]').on('click', function() {
var className = getMatchedClass();
console.log(className); // should output 'sorted-1'
});
Does anyone know if this is possible? I'm having a hard time coming up with search terms. I keep getting results on selected values which isn't what I want.
Thanks
Update
Based on #maheer-ali's answer I came up with the following solution.
$(function() {
function column(className) {
const regex = /sorted-([0-9]+)/;
return className.match(regex)[0].replace(regex, '$1');
}
$('[class*=sorted-]').each(function(i, r) {
// col is the dashed number after sorted
// if parsing `sorted-42`, `col` would equal 42
const col = column($(r).context.className);
// Use the `col` value here.
$(r).doSomething({ column: col });
});
});
You can use a match() and regular expression. And get the first element of result array.
$('[class*=sorted-]').on('click', function() {
var className = this.className.match(/sorted-[0-9]+/)[0];
console.log(className); // should output 'sorted-1'
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<p class="someclass sorted-1 anotherclass">test</p>
The other way is to use split() and startsWith(). split() the className by " " and use find() to get element element with startsWith the string "sorted-"
$('[class*=sorted-]').on('click', function() {
var className = this.className.split(' ').find(x => x.startsWith('sorted-'))
console.log(className); // should output 'sorted-1'
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<p class="someclass sorted-1 anotherclass">test</p>
The callback function that you're passing is called with the event that triggered it.
You can access event.target.classList to get an array of all of the classes on that object. If you have a fixed set of class patterns you're looking for, you could search that list for the class.
Hope this helped!
How to do the equivalent of this in jquery?
var myCollection = $(".sortable");
var link = _.find(myCollection, function(item){
return someInput.value == $(item).data("sort-column");
});
Knowing why you're trying to do this would help, but I don't think there's a built in function to replace for the underscore one. One of the comments mentions filter, but that is not the same as underscore's _.find, since find returns for the first found element.
That's the only suggestion I have, but that's just a forEach
var item
$.each(myCollection,function( index, element ) {
if ( condition ) {
item = element
return false
}
});
You can use $.grep
Finds the elements of an array which satisfy a filter function. The original array is not affected.
https://api.jquery.com/jQuery.grep/
var link = $(".sortable[data-sort-column=" + someInput.value + "]");
Have you looked at jQuery's each?
You might format it more like:
myCollection.each(function( item ) { ... });
I found another similar question about this with a solution but it didn't work for me. I am new to jquery so thanks in advance for helping me solve my noobie question.
I am trying to use a variable for the class name. So that I can loop through the right fields based on this variable. My variable returns .reqfields4 but I get this error Error: Syntax error, unrecognized expression: ", if I enter the value manually, it works.
How can I achieve this? Thanks.
var reqsection='\".reqfields4\"';
$(".reqfields4").each ( function() {
//$(reqsection).each ( function() {
if(( $(this).val())==''){
some code...
}
else{
some code...
}
});
Just change var reqsection='\".reqfields4\"'; to var reqsection='.reqfields4'; - you don't need the inner string quotes.
You don't need quotes inside the value of the variable:
var reqsection = '.reqfields4';
$(reqsection).each( ... );
If you have a class name — just a class name — you can add the .:
var reqsection = 'reqfields4';
$('.' + reqsection).each( ... )
You can try like follows,
var reqsection=".reqfields4";
$(reqsection).each ( function() {
if(( $(this).val())==''){
some code...
}
else{
some code...
}
});
If you say var reqsection= '\".reqfields4\"';
then
$(reqsection).each( function() {});
Consider it like like you told jQuery this:
$(' ".reqfields4" ').each( function() {});
In other words you said: [ Please select now ".reqfields4" including the quotemarks ]. All class selectors must start with dot(.), but you just started your jQuery selector with a quotemark (") so of course it won't work at all (it won't try to select any classes, of course), and probably would throw an error from jQuery - I don't think ANY jQuery selector string can have quotemark(") as the actual first character of the selector!.
If you do this instead:
var reqsection= ".reqfields4";
$(".reqfields4").each( function() {});
$(reqsection).each( function() {});
The above two lines are equivalent.
What is the best way to get the complement of a jQuery selector's result set? I want to do something like the following:
jQuery(this).find("div:contains('someValue')").show();
But I want the complement of this selection hidden:
jQuery(this).find("div:not(:contains('someValue'))").hide();
Is there a more elegant solution to this than just executing the complementary selector? An alternative I can see is finding all divs first, storing the result, and filter this:
var results = jQuery(this).find("div");
results.find(":contains('someValue')").show();
results.find(":not(:contains('someValue'))").hide();
But that doesn't seem that much better. Any ideas?
var results = jQuery(this).find("div"),
selector = ":contains('someValue')";
results.filter(selector).show();
results.not(selector).hide();
as #Simon mentioned in the comments there is a way to improve this particular solution:
var results = jQuery("div", this),
selector = ":contains('someValue')";
results.filter(selector).show();
results.not(selector).hide();
Try like this,
jQuery(this).find("div").hide();
jQuery(this).find("div:contains('someValue')").show();
Well, I think your code is fairly good, but another option could be running this single statement:
jQuery(this).find("div").each(
function() {
var me = $(this);
var f = me.is(":contains('someValue')") ? "show" : "hide";
me[f]();
}
);
/** $.grepl
* uses a regular expression for text matching within an internal $.grep.
*/
$.extend({
"grepl": function(el, exp){
exp=new RegExp(exp,'gi'); // create RegExp
return $(
this.grep( el, function(n,i){ // run internal grep
return el[i].textContent.match(exp) != null; // match RegExp against textContent
})
);
}
});
$.grepl( $('div'), '^.*someRegexp.*$' ).css('display','none'); // usage of the function
I know that this does not exactly use the ":contains" expression, but the result should be the same.
I am currently learning jQuery. I know that jQuery is a custom library for JavaScript.
I am doing some learning examples in a book that is only using JavaScript, and to further my learning experience, I am trying to make use of jQuery for anything that might be more efficient.
So, I have this code:
function addLetter(foo) {
$(foo).unbind('click');
var tileLetter = $(foo).attr('class').split(' ');
var letter = tileLetter[2].charAt(1);
if (document.getElementById('currentWord').childNodes.length > 0) {
$('#currentWord p').append(letter);
} else {
var p = document.createElement('p');
var txt = document.createTextNode(letter);
p.appendChild(txt);
$('#currentWord').append(p);
}
}
Question #1:
If I change document.getElementById('currentWord').childNodes.length to $('#currentWord').childNodes.length it doesn't work. I thought the jQuery selector was the same thing as the JS document.getElementById as that it brought me back the DOM element. If that was the case, it'd make sense to be able to use the .childNodes.length functions on it; but it doesn't work. I guess it's not the same thing?
Question #2:
The code is textbook code. I have added all the jQuery that there is in it. My jQuery knowlede is limited, is there a more efficient way to execute the function?
The function's purpose:
This function is supposed to create a p element and fill it with a Text Node if it's the first time it's run. If the p element has already been created, it simply appends characters into it.
This is a word generating game, so you click on a letter and it gets added to a 'currentWord' div. The tile's letter is embedded in the 3rd css class, hence the attr splitting.
Thanks!
document.getElementById('currentWord')
returns a DOM object whereas $('#currentWord') returns a DOM object wrapped inside a jQuery object.
To get the plain DOM object you can do
$('#currentWord').get(0)
So
$('#currentWord').get(0).childNodes.length
should work.
Question #1:
jQuery returns a jQuery object. To return it to a regular javascript object use $(object)[0] and you can then treat it as a plain javascript (or DOM) object.
Question #2:
The efficiency looks good to me. Although you might want to use spans instead of p elements.
I guess one thing you could do (even though yours looks to run very fast) is cache the dom element:
function addLetter(foo) {
$(foo).unbind('click');
var tileLetter = $(foo).attr('class').split(' ');
var letter = tileLetter[2].charAt(1);
var currentWord = document.getElementById('currentWord');
if (currentWord.childNodes.length > 0) {
$(currentWord).find('p').append(letter);
} else {
var p = document.createElement('p');
p.innerHTML = letter;
currentWord.appendChild(p);
}
}
Calls to the jQuery() function ($()) return a jQuery object containing the matching elements, not the elements themselves.
Calling $('#some-id') will, then, return a jQuery object that contains the element that would be selected by doing document.getElementById('some-id'). In order to access that element directly, you can get it out of that jQuery object, using either the .get() function or an array index syntax: $('#some-id')[0] (it's 0-indexed).
I think you can replace all of this with a call to the text function.
function addLetter(foo) {
$(foo).unbind('click');
var tileLetter = $(foo).attr('class').split(' ');
var letter = tileLetter[2].charAt(1);
var currentWordP = $('#currentWord p');
if (currentWordP.size() > 0) {
currentWordP.text(currentWordP.text() + letter);
} else {
$('#currentWord').append("<p>" + letter + "</p>");
}
}
1: Use $.get(0) or $[0] to get the DOM element. e.x. $('#currentWord')[0].childNodes.length.
2: Try this:
function addLetter(foo) {
$(foo).unbind('click');
var tileLetter = $(foo).attr('class').split(' ');
var letter = tileLetter[2].charAt(1);
if ($('#currentWord p').length > 0) {
$('#currentWord p').append(letter);
} else {
$('#currentWord').append(
$('<p />', { text: letter })
);
}
}
Question #1:
document.getElementById returns DOM object. more
childNodes.length is property of Node object which is returned by document.getElementById.
jQuery selector returns jQuery object more. You can get DOM object from jQuery object using .get
$('#IDselector').get(0) = document.getElementById('IDselector')
Question #2:
function addLetter(foo) {
$(foo).unbind('click');
var tileLetter = $(foo).attr('class').split(' ');
var letter = tileLetter[2].charAt(1);
if ($('currentWord p').length > 0) {
$('#currentWord p').append(letter);
} else {
var p = $('<p />').text(letter);
$('#currentWord').append(p);
}
}