I'm trying to make a 100% width 3px height div grow in height when I hover over a breadcrumb and I'm failing miserably. Here is the script:
var menuIsOpen = false;
function bc_MouseOver() {
if (!menuIsOpen)
{
menuIsOpen = true;
for (var int = 4; int == 20; int++)
{
document.getElementById("navmenu").style.height = int + "px";
}
}
}
and a bit of the html (using MVC):
<body>
<div id="navigation">
<ul id="navlist">
<li class="titleli">
Some Title
</li>
<li class="breadcrumb" onmouseover="bc_MouseOver()">Projects</li>
<li class="breadcrumb"></li>
</ul>
</div>
<div id="navmenu"> </div>
<div class="container">
#RenderBody()
</div>
</body>
Why aren't you using CSS for this? Using a :hover pseudo-class, or applying a class on hover to an element with a transition would seem like the best answer for this, but, if you're keen on JS:
for (var int = 4; int == 20; int++)
{
document.getElementById("navmenu").style.height = int + "px";
}
This block is synchronous, the new height wont get applied til (probably) the end of the next tick, whereby it will simply apply a height of '20px'.
You'd have to work out a way of applying a 1px increase each tick to make sure it has rendered and then opened. jQuery animate is pretty useful to save you having a work it all out (and solve any potential cross-browser issues) but if you're keen on vanilla JS:
var time = 0;
function bc_mouseOver( i ) {
var i = i || 4;
if ( i < 21 ) {
document.getElementById("navmenu").style.height = int + "px";
setTimeout( function() {
bc_mouseOver( i + 1 )
}, time );
}
}
You might have to check that bc_mouseOver is in scope because the setTimeout will be run in the context of the window. Using lodash/underscore defer method is a good way to hide the the setTimeout and the context shifting and generally makes things much neater and more reliable.
You might have to change the variable time as well to get exactly what you want, I've done a 0 timeout here to force it on the next tick but that might be too quick, particularly in some environments/platforms.
Really though, this can (adn probably should) be done in a few lines of CSS.
Problem is with your test condition in for loop. It fails everytime and loop is not executed.
Change it to:
for (var int = 4; int <= 20; int++) {
document.getElementById("navmenu").style.height = int + "px";
}
Related
$myWindow.on('resize', function(){
var $width = $myWindow.width();
if ($width > 870) {
console.log('hey im 870');
$('#the-team-wrapper .flex-content').empty();
ajax_results.done(function(data) {
// console.log(data.job_titles[3]);
var employee_job_titles;
function job_titles_display(jobtitle,ind){
if (jobtitle.job_titles[ind].length>1) {
var my_array = [];
for (var i = 0; i < jobtitle.job_titles[ind].length; i++){
my_array.push(jobtitle.job_titles[ind][i][0]['title']);
employee_job_titles = my_array.join(' | ');
}
}else {
var employee_job_titles;
employee_job_titles = jobtitle.job_titles[ind][0]['title'];
}
return employee_job_titles;
}
for (var i = 0; i < data.employee_info.length; i++) {
if(i%2 == 0){
$('#the-team-wrapper .flex-content').append('<div class="profile-parent"><div class="employee-profile-pic flex-item" data-id="'+data.employee_info[i]['id']+'"></div><div class="employee-bio-wrapper flex-item"><h2 data-id="'+data.employee_info[i]['id']+'">'+data.employee_info[i]['firstname']+" "+data.employee_info[i]['lastname']+'</h2><h3 data-id="'+data.employee_info[i]['id']+'">'+job_titles_display(data,i)+
'</h3><p class="employee-bio-text employee-bio-text-not-active">'+data.employee_info[i]['bio']+'</p></div><button type="button" class="bio-prev-butt-left">View '+data.employee_info[i]['firstname']+'\'s'+' Bio</button><div class="hide-bio-close-button-left">x</div></div>');
}else {
$('#the-team-wrapper .flex-content').append('<div class="profile-parent"><div class="employee-bio-wrapper flex-item"><h2 data-id="'+data.employee_info[i]['id']+'">'+data.employee_info[i]['firstname']+" "+data.employee_info[i]['lastname']+'</h2><h3 data-id="'+data.employee_info[i]['id']+'">'+job_titles_display(data,i)+'</h3 data-id="'+data.employee_info[i]['id']+
'"><p class="employee-bio-text employee-bio-text-not-active">'+data.employee_info[i]['bio']+'</p></div><div class="employee-profile-pic flex-item" data-id="'+data.employee_info[i]['id']+'"></div><button type="button" class="bio-prev-butt-right">View '+data.employee_info[i]['firstname']+'\'s'+' Bio</button><div class="hide-bio-close-button-right">x</div></div>');
}
var profile_pic_path = data.employee_info[i]['profile_pic'].split('\\').join('\\\\');
$("#the-team-wrapper .flex-content-wrapper .flex-content .employee-profile-pic:eq("+i+")").css({'background': 'url(_employee_pics/'+profile_pic_path+')','background-repeat': 'no-repeat','background-position': 'center', 'background-size': 'cover'});
}
});
}
I have this code, and it should fire when width is greater than 870, but instead it fires when width is greater than 970 on Opera, and when width is about 890 on Chrome. How can I fix this and get consistent results across browsers. Thanks in advance.
Are you using a CSS reset to neutralize the browser's default margin or padding on the <body> element?
Different browsers add different amounts of either padding or margin to the <body> of the page, which could explain why the function is triggered at different points in different browsers.
The problem is, the resize event fires at different times and rates depending on browser, CPU load, and how fast you actually do the resizing.
Test the following code in your browsers. When I do this in a clean browser at a reasonable rate of coverage the difference usually comes in within around 2px of the target.
(BTW, you'll see I am caching the jQuery selectors into variables. Not strictly necessary for this test, but you might be surprised to find out how many bugs I've fixed because coders have invoked uncached jQuery selectors willy-nilly in loops and other repetitive places throughout their code).
var $window = $(window);
$window.on('resize',function(){
var w = $window.width();
if (w > 1000) {
console.log( w );
} else {
console.log('nope: ' + w)
}
});
Ok so I've revised the markup/code to make it easier to understand. Using JavaScript I want to know how to create a text slider that changes a paragraph in html5 either "forwards" or "backwards" on click?
I only want one div to show at a time and the first div (div_1) needs to be visible at the beginning as a default setting. I also want to be able to add more text divs to it in the future. I'm new to JavaScript so I want to keep it as simple as possible.
I've had a go creating it in JavaScript which hasn't worked, I'm not sure if I'm going about this the right way.
<!DOCTYPE html>
<html lang="en">
<head>
<style type="text/css">
.showHide {
display: none;
}
</style>
<script type="text/javascript">
var sdivs = [document.getElementById("div_1"),
document.getElementById("div_2"),
document.getElementById("div_3"),
document.getElementById("div_4")];
function openDiv(x) {
//I need to keep div_1 open as a starting point
sdivs[0].style.display ="block";
var j;
for (var j = 0; j < sdivs.length; j++) {
if (j === x) {
continue;
}
else {
sdivs[j].style.display = "none";
}
}
}
</script>
<title>text</title>
</head>
<body>
forward
backwards
<div id="text_holder">
<div id="div_1" class="showHide">One</div>
<div id="div_2" class="showHide">Two</div>
<div id="div_3" class="showHide">Three</div>
<div id="div_4" class="showHide">Four</div>
</div>
</body>
</html>
When dealing with multiple elements like this, I've found CSS alone to be insufficient (though its brilliant for modifying simple hover states or whatever). This one method here is pretty simple and specific to this one set of markup (so modify as you see fit). More importantly - its to illustrate how to set up a simple javascript "class" to handle your logic.
http://jsfiddle.net/1z13qb58/
// use a module format to keep the DOM tidy
(function($){
// define vars
var _container;
var _blurbs;
var _blurbWidth;
var _index;
var _clicks;
// initialize app
function init(){
console.log('init');
// initialize vars
_container = $('#text_holder .inner');
_blurbs = $('.blurb');
_blurbWidth = $(_blurbs[0]).innerWidth();
_clicks = $('.clicks');
_index = 0;
// assign handlers and start
styles();
addEventHandlers();
}
// initialize styles
function styles(){
_container.width(_blurbs.length * _blurbWidth);
}
// catch user interaction
function addEventHandlers(){
_clicks.on({
'click': function(el, args){
captureClicks( $(this).attr('id') );
}
});
}
// iterate _index based on click term
function captureClicks(term){
switch(term){
case 'forwards':
_index++;
if(_index > _blurbs.length - 1){
_index = 0;
}
break;
case 'backwards':
_index--;
if(_index < 0){
_index = _blurbs.length - 1;
}
break;
}
updateView();
}
// update the _container elements left value
function updateView(){
//_container.animate({
//'left' : (_index * _blurbWidth) * -1
//}, 500);
_container.css('left', ((_index * _blurbWidth) * -1) + 'px');
}
init();
})(jQuery);
I'm using jQuery to handle event binding and animation, but, again - there are lots of options (including a combination of vanilla javascript and CSS3 transitions).
I'll note also that this is all html4 and css2 (save your doctype).
Hopefully that helps -
Trying to do a simple fade in using the opacity property of an h1 element. I'm learning javascript, so would like to try this using plain javascript (yes, I know it is much easier using jQuery).
Pasting only relevant snippets:
<body onload="fadeIn()">
...
<div class = "container">
<div class = "row">
<div class = "col-md-3">
<img class = "img-responsive" src="icons/Website_Logo.png">
</div>
<div class = "col-md-9 page-header">
<h1 id="welcomeHeader" style="opacity:0">
Welcome to the world!
</h1>
</div>
</div>
</div>
...
<script>
function fadeIn() {
var el = document.getElementById("welcomeHeader");
var op = parseFloat(el.style.opacity);
var timer = (function () {
if(op >= 1.0)
clearInterval(timer);
op += 0.1;
el.style.opacity = op;
}, 50);
}
</script>
</body>
Help is much appreciated! Thanks!
jsFIDDLE
You need to call the setInterval function first in order to invoke a timer. Rest is fine. Here is a working fiddle
Code Snippet:
function fadeIn() {
var el = document.getElementById("welcomeHeader");
var op = parseFloat(el.style.opacity);
var timer = setInterval(function () {
console.log('here');
if(op >= 1.0)
clearInterval(timer);
op += 0.1;
el.style.opacity = op;
}, 50);
}
You need to change your function to use setInterval like so:
var timer = setInterval(function () { // notice the setInterval added.
if(op >= 1.0)
clearInterval(timer);
op += 0.1;
el.style.opacity = op;
}, 50);
Notes:
I give you this answer to help you LEARN javascript as you mentioned, otherwise,
it would be better done with pure css of course.
Also, make sure your opacity is set to 0 in your css as a starting point.
You don't need a timer for this - all you need to do is change the class. Here's an example:
the CSS:
element{
/* whatever styles you have */
}
element_faded{
transition: opacity .5s;
opacity: 50%; /* or whatever values you want */
}
the javascript
var element = document.getElementById('element');
// in order to trigger the fade, just change the class
element.className = "element_faded";
In the transition will happen between the values of the original and new class, so if you want a fade-in, have the original opacity be 0% and the new one be 100% or something higher than zero, depending on what you want the final opacity to be. Also, remember that the transition characteristics are determined by the transition attribute in the new class.
Doing this without CSS will just make things more complicated unless you need to do something more sophisticated than just plain fading in or out. If that's the case, then use setInterval or perhaps even something like requestAnimationFrame if you're feeling adventurous.
Honestly, this isn't really the kind of thing you need to learn when first learning javascript. Eventually this will be really easy once you get some confidence under your belt doing things that work more easily in javascript (setTimeout and the like can have their own weird caveats). Try to set a meaningful, practical goal and fulfill it first, using whatever mix of javscript/css/html you can and you'll soon have the basics down well enough to find things like this obvious.
I am making an info screen, and for that, it needs to show reviews from their customers pulled from Trustpilot.
I got the reviews and everything formatted in HTML showing the 20 latest, but I want to present it very sweet. I am not a JavaScript guru, but I thought i would do it using jQuery and its fadein function.
What is want, is have 20 unique divs fading in with X milliseconds difference popping randomly up. By unique I mean, that each div must have unique content. And by randomly popping up, I mean that if box 1 spawns first, then the next should be 5, then 14 etc, and then another cycle the next time around.
Just like what I made here;
$(function() {
var box = $('.box');
var delay = 100;
for (i = 0; i < 30; i++) {
setTimeout(function() {
var new_box = box.clone();
$('.container').append(new_box);
new_box.fadeIn();
}, delay);
delay += 500; // Delay the next box by an extra 500ms
}
});
http://jsfiddle.net/CCawh/5/
Is this even possible, and how would this be done?
I am very new to JavaScript, so please bear with me if I ask to much
Thanks in advance.
EDIT:
The HTML i want to spawn will all be wrapped in divs, so it would go like this;
<div id="one">content</div>
<div id="two">content</div>
<div id="three">content</div>
<div id="four">content</div>
etc.
Made up a nice function for you. I believe this may be what you are looking for
Here's a rundown of how it works :
Populate an array with numbers randomly generated 1-10 in this case.
Run through that array with a set interval, and when everything has
been added stop the interval
pretty straightforward from there. Set the visibility etc. You should be able to change up the function to dynamically add HTML elements and what-not, but just giving you something to start with.
var usedNum = [];
var i, j, y;
i = 0;
for(y = 0; y < 10; y++){
var x = Math.floor((Math.random() * 10) + 1);
if(!isUsed(x)) usedNum.push(x);
else y--;
}
var showInterval = setInterval ( function(){
if(i == 10){
clearInterval(showInterval);
}
$(".container div[data-line='" + usedNum[i] + "']").css({opacity: 0.0, visibility: "visible"}).animate({opacity: 1.0});
i++;
}, 500);
function isUsed(num) {
var used = false;
for(j = 0; j < usedNum.length; j++){
if(usedNum[j] == num){
used = true;
}
}
return used;
}
Demo fiddle : http://jsfiddle.net/xS39F/3/
Edit:
You can also mess around with the speed of the animation. In this demo (http://jsfiddle.net/adjit/XYU34/1/) I set the speed to 1000 so the next element starts fading in before the last element was done fading in. Makes it look a little smoother.
Instead of using a for loop and setTimeout, would setInterval work better for what you need? Some HTML might help better understand what you're trying to achieve.
$(function() {
var box = $('.box');
var delay = 100;
var interval = setInterval(function() {
var new_box = box.clone();
$('.container').append(new_box);
new_box.fadeIn();
}, delay);
delay += 500; // Delay the next box by an extra 500ms
}, delay);
});
I need to have 2 of these one page but each with different percentages. When I try re-writing the JS or even use different class/ID names it still always pulls from the first SPAN.
http://jsfiddle.net/K62Ra/
<div class="container">
<div class="bw"></div>
<div class="show"></div>
<div id="bar" data-total="100">
<div class="text">Currently at <br/><span>70</span><br><i>Click To Give</div>
</div>
JS and CSS in the Fiddle.
Much Thanks.
This one will work smoothly:
http://jsfiddle.net/K62Ra/7/
$('.bar').each(function() {
var percentStart = 0;
var total = $(this).data('total');
var percent = parseInt($(this).find('span').html());
$(this).find('> div').addClass("load");
var that = this;
var timer = setInterval(function() {
$(that).siblings('.show').css('height', percentStart/total*100+'%');
$(that).css('height', percentStart/total*100+'%');
$(that).find('span').html('%'+percentStart);
if(percentStart<percent) { percentStart=percentStart+1; return; }
clearInterval(timer);
}, 35);
});
The interval has to be terminated as well, or it will run infinitely (though not doing anything).
I've changed your id="bar" into a class. Then I'm running a each loop for the .bar classes. here is the fiddle: http://jsfiddle.net/K62Ra/3/
here is the code:
$('.bar').each(function (index, element) {
percent = $(this).find('span').html();
total = $(this).attr('data-total');
percentStart = 0;
setInterval(function () {
$('.show').css('height', percentStart / total * 100 + '%');
$(this).css('height', percentStart / total * 100 + '%');
$(this).find('span').html('%' + percentStart);
if (percentStart < percent) {
percentStart = percentStart + 1;
}
}, 35);
});
$(".bar div").addClass("load");
Like some of the comments have stated, having duplicate ids is bad design and can cause some weird errors.
You can find a solution to your problem by changing a number of things. One, instead of
referring to divs in you selectors by id'#', you can infer them by class '.' like
$('.bar')
The next step would be to ensure exclusivity for each div with class 'container' by using a closure
$('.container').each(function(){
var x
var y
.
.
});
And finally, avoid 'selecting' elements in the selector directly, but use $(this) and .find() to ensure you are within the current div with class 'container'.
http://jsfiddle.net/K62Ra/5/
$('.container').each(function(){
var percent = $(this).find('div.bar div span').html();
var total = $(this).find('div.bar').attr('data-total');
var percentStart = 0;
var that = $(this);
setInterval(function() {
that.find('.show').css('height',percentStart/total*100+'%');
that.find('div.bar').css('height',percentStart/total*100+'%');
that.find('div.bar div span').html('%'+percentStart);
if(percentStart<percent) {percentStart=percentStart+1;}
},35);
$(this).find("div.bar div").addClass("load");
});
There are already several good answers here. I would recommend validating your html. Also some of your css was causing weirdness when there was scrolling involved (fixed background images weren't scrolling.)
I took a slightly different approach than everyone else. Instead of using a setInterval I went with $.animate and a step function. Like others, I chose a class to target each of the items: 'fill-me-up'.
Fiddle: http://jsfiddle.net/LFbKs/6/
NOTE: Check the fiddle since I modified the HTML (very slightly) and the css to a larger degree.
// for each item we need to "fill up"
$('.fill-me-up').each(function(){
// cache DOM references
var this$ = $(this)
, bar$ = this$.find('.bar')
, show$ = this$.find('.show')
, span$ = bar$.find('div span')
// the target percentage height for this item
, p = span$.text()
// combine '.bar' and '.show' so we can apply the animation to both
, toAnimate = $().add(bar$).add(show$);
// add class causing fade-in
bar$.find('div').addClass('is-visible');
// animate height to target height over 2 seconds and
// at each step, update the span with a truncated value
toAnimate.animate(
{ height: p+'%' },
{
duration: 2000,
step: function( currentStep ) {
span$.html('%'+currentStep.toFixed(0));
}
}
);
});
Cheers