Javascript: Setting Z-Index on Multiple Elements (ID & Class) - javascript

I have a javascript function that is supposed to hide and show layered divs by simply changing the z-index. I don't know if this is the best way to do it, but it works except for one issue. I have the content divs (absolutely positioned in CSS on top of each other), but I also have a navigation div (absolutely positioned in CSS at the bottom of the page) that should always remain on top. So I have this javascript code:
<script type="text/javascript">
var z = 1;
function showHide(id) {
document.getElementById(id).style.zIndex = z++;
document.getElementsByTagName('nav').style.zIndex = z++;
}
</script>
And I have this html:
<div id="1a" class="content" style="z-index:1;">Content</div>
<div id="1b" class="content">More Content</div>
<div id="1c" class="content">Even More Content</div>
<div class="nav" style="z-index:2;">
1
| 2
| 3</div>
The problem is that the z-index line for the navigation div messes it up. Not only does it not execute, but anything I put after it doesn't get executed as well (even a basic alert). If I change navigation from a class to an id, it works fine, but I'm going to have multiple navigation divs on each page (multiple slides in a SlideDeck). I could just set the navigation div's z-index to 99999, but I wanted to see why it wasn't working in the "cleaner" way, since it looks like I might be making a basic mistake.
Thank you.

I'm not sure if this is exactly what you're after, but you need to create a loop for getElementsByTagName or getElementsByClassName:
var cells = table.getElementsByClassName('nav');
for (var i = 0; i < cells.length; i++) {
cells[i].style.zIndex = z++;
}
Edit: Changed method call to getElementsByClassName. I initially just took what he wrote and added the loop.

Looks like your problem is that you are trying to use getElementsByTagName when you should be using getElementsByClassName. getElementsByTagName searches for elements based on tag name, like 'div' or 'span', not class names.
So, use it like this:
<script type="text/javascript">
var z = 1;
function showHide(id) {
document.getElementById(id).style.zIndex = z++;
document.getElementsByClassName('nav')[0].style.zIndex = z++;
}
</script>
Keep in mind that method was added in Firefox 3 and may not be supported in your browser. I would recommend using something like jQuery to maintain cross browser compatibility. Using jQuery, it would look like this:
<script type="text/javascript">
var z = 1;
function showHide(id) {
$('#'+id).style.zIndex = z++;
$('.nav').style.zIndex = z++;
}
</script>

Related

Drawing 3D objects

I'm looking to draw a 3D cylinder with javascript by copying the layers and applying an increased margin to these elements. I have tried to set the height of the element in my input and run the copy function while total margin of the copied elements is lower than the set height of elements.
http://jsfiddle.net/yuX7Y/3/
<form>
<input type="number" id="userHeight" />
<button type="submit" onclick="circleHeight">Submit</button>
</form>
<div class="circle">
</div>
<div class="slice">
</div>
$(document).ready(function(){
var initMargin = 4;
var totalMargin = 0;
var i = 0;
function copy(){
$(".slice").clone().appendTo( ".content" ).css({'margin-top': totalMargin + "px"});
console.log("cloned");
i++;
totalMargin = initMargin + 4;
}
function setH(){
while(i < (document.getElementById("userHeight").value)){
copy();
}
if(i>100){
initMargin = 4;
i=0;
}
}
});
Jump To The Result: http://jsfiddle.net/yuX7Y/15/
Notes
This Fiddle/question intrigued me so I went ahead and looked at it for a little while. There were actually a number of issues, some obvious and some less obvious. Somewhat in the order I noticed them these are some of the issues:
jQuery wasn't included in the fiddle
The click event wasn't wired up correctly - it was actually trying to submit the form. You need to use e.preventDefault to stop the form from submitting. Since you were already using jQuery I just wired up with the jQuery click event:
$("#recalculateHeight").click(function (e) {
e.preventDefault();
setH();
});
Because of the use of "global" variables (variables not initialized within the routines), the submit would only work once. Instead of this, I moved variable declarations to the appropriate routine.
Calling $(".slice").clone() clones ALL slice elements on the page. The first time you clone, this is fine. But after that you are cloning two elements, then three elements, etc (as many slice elements as are on the page). To solve this I created a slice template like:
<div class="slice" id="slice-template" style="display: none"></div>
Then you can clone to your hearts content like $("#slice-template").clone(). Just don't forget to call the jQuery show() method or set display back to block on the cloned element.
Finally, if you want to repeat the process many times you need to be able to clear previous elements from the page. I find this easiest to do by creating containers, then clearing the contents of the container. So I put all of the "slices" into this container:
<div class="content">
Now when you want to clear the content node you can just call $(".content").empty();.
I also made a few style based changes in my Fiddle, but those don't make it work or not work, they just help me read the code! So, there you have it! Best of luck!

Trying to override a dynamically generated inline style

I'm trying to quickly fix something that is broken on a wordpress site. The problem is that someone else created the soup sandwhich and I'm stuck fixing it. I have an element that shows up in two different sections on the page. The first is a post-status form, the second time it shows up is in a comment-add section that repeats indefinitely on the page. The block of code works on the comments, but doesn't work on the status form, so I wan't to simply hide it until I figure out how to A) find where the heck the code is being generated, B) fix the issue.
The element has a style that is being dynamically applied (assuming javascript) at load of the element. It starts off hidden, then something somewhere down the pipe shows it.
Here is what my code looks like, first the element that works:
<div class="activity-comments">
<div class="audio_controls fresh" style>
....
</div>
</div>
The block that is broken:
<div id="whats-new-post-in-box">
<div class="audio_controls fresh" style="display: block;">
...
</div>
<div>
So in that first block the code sits without a style in it, which for some odd reason whoever wrote it left the style tag in anyway without any style to apply (completely stupid and malformed code). But in the second element, the one that's broke, it has a display:block dynamically written in at run time. I'm trying to figure out how to force it to display:none. I've tried js, but I'm somehow not calling it correctly (not sure how to call nested elements, I only want the audio_controls within that nested ID but not the other class).
Anyone have any ideas for me?
You can do it with CSS:
#whats-new-post-in-box > .audio_controls.fresh {
display: none !important;
}
An !important style rule can override an inline style rule (unless the inline style rule is also !important).
Alternately, with JavaScript on any modern browser:
var list = document.querySelectorAll("#whats-new-post-in-box .audio_controls.fresh");
var n;
for (n = 0; n < list.length; ++n) {
list[n].style.display = "none";
}
For older browsers it's more of a pain:
var elm = document.getElementById("whats-new-post-in-box").firstChild;
while (elm) {
if (elm.className &&
elm.className.match(/\baudio_controls\b/) &&
elm.className.match(/\bfresh\b/)) {
elm.style.display = "none";
}
elm = elm.nextSibling;
}
Obviously, for the two JS solutions, you need to run that code after whatever it is that's setting the style in the first place...
Pretty sure you can write a CSS rule for #whats-new-post-in-box .audio_controls and mark it with !important.
Another way to hide the inner div, and this requires jQuery:
$('div.audio_controls', $('#whats-new-post-in-box')).hide();
This code select all div elements with an audio_controls class that are inside the element with an id of whats-new-post-in-box, and hides them.

Using JQuery/Javascript arrays to form two sided fading layout

When I do sites for clients I constantly get the request to have a two sided layout, where buttons on the left cause divs on the right to fade in and fade out appropriately. For a long while I've been writing each case. (which is a bit silly and time consuming). I want to systematize that, but I've been having a hard time since I don't understand how javascript/jquery works with .click() and arrays.
$(document).ready(function(){
var left = new Array($('#a'),$('#b'), $('#c'),$('#d'), $('#e'));
var right = new Array($('#1'),$('#2'),$('#3'),$('#4'),$('#5'));
// left[0].click(function(){right[0].fadeIn('fast');})
var numbers = new Array(1,2,3,4,5);
function fadey(x){
left[x].click(function(){
right[x].fadeIn('fast');
})
}
for (var i = 0; i < left.length; i++) {
fadey(i);
};
})
This code gets it so that the left hand side buttons cause the corresponding right hand div to appear. The problem is that I can't seem to get the other divs to disappear without causing all the divs to disappear.
Ideally it would be dope if I could have one line of code that simply checks when the left-hand jquery object array is clicked, gets its index value, and causes the corresponding right hand side jquery object array to appear, while also hiding the other ones.
This way I can just plug elements into each array and then never have to worry about writing these cases one by one.
Thank you so much for your help!
You could just make a generic event handler with classes instead of IDs:
$('.left button').click(function() {
var index = $(this).index();
$('.right section').eq(index).fadeIn('fast');
});
I'm assuming your HTML looks something like this:
<aside class="left">
<button>One</button>
<button>Two</button>
<button>Three</button>
</aside>
<aside class="right">
<section>One</section>
<section>Two</section>
<section>Three</section>
</aside>

How to target and affect dom element in js (noobie)

so long story short,
I'm testing something out, a simple rollover and i notice that for example, if i use this
css:
#box{ width:200px; height:200px; background-color:#F00;}
html:
<div id="box" class="boxClass">this is sample text</div>
Js:
var box = document.getElementById("box");
function changeBox(){
//box.style.backgroundColor = "#1896fa";
box.style.backgroundColor = "#1896fa";
}
box.onmouseover = changeBox;
it works, simple as can be. simple mouseover, simple js...simple. Mouse rolls over and changes from red to bue...good, but then when i try to target the same div via
var box = document.getElementsByTagName("div");
or
getElementsByClassName("boxClass");
nothing happens. my ? is why?
reason im asking is because, i have a simple image gallery and wanted to implement gallery wide rollovers but didnt want to write them for EVERY image.
was trying to somehow group them all together via tagName("img") or ClassName("boxClass")
but to no avail. i know older browsers dont support some of these but i looked it up and saw all modern browsers sans Ie are a go. what am i missing?
any tips help direction is appreciated. thanks in advance.
Contrary to the getElementById function which returns a single element, the getElementsByTagName function returns a NodeList of DOM elements (which is normal as you could have multiple elements with this tag). So if you want to change the background color to all <div> elements in the DOM you will have to first loop through the elements of this collection.
var boxes = document.getElementsByTagName("div");
for (var i = 0; i < boxes.length; i++) {
boxes[i].style.backgroundColor = "#1896fa";
}
Same remark stands true for the getElementsByClassName function.

make javascript repeat for each row in a view

I have created a view in Drupal. I'm using JavaScript to modify the CSS in each row. The script runs on the first row, but does not make the changes on the rest of rows from the view.
This is the script:
<script language="javascript" type="text/javascript">
window.onload = floatbr;
function floatbr() {
var f = document.getElementById('firstright') // Get div element
var s = document.getElementById('secondright') // Get div element
var w = document.getElementById('catwrapper') // Get div element
var sh = s.offsetHeight // secondright div height
var wh = w.offsetHeight // catwrapper div height
f.style.height = wh - sh + 'px'; }
</script>
I'm using it from this page: http://agsone.100webcustomers.com/floatbottom.php
having the script in the page once does not do the trick.
having the script in the view footer and repeating the script does not work.
The link to the jSfiddle with HTML, CSS and JavaScript is the following one: http://jsfiddle.net/YTN3K/.
Drupal provides and already uses jQuery, so you should use it too. Drupal has its own way to manage JavaScript and comes with some additional JavaScript API, mainly to handle passing variables from PHP to JavaScript properly, register script to run on page load and content addition, etc.
jQuery is well documented and popular, so finding documentation, tutorial and howto is easy. Its own documentation page is a good start. But it requires basic understanding of what an XHTML document is and how it is structured.
It's hard to tell from your question and the markup you've linked to exactly what you're trying to do, so here's some general information to get you going:
The function you're currently using, getElementById, returns a single element: The one on the page with that id value. (id values must be unique on the page.)
To deal with multiple elements, you have several options. Two of the most popular:
You can start with a given element and then use its childNodes, firstChild, nextSibling, and similar properties to navigate from it to other elements nearby.
You can use getElementsByTagName (on the document or on an element) to find all elements within that container (including ones several levels down) that have a given tag. For instance, document.getElementsByTagName("p") gives you a NodeList of all paragraphs on the page.
These are properties and methods of the "DOM" (the Document Object Model), which is the tree of elements and associated information the browser creates when parsing and rendering your HTML.
References:
DOM2 Core
DOM2 HTML bindings
DOM3 Core
HTML5 Specification's DOM info
Here's an example showing some very basic operations (live copy):
HTML:
<div id="justOneDiv">I'm the <code>justOneDiv</code> element. I'm unique on the page. JavaScript code on the page turned me red.</div>
<div id="container">I'm a container called "container" with <span>various</span> <code>span</code> elements. <span>Code</span> on the <span>page</span> has made all of the <code>span</code> elements in this container <span>bold</span>.</div>
<div>I'm a container with <span>various</span> <code>span</code> elements. <span>Note</span> that the <code>span</code> elements are <span>not</span> bold, because I'm <span>not</span> in the container above.</div>
<div>I'm a <code>div</code> with no class.</div>
<div class="foo">I'm a <code>div</code> with class "foo". Code on the page turned me blue.</div>
<div class="bar">I'm a <code>div</code> with class "bar". Code on the page turned me green.</div>
<div>Another classless <code>div</code></div>
<div class="foo other">Another "foo", also with class "other"</div>
<div class="bar">Another "bar"</div>
<div>Another classless <code>div</code></div>
<div class="foo">Another "foo"</div>
<div class="bar test">Another "bar", also with class "test"</div>
<div>Another classless <code>div</code></div>
<div class="foo">Another "foo"</div>
<div class="bar">Another "bar"</div>
<div>Another classless <code>div</code></div>
<div class="foo">Another "foo"</div>
<div class="bar">Another "bar"</div>
JavaScript:
(function() {
hookEvent(window, "load", go);
function go() {
var list, index, div, container;
// Get just the one element, turn it red
document.getElementById("justOneDiv").style.color = "red";
// Get the spans within the specific container
container = document.getElementById("container");
list = container.getElementsByTagName("span");
// Loop through making those spans bold
for (index = 0; index < list.length; ++index) {
list.item(index).style.fontWeight = "bold";
}
// Get a NodeList of all divs on the page
list = document.getElementsByTagName("div");
// Loop it, turning "foo"s blue and "bar"s green
for (index = 0; index < list.length; ++index) {
div = list.item(index);
if (/\bfoo\b/.test(div.className)) {
div.style.color = "blue";
}
else if (/\bbar\b/.test(div.className)) {
div.style.color = "green";
}
}
}
function hookEvent(element, eventName, handler) {
// Very quick-and-dirty, recommend using a proper library,
// this is just for the purposes of the example.
if (typeof element.addEventListener !== "undefined") {
element.addEventListener(eventName, handler, false);
}
else if (typeof element.attachEvent !== "undefined") {
element.attachEvent("on" + eventName, handler);
}
else {
element["on" + eventName] = handler;
}
}
})();
Side note: The operations above can be made dramatically simpler by leveraging the utility functionality provided by any decent JavaScript library like jQuery, Prototype, YUI, Closure, or any of several others.
For example, using that same HTML, here's the JavaScript code using jQuery for the same result (live copy):
jQuery(function($) {
// Get just the one element, turn it red
$("#justOneDiv").css("color", "red");
// Get the spans within the specific container
// Loop through making those spans bold
$("#container span").css("font-weight", "bold");
// Turn all divs with the class "foo" blue
$("div.foo").css("color", "blue");
// Turn all divs with the class "bar" green
$("div.bar").css("color", "green");
});
The DOM is the official API; libraries like jQuery provide alternate or enhanced APIs. They're very useful and powerful, but I would recommend having some understanding of the DOM itself, even if you use a library and end up rarely writing code directly to the DOM API.

Categories