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 ) { ... });
Related
I have the following JavaScript code:
var selectEnabledGenerators = function(generators) {
//List of generator indexes to show
var list = generators;
var allGenerators = $(".generatorContainer");
//Hide all generators
allGenerators.hide();
//maybe use filter here?
for (var i = 0, max = list.length; i < max; i++) {
$(".generatorContainer[data-generator=" + list[i] + "]").show();
}
};
Is there any way to rewrite the for loop using filter()?
I know that I can use a for each loop but I want to do this by using filter.
There's no need to use filter here. Since you're not returning anything forEach would be the more appropriate function.
Something along the lines of this should do:
list.forEach(item => $(".generatorContainer[data-generator=" + item + "]").show());
or
list.forEach(function(item){
$(".generatorContainer[data-generator=" + item + "]").show();
});
if you don't like/can't use lambdas
Can I use filter anyway
Yes. But there's really no reason to. If I saw you using filter in this way I would reject your code review.
The use case of filter is to quickly pare down a list of items by passing in a predicate function (a function that answers "does this stay in"). This function's type for an Array<T> would be T => boolean. This filter function will execute the predicate function's code block on every item and then check the return value of that predicate function. If that return value is truthy, it will mark that object that was passed into the predicate function and then return all the objects that resulted in truthy values as a new array. forEach will also execute a function on each parameter, just without doing the extra work of returning a value and managing a new list.
If you do not make use of the returned result from filter, it is nonsensical to use filter. Not only is it useless, it will confuse people reading your code in the future who are trying to understand why you use filter here.
Ultimately the code is the same:
list.filter(item => $(".generatorContainer[data-generator=" + item + "]").show());
The .show() is treated as a side effect (which filter functions really should not have).
You could use .filter() like this:
allGenerators.filter(function () {
return list.indexOf(+$(this).attr('data-generator')) > -1
}).show();
Simplified demo:
$('div').hide().filter(function (i) {
return [1,3].indexOf(+$(this).attr('data-generator')) > -1
}).show();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div data-generator=1>test1</div>
<div data-generator=2>test2</div>
<div data-generator=3>test3</div>
<div data-generator=4>test4</div>
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
doStuff(document.getElementById("myCircle1" "myCircle2" "myCircle3" "myCircle4"));
This doesn't work, so do I need a comma or semi-colon to make this work?
document.getElementById() only supports one name at a time and only returns a single node not an array of nodes. You have several different options:
You could implement your own function that takes multiple ids and returns multiple elements.
You could use document.querySelectorAll() that allows you to specify multiple ids in a CSS selector string .
You could put a common class names on all those nodes and use document.getElementsByClassName() with a single class name.
Examples of each option:
doStuff(document.querySelectorAll("#myCircle1, #myCircle2, #myCircle3, #myCircle4"));
or:
// put a common class on each object
doStuff(document.getElementsByClassName("circles"));
or:
function getElementsById(ids) {
var idList = ids.split(" ");
var results = [], item;
for (var i = 0; i < idList.length; i++) {
item = document.getElementById(idList[i]);
if (item) {
results.push(item);
}
}
return(results);
}
doStuff(getElementsById("myCircle1 myCircle2 myCircle3 myCircle4"));
This will not work, getElementById will query only one element by time.
You can use document.querySelectorAll("#myCircle1, #myCircle2") for querying more then one element.
ES6 or newer
With the new version of the JavaScript, you can also convert the results into an array to easily transverse it.
Example:
const elementsList = document.querySelectorAll("#myCircle1, #myCircle2");
const elementsArray = [...elementsList];
// Now you can use cool array prototypes
elementsArray.forEach(element => {
console.log(element);
});
How to query a list of IDs in ES6
Another easy way if you have an array of IDs is to use the language to build your query, example:
const ids = ['myCircle1', 'myCircle2', 'myCircle3'];
const elements = document.querySelectorAll(ids.map(id => `#${id}`).join(', '));
No, it won't work.
document.getElementById() method accepts only one argument.
However, you may always set classes to the elements and use getElementsByClassName() instead. Another option for modern browsers is to use querySelectorAll() method:
document.querySelectorAll("#myCircle1, #myCircle2, #myCircle3, #myCircle4");
I suggest using ES5 array methods:
["myCircle1","myCircle2","myCircle3","myCircle4"] // Array of IDs
.map(document.getElementById, document) // Array of elements
.forEach(doStuff);
Then doStuff will be called once for each element, and will receive 3 arguments: the element, the index of the element inside the array of elements, and the array of elements.
getElementByID is exactly that - get an element by id.
Maybe you want to give those elements a circle class and getElementsByClassName
document.getElementById() only takes one argument. You can give them a class name and use getElementsByClassName() .
Dunno if something like this works in js, in PHP and Python which i use quite often it is possible.
Maybe just use for loop like:
function doStuff(){
for(i=1; i<=4; i++){
var i = document.getElementById("myCiricle"+i);
}
}
Vulgo has the right idea on this thread. I believe his solution is the easiest of the bunch, although his answer could have been a little more in-depth. Here is something that worked for me. I have provided an example.
<h1 id="hello1">Hello World</h1>
<h2 id="hello2">Random</h2>
<button id="click">Click To Hide</button>
<script>
document.getElementById('click').addEventListener('click', function(){
doStuff();
});
function doStuff() {
for(var i=1; i<=2; i++){
var el = document.getElementById("hello" + i);
el.style.display = 'none';
}
}
</script>
Obviously just change the integers in the for loop to account for however many elements you are targeting, which in this example was 2.
The best way to do it, is to define a function, and pass it a parameter of the ID's name that you want to grab from the DOM, then every time you want to grab an ID and store it inside an array, then you can call the function
<p id="testing">Demo test!</p>
function grabbingId(element){
var storeId = document.getElementById(element);
return storeId;
}
grabbingId("testing").syle.color = "red";
You can use something like this whit array and for loop.
<p id='fisrt'>??????</p>
<p id='second'>??????</p>
<p id='third'>??????</p>
<p id='forth'>??????</p>
<p id='fifth'>??????</p>
<button id="change" onclick="changeColor()">color red</button>
<script>
var ids = ['fisrt','second','third','forth','fifth'];
function changeColor() {
for (var i = 0; i < ids.length; i++) {
document.getElementById(ids[i]).style.color='red';
}
}
</script>
For me worked flawles something like this
doStuff(
document.getElementById("myCircle1") ,
document.getElementById("myCircle2") ,
document.getElementById("myCircle3") ,
document.getElementById("myCircle4")
);
Use jQuery or similar to get access to the collection of elements in only one sentence. Of course, you need to put something like this in your html's "head" section:
<script type='text/javascript' src='url/to/my/jquery.1.xx.yy.js' ...>
So here is the magic:
.- First of all let's supose that you have some divs with IDs as you wrote, i.e.,
...some html...
<div id='MyCircle1'>some_inner_html_tags</div>
...more html...
<div id='MyCircle2'>more_html_tags_here</div>
...blabla...
<div id='MyCircleN'>more_and_more_tags_again</div>
...zzz...
.- With this 'spell' jQuery will return a collection of objects representing all div elements with IDs containing the entire string "myCircle" anywhere:
$("div[id*='myCircle']")
This is all! Note that you get rid of details like the numeric suffix, that you can manipulate all the divs in a single sentence, animate them... Voilá!
$("div[id*='myCircle']").addClass("myCircleDivClass").hide().fadeIn(1000);
Prove this in your browser's script console (press F12) right now!
As stated by jfriend00,
document.getElementById() only supports one name at a time and only returns a single node not an array of nodes.
However, here's some example code I created which you can give one or a comma separated list of id's. It will give you one or many elements in an array. If there are any errors, it will return an array with an Error as the only entry.
function safelyGetElementsByIds(ids){
if(typeof ids !== 'string') return new Error('ids must be a comma seperated string of ids or a single id string');
ids = ids.split(",");
let elements = [];
for(let i=0, len = ids.length; i<len; i++){
const currId = ids[i];
const currElement = (document.getElementById(currId) || new Error(currId + ' is not an HTML Element'));
if(currElement instanceof Error) return [currElement];
elements.push(currElement);
};
return elements;
}
safelyGetElementsByIds('realId1'); //returns [<HTML Element>]
safelyGetElementsByIds('fakeId1'); //returns [Error : fakeId1 is not an HTML Element]
safelyGetElementsByIds('realId1', 'realId2', 'realId3'); //returns [<HTML Element>,<HTML Element>,<HTML Element>]
safelyGetElementsByIds('realId1', 'realId2', 'fakeId3'); //returns [Error : fakeId3 is not an HTML Element]
If, like me, you want to create an or-like construction, where either of the elements is available on the page, you could use querySelector. querySelector tries locating the first id in the list, and if it can't be found continues to the next until it finds an element.
The difference with querySelectorAll is that it only finds a single element, so looping is not necessary.
document.querySelector('#myCircle1, #myCircle2, #myCircle3, #myCircle4');
here is the solution
if (
document.getElementById('73536573').value != '' &&
document.getElementById('1081743273').value != '' &&
document.getElementById('357118391').value != '' &&
document.getElementById('1238321094').value != '' &&
document.getElementById('1118122010').value != ''
) {
code
}
You can do it with document.getElementByID Here is how.
function dostuff (var here) {
if(add statment here) {
document.getElementById('First ID'));
document.getElementById('Second ID'));
}
}
There you go! xD
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.
Assume you have an array:
var arrStateCityAll=['CA_Alameda','CA__Pasadena','CA_Sacramento','NY_Albany','NY_Buffalo','NY_Ithaca']
Is there an easy way using javascript and/or jQuery to filter the arrStateCityAll to get a new array (a subset of arrStateCityAll); something like this:
// return's ['CA_Alameda','CA__Pasadena','CA_Sacramento']
var arrStateCityCA=FilterArray('CA',arrStateCityAll);
Likely you want to do a regex on each item. You can do this with jQuery's grep function.
http://api.jquery.com/jQuery.grep/
You can use javascript's Array.filter.
var arrStateCityAll = ['CA_Alameda','CA__Pasadena','CA_Sacramento','NY_Albany','NY_Buffalo','NY_Ithaca']
var arrStateCityCA = arrStateCityAll.filter( function (element) {
return element.indexOf("CA_") == 0;
});
The mozilla documentation linked to above has a solution for browsers that don't implicitly support filter.
This should work.
var arrStateCityCA = [];
for (var i = 0;i<arrStateCityAll.length;i++){
if (arrStateCityAll[i].substr(0,2) == 'CA'){
arrStateCityCA.push(arrStateCityAll[i]);
}
}
You could use jQuery.grep
var arrStateCityCA =
$.grep(arrStateCityAll,function(el,i){return (el.substring(0,2)=='CA')});
Demo at jsfiddle
To implement you actual FilterArray function as shown in your post you could do
function FilterArray(state,arr){
return $.grep(arr,
function(el,i) {return (el.substring(0,2)==state)}
);
}
This makes a few assumptions.
State is always 2 chars.
State is always the first 2 chars.
And of course remember case-sensitivity (this function is case sensitive) ie 'CA' not equal to 'Ca'.
if you are going to have an undescore between your state and city name, you can split on the underscore and test against the first array value
function getSubSetByState(set,state) {
var result = [];
for(var i=0,l=set.length;i<l;++i) {
if(set[i].split('_')[0] === state) {
result.push(set[i]);
}
}
return result;
}
Use if by giving it the set of places, and then the state you are searching for.