I have written following code in html:
<input type="text" id="id_1" name="text_1">
<input type="text" id="id_2" name="text_2">
<input type="text" id="id_3" name="text_3">
Here I have to get all textBoxes in an array in javascript function whose id starts with "id". So, that I can get above two textBoxes in an array.
How to get all textBoxes whose id start with "id"?
var nodeList = document.querySelector("input[name^='text_'")
A nodeList should be sufficiently like an array for your purposes.
Note that support for querySelector might not be sufficient for your purposes (in which you will need to getElementsByTagName and then filter the results in a loop).
Alternatively you could use a library which provides its own selector engine. In YUI 3 you could:
var listOfYUIObjects = Y.all("input[name^='text_'");
Mootools, Prototype, jQuery and a host of other libraries provide similar functionality.
var ele = document.getElementsByTagName("input");
var matchingEle = [];
var eleName = '';
for (var i = 0; i < ele.length; ++i) {
el = ele[i];
eleName = el.getAttribute("name");
if (eleName && eleName.indexOf("text_") == 0) {
matchingEle.push(el);
}
}
You could use a generic function that filters a list of elements based on a pattern. This is useful if you want to do a similar thing in future but with different criteria on the properties.
http://jsfiddle.net/3ZKkh/
function filter(elements, pattern) {
var i, j, match, e, f = [];
for (i = 0; i < elements.length; i += 1) {
e = elements[i];
match = true;
for (j in pattern) {
if (pattern.hasOwnProperty(j)) {
if (!(j in e && pattern[j](e[j]))) {
match = false;
break;
}
}
}
if (match) {
f.push(e);
}
}
return f;
}
var pattern = {
'type': function (t) {
return t.toLowerCase() === 'text';
},
'name': function (t) {
return t.toLowerCase().search('text') === 0;
}
};
console.log(filter(document.getElementsByTagName("input"), pattern));
var list = document.getElementsByTagName('input'); //Array containing all the input controls
var textBoxArray = []; //target Array
for (var i = 0; i < list.length; i++)
{
var node = list[i];
if (node.getAttribute('type') == 'text' && node.getAttribute("id").substring(0, 1) == "id")
{
/*
insert matching textboxes into target array
*/
textBoxArray.push(node);
}
}
Related
I am trying to find all elements in the page by passing class name in this function, I getting all elements as arrays object but I need only those elements those are having my className only.
var custSearch = function (element, className) {
var elementsArray = [];
// add spaces
var q = ' ' + className + ' ';
(function recFind (node) {
// Looping through all the child nodes
for (var i = 0; i < node.childNodes.length; i++) {
var currentNode = node.childNodes[i];
var currentClass = currentNode.className;
// check if current class match with param class
if ((' '+currentClass+' ').indexOf(q)) {
elementsArray.push(currentNode);
}
currentNode.childNodes && recFind(currentNode);
}
})(element);
return elementsArray;
};
custSearch(document, 'spch');
I don't want to use getElementsByClassName function but I want similar result, this above function should give me exact result but I am not finding what I am doing wrong, Can someone tell me if I am making any logical error?
HTML is like this
<div class="spch s2fp-h" style="display:none" id="spch"><div class="spchc" id="spchc"><div class="_o3"><div class="_AM"><span class="_CMb" id="spchl"></span><span class="button" id="spchb"><div class="_wPb"><span class="_AUb"></span><div class="_Fjd"><span class="_oXb"></span><span class="_dWb"></span></div></div></span></div><div class="_gjb"><span class="spcht" id="spchi" style="color:#777"></span><span class="spcht" id="spchf" style="color:#000"></span></div><div class="google-logo"></div></div><div class="_ypc"><div class="_zpc"></div></div></div><div class="close-button" id="spchx">×</div></div>
Try the following:
function myGetElementsByClassName(className) {
var nodes = document.getElementsByTagName('*');
var out = [];
for( var i=0, len=nodes.length; i<len; i++) {
if( nodes[i].classList.contains( className ) ) {
out.push( nodes[i] );
}
}
return out;
}
I'm processing a form onchange event, in this form i got a few inputs, selects and textareas, I was wondering if something like this would work for grabbing the input values in this form
var lat = {
listen: function () {
var input = document.getElementsByTagName('input');
var select = document.getElementsByTagName('select');
var textarea = document.getElementsByTagName('textarea');
var elements = [input,select,textarea];
console.log(elements.length);
for (var a = 0 ; a < elements.length ; a++) {
for ( var b = 0 ; elements[a].length ; b++) {
console.log(elements[a][b].value);
}
}
}
};
Get silly wit it
http://jsfiddle.net/jkabxpkw/1/
var values = document.getElementById('form') ? (function (array) {
var elements = document.getElementById('form').children;
for (var element in elements) {
if (elements.hasOwnProperty(element)) {
if (elements[element].value) {
array.push(elements[element].value);
}
}
}
return array;
}([])) : null;
Yes, you can map and reduce like so:
var elements = [
document.getElementsByTagName('input'),
document.getElementsByTagName('select'),
document.getElementsByTagName('textarea')
].map(function(i) {
// converts the HTMLCollection elements to an array
return Array.prototype.slice.call(i);
}).reduce(function(result, value) {
return result.concat(value);
}, []).forEach(function(element) {
console.log(element.value);
});
I'm aware of [name^="value"] selector but is there a analogous selector (or technique) that queries all attributes starting with the given value?
I'm looking for something like $("[*^='http://www.something.com']")(that does not exist).
It would match all elements which contains at least one attribute with a value that begins with http://www.something.com.
Say:
<img src="http://www.something.com/image.jpg" />
Something
<link rel="stylesheet" href="http://www.something.com/css/style.css" type="text/css">
Attribute name could be anything, not just src and href, even non standard attributes.
Is there a known way to do it?
I've put together some of the ideas from other answers and wrote a custom selector.
Selector
$.expr[':'].hasAttrStartingWithValue = function (obj, index, meta) {
var startsWithAttrValue = false;
var value = meta[3];
for (var i = 0; i < obj.attributes.length; i++) {
var attr = obj.attributes[i];
// attr.value starts with value
if (attr.specified && attr.value.lastIndexOf(value, 0) === 0) {
startsWithAttrValue = true;
break;
}
}
return startsWithAttrValue;
};
It has not been properly tested for cross-browsing and correctness, and I'm sure that it can be further optimized, but it seems to be working well with IE 11, FF 24 and Chrome 32.
Usage
// Logs every occurrence of a value in any attribute of the page
$(":hasAttrStartingWithValue('http://www.something.com')").each(function (i, e) {
console.log(i + " - " + e.outerHTML);
});
// Matches only children of test
$("#test :hasAttrStartingWithValue('http://www.something.com')")
.css('background-color', 'red');
Working Fiddle.
function strstr (haystack, needle, bool) {
var pos = 0;
haystack += '';
pos = haystack.indexOf(needle);
if (pos == -1) {
return false;
} else {
if (bool) {
return haystack.substr(0, pos);
} else {
return haystack.slice(pos);
}
}
}
$( document ).ready(function(){
$('*').each(function() {
$.each(this.attributes, function() {
// this.attributes is not a plain object, but an array
// of attribute nodes, which contain both the name and value
if(this.specified) {
if( strstr(this.value,'http://') )
alert(this.name+'+'+this.value);
}
});
});
});
Alert All attributes And values...
Custom this code...
jsfiddle
If you want to do it for img, a, and link tags, then you could do it like this:
var ref = '"http://www.something.com"';
var elems = [].slice.call(document.querySelectorAll('img[src='+ref+'], a[href='+ref+'], link[href='+ref+']'));
//do something with the elems array
If you want to go the other route...
JS Fiddle of Working Abomination in Vanilla JS
Code that makes me sad (query everything in sight, loops in loops, regex in loops, etc.):
var rx = /(^http:\/\/www.something.com)/;
var loopAgain = function () {
for (var j = 0, leng = attrs.length; j < leng; j++) {
if (rx.test(attrs[j].value)) {
return true;
}
return false;
}
};
var allTheThings = [].slice.call(document.querySelectorAll('*'));
for (var i = 0, len = allTheThings.length; i < len; i++) {
var attrs = allTheThings[i].attributes;
if (loopAgain()) {
console.log(allTheThings[i]);
}
}
I have a XSL that created multiple elements with the id of "createdOn" plus a $unique-id
Example : createdOnid0xfff5db30
I want to find and store these in a variable using JavaScript. I've tried
var dates = document.getElementsById(/createdOn/);
but that doesn't appear to work.
Using jQuery you can use the attr starts with selector:
var dates = $('[id^="createdOnid"]');
Using modern browsers, you can use the CSS3 attribute value begins with selector along with querySelectorAll:
var dates = document.querySelectorAll('[id^="createdOnID"]');
But for a fallback for old browsers (and without jQuery) you'll need:
var dateRE = /^createdOnid/;
var dates=[],els=document.getElementsByTagName('*');
for (var i=els.length;i--;) if (dateRE.test(els[i].id)) dates.push(els[i]);
You should have just used simple CSS selector together with JavaScript's .querySelectorAll() method.
In your case :
var dates = document.querySelectorAll('[id^="createdOnId"]');
Because you didn't tag jQuery, and you probably don't need it, my suggestion would be to add a class to these elements when you create them. Then use the getElementsByClassName() function that's built into most browsers. For IE you would need to add something like this:
if (typeof document.getElementsByClassName!='function') {
document.getElementsByClassName = function() {
var elms = document.getElementsByTagName('*');
var ei = new Array();
for (i=0;i<elms.length;i++) {
if (elms[i].getAttribute('class')) {
ecl = elms[i].getAttribute('class').split(' ');
for (j=0;j<ecl.length;j++) {
if (ecl[j].toLowerCase() == arguments[0].toLowerCase()) {
ei.push(elms[i]);
}
}
} else if (elms[i].className) {
ecl = elms[i].className.split(' ');
for (j=0;j<ecl.length;j++) {
if (ecl[j].toLowerCase() == arguments[0].toLowerCase()) {
ei.push(elms[i]);
}
}
}
}
return ei;
}
}
function idsLike(str){
var nodes= document.body.getElementsByTagName('*'),
L= nodes.length, A= [], temp;
while(L){
temp= nodes[--L].id || '';
if(temp.indexOf(str)== 0) A.push(temp);
}
return A;
}
idsLike('createdOn')
Try the following:
var values = new Array(valueKey_1);
var keys = new Array("nameKey_1");
var form = document.forms[0];
for (var i = 0; i < form.length; i++) {
name = form.elements[i].name;
var startName = name.toLowerCase().substring(0, 18);
if (startName == 'startStringExample') {
values.push(name.value);
keys.push(name);
}
}
Let's say I have a list that looks like this:
<ul>
<li id="q"></li>
<li id="w"></li>
<li id="e"></li>
<li id="r"></li>
<li id="t"></li>
<li id="y"></li>
<li id="u"></li>
<li id="i"></li>
<li id="o"></li>
</ul>
I need to do something like this:
function get_important_elements() {
// completely contrived;
// elements are guaranteed to be contained within same ul
// but nothing else unique in common (class, attrs, etc)
return $('#q, #w, #r, #u, #i, #o');
}
function group_adjacent($elems) {
return $elems; //:(
}
$(function () {
var $filtered_list = get_important_elements();
var groups = group_adjacent($filtered_list);
// groups should be
// (shown by ID here, should contained actual elements contained
// within jQuery objects):
// [$([q, w]), $([r]), $([u, i, o])]
});
How could I go about this?
Note that the IDs and classes used in the list are 100% contrived. In the real code upon which I'm basing this, I have a collection of li elements that are a subset of the lis contained in a single ul. This subset was determined by their contents, which are not important to the question at hand, not by class. They only share a class in the example for ease of getting my point across.
function group_adjacent($elems) {
var rArr = [],
currArr = $([]);
$elems.each(function() {
var $this = $(this);
currArr = currArr.add($this);
if (!$elems.filter($this.next()).length) {
rArr.push(currArr);
currArr = $([]);
}
});
return rArr;
}
http://jsfiddle.net/adamjford/5q8fZ/3/
Using plain script, you can get a collection of all the LIs and loop over it. If an element has the true class put it in a group array. If the next element has the class, put it in the same array. If it doesn't, start a new array. e.g.
function groupLis(){
var el, els = document.getElementsByTagName('li');
var group = [], groups = [group];
for (var i=0, iLen=els.length; i<iLen; i++) {
el = els[i];
if (hasClass(el, 'true')) {
if (!group) {
group = [];
groups.push(group);
}
group.push(el);
} else if (group && group.length != 0) {
group = null;
}
}
return groups;
}
// Helper function
function hasClass(el, cName) {
var re = new RegExp('(^|\\s+)' + cName + '(\\s+|$)');
return el && re.test(el.className);
}
Edit
Ok, here is an answer for the revised question: given an array of elements, group them into arrays of adjacent siblings.
Note that it doesn't care if the elements are the same type, only that they are adjacent siblings (or not).
// el is a DOM node
// Returns the next element sibling, or undefined if here isn't one
function getNextSiblingElement(el) {
while ((el = el.nextSibling)) {
if (el.nodeType == 1) {
return el;
}
}
}
// els is an array of DOM elements
// Returns an array of sibling element arrays
function groupEls2(els) {
var el = els[0],
group = [el],
groups = [group];
for (var i=1, iLen=els.length; i<iLen; i++) {
el = els[i];
el == getNextSiblingElement(els[i-1])? group.push(el) : groups.push((group = [el]));
}
return groups;
}
function group_adjacent($elems) {
var temp = new Array();
var i = 0;
var j = 0;
var last = null;
for(i = 0; i < $elems.length; i++) {
if(last == $elems[i].previousSibling) {
temp[i][j++] = $elems[i];
}
else {
j = 0;
temp[i] = new Array();
temp[i][j++] = $elems[i];
}
last = $elems[i];
}
return temp;
}