Is it possible to get an element from the value of the "src" attribute?
There is no DOM method to filter elements by attributes. You need to go through all the elements of a particular tag and filter out those with a matching src value:
function getElementsBySrc(srcValue) {
var nodes = [];
var e = document.getElementsByTagName('img');
for (var i = 0; i < e.length; i++) {
if (e[i].hasAttribute('src') && e[i].getAttribute('src') == srcValue) {
nodes.push(e[i]);
}
}
return nodes;
}
The nodes array will contain all the img elements with a src attribute that has a value image.png.
UPDATE:
Further to the comment below, keep in mind that there might be more than one element with the same src value. That is why the function above returns an array.
You can use the element.setAttribute() method to change the value of an attribute:
var n = getElementsBySrc('old-image.png');
for (var i = 0; i < n.length; i++) {
n[i].setAttribute('src', 'new-image.png');
}
I found some code when google:
function getElementsByAttribute(oElm, strTagName, strAttributeName, strAttributeValue){
var arrElements = (strTagName == "*" && oElm.all)? oElm.all : oElm.getElementsByTagName(strTagName);
var arrReturnElements = new Array();
var oAttributeValue = (typeof strAttributeValue != "undefined")? new RegExp("(^|\\s)" + strAttributeValue + "(\\s|$)", "i") : null;
var oCurrent;
var oAttribute;
for(var i=0; i<arrElements.length; i++){
oCurrent = arrElements[i];
oAttribute = oCurrent.getAttribute && oCurrent.getAttribute(strAttributeName);
if(typeof oAttribute == "string" && oAttribute.length > 0){
if(typeof strAttributeValue == "undefined" || (oAttributeValue && oAttributeValue.test(oAttribute))){
arrReturnElements.push(oCurrent);
}
}
}
return arrReturnElements;
}
Source: http://snipplr.com/view/1853/get-elements-by-attribute/
AFAIK (As Far As I Know) there is no native method to get the an element from the value of the src attribute. But using a JavaScript library you can achieve this in one line.
If you use jQuery, you can get the element writing the following code:
var elem = $('[src="path/to/something.xyz"]');
More documentation about this previous code in the jQuery doc.
Related
Can someone help me write this line of jQuery in javascript. It applies a single rule of styling to a class.
$('.dataCard').css('visibilty', 'visible !important');
As !important doesn't apply when setting styles with javascript, it would be something like this
var elems = document.querySelectorAll('.dataCard');
for (var i=elems.length; i--;) {
elems[i].style.visibility = 'visible';
}
If you want to make a general purpose function that can replace what you had in jQuery, you could do this:
function setStyle(elemOrSelector, prop, val) {
var items;
if (typeof elemOrSelector === "string") {
// run selector query
items = document.querySelectorAll(elemOrSelector);
} else if (elemOrSelector.nodeName) {
// must be single DOM object
items = [elemOrSelector];
} else if (elemOrSelector.length)
// must be an array or nodeList
items = elemOrSelector;
} else {
// don't know what it is
return;
}
for (var i = 0; i < items.length; i++) {
items[i].style[prop] = val;
}
}
setStyle('.dataCard', "visibility", "visible");
This general purpose function allows you to pass either a DOM element, an array like list of DOM elements or a selector string.
If you don't want the general purposeness, then you can just use this:
function setStyle(selector, prop, val) {
var items = document.querySelectorAll(selector);
for (var i = 0; i < items.length; i++) {
items[i].style[prop] = val;
}
}
setStyle('.dataCard', "visibility", "visible");
I am doing some cleaning up of an html page by removing anchor and just leaving the text node, wrapping all the text nodes (no elements surrounding it) with the tag <asdf>, remove all empty elements like <div></div> or <span> </span>.
When I try it on different websites, it seems to have different levels of success when I copy paste the entire script. However, when I run it chunk by chunk, it works as expected and no error is thrown.
//remove anchors but text intact
$('a').replaceWith(function() {
return $.text([this]);
});
//wrap text nodes
var items = window.document.getElementsByTagName("*"); for (var i = items.length; i--;) { wrap(items[i]) }; function wrap(el){ var oDiv = el; for (var i = 0; i < oDiv.childNodes.length; i++) { var curNode = oDiv.childNodes[i]; if (curNode.nodeName === "#text" && oDiv.childNodes.length !== 1) { var firstText = curNode; var newNode = document.createElement("asdf"); newNode.textContent = firstText.nodeValue; firstText.parentNode.replaceChild(newNode, firstText); } } }
//remove empty elements
$("*").filter(function () {
return !($.trim($(this).text()).length);
}).hide();
$('*').filter(function() {
return $.trim($(this).text()) === '' && $(this).children().length == 0
}).remove()
It throws an error like
NotFoundError: An attempt was made to reference a Node in a context where it does not exist.
this is caused by:
$('a').replaceWith(function() {
return $.text([this]);
});
so maybe if I fix that, it will work.
Did you test the script by having it written all in one line:
$('a').replaceWith(function() { return document.createTextNode($.text([this]));}); var items = window.document.getElementsByTagName("*"); for (var i = items.length; i--;) { wrap(items[i]) }; function wrap(el){ var oDiv = el; for (var i = 0; i < oDiv.childNodes.length; i++) { var curNode = oDiv.childNodes[i]; if (curNode.nodeName === "#text" && oDiv.childNodes.length !== 1) { var firstText = curNode; var newNode = document.createElement("asdf"); newNode.textContent = firstText.nodeValue; firstText.parentNode.replaceChild(newNode, firstText); } } };$("*").filter(function () { return !($.trim($(this).text()).length);}).hide();$('*').filter(function() { return $.trim($(this).text()) === '' && $(this).children().length == 0;}).remove();
On Chrome it worked everywhere I tested and jQuery was present.
var test = document.body.getElementsByTagName("a");
for (var i=0; i<test.length; i++)
if(test[i].innerHTML().indexOf("search string") != -1){test[i].style.color="black";}
Hopefully it's obvious what I'm trying to do - if there is a link on the page that contains the search phrase, change it's color to black. This isn't working though. Any ideas?
Thanks.
innerHTML is a property not a function, so don't use ().
innerHTML is not a function, it is a property. Try doing this instead:
var test = document.body.getElementsByTagName("a");
for (var i=0; i<test.length; i++)
if(test[i].innerHTML.indexOf("search string") != -1){test[i].style.color="black";}
A cleaner way of doing it would be to use jQuery:
var searchTerm = 'term1';
$('a').filter(function (a) {
if (this.innerHTML.indexOf(searchTerm) != -1)
return true;
return false;
}).css('color','red')
var test = document.body.getElementsByTagName("a");
for (var i=0; i<test.length; i++) {
var newElem = test[i].innerHTML;
if(newElem.indexOf("searchString") != -1){
test[i].style.color="black";
}
}
innerHTML is no function! It's a property!
I have text on a page, its in a <h3> tag, which has a class ms-standardheader, but there are other texts on the page with the same class in its own <h3> tag. I also know the text I want to hide is 'Session'.
With this how can I write a javascript function to hide only this text?
Here is an image of the developtools from IE.
I'd suggest, if you're restricted (as your tags suggest) to non-library plain JavaScript, the following:
var h3s = document.getElementsByTagName('h3'),
classedH3 = [];
for (var i = 0, len = h3s.length; i < len; i++) {
if (h3s[i].className.indexOf('ms-standardheader') > -1) {
classedH3.push(h3s[i]);
}
}
for (var i = 0, len = classedH3.length; i < len; i++) {
if (classedH3[i].firstChild.nodeValue == 'the text to hide'){
classedH3[i].style.display = 'none';
}
}
JS Fiddle demo.
References:
push().
document.getElementsByTagName().
element.className.
node.nodeValue.
indexOf().
Can't you give the target element an ID? That would make things much more simple. Otherwise, you have to go through all <h3> elements until you find the one you want to hide:
var headings = document.getElementsByTagName("h3");
for(var i=0; i<headings.length; i++) {
var contentElement = headings[i].getElementsByTagName('nobr');
var content = "";
if(contentElement.length) {
content = contentElement[0].textContent ? contentElement[0].textContent : contentElement[0].innerText;
}
var content = contentElement.length ? contentElement[0].childNodes[0].nodeValue : '';
if(headings[i].className == 'ms-standardheader' && content == 'Session') {
headings[i].style.display = 'none';
}
}
you should try this :
window.onload = function()
{
getElementByClass('ms-standardheader');
}
window.getElementByClass = function(theClass){
var allHTMLTags=document.getElementsByTagName('*');
for (i=0; i<allHTMLTags.length; i++) {
if (allHTMLTags[i].className==theClass) {
var content = allHTMLTags[i].innerHTML;
var search = /session/;
if (search.test(content))
{
alert(search);
allHTMLTags[i].style.display='none';
}
}
}
}
See Demo : http://jsfiddle.net/3ETpf/18/
Always favour a unique Id where possible. If not possible then you have to manually traverse the DOM to find the elements you are looking for. Here's an example using getElementsByTagName().
var i, header, headers = document.getElementsByTagName('h3');
for (i = 0; i < headers.length; i += 1) {
header = headers[i];
if (header.className === 'ms-standardheader' &&
(header.textContent || header.innerText) === 'Session') {
header.style.display = 'none';
}
}
see: http://jsfiddle.net/whP5z/
If you have jquery you may type this :
$("h3.ms-standardheader:contains('Session')").hide();
I am having issues figuring out how to resolve the getElementsByClassName issue in IE. How would I best implement the robert nyman (can't post the link to it since my rep is only 1) resolution into my code? Or would a jquery resolution be better? my code is
function showDesc(name) {
var e = document.getElementById(name);
//Get a list of elements that have a class name of service selected
var list = document.getElementsByClassName("description show");
//Loop through those items
for (var i = 0; i < list.length; ++i) {
//Reset all class names to description
list[i].className = "description";
}
if (e.className == "description"){
//Set the css class for the clicked element
e.className += " show";
}
else{
if (e.className == "description show"){
return;
}
}}
and I am using it on this page dev.msmnet.com/services/practice-management to show/hide the description for each service (works in Chrome and FF). Any tips would be greatly appreciated.
I was curious to see what a jQuery version of your function would look like, so I came up with this:
function showDesc(name) {
var e = $("#" + name);
$(".description.show").removeClass("show");
if(e.attr("class") == "description") {
e.addClass("show");
} else if(e.hasClass("description") && e.hasClass("show")) {
return;
}
}
This should support multiple classes.
function getElementsByClassName(findClass, parent) {
parent = parent || document;
var elements = parent.getElementsByTagName('*');
var matching = [];
for(var i = 0, elementsLength = elements.length; i < elementsLength; i++){
if ((' ' + elements[i].className + ' ').indexOf(findClass) > -1) {
matching.push(elements[i]);
}
}
return matching;
}
You can pass in a parent too, to make its searching the DOM a bit faster.
If you want getElementsByClassName('a c') to match HTML <div class="a b c" /> then try changing it like so...
var elementClasses = elements[i].className.split(/\s+/),
matchClasses = findClass.split(/\s+/), // Do this out of the loop :)
found = 0;
for (var j = 0, elementClassesLength = elementClasses.length; j < elementClassesLength; j++) {
if (matchClasses.indexOf(elementClasses[j]) > -1) {
found++;
}
}
if (found == matchClasses.length) {
// Push onto matching array
}
If you want this function to only be available if it doesn't already exist, wrap its definition with
if (typeof document.getElementsByClassName != 'function') { }
Even easier jQuery solution:
$('.service').click( function() {
var id = "#" + $(this).attr('id') + 'rt';
$('.description').not(id).hide();
$( id ).show();
}
Why bother with a show class if you are using jQuery?
Heres one I put together, reliable and possibly the fastest. Should work in any situation.
function $class(className) {
var children = document.getElementsByTagName('*') || document.all;
var i = children.length, e = [];
while (i--) {
var classNames = children[i].className.split(' ');
var j = classNames.length;
while (j--) {
if (classNames[j] == className) {
e.push(children[i]);
break;
}
}
}
return e;
}
I used to implement HTMLElement.getElementByClassName(), but at least Firefox and Chrome, only find the half of the elements when those elements are a lot, instead I use something like (actually it is a larger function):
getElmByClass(clm, parent){
// clm: Array of classes
if(typeof clm == "string"){ clm = [clm] }
var i, m = [], bcl, re, rm;
if (document.evaluate) { // Non MSIE browsers
v = "";
for(i=0; i < clm.length; i++){
v += "[contains(concat(' ', #"+clc+", ' '), ' " + base[i] + " ')]";
}
c = document.evaluate("./"+"/"+"*" + v, parent, null, 5, null);
while ((node = c.iterateNext())) {
m.push(node);
}
}else{ // MSIE which doesn't understand XPATH
v = elm.getElementsByTagName('*');
bcl = "";
for(i=0; i < clm.length; i++){
bcl += (i)? "|":"";
bcl += "\\b"+clm[i]+"\\b";
}
re = new RegExp(bcl, "gi");
for(i = 0; i < v.length; i++){
if(v.className){
rm = v[i].className.match(bcl);
if(rm && rm.length){ // sometimes .match returns an empty array so you cannot use just 'if(rm)'
m.push(v[i])
}
}
}
}
return m;
}
I think there would be a faster way to iterate without XPATH, because RegExp are slow (perhaps a function with .indexOf, it shuld be tested), but it is working well
You can replace getElementsByClassName() with the following:
function getbyclass(n){
var elements = document.getElementsByTagName("*");
var result = [];
for(z=0;z<elements.length;z++){
if(elements[z].getAttribute("class") == n){
result.push(elements[z]);
}
}
return result;
}
Then you can use it like this:
getbyclass("description") // Instead of document.getElementsByClassName("description")