Doing a roll-in/roll-out slideshow in jQuery - javascript

I am trying to create a roll-in / roll-out slideshow in jQuery/JavaScript.
My problem is, that it needs to be repeated. And right now when it's starting over, the pictures doesnt come from the right side anymore :(
The reason for which I have created the slideLeft function, is that afterwards I need to create 2 functions, where the user can interrupt the slideshow manually pressing a left or right button.
This is what I've got:
<script class="jsbin" src="http://code.jquery.com/jquery-1.7.2.min.js"></script>
<div style='background: #c4c4c4; border: 1px solid #7b7b7b; height: 220px; overflow: hidden; padding: 5px; position: absolute; width: 590px;'>
<div id='slider-image-1' style='left: 5px; background: red; height: 216px; padding: 2px; position: absolute; top: 5px; width: 586px;'></div>
<div id='slider-image-2' style='left: 600px; background: yellow; height: 216px; padding: 2px; position: absolute; top: 5px; width: 586px;'></div>
<div id='slider-image-3' style='left: 600px; background: green; height: 216px; padding: 2px; position: absolute; top: 5px; width: 586px;'></div>
<div id='slider-image-4' style='left: 600px; background: blue; height: 216px; padding: 2px; position: absolute; top: 5px; width: 586px;'></div>
</div>
<script type='text/javascript'>
$(document).ready(function() {
var amount = 0;
var nextamount = 1;
setInterval(function() {
amount++;
nextamount++;
if (nextamount === 5) nextamount = 1;
if (amount === 5) amount = 1;
slideLeft(amount, nextamount);
}, 2000);
});
function slideLeft(i, j) {
var $theItem = $('#slider-image-' + i);
$theItem.animate({
left: parseInt($theItem.css('left'), 10) == 5 ? -$theItem.outerWidth() : 5
}, 500);
var $theItem = $('#slider-image-' + j);
$theItem.animate({
left: parseInt($theItem.css('left'), 10) == 5 ? $theItem.outerWidth() + 10 : 5
}, 500);
};
</script>

You need to prepare element, which is going to roll in, to be on the right.
function slideLeft(i, j) {
var $theItem = $('#slider-image-' + i);
$theItem.animate({
left: parseInt($theItem.css('left'), 10) == 5 ? -$theItem.outerWidth() : 5
}, 500);
var $theItem = $('#slider-image-' + j);
$theItem.css('left', '600px'); // moves in item to the right before animation
$theItem.animate({
left: parseInt($theItem.css('left'), 10) == 5 ? $theItem.outerWidth() + 10 : 5
}, 500);
};
I think you've tried it with your parseInt, but it doesn't work, so you can get rid of it.
function slideLeft(i, j) {
var $outItem = $('#slider-image-' + i);
$outItem.animate({ left: -$outItem.outerWidth() }, 500);
var $inItem = $('#slider-image-' + j);
$inItem.css('left', '600px');
$inItem.animate({ left: 5 }, 500);
}

I have made something like this before, i dont know if this will help you, what i did was:
Add a copy of the first slide in the end of the collection of images/slides. Then, when you are showing the last "real" image and it will look like you are scrolling to the first image (but that is just a copy of the first image), and then when the animation is done you can position it with the default "left" css value. If you want it to scroll both ways, you can do the same with a copy of the last image/slide before the first image, but then you'll have to start the slider with a offset.
its a bit hard to explain, do you get the point? :)

Related

How can I make an element on hover?

All I'm trying to do is something like this mechanism:
Here is what I've tried so far:
$(document).ready(function(){
$('a').bind('mouseenter', function() {
var self = $(this);
this.iid = setInterval(function() {
var tag_name = self.text(),
top = self.position().top + self.outerHeight(true),
left = self.position().left;
self.append("<div class='tag_info'>Some explanations about"+tag_name+"</div>")
$(".tag_info").css({top: top + "px", left: left + "px"}).fadeIn(200);
}, 525);
}).bind('mouseleave', function(){
this.iid && clearInterval(this.iid);
});
});
body{
padding: 20px;
}
a {
color: #3e6d8e !important;
background-color: #E1ECF4;
padding: 2px 5px;
}
.tag_info{
position: reletive;
width: 130px;
height: 30px;
display:none;
background-color: black;
color: white;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<a>tag1</a>
<a>tag2</a>
As you see, it will be repeated every time. How can I execute it once per hover? And why the position doesn't apply?
Also is what I'm doing a right algorithm for such thing?
Thank you.
I am not sure why you are using setInterval but I think this should work. I removed setInterval and everytime the mouseenter event occurs we can append <div class='tag_info'> and every time mouseleave event occurs we can remove the the appended div.
$(document).ready(function(){
$('#test').bind('mouseenter', function() {
var self = $(this);
var tag_name = self.text(),
top = self.position().top + self.outerHeight(true),
left = self.position().left;
self.append("<div class='tag_info'>Some explanations about"+tag_name+"</div>")
$(".tag_info").css({top: top + "px", left: left + "px"}).fadeIn(200);
}).bind('mouseleave', function(){
$(this).children('.tag_info').remove();
});
});
body{
padding: 20px;
}
a {
color: #3e6d8e !important;
background-color: #E1ECF4;
padding: 2px 5px;
}
.tag_info{
position: reletive;
width: 130px;
height: 30px;
display:none;
background-color: black;
color: white;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<a id="test">tag1</a>
Like Dij said:
What you're doing:
setInterval - (repeats your function every 525ms)
What you want:
setTimeout - (executes your function once after 525ms delay)
Read more:
setInterval https://www.w3schools.com/jsref/met_win_setinterval.asp
setTimeout https://www.w3schools.com/jsref/met_win_settimeout.asp

How to add text to different parts of chart made from css, html, and javascript?

I'd like to add text to three different parts of the below row chart:
http://codepen.io/chriscruz/pen/ByjZdp
A number at the beginning of where the orange begins
a percentage right before the organge ends
A number at the end of the entire bar where the gray ends.
Something like this:
HTML:
<div class="progress-wrap progress" data-progress-percent="50">
<div class="progress-bar-state progress">50</div>
</div>
CSS:
.progress {
width: 100%;
height: 50px;
}
.progress-wrap {
background: #f80;
margin: 20px 0;
overflow: hidden;
position: relative;
.progress-bar-state {
background: #ddd;
left: 0;
position: absolute;
top: 0;
}
}
Javascript:
// on page load...
moveProgressBar();
// on browser resize...
$(window).resize(function() {
moveProgressBar();
});
// SIGNATURE PROGRESS
function moveProgressBar() {
console.log("moveProgressBar");
var getPercent = ($('.progress-wrap').data('progress-percent') / 100);
var getProgressWrapWidth = $('.progress-wrap').width();
var progressTotal = getPercent * getProgressWrapWidth;
var animationLength = 2500;
// on page load, animate percentage bar to data percentage length
// .stop() used to prevent animation queueing
$('.progress-bar-state').stop().animate({
left: progressTotal
}, animationLength);
}
I've tried to just insert the numbers after, but I can't seem to make the numbers relative to the position of 'progress-wrap' or 'progress.' See my attempt here: http://codepen.io/chriscruz/pen/MYKoBq
You can use :before and :after :pseudo-elements.
// on page load...
moveProgressBar();
// on browser resize...
$(window).resize(function() {
moveProgressBar();
});
// SIGNATURE PROGRESS
function moveProgressBar() {
console.log("moveProgressBar");
var getPercent = ($('.progress-wrap').data('progress-percent') / 100);
var getProgressWrapWidth = $('.progress-wrap').width();
var progressTotal = getPercent * getProgressWrapWidth;
var animationLength = 2500;
// on page load, animate percentage bar to data percentage length
// .stop() used to prevent animation queueing
$('.progress-bar-state').stop().animate({
left: progressTotal
}, animationLength);
}
.progress {
width: 100%;
height: 50px;
}
.progress-wrap:before {
content: '66';
position: absolute;
left: 5px;
line-height: 50px;
}
.progress-wrap:after {
content: '$250,000';
right: 5px;
position: absolute;
line-height: 50px;
}
.progress-wrap {
background: #f80;
margin: 20px 0;
overflow: hidden;
position: relative;
}
.progress-wrap .progress-bar-state {
background: #ddd;
left: 0;
position: absolute;
top: 0;
line-height: 50px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<!-- Change the below data attribute to play -->
<div class="progress-wrap progress" data-progress-percent="50">
<div class="progress-bar-state progress">50</div>
</div>
As given below, Add/Modify HTML , CSS and JS. It gets your desired output
$('.progress-bar-state').stop().animate({
left: progressTotal
width:getProgressWrapWidth - progressTotal
}, animationLength);
HTML
<!-- Change the below data attribute to play -->
<div class="progress-wrap progress" data-progress-percent="7">
vd
<div class="progress-bar-state progress">8
<div class="right-content" >RightEnd</div></div>
</div>
CSS
.right-content
{
float:right;
}

jitter when using jquery to alter background-position

Here's the jsfiddle.
It's the interface to cropping an image. As you can see the selection div takes the same background image and positions it to the negative of the top and left attributes of the selection div. In theory this should give a perfect overlap, but there's a jitter as you move the selection div around, and I can't seem to figure out what is causing it.
html
<div id="main">
<div id="selection"></div>
</div>
css
#main {
width: 600px;
height: 450px;
position: relative;
background: url("http://cdn-2.historyguy.com/celebrity_history/Scarlett_Johansson.jpg");
background-size: contain;
}
#selection {
width: 100px;
height: 100px;
position: absolute;
background: url("http://cdn-2.historyguy.com/celebrity_history/Scarlett_Johansson.jpg");
border: 1px dotted white;
background-size: 600px 450px;
}
jquery
$(document).ready(function () {
var move = false;
var offset = [];
var selection = null;
$("#selection").mousedown(function (e) {
move = true;
selection = $(this);
offset = [e.pageX - selection.offset().left, e.pageY - selection.offset().top];
});
$("#selection").mousemove(function (e) {
if (move == true) {
selection.css("left", e.pageX - offset[0]);
selection.css("top", e.pageY - offset[1]);
selection.css("background-position", (((-selection.position().left) - 1) + "px " + ((-selection.position().top ) - 1) + "px"));
}
});
$("#selection").mouseup(function (e) {
move = false;
});
})
It would appear that there is a value of 5 offset that needs to be added to ensure seamlessness
DEMO http://jsfiddle.net/nzx0fcp5/2/
offset = [e.pageX - selection.offset().left + 5, e.pageY - selection.offset().top + 5];
So, while experimenting I discovered that this was only a problem at certain sizes of the image. At the original size it is no problem, neither at half nor a quarter of this size. It wasn't simply a matter of keeping the image in proportion not having the image square or using even pixel sizes. I'm assuming this had something to do with partial pixel sizes, but I'm not sure, and I couldn't see any way to work around this, at least none that seemed worth the effort.
So while checking out the code of other croppers I took a look at POF's image cropper, they seem to have got round the problem by not using the background-position property at all (I'm not sure if it's plugin or they coded it themselves). They just set the image down and then used a transparent selection div with 4 divs stuck to each edge for the shading. So there's no pixel crunching on the fly at all. I like the simplicity and lightweight nature of this design and knocked up a version myself in jsfiddle to see if I could get it to work well.
new jitter free jsfiddle with no pixel crunching
I liked the solution for the preview box as well.
html
<body>
<div id="main">
<img src="http://flavorwire.files.wordpress.com/2012/01/scarlett_johansson.jpg" />
<div id="upperShade" class="shade" > </div>
<div id="leftShade" class="shade" > </div>
<div id="selection"></div>
<div id="rightShade" class="shade"></div>
<div id="lowerShade" class="shade" ></div>
</div>
</body>
css
#main {
position:relative;
width: 450px;
height: 600px;
}
#selection {
width: 148px;
height: 148px;
position: absolute;
border: 1px dotted white;
top: 0px;
left: 0px;
z-index: 1;
}
.shade {
background-color: black;
opacity: 0.5;
position: absolute;
}
#upperShade {
top: 0px;
left: 0px;
width: 600px;
}
#leftShade {
left: 0px;
top: 0px;
height: 150px;
width: auto;
}
#rightShade {
left: 150px;
top: 0px;
height: 150px;
width: 450px;
}
#lowerShade {
left:0px;
top: 150px;
width: 600px;
height: 300px;
}
jquery
$(document).ready(function () {
var move = false;
var offset = [];
var selection = null;
$("#selection").mousedown(function (e) {
move = true;
selection = $(this);
offset = [e.pageX - selection.offset().left, e.pageY - selection.offset().top];
});
$("#selection").mousemove(function (e) {
if (move == true) {
selection.css("left", e.pageX - offset[0]);
selection.css("top", e.pageY - offset[1]);
setShade();
}
});
function setShade() {
$("#upperShade").css("height", selection.position().top);
$("#lowerShade").css("height", 600 - (selection.position().top + 150));
$("#lowerShade").css("top", selection.position().top + 150);
$("#leftShade").css("top", selection.position().top);
$("#leftShade").css("width", selection.position().left);
$("#rightShade").css("top", selection.position().top);
$("#rightShade").css("left", selection.position().left + 150);
$("#rightShade").css("width", 450 - selection.position().left);
}
$("#selection").mouseup(function (e) {
move = false;
});
});

Flickering when the dynamic change width

I want to dynamically change the width of an element. I've got working code, but it's sometimes flickering. Any idea, why?
JS:
var counter = 0;
setInterval(function() {
counter = (counter + 1) % 100;
$(".xxx").css("width", counter + "%");
}, 40);
CSS:
.xxx {
max-width: 70px;
height: 3px;
width: 0%;
background-color: orange;
}
That is how it is going to look if you try to increment 1% at a time. Rather use jquery animate to get better transition
DEMO: http://plnkr.co/edit/8OsVuRJGCLQsJWfrlzJ4
var counter =0;
setInterval(function() {
counter = (counter + 1) % 100;
$(".xxx").animate({width:counter+'px'});
}, 40);
If you want to reach a 70px width when it gets to 100%, you need to add a div parent to .xxx
like this:
<div class="yyy">
<div class="xxx"></div>
</div>
<p id="text"></p>
css:
.xxx{
height: 3px;
width: 0%;
background-color: orange;
}
.yyy{
width: 70px;
}

dynamically resize div element with "position: absolute" children

i'm having the following piece of code:
<head>
<style>
#mainDiv {
background-color: grey;
position: absolute;
}
#one {
height: 150px;
width: 70px;
bottom: 300px;
right: 500px;
background-color: green;
position: absolute;
}
#two {
height: 200px;
width: 200px;
margin-top: 50px;
margin-bottom: 20px;
margin-left: 90px;
margin-right: 5px;
background-color: blue;
position: absolute;
}
</style>
</head>
<body>
<div id="mainDiv">
<div id="one"></div>
<div id="two"></div>
</div>
</body>
i want to resize #mainDiv so it will include its children and will consider all positioning and margin attributes (basically #mainDiv's grey area will surround children and visually show the positioning and margins spaces).
i know it can't be done dynamically using CSS. how can i implement such using pure JavaScript without the use of JQuery?
note: there's no restriction on children's position attribute it can be any of them but "fixed".
code need to support all major browsers + IE8 + mobile (android 2.3 + 4, iphone).
thanks!
Use position relative for second div so the mainDiv greay area will surround your children element
#mainDiv {
background-color: grey;
position: absolute;
}
#one {
height: 150px;
width: 100px;
bottom: 300px;
right: 500px;
background-color: yellow;
}
#two {
height: 200px;
width: 200px;
margin-top: 50px;
margin-bottom: 20px;
margin-left: 90px;
margin-right: 5px;
background-color: blue;
position: relative;
}
I did something maybe complicated that you can find here: http://jsfiddle.net/YMmHz/1/
Basically I get all possible values:
var widthOne, widthTwo, heightOne, heightTwo;
var leftOne, leftTwo, rightOne, rightTwo, topOne, topTwo, botOne, botTwo;
var marginLeftOne, marginLeftTwo, marginRightOne, marginRightTwo, marginTopOne, marginTopTwo, marginBotOne, marginBotTwo;
var paddingLeftOne, paddingLeftTwo, paddingRightOne, paddingRightTwo, paddingTopOne, paddingTopTwo, paddingBotOne, paddingBotTwo;
var maxWidthOne, maxWidthTwo, maxHeightOne, maxHeightTwo;
With different tests:
widthOne = $('#one').width();
widthTwo = $('#two').width();
(parseInt($('#one').css('left')))? leftOne = parseInt($('#one').css('left')):leftOne = 0;
(parseInt($('#two').css('left')))? leftTwo = parseInt($('#two').css('left')):leftTwo = 0;
And then define the size of the #mainDiv like this:
(maxWidthOne>=maxWidthTwo)? $('#main_div').width(maxWidthOne):$('#main_div').width(maxWidthTwo);
(maxHeightOne>=maxHeightTwo)? $('#main_div').height(maxHeightOne):$('#main_div').height(maxHeightTwo);
In your case it's not possible because of some logical reasons.
How is it possible to find a right position for id one when the
parent has no size and therefor no usable right position.
If you are using left instead of right for id one the situation
becomes better.
all the best
try this one
<script>
window.onload = function() {
var elems, max_top, max_right;
elems = mainDiv.getElementsByTagName( 'div' );
for( i = 0; i < elems.length; i++ ) {
elem = elems[ i ].offsetLeft + elems[ i ].offsetWidth + elems[ i ].style.marginLeft;
max_right = ( max_right > elem ) ? max_right : elem;
elem = elems[ i ].offsetTop + elems[ i ].offsetHeight + elems[ i ].style.marginBottom;
max_top = ( max_top > elem ) ? max_top : elem;
}
console.log( 't: ' + max_top + ', r: ' + max_right );
mainDiv.style.height = max_top;
mainDiv.style.width = max_right;
}
</script>
The code is having some problem with getting the margins.
I found a good page which solves the problem.
http://www.quirksmode.org/dom/getstyles.html

Categories

Resources