Changing getElementById to getElementsByClassName - javascript

I am sure is a common problem in JS, i have created resizing function using JS, initially this function was only going to be used on one item of my site, however now i have chosen to use it on multiple items. My JS function currently uses document.getElementById(id); however i want to change this so it looks out for the class name .resize. How can this be done?
Below is a snippet of my JS
function ebi(id){
return document.getElementById(id);
}
if(ebi('resize')
.complete==true){
iscale(ebi(''));
}
ebi('resize')
.onload=function(){iscale(this);
}
function iscale(o){
//alert(o.width);
var sar=o.width/o.height;
var tar=1,tiw,tih,xoff,yoff;
if(o.width<=425&&o.height<=467){
tiw=o.width;
tih=o.height;
}else if(tar>sar){
tiw=425*sar;
tih=467;
}
else{
tiw=425;
tih=467/sar;
}
xoff=(680-tiw)>>1;
yoff=(209-tih)>>1;
//alert(xoff);
o.width=tiw;o.height=tih;
o.style.top=yoff+"px";
o.style.left=xoff+"px";
}
function $(id){return document.getElementById(id);}
html
<section id="homeSlide" class="shadow">
<img id="resize"class='opaque' src="http://www.colette.fr/media/push/pony_01239.jpg" />
<img id="resize" src="http://www.colette.fr/media/push/EGIFT_01234.jpg" />
<img id="resize" src="http://www.colette.fr/media/push/swa_mmm_001255.jpg" />
</section>
At the moment the resize function only works for the first image, however the other images do not resize. Before anyone attacks me about web standards the id's in the img tags were just to test the function.

id have to be unique, that's why this didn't works.
You can use document.getElementsByClassName() (as you thought) : simply add class="resize" (instead of id="resize") and use that kind of loop:
function callResize()
{
var elements = document.getElementsByClassName("resize");
for (var i=0;i<elements.length;i++)
{
var element = elements[i];
// do things with element
iscale(element);
}
}
document.getElementById('homeSlide').onload = function(){callResize();}

the point is id should be unique and to do what you want why don't you use jQuery. using jQuery you can easily do what you want, using this
jQuery("#homeSlide>img")
and you can also add this:
jQuery("#homeSlide>img").each(function(imgNode){
resize(imgNode);
});
but if you want to do it without jQuery, as far as some functions like getElementsByClassName and getElementsByTagName are not cross browser, you'd better try this:
var homeSlide = document.getElementById('homeSlide');
var myImgNodes = [];
for(var i=0;i<homeSlide.childNodes.length;i++){
var childNode = homeSlide.childNodes[i];
if(childNode.nodeType==1 && childNode.tagName.toLowerCase()=="img"){
myImgNodes.push(childNode);
}
}
afterwards myImgNodes would be exactly what you want.
I just changed your fiddle example and tried not to change your functionality, you can check this out, it perfectly works. This is your updated jsfiddle DEMO

First, an ID has to be unique in your HTML document. But in your example code you assign the ID "resize" three times. Just replace the ID from all three elements and add class="resize".
Second, I suggest to use the jQuery.each() method to iterate over the returned collection instead of a loop.
Example:
var elements = document.getElementsByClassName("resize")
jQuery.each(elements, function(element) {
iscale(element)
})

Related

show all the values with .html [duplicate]

Lets say I have an empty div:
<div id='myDiv'></div>
Is this:
$('#myDiv').html("<div id='mySecondDiv'></div>");
The same as:
var mySecondDiv=$("<div id='mySecondDiv'></div>");
$('#myDiv').append(mySecondDiv);
Whenever you pass a string of HTML to any of jQuery's methods, this is what happens:
A temporary element is created, let's call it x. x's innerHTML is set to the string of HTML that you've passed. Then jQuery will transfer each of the produced nodes (that is, x's childNodes) over to a newly created document fragment, which it will then cache for next time. It will then return the fragment's childNodes as a fresh DOM collection.
Note that it's actually a lot more complicated than that, as jQuery does a bunch of cross-browser checks and various other optimisations. E.g. if you pass just <div></div> to jQuery(), jQuery will take a shortcut and simply do document.createElement('div').
EDIT: To see the sheer quantity of checks that jQuery performs, have a look here, here and here.
innerHTML is generally the faster approach, although don't let that govern what you do all the time. jQuery's approach isn't quite as simple as element.innerHTML = ... -- as I mentioned, there are a bunch of checks and optimisations occurring.
The correct technique depends heavily on the situation. If you want to create a large number of identical elements, then the last thing you want to do is create a massive loop, creating a new jQuery object on every iteration. E.g. the quickest way to create 100 divs with jQuery:
jQuery(Array(101).join('<div></div>'));
There are also issues of readability and maintenance to take into account.
This:
$('<div id="' + someID + '" class="foobar">' + content + '</div>');
... is a lot harder to maintain than this:
$('<div/>', {
id: someID,
className: 'foobar',
html: content
});
They are not the same. The first one replaces the HTML without creating another jQuery object first. The second creates an additional jQuery wrapper for the second div, then appends it to the first.
One jQuery Wrapper (per example):
$("#myDiv").html('<div id="mySecondDiv"></div>');
$("#myDiv").append('<div id="mySecondDiv"></div>');
Two jQuery Wrappers (per example):
var mySecondDiv=$('<div id="mySecondDiv"></div>');
$('#myDiv').html(mySecondDiv);
var mySecondDiv=$('<div id="mySecondDiv"></div>');
$('#myDiv').append(mySecondDiv);
You have a few different use cases going on. If you want to replace the content, .html is a great call since its the equivalent of innerHTML = "...". However, if you just want to append content, the extra $() wrapper set is unneeded.
Only use two wrappers if you need to manipulate the added div later on. Even in that case, you still might only need to use one:
var mySecondDiv = $("<div id='mySecondDiv'></div>").appendTo("#myDiv");
// other code here
mySecondDiv.hide();
if by .add you mean .append, then the result is the same if #myDiv is empty.
is the performance the same? dont know.
.html(x) ends up doing the same thing as .empty().append(x)
Well, .html() uses .innerHTML which is faster than DOM creation.
.html() will replace everything.
.append() will just append at the end.
You can get the second method to achieve the same effect by:
var mySecondDiv = $('<div></div>');
$(mySecondDiv).find('div').attr('id', 'mySecondDiv');
$('#myDiv').append(mySecondDiv);
Luca mentioned that html() just inserts hte HTML which results in faster performance.
In some occassions though, you would opt for the second option, consider:
// Clumsy string concat, error prone
$('#myDiv').html("<div style='width:'" + myWidth + "'px'>Lorem ipsum</div>");
// Isn't this a lot cleaner? (though longer)
var newDiv = $('<div></div>');
$(newDiv).find('div').css('width', myWidth);
$('#myDiv').append(newDiv);
Other than the given answers, in the case that you have something like this:
<div id="test">
<input type="file" name="file0" onchange="changed()">
</div>
<script type="text/javascript">
var isAllowed = true;
function changed()
{
if (isAllowed)
{
var tmpHTML = $('#test').html();
tmpHTML += "<input type=\"file\" name=\"file1\" onchange=\"changed()\">";
$('#test').html(tmpHTML);
isAllowed = false;
}
}
</script>
meaning that you want to automatically add one more file upload if any files were uploaded, the mentioned code will not work, because after the file is uploaded, the first file-upload element will be recreated and therefore the uploaded file will be wiped from it. You should use .append() instead:
function changed()
{
if (isAllowed)
{
var tmpHTML = "<input type=\"file\" name=\"file1\" onchange=\"changed()\">";
$('#test').append(tmpHTML);
isAllowed = false;
}
}
This has happened to me . Jquery version : 3.3.
If you are looping through a list of objects, and want to add each object as a child of some parent dom element, then .html and .append will behave very different. .html will end up adding only the last object to the parent element, whereas .append will add all the list objects as children of the parent element.

How to move onclick code to one place using something like class. Repeated code at various html tags

onclick="triggersTracking($(this).attr('a'),$(this).attr('b'),$(this).attr('c'),Enum.BtnSellerView)"
I have this line at various HTML tags/buttons. I want to move this code to one place for better maintainability. The problem is with third/last attribute i am passing since its Enum, it has different values being passed from different tag elements.
How can i move it to one common place where it would get invoke. For example I could have made a class if i have had just these (this).attr since its common for every tag.
You can do like
Give all the elements a common class name
Then add a data attribute, "data-enum" to each tag with corresponding value.
Then you can write the code like this,
$(".className").click(function () {
var a = $(this).attr('a');
var b = $(this).attr('b');
var c = $(this).attr('c');
var enum = $(this).data('enum');
});
You can use jquery to get this:
$("body").on("click", "someClass", function() {
//code here
});
you don't need to write $(this).attr('a'),$(this).attr('b'),$(this).attr('c')
again and agin on every onclick just paas this object and get them all in function like :
onclick="triggersTracking(this,Enum.BtnSellerView)"
function triggersTracking(obj,enumVal){
// get these values here by obj (no repetitive code needed in every onclick )
$(obj).attr('a')
$(obj).attr('c')
$(obj).attr('b')
}
Do some thing like this
.click()
.on()
.data()
if you use attributes like data-enum , data-e....
so use $(this).data() it will return all attributes in JSON which is starting
from data-
$('.click').click(function(e) {
console.log($(this).data())
$('body').append($(this).attr('a'))
})
// if you have dynamic html tag then go for .on
$('body').on('click','.click',function(){
//callback
console.log($(this).data())
$('body').append($(this).attr('a'))
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<p class="click" a="i am a attr of p" b="i am b" data-a="i am data a">i am p</p>
<h2 class="click" a="i am a attr of h2">i am h2</h2>

How to get link inside div and click it using js

I am trying to write a function for an extension that can find a link inside a specific div and click it. The link has no id or class name, so I was looking for something similar to a CSS selector but with JS without using '$' or 'jQuery' since that will require me to embed a jquery library with the extension.
The div has a class name and then a link inside, so this is the code I have so far --
function COut() {
var a = document.getElementsByClassName('bottom_row').getElementsByTagName('a');
for (var i = 0; i < a.length; i++) {
var elem = a[i],
elem.click();
}
}
This the markup for the div and link -
<div class="bottom_row">
<a onclick="miniAddToCart.closeMiniAddToCart({cmConversionEvent: 'Checkout'})" href="http://www.domain.com/shoppingcart/default.cfm?checkout=1&"><img src="http://www.domain.com/images/eb/minicart/checkout.gif" alt="Checkout"></a>
</div>
Any ideas what Im doing wrong?
getElementsByClassName('bottom_row').getElementsByTagName('a');
getElementsByClassName returns a set, not a single item
getElementsByClassName('bottom_row')[0].getElementsByTagName('a');
^^^
If there can be more than one item with the className, than you will need to loop. And if you support modern day browsers, you can look into querySelectorAll
And finally clicking on a link is not as easy as calling click()
How can I simulate a click to an anchor tag?
If you want it to do to the url, you might be better off just setting window.location.href
If there is a single A tag, I won't prefer to make loop for that. Instead you can just do it like:
function COut() {
var a = document.getElementsByClassName('bottom_row')[0].getElementsByTagName('a')[0];
if(a){
a.click();
}
}

How can i embed a javascript function in css in html?

I have a javascript function named "background_url" that outputs
a random background image.
I'm trying to call the function in this way:
<td style="<script type="text/javascript">background_url();</script>"></td>
but the only thing outputted in my browser is:
a string "background_url();"
The javascript function is as follows
function background_url(){
var myimages=new Array()
myimages[1]="images/img1.jpg"
myimages[2]="images/img2.jpg"
myimages[3]="images/img3.jpg"
//call a random function that returns id of image etc
document.write('background-image: url('+myimages[id]+')');
}
</script>
The background image is not shown,what can i do in order to fix that?
Thanks, in advance
Don't.
Do it the right way.
Give the td element a class (if there are more than one that share the background) or an id (if this element is unique) and use JavaScript to set the style using the appropriate selector.
var tds = document.querySelectorAll('td.some-class-name');
for(var i = 0; i < tds.length; i++){
var td = tds[i];
td.style.backgroundImage = 'url(' + randomImageUrl + ')';
}
Or, if you're using a library like jQuery, it's a little easier:
$('td.some-class-name').css('background-image','url(' + randomImageUrl + ')');
The thing you're running into is that script execution can happen in 2 places: inside a <script> tag (which can't be in an attribute or, as part of an attribute only if it's an event handler. So your choices are:
<script>
background_url()
</script>
Or
<script src="path/to/your/script.js"></script>
Or
<td onmouseover="background_url()">
Given those are your choices, typically people try to use the second option, meaning you'll need to have some mechanism to link your element to the code in question. So you might add an id in your td:
<td id="randomBgElement">
Then onload do this:
document.getElementById('randomBgElement').style = background_url()
Where "background_url()" is a function that returns a valid style, like background-image: url(images/img3.jpg) generated randomly.

User Definable Attributes on HTML Elements?

What I need to do is be able to store some piece of data about an element.
For example, lets say I have a list item <li>, and I want to store some data about it in the element, like "This is element 1 from XYZ".
The only way I know how to do this (which I don't want to do if I can avoid) is this:
<li id='item1'>
Item 1
<!--This is element 1 from XYZ-->
</li>
<script>
// read it something like this
var e = document.getElementById('item1').innerHTML;
// then parse out the comment, etc.
// --
</script>
What I really want is something like this (which I am fairly certain is not possible):
// example
<li id='item1' userdata='This is element 1 from XYZ'>Item 1</li>
.. of course, I would like to be able to access it somehow via javasscript.
Alternatively, is there some other way to achieve this?
Thanks -
You can access your userdata="" attribute from JavaScript. Just do:
var theData = document.getElementById('item1').getAttribute('userdata');
If you want to do it the HTML5 way, then you would use attributes named data-*, e.g.:
<li id='item1' data-foo='This is element 1 from XYZ'>Item 1</li>
that way it will still be valid (i.e., it'll make you feel better for not using an invalid attribute). New browsers will support accessing the data-* attributes like so:
var theData = document.getElementById('item1').data.foo;
but I don't think that is implemented widely enough to rely upon yet.
If you do want to store the data in a comment (although I'd advise going the attribute route instead) you could do something like:
var e = document.getElementById('item1');
var n = e.firstChild;
while (n && n.nodeType != Node.COMMENT_NODE) {
n = n.nextSibling;
}
// now n.nodeValue will have the comment contents
(No guarantees about whether IE likes any of the above.)
You can't add arbitrary elements to HTML. Well you can but it won't be valid and beheaviour is undefined. For this kind of thing I tend to use jQuery. It has a data() call that can add arbitrary data to an element. I believe it encodes it in the class attribute but the implementation is not important.
You could do this yourself but why bother? It's easy to get wrong by putting the wrong characters in, not correctly escaping/unescaping data or inadvertently destroying informatino. Instead just do:
$("#item1").data({source: "Thsi is element 1 from XYZ"});
Since you can accept adding comments, a better solution would be to add a span element with the content you wanted..
<span class="data">.....</span>
you define your data class to have display:none and it is invisible ...
this way you can have access to it with the normal DOM traversing methods..
You can use setUserData() and getUserData() function
http://www.w3.org/TR/2004/REC-DOM-Level-3-Core-20040407/core.html#Node3-setUserData
For example:
<html>
<head>
<script type="text/javascript">
function set(){
var a = document.getElementById("testElement");
a.setUserData("testData", "Some text", null);
}
function get(){
var a = document.getElementById("testElement");
alert(a.getUserData("testData"));
}
</script>
</head>
<body>
<span id="testElement"/>
<form>
<input type="button" value="setUserData" onclick="set()"/>
<input type="button" value="getUserData" onclick="get()"/>
</form>
</body>
If you don't need the HTML to be valid, you can make any attribute you want, and you can access it in Javascript by calling the getAttribute method.
You can add a nested invisible element with an id and your data as the innerText. Use the style attribute to make sure it's invisible.
But it all really depends on what you're trying to achieve. Could you elaborate more?
// If you want to include data in the html why not give it its own node?
.hiddendata{
display: none
}
<li id= 'item1'>
Item 1
<span class= "hiddendata"> This is element 1 from XYZ</span>
</li>
function readHiddenData(who){
var A= [], n= who.firstChild;
while(n){
if(n.className= 'hiddendata'){
A[A.length]= n.textContent || n.innerText || '';
}
n= n.nextSibling;
}
return A;
}
function showHiddenData(who){
var n= who.firstChild;
while(n){
if(n.className= 'hiddendata'){
n.style.display= "inline"
}
n= n.nextSibling;
}
}

Categories

Resources