Selecting a div by classname - javascript

I got this div...
<div tabindex="0" class="button-base inline-block button aw-btn button-base-active">
<input type="text" tabindex="-1" style="opacity: 0; height: 1px; width: 1px; z-index: -1; overflow-x: hidden; overflow-y: hidden; position: absolute; ">
</div>
in the middle of my page, it has no id and I am unable to edit the pages HTML, I am also no able to use jQuery. Also trying to do it with IE7 and IE8.
Nightmare here :)
The solution would be document.getElementsByClassName but that is not ie7 and ie8 compatible.
This div is buried in about 10 divs, all of which are similar style with no id's etc. The classes on this div are unique!
The only solution I can see is to get ALL divs and loop them looking for hasAttriutes similar.
Anyone have a better idea?

Here's a cross-browser implementation of getElementsByClassName for non-compliant browsers (citation):
if (!document.getElementsByClassName)
{
document.getElementsByClassName = function(classname)
{
var elArray = [];
var tmp = document.getElementsByTagName("*");
var regex = new RegExp("(^|\\s)" + classname + "(\\s|$)");
for ( var i = 0; i < tmp.length; i++ ) {
if ( regex.test(tmp[i].className) ) {
elArray.push(tmp[i]);
}
}
return elArray;
};
}

Nope, that's how it's done. Unless they're in something with an ID you're stuck iterating all DIVs on the page. Fortunately it is just a list though (no need to recurse through a tree) so it's not so bad.

I would suggest using XPaths to select the nodes. Might work...

Use jQuery/Sizzle. IE6 and up. :)
Load it:
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.5.1/jquery.min.js"></script>
Use it:
jQuery('.class.otherclass.anotherclass')

Related

Why are "fadeIn" and "fadeOut" functions moving my divs?

I'm starting a new website and I'm using JQuery for display a div inside another (a title). I have 4 divs displayed inline-block and my result need to be like this :
I'm using Jquery for display the div containing "Accueil" with the function fadeIn and fadeOut but my problem is the following : When the move is over a div, the hidden div is animated and fade in like desired but the other div (on the right) is moving down !
My html is the following :
The left box :
<div class="box-interactive box-interactive1">
<div class="contenu-box">
titi 1
</div>
<div id="bandeau1" class="bandeau">
rr
</div>
</div>
The right box :
<div class="box-interactive box-interactive2">
<div class="contenu-box">
titi 2
</div>
<div id="bandeau2" class="bandeau" style="display : block;">
accueil 2
</div>
</div>
My css :
/*CSS for boxes and interactive text*/
.box-interactive {
width: 300px;
height: 200px;
background-color: red;
margin: 20px;
display: inline-block;
size: fixed;
}
.contenu-box{
width: 300px;
height: 160px;
}
.bandeau {
width: 300px;
height: 40px;
background-image: url("../../img/Alex/accueil.png");
background-size: auto 100%;
position: relative;
display: none;
}
And my JS :
$(function(){
$("div[class^='box-interactive']").hover(
function(){
var id = new Array;
id = $(this).attr('class').split(' ');
for (var i in id) {
if(id[i].match('box-interactive.+')){
var idnum = 'bandeau'+id[i].substring(15);
$("#"+idnum+"").fadeIn(800);
}
}
},
function(){
var id = new Array;
id = $(this).attr('class').split(' ');
for (var i in id) {
if(id[i].match('box-interactive.+')){
var idnum = 'bandeau'+id[i].substring(15);
$("#"+idnum+"").fadeOut(500);
}
}
}
);
});
The second div (it works in both ways) is moving down with specificities : the top of the moving div is equal to the bottom of the first div (the one befor the hidden). Do you have an explaination ?
Fiddle : http://jsfiddle.net/Msh2T/1/ open large the right window to see the problem ;) thx
fadeIn and fadeOut will set an element to "display: none" once the animation completes, removing it from the layout. If you don't want the animation to affect the layout, animate the opacity.
$("#"+idnum+"").animate({opacity: 0}, 800);
...
$("#"+idnum+"").animate({opacity: 1}, 800);
You can float the .bandeau divs so that they aren't affecting the inline layout flow, effectively limiting their scope to the parent div.
.bandeau {
width: 300px;
height: 40px;
background-image: url("../../img/Alex/accueil.png");
background-size: auto 100%;
position: relative;
display: none;
float: left; /* ADD THIS */
}
Fiddle: http://jsfiddle.net/Msh2T/3/
One option would be to animate the opacity either to 1 or to 0 instead of using fadeIn and fadeOut:
$("#"+idnum+"").animate( { opacity:1 }, 800 );
and
$("#"+idnum+"").animate( { opacity:0 }, 500 );
Here's a working fiddle to demonstrate this approach.
A few other notes about the code...
First, your hover-in and hover-out functions are nearly identical. Any time you have that much code that is so similar, it's a very good idea to combine it into a single function.
Where you have this code:
var id = new Array;
id = $(this).attr('class').split(' ');
it's unnecessary to have the new Array, since you are just replacing the value in the next line. Also, I recommend using a plural name for an array instead of a singular name:
var ids = $(this).attr('class').split(' ');
The next line is:
for (var i in id) {
Never use a 'for..in' loop on an array. It will bite you if anyone ever augments Array.prototype with new methods or properties. Instead, use a numeric for loop or an iterator such as jQuery's $.each().
Next is this code:
if(ids[i].match('box-interactive.+')){
var idnum = 'bandeau'+id[i].substring(15);
...
When you use .match to test a string like this, you can also use it to extract the part of the string you want, without resorting to a brittle-to-maintain .substring(15) call:
var match = ids[i].match( /box-interactive(.+)/ );
if( match ) {
var idnum = 'bandeau' + match[1];
...
Now having said all this, why not simplify things much further and let jQuery do all the work for you? There's no need for any of this fancy array looping and checking of classnames. You can replace the entire JavaScript code with this:
$(function(){
$("div[class^='box-interactive']").hover(
function(){
$(this).find('.bandeau').animate( { opacity:1 }, 800 );
},
function(){
$(this).find('.bandeau').animate( { opacity:0 }, 500 );
}
);
});
Updated fiddle
(You may note that I've contradicted my first piece of advice here and didn't combine the bit of duplicate code in the hover-in and hover-out functions. But there's now so little code that that the duplication isn't worth worrying about.)
Try using z-index in your CSS to stack your divs on top of each other

getBoundingClientRect to know if an element is above a particular vertical point

I am using getBoundingClientRect to know if an element is above a particular point in the page. So I do this:
var rect = el.getBoundingClientRect();
if (rect.top < bottom_limit) {
return true;
}
I think this is working well, but in some debugging I have found that some elements return 0 for all top,bottom,right,left. For example: Example1 and Example2
<span id='a'>
<span id='b'>This is some crazy text.</span>
</span>
#b {
float: left;
}
and
#b {
position: absolute;
}
I am concerned about getting all zeros. Why is this happening? Can I trust this method for what I am trying to accomplish?
You could look into using document.getBoxObjectFor(el), or try el.offsetTop/offsetLeft/offsetWidth/offsetHeight. Think they may be Mozilla only though, and not sure if they will work with non-block level elements.

how to find specific particular attribute in javascript

<div __jx__id="___$_15" style="position: absolute; overflow: hidden;">
I would like to modify the above div by adding display:block to the style using javascript
<div __jx__id="___$_15" style="display:block;position: absolute; overflow: hidden;">
I tried using
function getAllElementsWithAttribute(attribute)
{
var matchingElements = [];
var allElements = document.getElementsByTagName('*');
for (var i = 0; i < allElements.length; i++)
{
if (allElements[i].getAttribute(attribute))
{
// Element exists with attribute. Add to array.
matchingElements.push(allElements[i]);
}
}
return matchingElements;
}
getAllElementsWithAttribute('__jx__id="___$_15);
adapted from
Get elements by attribute when querySelectorAll is not available without using libraries?
the selector itself is not working let alone add the additonal display:block to the div
The name of your attribute is __jx__id and the value is ___$_15.
so try: getAllElementsWithAttribute("__jx__id");
If you also want to filter by the value of the attribute then you'll need to pass it in seperately: getAllElementsWithAttributeAndValue("__jx__id", "___$_15");
A lot easier with jQuery:
$("div[__jx__id]").css({display:block});
or even
$("div[__jx__id]").show();

Move only some CSS styles from one element to another

I've created a jQuery plugin which takes a HTML table, makes it sortable, and fixes the header and footer. See http://jsfiddle.net/aXDzz/ for an example (click create to create the table).
Works good, but then recently needed to add some padding or margin around the table. This caused some problems.
My plugin basically replaces the original <table> with a <div> which contains a <table> for the header, a <div> which intern contains a <table> for the body, and a <table> for the footer. My intent was for the user to apply CSS to the original table, and upon using my plugin, the CSS would appropriately transfer. As stated above, however, I wrap a <div> around the table so that now the margin or padding should be applied to the <div> and not the <table>.
So, looks like I need to move any CSS which applies to the exterior of the <table> to the <div> such as margin, but then leave any CSS which applies to the interior of the <table> such as the row color alone.
How would I do this? Or is there a better way altogether I should be implementing this? Thanks
PS. Please feel free to critique my plugin as it is my first attempt.
I tried to modify this plugin for your needs:
(function($){
$.fn.copyStyle = function(jqCopyTo,styleStartsWith,overideStyle){
var dom = this.get(0);
var style;
var returns = {};
if(window.getComputedStyle){
var camelize = function(a,b){
return b.toUpperCase();
};
style = window.getComputedStyle(dom, null);
for(var i = 0, l = style.length; i < l; i++){
var prop = style[i];
for(var m = 0; m < styleStartsWith.length; m++){
if(prop.lastIndexOf(styleStartsWith[m], 0) === 0) {
var camel = prop.replace(/\-([a-z])/g, camelize);
var val = style.getPropertyValue(prop);
returns[camel] = val;
overideStyle==true ? $(this).css(prop,0):null;
}
}
};
};
if(style = dom.currentStyle){
for(var prop in style){
for(var m = 0; m < styleStartsWith.length; m++){
if(prop.lastIndexOf(styleStartsWith[m], 0) === 0) {
returns[prop] = style[prop];
overideStyle==true ? $(this).css(prop,0):null;
}
}
};
};
//copy
$(jqCopyTo).css(returns);
return this;
}
})(jQuery);
on a structure like this:
#inner {
margin:20px;
padding:20px;
background-color:#F00;
}
#wrapper {
background-color:#f80;
}
html:
<div id="wrapper">
<div id="inner">
Table Content
</div>
</div>
you can use this plugin like this:
$("#inner").copyStyle("#wrapper",["margin","padding"],true);
the result is that the inner-div margin and padding get overwritten and the style is added to the wrapper-div. you can handle the override behavior with the last Boolean indicator.
here is a full example on jsFiddle. I can't guarantee that it works in all browser (just tested Firefox and ie9)
I have inspected your code, and I have tried to apply margin to your table:
.myTable {
width:600px;
matgin-left: 50px;
}
And I then saw where the problem is. But then I have looked the code, and you are specifying fixed width
<div style="width: 618px; overflow-y: auto; max-height: 300px;"><table id="myTable" class="myTable">
And that seems causes the problem.
Take a look at:
width: 618px;
If I understood the question correctly, this is not calculated good. Maybe you could try to find in your plugin where width is calculated, and then to include margin into count how to calculate width. I haven't find so far. The plugin is long..
When I put , for example 665px, it looks somewhat good..
Maybe that is the solution.

change a different div's class on mouseover

There's many examples of this but I can't find the right one for me - I believe mine is a more simple example.
I have as follows:
<li onmouseover="this.className='change-here2'" onmouseout="this.className='change-here'">
<div class="change-here">
Text Here
</div>
</li>
The li element has a background image, and a hover effect that changes the background image.
Using this.className changes the li class, when what I want is to change the div below it's class.
Shouldn't I be able to modify this to div.change-here, or something similar? I don't know the syntax...
Any help is appreciated.
EDIT: TimWolla's solution works brilliantly. Thank you all.
Why don't you use CSS only?
li .class { background-color: red; }
li:hover .class { background-color: green; }
See: http://jsfiddle.net/TimWolla/zp2td/
Can you do something to the affect of $(this).children(':first').addClass('change-here'); for that?
May I suggest:
var lis = document.getElementsByTagName('li');
for (var i=0, len=lis.length; i<len; i++){
lis[i].onmouseover = function(){
var firstDiv = this.getElementsByTagName('div')[0];
firstDiv.className = 'change-here';
};
lis[i].onmouseout = function(){
var firstDiv = this.getElementsByTagName('div')[0];
firstDiv.className = '';
};
}
JS Fiddle demo.
The reason I'm taking this approach, rather than using the in-line onmouseover attribute, is to make it somewhat easier to adapt in the case of the requirements changing at a later date. Also, it's slightly less 'intrusive' this way, and leaves the html somewhat easier to read. It is, of course a personal preference, though.
It's worth noting that the CSS-approach, as mentioned by TimWolla is far more sensible than involving JavaScript.
Updated answer to incorporate all the suggestions
<style>
.div_1 {
color: #F00;
}
.div_2 {
color: #0F0;
}
</style>
<li onMouseOver="this.childNodes[0].className = 'div_1';" onMouseOut="this.childNodes[0].className = 'div_2';">
<div class="div_1">
Text Here
</div>
</li>
This should work:
this.childNodes[0].className = 'change-here';

Categories