Suppose in jQuery I push DOM elements into an array,
var elemarray = [];
elemarray.push($('#elem1'));
elemarray.push($('#elem2'));
Would it be possible to then use $.inArray to determine if the array contains an element?
if ( $.inArray($('#elem2'), elemarray) > -1 ) { .. }
The only examples I saw for primitive types, strings and numbers.
JSFiddle, not working: https://jsfiddle.net/5knyrcph/2/
The problem is that you are not storing DOM elements, but jQuery wrappers. Every time you create such a wrapper, it is a new jQuery object.
Instead use the real DOM elements themselves, which with jQuery you can get with .get():
var elemarray = [];
elemarray.push($('#elem1').get(0));
elemarray.push($('#elem2').get(0));
if ($.inArray($('#elem1').get(0), elemarray) > -1) {
console.log('Found');
}
else {
console.log('Not found');
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="elem1">
Test
</div>
<div id="elem2">
Test2
</div>
In HTML5 / ES6 you can do this without jQuery in shorter code:
const elemSet = new Set([elem1, elem2]);
if (elemSet.has(elem1)) {
console.log('Found');
}
else {
console.log('Not found');
}
<div id="elem1">
Test
</div>
<div id="elem2">
Test2
</div>
You really should use !== -1
And here is the fiddle to the corrected JS: https://jsfiddle.net/5knyrcph/3/
Code:
var elemarray = [];
elemarray.push($('#elem1').text());
elemarray.push($('#elem2').text());
alert(elemarray[0]);
if ($.inArray($('#elem1').text(), elemarray) !== -1) {
alert('Found');
}
else {
alert('Not found');
}
Jquery return an Array of items that match the criteria, so when ever you select an element it always will construct a brand new array of objects that match your criteria, in order to compare the elements you need to either get the element inside the array with these two options:
$(".element")[position]; //or
$(".element").get(position);
If in your fiddle instead of pushing the Jquery object, you push the actual element, then you'll get your results right.
Fiddle Updated
Hope this help
Related
I have search through quite a lot of questions here, but havent found one that i think fits my bill, so if you know of one please link to it.
I have an array that i want to search through for a specific number and if that number is in the array, i then want to take an action and if not then another action.
I have something like this
var Array = ["1","8","17","14","11","20","2","6"];
for(x=0;x<=Array.length;x++)
{
if(Array[x]==8)
then change picture.src to srcpicture1
else
then change picture.src to srcpicture2
}
but this will run the lenght of the array and end up checking the last element of the array and since the last element is not 8 then it will change the picture to picture2.
Now i can see why this happens, i just dont have any ideas as to how to go about checking if an array contains a specific number.
Thanks in advance.
What you can do is write yourself a function to check if an element belongs to an array:
function inArray(array, value) {
for (var i = 0; i < array.length; i++) {
if (array[i] == value) return true;
}
return false;
}
And the just do:
var arr = ["1","8","17","14","11","20","2","6"];
if (inArray(arr, 8)) {
// change picture.src to srcpicture1
} else {
// change picture.src to srcpicture2
}
It's a lot more readable to me.
For extra points you can add the function to the array prototype like so:
Array.prototype.has = function (value) {
for (var i = 0; i < this.length; i++) {
if (this[i] === value) return true;
}
return false;
};
And then the call would be
if (arr.has(8)) // ...
Pushing this even further, you can check for indexOf() method on array and use it - if not - replace it with the code above.
P.S. Try not to use Array for a variable name, since it's reserved for the actual array type.
use this
http://developer.mozilla.org/En/Core_JavaScript_1.5_Reference/Objects/Array/IndexOf
ie version
https://developer.mozilla.org/En/Core_JavaScript_1.5_Reference/Objects/Array/IndexOf#Compatibility
Why don't just you abort the loop when you find the right number :
for(x=0;x<=Array.length;x++)
{
if(Array[x]==8) {
//change picture.src to srcpicture1
break;
}
}
You could sort the array first then check the array only up to the point at which a number would be in the array, were it to exist.
If you have unique keys and a faster retrieval is what you care about a lot, you can consider using a map instead of an array (if there's a hard-bound case of using an array, then it won't work of course). If using a map, you just check "if( num in arr ) ".
I am looking to select the common parent of multiple nested elements for which I only know the inner text.
For example, in the following code:
<unknown>
<unknown class="unknown">
....
<unknown>
<unknown>Sometext</unknown>
</unknown>
<unknown>
<unknown>Sometext</unknown>
</unknown>
<unknown>
<unknown>Sometext</unknown>
</unknown>
....
</unknown>
</unknown>
I would like to get the closest element (common parent) that has class unknown in this scenario. I do not know the actual tags or class names. I only know that the nest element contains the "Sometext". I know this can be done through a loop using jQuery/Javascript, but is there a CSS selector that I can use with jQuery to find this? I tried using a combination of closest(), parents(), parentsUntil() but I can't seem to get to this element.
Thank you!
First, you need to ensure you only match the leaf nodes (nodes with no child nodes), so use:
:not(:has(*))
So to find all the exact matches (just the leaf nodes), use:
var matches = $(':not(:has(*))').filter(function () {
return $(this).text() == "Sometext";
});
or just using a combined filter on all elements (with an added check for 0 children):
var matches = $('*').filter(function () {
return !$(this).children().length && $(this).text() == "Sometext";
});
Note: I have not yet tested which of these two options is fastest.
Then you need to find the first ancestor (of the first match), that contains all the matches:
var commonparent = matches.first().parents().filter(function () {
return $(this).find(matches).length == matches.length;
}).first();
JSFiddle: http://jsfiddle.net/TrueBlueAussie/v4gr1ykg/
Based on David Thomas' suggestion, here it is as a pair of jQuery extensions (commonParents() and commonParent()) that may be of future use for people:
To find all common parents of a jQuery collection use `commonParents()':
$.fn.commonParents = function (){
var cachedThis = this;
return cachedThis.first().parents().filter(function () {
return $(this).find(cachedThis).length === cachedThis.length;
});
};
JSFiddle: (commonParents): http://jsfiddle.net/TrueBlueAussie/v4gr1ykg/3/
To find the closest common parent of a jQuery collection use commonParent():
$.fn.commonParent = function (){
return $(this).commonParents().first();
};
JSFiddle: (commonParent): http://jsfiddle.net/TrueBlueAussie/v4gr1ykg/2/
Notes:
jQuery optimises the combined use of first() in commonParent with the commonParents filter() and it only calls the code in commonParents until a first match is made, so commonParent does not need to be made more efficient.
This should do the job. You basically find all the relevant parents of all the matching elements, get the intersection of each of those sets, then grab the first one to get the most nested common parent.
You can even wrap it up as as jquery plugin.
if(console && console.clear) console.clear();
// create a handy intersection method for Arrays
// see http://stackoverflow.com/a/16227294/1901857
Array.prototype.intersect = function(arr) {
var a = this, b = arr;
var t;
if (b.length > a.length) t = b, b = a, a = t; // indexOf to loop over shorter
return a.filter(function (e) {
return b.indexOf(e) > -1;
});
};
;(function($) {
$.fn.commonParents = function(selector) {
// find all relevant parents for each element and get set intersection
// pushStack means you can use end() etc in chaining correctly
return this.pushStack(sometexts.get().reduce(function(prevParents, el) {
// common parents for this element - note the lowest level parent is first
var parents = $(el).parents(selector || '*').get();
// intersect with the previous value (or itself if first)
return (prevParents || parents).intersect(parents);
}, null), "commonParents", arguments);
};
})(jQuery);
// text to search for
var search = "Sometext";
// parent selector to filter parents by e.g. '.unknown' - use null for all parents
var parentSelector = null;
// find everything containing search
var sometexts = $(":contains('" + search + "')").filter(function() { return $(this).text() == search; });
// grab the first common parent - the lowest level one - or null if there isn't one
var commonParent = sometexts.commonParents(parentSelector).get(0);
console.log(commonParent);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div>
<div class="unknown test">
<div class="unknown test2">
<div class="unknown">
<div>Sometext</div>
</div>
<div>
<div>Sometext</div>
</div>
<div>
<div>Sometext</div>
</div>
</div>
</div>
</div>
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
Using this syntax:
var position = array($('#ipadmenu > section').attr('data-order'));
I cannot get my code to work. I have never used arrays before so im kind of lost on how to use them. (especially in jquery).
How would I make an array of all section elements and associate the value of data-order to that list. Example:
first section - data-order:1
second section - data-order:2
etc and then use that info afterwards.
Thank you!
Since .attr just gets one attribute -- the first one found by the jQuery selector -- you need to build your array element by element. One way to do that is .each (you can also use .data to extract data attributes):
var position = new Array;
$('#ipadmenu > section').each(function() {
position.push($(this).data('order'));
});
alert(position[0]); // alerts "1"
This will be an indexed array, not an associative array. To build one of those (which in JavaScript is technically an object, not any kind of array) just change the inner part of your .each loop:
var position = {};
$('#ipadmenu > section').each(function(i) {
position["section"+i] = $(this).data('order');
});
The resulting object position can now be accessed like:
alert(position['section1']); // alerts "1"
A different approach involves using jQuery.map, but since that only works on arrays, not jQuery objects, you need to use jQuery.makeArray to convert your selection into a true array first:
var position = $.map($.makeArray($('#ipadmenu > section')), function() {
return $(this).data('order');
} ); // position is now an indexed array
This approach is technically shorter than using .each, but I find it less clear.
Javascript:
var orders = [];
$('#ipadmenu > section').each(function() {
orders.push($(this).data('order'))
});
HTML:
<div id="ipadmenu">
<section data-order="1">1</section>
<section data-order="2">2</section>
</div>
You will want to do something like this:
// Get the elements and put them in an array
var position = $('#ipadmenu section').toArray();
console.log(position);
// Loop through the array
for (var i = 0; i < position.length; i++){
// Display the attribute value for each one
console.log("Section " + i + ": " + $(position[i]).attr('data-order'));
}
Working example here: http://jsfiddle.net/U6n8E/3/
I need to get the ID of an element but the value is dynamic with only the beginning of it is the same always.
Heres a snippet of the code.
<form class="form-poll" id="poll-1225962377536" action="/cs/Satellite">
The ID always starts with poll- then the numbers are dynamic.
How can I get the ID using just JavaScript and not jQuery?
You can use the querySelector for that:
document.querySelector('[id^="poll-"]').id;
The selector means: get an element where the attribute [id] begins with the string "poll-".
^ matches the start
* matches any position
$ matches the end
jsfiddle
Try this.
function getElementsByIdStartsWith(container, selectorTag, prefix) {
var items = [];
var myPosts = document.getElementById(container).getElementsByTagName(selectorTag);
for (var i = 0; i < myPosts.length; i++) {
//omitting undefined null check for brevity
if (myPosts[i].id.lastIndexOf(prefix, 0) === 0) {
items.push(myPosts[i]);
}
}
return items;
}
Sample HTML Markup.
<div id="posts">
<div id="post-1">post 1</div>
<div id="post-12">post 12</div>
<div id="post-123">post 123</div>
<div id="pst-123">post 123</div>
</div>
Call it like
var postedOnes = getElementsByIdStartsWith("posts", "div", "post-");
Demo here: http://jsfiddle.net/naveen/P4cFu/
querySelectorAll with modern enumeration
polls = document.querySelectorAll('[id ^= "poll-"]');
Array.prototype.forEach.call(polls, callback);
function callback(element, iterator) {
console.log(iterator, element.id);
}
The first line selects all elements in which id starts ^= with the string poll-.
The second line evokes the enumeration and a callback function.
Given that what you want is to determine the full id of the element based upon just the prefix, you're going to have to do a search of the entire DOM (or at least, a search of an entire subtree if you know of some element that is always guaranteed to contain your target element). You can do this with something like:
function findChildWithIdLike(node, prefix) {
if (node && node.id && node.id.indexOf(prefix) == 0) {
//match found
return node;
}
//no match, check child nodes
for (var index = 0; index < node.childNodes.length; index++) {
var child = node.childNodes[index];
var childResult = findChildWithIdLike(child, prefix);
if (childResult) {
return childResult;
}
}
};
Here is an example: http://jsfiddle.net/xwqKh/
Be aware that dynamic element ids like the ones you are working with are typically used to guarantee uniqueness of element ids on a single page. Meaning that it is likely that there are multiple elements that share the same prefix. Probably you want to find them all.
If you want to find all of the elements that have a given prefix, instead of just the first one, you can use something like what is demonstrated here: http://jsfiddle.net/xwqKh/1/
I'm not entirely sure I know what you're asking about, but you can use string functions to create the actual ID that you're looking for.
var base = "common";
var num = 3;
var o = document.getElementById(base + num); // will find id="common3"
If you don't know the actual ID, then you can't look up the object with getElementById, you'd have to find it some other way (by class name, by tag type, by attribute, by parent, by child, etc...).
Now that you've finally given us some of the HTML, you could use this plain JS to find all form elements that have an ID that starts with "poll-":
// get a list of all form objects that have the right type of ID
function findPollForms() {
var list = getElementsByTagName("form");
var results = [];
for (var i = 0; i < list.length; i++) {
var id = list[i].id;
if (id && id.search(/^poll-/) != -1) {
results.push(list[i]);
}
}
return(results);
}
// return the ID of the first form object that has the right type of ID
function findFirstPollFormID() {
var list = getElementsByTagName("form");
var results = [];
for (var i = 0; i < list.length; i++) {
var id = list[i].id;
if (id && id.search(/^poll-/) != -1) {
return(id);
}
}
return(null);
}
You'll probably have to either give it a constant class and call getElementsByClassName, or maybe just use getElementsByTagName, and loop through your results, checking the name.
I'd suggest looking at your underlying problem and figure out a way where you can know the ID in advance.
Maybe if you posted a little more about why you're getting this, we could find a better alternative.
You use the id property to the get the id, then the substr method to remove the first part of it, then optionally parseInt to turn it into a number:
var id = theElement.id.substr(5);
or:
var id = parseInt(theElement.id.substr(5));
<form class="form-poll" id="poll-1225962377536" action="/cs/Satellite" target="_blank">
The ID always starts with 'post-' then the numbers are dynamic.
Please check your id names, "poll" and "post" are very different.
As already answered, you can use querySelector:
var selectors = '[id^="poll-"]';
element = document.querySelector(selectors).id;
but querySelector will not find "poll" if you keep querying for "post": '[id^="post-"]'
If you need last id, you can do that:
var id_list = document.querySelectorAll('[id^="image-"]')
var last_id = id_list.length
alert(last_id)