I have simple html document that contains divs which hold a series of images:
<div id="container">
<div id="imagelist">
<a href="images/1.jpg"><img src="images/1b.jpg"/>
<a href="images/2.jpg"><img src="images/2b.jpg"/>
<a href="images/3.jpg"><img src="images/3b.jpg"/>
<a href="images/4.jpg"><img src="images/4b.jpg"/>
<a href="images/5.jpg"><img src="images/5b.jpg"/>
<a href="images/6.jpg"><img src="images/6b.jpg"/>
</div>
</div>
I would like to be able to scroll horizontall through the images when hovering over the left or right edge of the div (I have multiple #imagelists all stacked vertically)
I'm trying to use the .scrollWidth() function as such (this is in my script.js file):
var imglist = $('#imagelist');
$(imglist).mousemove(function(e) {
var percent = e.clientX / $(imglist).width();
$(imglist).scrollWidth($(imglist).width() * percent);
});
This doesn't work at all, of course! I've been trying to model this after some good examples I've seen, such as This. What should I alter to make my #imagelist scrollable?
Here's a way to do it using offset and relative positioning.
demo
The HTML looks similar to yours, with the exception that we create elements for the edges. The benifit is that we can style them with CSS, should you ever decide you want :hover styles (example in the demo).
<div class="imagecontainer">
<div class="imagelist">
<img src="http://placehold.it/400x300">
...
<img src="http://placehold.it/400x300">
</div>
<div class="edge right"></div>
<div class="edge left"></div>
</div>
The entire CSS is in the demo, this is just the essentials.
.imagecontainer {
width: 100%;
height: 400px;
overflow-x: hidden;
position: relative;
}
.imagelist {
/* Width allows up to 100 screenfuls, feel free to add a 0
Limiting can be done in the JavaScript */
width: 10000%;
height: 400px;
position: relative;
/* Give it a default left of negative to allow scrolling in either direction */
left: -500px; top: 0;
clear: right;
}
.imagelist img {
float: left;
}
.edge {
position: absolute; top: 0;
width: 50px; height: 100%;
}
.edge.left { left: 0; }
.edge.right { right: 0; }
The JavaScript is the fun part. We find the edges and watch for hover and leave events. Considering only one may be hovered at once (both practically and due to mouseenter), we simply have one timer pointer. This timer controls our animation, and is used to stop the animation (clearInterval) on mouseleave. 20 times per second we move the .imagelist 5 pixels in one direction. That's determined based on which edge we're hovering over.
Instead of using $('.imagelist') we use .parent().find('.imagelist') so that there may be any number of image lists on the page.
var timer = 0;
$('.edge').mouseenter(function(){
var $self = $(this);
var $imglist = $self.parent().find('.imagelist');
timer = setInterval(function(){
var amount, changed;
if ($self.hasClass("left"))
amount = -5;
else
amount = 5;
changed = $imglist.offset().left + amount;
$imglist.offset({left: changed});
}, 50)
}).mouseleave(function(){
clearInterval(timer);
});
It's a little rough, but you can polish it up to suit your needs.
Related
I'm currently working on a project where the desired user experience involves a very customized interaction with scroll events.
Problem to solve:
The page has X sections, each of them with a height equal to the viewport hight height: 100vh;. When a user scrolls down on the viewport, the current visible section stays where it is and a scroll indicator animates based on a threshold of distance scrolled (30px, for example). Once the user has scrolled the threshold, the next section comes up from the bottom of the screen and covers up the current section (which still doesn't move).
Initial Approach:
Set each section to an absolute position and adjust them with by changing CSS classes based on the scrollwheel event. Body overflow:hidden and transform property to manipulate the sections. I am running in to issues, though.
The scrollwheel event seems to be documented as very unstable solution to implement.
The .wheelDelta aspect of the event fires asynchronously and is difficult to capture a gesture with. (On chrome, it just spits out a multiple of 3 a bunch of times rather than a distance of the gesture in px). This makes it difficult to set a threshold and animate the elements that are responsive to that threshold.
I basically want to be able to track the number of pixels a scrollwheel-like event is covering and apply that number to the position of a certain scroll-hint element until the scroll threshold is met. Once it is met, a function fires to change the classes and update some information on the page. If the threshold is not met, the scroll hint element goes back to it's default position.
My attached approach doesn't feel very conducive to accomplishing this, so I'm looking for either 1) a different and more stable approach or 2) revisions / criticisms on what I'm doing wrong with this approach to make it stable.
(function scrollerTest($){
$('body').on ('mousewheel', function (e) {
var delta = e.originalEvent.wheelDelta,
currentScreenID = $('section.active').data('self').section_id,
currentScreen = $('section.part-' + currentScreenID),
nextScreenID = currentScreenID + 1,
nextScreen = $('section.part-' + nextScreenID);;
if (delta < 0) { // User is Scrolling Down
currentScreen.removeClass('active').addClass('top');
nextScreen.removeClass('bottom').addClass('active')
} else if (delta > 0) { // User is Scrolling Up
}
});
}(jQuery));
body {
overflow: hidden;
padding: 0;
margin: 0;
}
section {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100vh;
z-index: 999;
background-color: #CA5D44;
transition: 0.8s all ease-in-out;
}
section.part-1 {
position: relative;
z-index: 9;
}
section.part-2 {
background-color: #222629;
}
section.active {
transform: translateY(0);
}
section.top {
transform: translateY(-10%);
}
section.bottom {
transform: translateY(100%);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script>
<body>
<section class="part-1 home active" data-self='{ "section_id" : 1, "section_title" : "Home", "menu_main_clr" : "#fff" , "menu_second_clr" : "#CA5D44", "logo_clr" : "white" }'>
</section>
<section class="part-2 about bottom" data-self='{ "section_id" : 1, "section_title" : "About", "menu_main_clr" : "#CA5D44" , "menu_second_clr" : "#fff", "logo_clr" : "white" }'>
</section>
<section class="part-3 contact bottom" data-self='{ "section_id" : 1, "section_title" : "Contact", "menu_main_clr" : "#fff" , "menu_second_clr" : "#CA5D44", "logo_clr" : "white" }'>
</section>
</body>
Edit Note:
The snippet seems to have some issue with firing the event and changing classes after the first instance - not sure why. On my local example it fires them all at once..
**Edite Note 2: **
Listed code is just a copy of the closest behaviour I could achieve. The whole threshold functionality seems pretty unattainable with this method, unfortunately, as the wheel event doesn't behave like a scroll event.
the whole scroll topic is rather complex especially when you think about touch scroll events, too.
There are some libraries out there - see this list for example: http://ninodezign.com/30-jquery-plugins-for-scrolling-effects-with-css-animation/
I used https://projects.lukehaas.me/scrollify/ before and it might allow you to do what you intend (using the before callback eventually) but I can't tell without trying myself. Also regard that scrollify is relatively big (8kb minified) in comparison to other libraries.
You can approach this using by ensuring each content-filled section is followed by a blank transparent gap (in the example below, also 100vh in height) and then using javascript to apply position:fixed to each content-filled section when it hits the top of the viewport.
Example:
var screens = document.getElementsByClassName('screen');
function checkPosition() {
for (var i = 0; i < (screens.length - 1); i++) {
var topPosition = screens[i].getBoundingClientRect().top;
if (topPosition < 1) {
screens[i].style.top = '0';
screens[i].style.position = 'fixed';
}
}
}
window.addEventListener('scroll',checkPosition,false);
.screen {
position: absolute;
display: block;
left: 0;
width: 100%;
height: 100vh;
}
.red {
position: fixed;
top: 0;
background-color: rgb(255,0,0);
}
.orange {
top: 200vh;
background-color: rgb(255,140,0);
}
.yellow {
top: 400vh;
background-color: rgb(255,255,0);
}
.green {
top: 600vh;
background-color: rgb(0,191,0);
}
.blue {
top: 800vh;
background-color: rgb(0,0,127);
}
p {
font-size: 20vh;
line-height: 20vh;
text-align: center;
color: rgba(255,255,255,0.4);
}
<div class="red screen">
<p>Screen One</p>
</div>
<div class="orange screen">
<p>Screen Two</p>
</div>
<div class="yellow screen">
<p>Screen Three</p>
</div>
<div class="green screen">
<p>Screen Four</p>
</div>
<div class="blue screen">
<p>Screen Five</p>
</div>
I have a div which becomes fixed when it is scrolled to. I would like this div to go full width when it is in it's fixed state. I have done this by setting width: 100% to the div in question. The problem is I would like the content of the div to still line up with the content of the page, instead of going to the left. I would like to be able to do this without changing the current html markup.
Example: Full width when scrolled to and in fixed state.
Fiddle: https://jsfiddle.net/DTcHh/19335/
Example: If I add padding left to bring the content inwards this works. The problem is the padding left could be any number -is there a way of reliably working this out?
Fiddle: https://jsfiddle.net/DTcHh/19337/
CSS:
#myDiv.fixed {
position: fixed;
bottom: 0;
left: 0;
width: 100%;
}
Jquery:
$(window).scroll(function() {
if (isScrolledIntoView($('#myDivWrapper'))) {
if (!initSet) {
initSet = true;
}
$("#myDiv").removeClass('fixed');
} else if (initSet) {
$("#myDiv").addClass('fixed');
}
});
Add an extra .container div inside the #myDiv and adjust the padding as and when the fixing takes place.
<div id="myDivWrapper">
<div id="myDiv">
<div class="container">
<p>
This should be fixed once it comes into view and then goes out of view.
</p>
</div>
</div>
</div>
#myDiv .container {
padding: 0;
}
#myDiv.fixed {
position: fixed;
bottom: 0;
left: 0;
width: 100%;
}
#myDiv.fixed .container {
padding: 0 15px;
}
This can probably be tidied up a little but I think you get the idea.
JSfiddle
Don't write left:0
enter link description here
#myDiv.fixed {
position: fixed;
bottom: 0;
width: 100%;
}
You simply need to calculate the measurement between the content and the window edge and then apply this as left padding when required.
var measure = ($(window).width() - ($('#myDiv').offset().left + $('#myDiv').width()));
$(window).scroll(function() {
if (isScrolledIntoView($('#myDivWrapper'))) {
if (!initSet) {
initSet = true;
}
$("#myDiv").removeClass('fixed').css('padding-left', 0);
} else if (initSet) {
$("#myDiv").addClass('fixed').css('padding-left', measure+'px');
}
});
DEmo Fiddle https://jsfiddle.net/DTcHh/19338/
EDIT: If editing the markup is an option i'd recommend #Paulie_D 's approach. You don't need to add another container though - simply add a class to your existing markup.
Demo Fiddle https://jsfiddle.net/DTcHh/19340/
<div id="myDivWrapper">
<div id="myDiv">
<p class="container">
This should be fixed once it comes into view and then goes out of view.
</p>
</div>
</div>
Since all your paragraphs are inside a container class, you can also add this class to your fixed paragraph as well.
$("#myDiv").removeClass('fixed');
$("#myDiv p").removeClass('container');
...
$("#myDiv").addClass('fixed');
$("#myDiv p").addClass('container');
Further more, you will need to tell #myDivto go full width:
#myDiv.fixed {
position: fixed;
bottom: 0;
left:0;
right:0;
}
See working example here.
I need the contents of an iframe which has height of 100px(displays only part of iframe) to expand like an animation on read more button click,and fill up the entire screen(expands in all directions), and on clicking close button positioned on top of it, it needs to animate and shrink to it original size.
I found a fiddle that dooes something similar
http://jsfiddle.net/FP2DZ/.
But my issue is that my div cannot be absolutely positioned as I have contents underneath that and that gets affected if I make this one absolutely positioned.
Absolutely positioning rest of the contents also does not seem to me like a good solution
Code
<html>
<head>
<script type="text/javascript">
var isFullscreen = false;
function fullscreen(){
//var d = document.getElementById('controls').style;
var d = {};
var speed = 900;
if(!isFullscreen){ // MAXIMIZATION
/*comment to have smooth transition from centre but loose covering the header*/
//document.getElementById('controls').style.position= "absolute";
d.width = "100%";
d.height="100%";
//d.left="0%";
d.top="0px";
//d.margin="0 0 0 0";
$("#header").animate({
height: 0
}, speed);
$("#controls2").animate(d,speed);
isFullscreen = true;
}else{ // MINIMIZATION
d.width="300px";
d.height="100px";
d.margin="0 auto";
d.position="relative";
//d.top="+=30px";
/* comment to have smooth minimze transition but not be placed below header */
// document.getElementById('controls').style.position= "relative";
$("#header").animate({
height: 30
}, speed);
$("#controls2").animate(d,speed);
isFullscreen = false;
}
}
</script>
<style>
* { margin: 0 }
#controls {
width:100%;
height:100%;
margin: 0 auto;
display:block;
position:absolute;
left: 50%;
z-index:5;
}
#controls2 {
overflow:visible;
width: 300px;
height: 100px;
position: relative;
left: -50%;
background-color: green;
z-index:10;
}
</style>
</head>
<body>
<h1 id="header" align=center> Header (To be covered on Fullscreen) </h1>
<div id='controls' style="" align="center">
<div id='controls2'>
<input type='button' value='fullscreen' onclick='fullscreen();' /><br>
I am some centered shrink-to-fit content! <br />
tum te tum
</div>
</div>
</body>
Probably the easiest way is to utilize the .animate({}) method in Jquery.
Check out this fiddle: http://jsfiddle.net/cm6v7bca/2/
$("#clickhere").on("click", function () {
$("#myframe").animate({
width: "200px",
height: "200px"
}, 1000);
});
.animate({}) allows you to change the css properties and then smoothly animates the changes onto the element. There are several different parameters you can pass. In the fiddle you'll see that I passed "1000" - that's the duration for the animation to complete in ms.
You can read more about the parameters and the method here: https://api.jquery.com/animate/
That really helps. But then the iframe needs to cover rest of the contents in the page and overlay them, Thats seems possible only if iframe is absolutely positioned. But there is so much dynamic content in the page, I do not want to absolute position the iframe.
http://jsfiddle.net/CvhkM/2833/
this is like what I want just that am not able to absolute position.
JS:
$(this).stop().animate({
left: parseInt(this.style.left)-100,
top: parseInt(this.style.top)-100,
width: parseInt(this.style.width)+200,
height: parseInt(this.style.height)+200
}, 300);
Ok, so i want to have a series of divs which are the exact width and height of the user's browser window, regardless of the screen size. I can easily make the divs stretch horizontally with "width: 100%;" but i cant work out how to make the height stretch itself. I am guessing that i need to use some bit of javascript to judge the height, and then another piece to resize the seperate divs. Unfortunately I am a complete javascript n00b and after two hours of seemingly fruitless searching and coming up with about 100 "solutions" this was as far as id gotten (Im sure that at some point I have probably been closer to the answer):
var viewportHeight = "height:" + document.documentElement.clientHeight;
getElementById('section-1').setAttribute('style', viewportHeight);
<div class="section" id="section-1"></div>
<div class="section" id="section-2"></div>
<div class="section" id="section-3"></div>
edit:
ah i should be more clear, im attempting to have all three divs take up the entire screen, so you have to scroll down to see each one - almost like seperate slides. The idea is that each one takes up the entire screen so you cant see the next section until you scroll down, rather than having three divs which take up a third of the screen.
If you haven't already tried it, you'll want to look at parent:child inheritance of elements within the DOM by way of using CSS.
What I want to STRESS is that everyone giving you JS hacks to accomplish this is not only providing you with overkill (YOU did ask for a JavaScript solution, so they gave it to you!), but it's also a deviation from standards. HTML is for structure, CSS is for presentation, and JavaScript is for behavioral aspects... setting a div to the width of the viewport on load is a PRESENTATION aspect and should be done in CSS... not JavaScript. If you were trying to change the width based on events or user interaction, then yes JavaScript is your friend... but stick with just HTML and CSS for now.
The trick is that most elements have an undefined height - and height is later defined by the content that the element holds.
If you want to 'trick' an element into having a height other than what it wants to default to, you'll have to explicitly define it. Since you want to inherit your height from the viewport, you'll have to define the height at the top and bring it down...
You might be in luck and can avoid JavaScript altogether (unnecessary). Just use CSS.
Try something like:
html, body {
height: 100%;
width: 100%;
}
Now, when you try to set your div's later on, specify width: 100% and the height gets inherited from the html --> body --> div.
Try that and see if that solves your problem - if not, point us to a website, a pastebin, or a SOMETHING with code in it that we can just show you how to do it (whereas what you posted for code was an attempt in JavaScript which is only 1 part of the code - post the full thing either to a server or temp site like pastebin).
Here is some sample code I wrote (tested in Chromium):
The HTML:
<html>
<head>
<title>Test Divs at 100%</title>
<link rel="stylesheet" type="text/css" href="divtest.css"
</head>
<body>
<div class="test1">aef</div>
<div class="test2">aef</div>
<div class="test3">aef</div>
</body>
</html>
The CSS:
html, body {
width: 100%;
height: 100%;
background-color: #793434;
padding: 0;
margin: 0;
}
div {
height: 100%;
width: 100%;
}
.test1 {
background-color: #E3C42E;
}
.test2 {
background-color: #B42626;
}
.test3 {
background-color: #19D443
}
try this
div#welcome {
height: 100vh;
background: black;
color: white;
}
div#projects {
height: 100vh;
background: yellow;
}
<div id="welcome">
your content on screen 1
</div>
<div id="projects">
your content on screen 2
</div>
it should work for you, but little support in IE
A bit of jQuery should do it:
$(document).ready(function() {
var window_height = $(window).height();
$('#section-1").height(window_height);
});
And if you want to keep 100% height on window resize:
$(document).ready(function() {
function viewport_height() {
var window_height = $(window).height();
$('#section-1").height(window_height);
}
viewport_height();
$(window).resize(function() {
viewport_height();
});
});
try this
window.onload = init;
function init()
{
var viewportHeight = "height:" + document.documentElement.clientHeight+"px;";
document.getElementById('section-1').setAttribute('style', viewportHeight);
}
Here is a script free solution, just CSS. This assumes that the divs are directly in the body element or a parent with position absolute and the parent has no padding.
#section-1 {
position: absolute;
height: 100%;
width: 100%;
background: #ff0000;
}
#section-2 {
position: absolute;
width: 100%;
top: 100%;
height: 100%;
background: #00ff00;
}
#section-3 {
position: absolute;
width: 100%;
top: 200%;
height: 100%;
background: #0000ff;
}
See fiddle: http://jsfiddle.net/QtvU5/1/
What I'm trying to achieve is to have an image fade upon mouseover so that text is visible - the image is (eg) a cd cover, and when the mouse-pointer is placed over the image, it should fade to show the track listing of the album. Each track listing is a hyperlink to the track on youtube.
I've zero experience of jquery, so am hoping to do this with javascript.
I'd be very appreciative of any help, as I've spent about two days now trying to google an answer.
If under "fade" you mean animation, try this:
function SetObjectOpacity(obj, op, op100)
{
obj.style.opacity = op.toString();
obj.style["-moz-opacity"] = op.toString();
obj.style["filter"] = "alpha(opacity=" + op100 + ")";
}
function FadeImage(imageid)
{
var framedelay = 50;
var frame = 0, img = document.getElementById(imageid), animint;
animint = setInterval(function() {
frame++;
SetObjectOpacity(img, frame / 20, frame * 5);
if (frame == 20) {
img.style.visibility = 'hidden';
clearInterval(animint);
}
}, framedelay);
}
And in HTML code:
<div style="width: 200px; height: 200px; position: relative;">
<div style="position: absolute; top: 0; left: 0; width: 200px; height: 200px;">
text you want to show
</div>
<img src="yourimage.jpg" id="yourimage" onMouseOver="FadeImage('yourimage');" style="position: absolute; top: 0; left: 0;">
</div>
Fading back on mouse out is obvious.
I really do recommend you use jQuery—it makes everything so much easier. And it's not really difficult. After all, we have the code ready for you (and I would be glad to explain it further), so all you need to do is include it.
So, assuming you go with jQuery, try this:
$(".overlay").hover(function(){
$(this).stop().fadeTo(300,0.8);
},function(){
$(this).stop().fadeTo(300,0);
});
And here's your HTML/CSS:
<div class="container">
<img src="http://placehold.it/200/200" />
<div class="overlay">
Hi<br>
Hi<br>
Hi<br>
</div>
</div>
.overlay {
position:absolute;
margin-top:-205px;
width:200px;
height:200px;
background-color:black;
opacity:0;
}