Why is Jquery hide and js style.display="none" not interchangeable - javascript

There is a simple Slider Effect below, but I have some question with it:
it's work
$(function () {
var slideIndex = 1;
SliderShow(slideIndex);
function plusIndex(n) {
SliderShow(slideIndex += n);
}
function SliderShow(n) {
var Slider = $('.Slider');
var SliderItem = Slider.children('li');
if (n > SliderItem.length) {
slideIndex = 1;
}
if (n < 1) {
slideIndex = SliderItem.length;
}
for (var i = 0; i < SliderItem.length; i++) {
SliderItem[i].style.display = "none";
}
SliderItem[slideIndex - 1].style.display = "block";
}
$('.prevBtn').click(function () {
plusIndex(-1);
});
$('.nextBtn').click(function () {
plusIndex(+1);
});
});
but when I change SliderItem[i].style.display = "none" to SliderItem[i].hide() the slide was broken, what's wrong with it?
There is any different between Jquery hide and js style?
Did I misunderstand sometihing?

Because this SliderItem[slideIndex-1] returns a native DOM element which does not have a hide method, you need to wrap it with jQuery function $:
$(SliderItem[slideIndex-1]).hide();

To answer your first question "difference between jquery hide and js style"
The behaviour of these two are most likely the same except for one thing.
By using SliderItem[i].style.display = "none"
You are only changing the style display to none
While JQuery .hide() does an extra stuff which is saving the previous value of display property to cache so you can get back to it later when you use .show().
You may check this link as reference.

Related

javascript collapsible table without jquery

This is a simple question I can't seem to figure out and every google search returns a million ways to do this via jquery, but I'd prefer to use vanilla javascript because I am new to it and want to learn it well before using any libraries. What I am trying to do is have a button collapse part of a table when clicked and then show those hidden parts again when clicked again. Basically just toggling the display of a class of elements.
I have a button that calls the test() function
when clicked nothing on my table changes. Here is my javascript code. I am using collapse[0] because if I understand it correctly collapse is a nodeList and I always close and open all of these together so I only need to check the first element.
function test() {
var collapse = document.getElementsByClassName("catOne");
var i = 0;//Counter for loops
if(collapse[0].style.display === "table-row"){
for(i = 0; i < collapse.length; i += 1){
collapse[i].style.display = "none";
}
}
if(collapse[0].style.display === "none"){
for(i = 0; i < collapse.length; i += 1){
collapse[i].style.display = "table-row";
}
}
}
I've tested the function with this code:
function test() {
var collapse = document.getElementsByClassName("catOne");
var i = 0;//Counter for loops
for (i = 0; i < collapse.length; i += 1) {
collapse[i].style.display = "none";
}
which works fine on collapsing the elements so evidentally the issue is with my if statement, but my IDE, Netbeans, doesn't throw any errors and as far as I can tell it should be working.
Thanks for the help.
Link to html and javascript: https://jsfiddle.net/ozjbekjy/
I suspect there are a few problems working against you.
First, you need to make sure the test() function is defined earlier in the page than it's being used. With jQuery, that means using the $(function(){}) wrapper to apply event handlers on DOM ready. You can approximate the same thing yourself with something like this answer.
Otherwise, simply place the <script> tag somewhere before the table (probably in the <head>), and the onclick will work.
You also are using i += 1 where you could be using i++ - they accomplish the same behavior.
Secondly, instead of manipulating the style attribute, use the classList.toggle() function to simply add and remove a class that has the rule display: none, like so:
CSS
.hide-me {
display: none;
}
JavaScript
function test() {
var collapse = document.getElementsByClassName("catOne");
for (var i = 0; i < collapse.length; i++) {
collapse[i].classList.toggle("hide-me");
}
}
Your JSFiddle, with the suggested updates: https://jsfiddle.net/ozjbekjy/4/

Iterating through an array of divs

Im still new at javascript ive been learning the concepts for several months and this is my first time taking a crack at it.
Im trying to create a carousel using css3 and Javascript (no Jquery)
the console keeps throwing an error.
Uncaught TypeError: Cannot read property display of undefined
The following is my html and javascript code
var slideShow = document.querySelectorAll('.inside');
for (var i = 0; i < slideShow.length; i++) {
setTimeout(function() {
slideShow[i].display.style = 'inline-block';
}, 2000)
}
<div class="inside">
<div class="inner1">
<h1>This is Inner div 1</h1>
</div>
<div class="inner2">
<h1>This is Inner div2</h1>
</div>
<div class="inner3">
<h1>This is Inner div3</h1>
</div>
<div class="inner4">
<h1>This is Inner div4</h1>
</div>
</div>
Aside from display and style being in the wrong order, the problem is that by the time the setTimeout callback function is executed, the for loop has already ended, and i is equal to the length of the nodeList (and since the last element's index is one less than the length of the nodeList, an error is thrown).
You could capture the value of i in an IIFE:
Example Here
var slideShow = document.querySelectorAll('.inside');
for (var i = 0; i < slideShow.length; i++) {
(function (i) {
setTimeout(function () {
slideShow[i].style.display = 'inline-block';
}, 2000 * (i + 1));
})(i);
}
or you could use the .forEach() method:
Example Here
var slideShow = document.querySelectorAll('.inside');
Array.prototype.forEach.call(slideShow, function (el, i) {
setTimeout(function () {
el.style.display = 'inline-block';
}, 2000 * (i + 1));
});
Alternatively, you could just use setInterval:
Example Here
var slideShow = document.querySelectorAll('.inside');
var i = 0;
var interval = setInterval(function () {
if (i < slideShow.length) {
slideShow[i].style.display = 'inline-block';
i++;
} else {
clearInterval(interval);
}
}, 2000);
You have display and style in the wrong order.
It should be slideShow[i].style.display='inline-block';
Additionally, slideShow is only an array-like object of length 1: it contains the div .inner but not its children. If you want to iterate through the child elements, use
var slideShow = document.querySelector('.inside').children;
Edit: As Josh pointed out in a separate answer, you have another problem as well in using setTimeout within a for loop. By the time the function inside the timeout executes, i will be 4, which will give you an undefined value.
If you insist on using a for loop, you can also do this using the forEach method. However, slideShow is not technically an array, but rather an "array-like object", so it does not have its own forEach method. Instead, you must invoke the Array.prototype method as such:
[].forEach.call(slideShow, function(item) {
setTimeout(function() {
item.style.display = 'inline-block';
}, 2000);
});
problem is you are only selecting div.inside and it is not returning div.inner
Try this if you want to select all .inner
change class="inside" to id="inside" and copy this js
var slideShow=document.getElementById("inside").querySelectorAll('div');
slideShow[1].style.backgroundColor = "red";
for (var i=0; i<slideShow.length; i++){
setTimeout(myFun(i), 2000)
}
function myFun(i ){slideShow[i].style.display = "inline-block";}

Hide numbers with javascript, without using jQuery

I have the following fiddle.
When you click the Hide button the numbers 2, 3 and 1 are hidden. All works great using this Jquery code:
$( "#hide" ).click(function() {
$('span').each(function(){
if($(this).text().match(/^([1-9])$/))$(this).hide()
});
});
Now I want the same thing, but with using a good old javascript function instead of the jQuery solution given above. How to do this? See my (not working) attempt here.
Many thanks
Here is a simple vanilla JS version:
function hide() {
var spans = document.getElementsByTagName('span'), i = 0;
for(i=0; i<spans.length; i++) {
spans[i].style.display = (spans[i].innerText.match(/^[1-9]+$/) ? 'none' : '');
}
}
Note: I've corrected your regex to match numbers with more than 1 digit in it.
Updated fiddle: http://jsfiddle.net/WnLUu/6/
In plain javascript you could access the style attribute, so instead of $(this).hide() you could call
this.style.visibility = "hidden"
Maybe something like this.
function buttonClicked(evt) {
var spans = document.getElementsByTagName("span");
for (var i = 0, length = spans.length; i < length; ++i) {
if (/^([1-9])$/.test(spans[i].innerHTML)) {
spans[i].style.display = "none";
}
}
};
document.getElementById("hide").addEventListener("click", buttonClicked, false);
Please try this (works on IE and other browsers, .innerText is IE specific):
function hide() {
var spans = document.getElementsByTagName('SPAN');
for (var i=0; i < spans.length; i++) {
alert(spans[i].textContent);
if (spans[i].textContent !== undefined && spans[i].textContent.match(/^[1-9]$/))
spans[i].style.display = 'none';
else if (spans[i].innerText !== undefined && spans[i].innerText.match(/^[1-9]$/)) // IE
spans[i].style.display = 'none';
}
}

css3 animation on click with javascript

I need to animate several items at the same time, several times on click. I'm not allowed to use Jquery so I'm working with native javascript and CSS3.
Array.prototype.forEach.call(els, function(el) {
elemId = el.getAttribute("id");
var toWidth = boxPos[thisId][elemId].width;
var toHeight = boxPos[thisId][elemId].height;
var toTop = boxPos[thisId][elemId].top;
var toLeft = boxPos[thisId][elemId].left;
var from = "0% {width:"+currPos[elemId].width+"; height:"+currPos[elemId].height+"; top:"+currPos[elemId].top+"; left:"+currPos[elemId].left+";}";
var to = "100% { width:"+toWidth+"; height:"+toHeight+"; top:"+toTop+"; left:"+toLeft+";}";
currPos[elemId].width = toWidth;
currPos[elemId].height = toHeight;
currPos[elemId].top = toTop;
currPos[elemId].left = toLeft;
var styleSheets = document.styleSheets;
for (var i = 0; i < styleSheets.length; ++i) {
for (var j = 0; j < styleSheets[i].cssRules.length; ++j) {
if (styleSheets[i].cssRules[j].type == window.CSSRule.WEBKIT_KEYFRAMES_RULE && styleSheets[i].cssRules[j].name == elemId){
keyframes = styleSheets[i].cssRules[j];
}
}
}
keyframes.deleteRule("0%");
keyframes.deleteRule("100%");
keyframes.insertRule(from);
keyframes.insertRule(to);
el.style.webkitAnimationName = elemId;
});
I've searched around the site and have tried using some of the code. The animation will run once, all the elements but just the first time :'(
Here's a non working example code http://jsfiddle.net/kR384/2/
The animation will run once, all the elements but just the first time
You seem to be looking for the animation-iteration-count CSS property, which specifies how often an animation will run. You can set it to infinite or any numerical (positive) value.
The problem you have with your animations is that they are only started on the first click. After that, you don't change the element's styles (reassigning the animation-name doesn't help) - so no animation will get triggered (even if you changed the keyframes rules). The article at http://css-tricks.com/restart-css-animation/ discusses this and a few solutions.
In your case it would even make sense to change the name of animation to something containing the "state":
if( …cssRules[j].name.split("-")[0] == elemId)
keyframes = styleSheets[i].cssRules[j];
…
var newname = elemId+"-"+thisId;
keyframes.name = newname;
…
el.style.animationName = newname;
(Demo with standard properties and a few bugfixes, updated demo with webkit prefixes)
I was able to fix it just by adding a setTimeout(0) to call the animation after the animation name was set to none.
Here's the fixed code http://jsfiddle.net/kR384/3/:
function resetAndRun(o){
one.style.webkitAnimationName = "none";
…
ten.style.webkitAnimationName = "none";
setTimeout(function(){o.animateBox();}, 0);
}
I hope it's useful for someone.

Jquery Problem Sort of Auto Slideshow

I'm having some problems, I'd like to have a sort of slideshow where users have 4 buttons, and when they click one div appears and the others disappear. The div's are all in the same place with the same size. I'd also like to put this automatic
var Idx = 1;
var IntervalKey = setInterval = (auto, 5000);
var auto = function() {
$("#MainImage").eq(Idx).fadeIn(1000);
while(Idx <3) {
Idx++;
$("#MainImage").eq(Idx).hide();
}
Idx++;
if(Idx>3) {
Idx = 0;
}
};
$(".botao-imagem").click(function(){
Idx = $(".botao-imagem").index(this);
auto();
});
Your main issue is repeated IDs, IDs must be unique, so $("#ID").eq() doesn't every have a purpose really, since it should be 1 or 0 results. First give the elements a class instead:
<div class="MainImage"><p>111111</p></div>
<div class="MainImage"><p>222222</p></div>
<div class="MainImage"><p>333333</p></div>
<div class="MainImage"><p>444444</p></div>​
and use a class selector, like this:
$(".MainImage")
Also auto needs to be declared before using it or define it as a function directly, overall like this:
var Idx = 0;
var IntervalKey = setInterval(auto, 5000);
function auto() {
$(".MainImage").hide().eq(Idx).fadeIn(1000);
Idx++;
if(Idx>3) Idx = 0;
};
$(".botao-imagem").click(function(){
Idx = $(".botao-imagem").index(this);
auto();
});
You can test the updated/working version with the above code here.

Categories