Creating Seamless nested scroll rollover - javascript

I am attempting to create a series of window sized divs with inner divs of variable sizes > window size. The catch is it needs to scroll as if the divs where not nested.
In short I want THIS:
css{
block{ height:100wh; }
innerBlockSmall{ height:100wh; }
innerBlockLarge{ height:200wh; }
}
<div class="block">
<div class="innerBlockLarge"></div>
</div>
<div class="block">
<div class="innerBlockSmall"></div>
</div>
https://jsfiddle.net/cbuh8psd/
to act just like THIS
css{
innerBlockSmall{ height:100wh; }
innerBlockLarge{ height:200wh; }
}
<div class="innerBlockLarge"></div>
<div class="innerBlockSmall"></div>
https://jsfiddle.net/t6zrvo7u/1/
Unfortunately scroll "Focus" is triggered by hovering over the scrollable element. In this case it is an undesirable behavior.
There are 2 possible solutions that I am currently aware of.
Manually Assigning scroll "Focus" via javascript. (Optimal)
Completely overwriting default HTML scrolling javascript, for
example the library ISCROLL5.
(ok, if the performance hit is small)
Unfortunately after looking through developer.mozilla's HTML5 documentation I have not run across any way to "Focus" scrolling to an element via javascript.
As for option 2 : ISCROLL5 has had an undesirable performance hit with over ~15-20 scrolling divs.
I am hoping I am missing something here, any solutions, fixes, or advice would be much appreciated.

This solution allows scrolling over entire document while keeping the possibility of scrolling each nested div with mouse. I hope I understood you correctly.
This is just a concept, it does not prevent nested elements from scrolling along with window. But it can be improved.
Array.prototype.slice.call( document.getElementsByClassName('sbRemover') )
.forEach(function (div) {
var scroll = 0,
mousedown = false,
mouseBtnHandler = function (e) {
mousedown = e.type == 'mousedown';
}
div.addEventListener('scroll', function (e) {
// Change of div's scrollTop. Negative when scrolling down
var diff = scroll - e.target.scrollTop;
// Save new scroll value to be able to compare with it later
scroll = e.target.scrollTop;
// Do nothing when div is scrolled by dragging the scrollbar
if (!mousedown) {
// Scroll the window to the same amount of pixels the div was scrolled
window.scrollTo(window.pageXOffset, window.pageYOffset - diff);
}
});
div.addEventListener('mouseup', mouseBtnHandler);
div.addEventListener('mousedown', mouseBtnHandler);
});
body, div {
margin: 0;
padding: 0;
}
.block{
position: relative;
width:100vw;
height:100vh;
overflow: hidden;
z-index: 1;
opacity: 100;
}
.sbRemover{
width:100%;
height:100%;
padding-right:15px;
overflow: auto;
}
.largeContent{
height:225vh;
}
.smallContent{
height:100vh;
}
<div id="simpleCanvas">
<div class="block" style="background-color: blue">
<div class="sbRemover">
<div id="ok" class="largeContent" style="background-image: url('http://silviahartmann.com/background-tile-art/images/grey-repeating-background-8.jpg');"></div>
</div>
</div>
<div class="block" style="background-color: red;">
<div class="sbRemover">
<div class="largeContent" style="background-image: url('http://a1star.com/images/star--background-seamless-repeating9.jpg');"></div>
</div>
</div>
<div class="block" style="background-color: green">
<div class="sbRemover">
<div class="smallContent"></div>
</div>
</div>
<div class="block" style="background-color: blue">
<div class="sbRemover">
<div class="smallContent"></div>
</div>
</div>
<div class="block" style="background-color: red;">
<div class="sbRemover">
<div class="largeContent" style="background-image: url('http://people.stfx.ca/x2011/x2011ane/info102/assignment1/11500341-abstract-colorful-repeating-background.jpg');"></div>
</div>
</div>
<div class="block" style="background-color: green">
<div class="sbRemover">
<div class="smallContent"></div>
</div>
</div>
</div>

I have no idea why you would wish to do this, but the only way I can think of achieving the effect you want is along the lines of recreating the scrollbar, the good news however is that this needs not come at the cost of losing your native like experience.
Sadly I can't remember the project I wrote this code for, though one way to achieve this is to make yourself a scrollbar component. This scrollbar component would indeed provide a fake scrollbar, but provide a native like interface. So, how do you do this?
You determine the width of the scrollbar by taking the difference between an element with and without overflow: scroll. Let this be scrollWidth
You create a <div> with overflow: auto of width scrollWidth and position: fixed this in place on the right side of the body. Let the scrollTop property be scrollPosition.
Inside the element you add another <div> with width 0 (this at least works in Chrome, check whether other browsers treat this differently) and let height be documentLength.
Now, you can fully control the scrollbar by setting documentLength and scrollPosition any way you wish to. In your case you would set documentLength as the combined scrollHeights of each element and scrollPosition based on the relative scrollTop's in those nodes.
A very basic demonstration of the concept (not the implementation) can be found in this jsfiddle (note the width of the scrollbar is fixed to 20px in this case and there is no dynamic code whatsoever).

Related

How to use CSS transition for elements without positioning

I have this code:
<button id="delete-row">delete</button>
<div id="a">
<div class="row" style="height:150px;">Some content</div>
<div class="row" style="height:150px;">Some content</div>
<div class="row" style="height:150px;">Some content</div>
</div>
The height of the a div depends on how many row divs are inside it. Now I remove the middle row with javascript and the a div changes automatically its height and the lower row moves up. What I wanna now is how to use Css transitions to make this change happening smoothly.
I tried:
#a{
transition-property: height;
transition-duration:0.5s;
}
And also I tried the code below, so I can make the lower row change the top property slowly but the case is that they are not positioned relative or absolute so they don't have any top property.
.row{
transition-property: top;
transition-duration:0.5s;
}
What property is here triggered when elements change their positions on page in case we don't use any positioning and the elements are positioned by the normal flow?
Unfortunately CSS alone cannot achieve what you require. The transition property only applies when a property of an element is directly changed. In your case you remove an element, so the height of the #a div is changed by proxy when the child is removed.
Instead, you can use jQuery's slideUp() method to animate the height transition before removing the .row. Try this:
$('#delete-row').click(function() {
$('.row:eq(1)').slideUp(function() {
$(this).remove();
})
})
#a { border: 1px solid #C00; }
.row { height: 150px; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id="delete-row">delete</button>
<div id="a">
<div class="row">Some content</div>
<div class="row">Some content</div>
<div class="row">Some content</div>
</div>

Parent Container Doesn't Respect Child Height

Pretty common question, and typically revolves around a current situation, so after reading up on a bunch of different solutions and trying to slide them in I thought I'd just ask the age old question myself based on my situation.
Situation
I've built a little page slider using jQuery, and it appears to work as expected, then I noticed the CSS height was still set to a default value I had used for testing. After removing it I can't seem to get the height of the parent to open to the height of the different children. I know that setting the position of the different divs to relative instead of absolute will display them, but then the divs aren't positioned correctly anymore (situated underneath each other). Other solutions I've found revolve around not using markup that is even remotely common to my own.
Question
Is there a CSS fix for this that allows me to leverage Bootstrap the way I have it set up, and the jQuery animation I've already written? Or is their any suggestion(s) that will make this work without too much alteration to the markup? I've tried a couple different variations and this seems to be the most stable.
Code
I've added it to a jsFiddle. I couldn't get the animation to work in the fiddle for some reason (works on my laptop in all browsers), but the default layout should be enough to see how the parent doesn't respect the child elements.
<style>
.container {
margin-top: 50px;
}
.row {
margin-bottom: 20px;
}
.windowBox {
overflow: hidden;
}
.box {
background-color: #FFF;
position: absolute;
width: 100%;
}
.page1 {
top: 0;
left: 0;
opacity: 1;
z-index: 999; /* set to be over page2 onload */
}
.page2 {
top: 0;
left: 0;
opacity: 0;
z-index: 99; /* set to be under page1 onload */
}
</style>
<div class="container">
<div class="row">
<div class="col-sm-12">Header text should be above either page.</div>
</div>
<div class="row">
<div class="text-center">
<button type="button" id="showPage1" class="btn btn-danger" disabled>Page 1</button>
<button type="button" id="showPage2" class="btn btn-primary">Page 2</button>
</div>
</div>
<div class="row">
<div class="col-sm-12 windowBox">
<div class="row">
<div class="box page1">
<div class="hidden-xs col-sm-6">...</div>
<div class="col-sm-6">...</div>
</div>
<div class="box page2">
<div class="col-sm-12">...</div>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-sm-12">Footer text should be under either page.</div>
</div>
</div>
DEMO
Added an .over class to your markup.
Thats the only change made there.
css
Over class is the container of the windowBox.
We want this to have a hidden overflow because it will contain all our pages side by side.
.over {
overflow: hidden;
}
This is a fixed value unfortunately. Basically its the width of your window X pages. If your going to add more then just one page, you can set this value in JavaScript.
.windowBox {
width: 220vw;
}
Then we simply set the container to be a "kind of" fixed width.
responsive width.. so 95 of view port width is reasonable.
.box {
background-color: #FFF;
width: 95vw;
display: inline-block;
float: left;
}
And in the JavaScript instead of setting the left property you set the margin-left.
You only need to do this for the first element so. If you want to scroll to page 4 you can set the first pages margin to -4 * 95vw

Scrolling the page causes issues to buttons

I just finished a website, everything was working fine (what I thought)
Until I discover a huge BUG that couldn't fix:
I have a navigation BAR (png file) and added on it buttons (simple DIVs elements), When the page is openned 1st, all is fine, but if you scroll the page a bit, the buttons aren't working as they should.
Please check this link: (scroll the page a bit down and you'll notice that button aren't interacting anymore)
http://www.genius-solutions.net/GSIS/index.html
But if you move the cursor a bit above the buttons, you'll find them:
(HTML - JavaScript)
here the CSS part:
#btn {position:absolute;left:0px;top:0px;z-index:4;}
#btn1 {position:absolute;left:80px;top:280px;width:140px;height:35px;background:#DDE6E3;opacity:0.0;cursor:pointer;}
#btn2 {position:absolute;left:230px;top:280px;width:140px;height:35px;background:#DDE6E3;opacity:0.0;cursor:pointer;}
#btn3 {position:absolute;left:380px;top:280px;width:140px;height:35px;background:#DDE6E3;opacity:0;cursor:pointer;}
#btn4 {position:absolute;left:530px;top:280px;width:140px;height:35px;background:#DDE6E3;opacity:0;cursor:pointer;}
#btn5 {position:absolute;left:680px;top:280px;width:140px;height:35px;background:#DDE6E3;opacity:0;cursor:pointer;}
#btn6 {position:absolute;left:830px;top:280px;width:140px;height:35px;background:#DDE6E3;opacity:0;cursor:pointer;}
#html, body {
background:#002a4c;
overflow:scroll;
width:1024px;
height:768px;
margin: 20px auto; /* center */ padding: 20px;
}
and here the HTML part:
<body >
<div id = 'applet' home='579' services='1437' solutions='1192' partners='100' aboutus='654' contacts='216'>
<div id='applet_t'>
<div id='btn'>
<div id='btn1'></div>
<div id='btn2'></div>
<div id='btn3'></div>
<div id='btn4'></div>
<div id='btn5'></div>
<div id='btn6'></div>
</div>
</div>
<div id='inf'></div>
</div>
</body>
Your issue lies in IMO very improper use of absolute positioning of your elements. As soon as you scroll the page the location of the actual "hit" placeholder moves with the page but not your background.
Test case: try to move your page up a little bit and you will be able to "click" above the actual buttons.
Unless you have a good reason for absolutely positioned element use static == default positioning for most of your elements.

How to move an entire group of objects with Javascript

I am trying to move everything contained within the div id "tile", to the center of the web browser. By default the CSS is undefined and it appears on the left side of the browser. What I would like to do is move the entire div to the center using javascript when the button "move" is clicked.
The html is shown directly below, and the attempted (but not working) javascript is shown below that.
html
<div id="tile">
<div class="menu">
<ul>
<li> Vis </li>
</ul>
</div>
<div id="tabcontent4">Some generic content</div>
<button onclick="move();" type="button">Move</button>
</div>
</div>
javascript
document.getElementsById("tile").style.align='center';
EDIT: How would I move the div to a specific location?
There is no "align" property in CSS. The closest is text-align, but you probably want to use the CSS declaration margin: 0 auto, which will move the whole <div> to the center of the page. So you want:
document.getElementById("tile").style.margin="0 auto";
Make sure that tile has a specified width.
You can do this with just CSS:
<div id="tile" style='margin:0 auto;width:300px'>
...
</div>
Or, put it in a container, and center its content:
<div id='container' style='text-align:center'>
<div id='tile' style='width:300px'>
...
</div>
</div>
Of course, non-inline styles are preferred.
Nice username, BTW.
// EDIT
To place the div in a specific location with javascript:
document.getElementById('tile').style.position = "absolute";
document.getElementById('tile').style.left = "100px";
document.getElementById('tile').style.top = "100px";
It must have a position defined, usually absolute or relative.
Once again, this can - and usually should - be done with CSS:
#tile { position:absolute; left:100px; top:100px }

How can I get the TRUE height of a div?

I'm trying to determine the height of a div. This sounds simple, but is complicated by the fact that it's only descendant contents are floated, so asking for the height/outerHeight (using jQuery)/clientHeight/offsetHeight only returns 0, even though it's clear that on the page, it is rendered certainly with a height. Here is an example of the HTML structure:
<div id="root">
<div class="header"></div>
<div class="body">
<div class="text-left" id="text-one">
<p>Some text taking up multiple lines</p>
</div>
<div class="text-right" id="text-two">
<p>Other text</p>
</div>
</div>
</div>
The "text-left" and "text-right" elements have "float: left;" and "float: right;" on them, so when I ask for the height of "root", it tells me it's 0. However, of course, when I get the height of the "text-one" and "text-two", it correctly tells me that it's 20 or whatever.
How can I determine the REAL height of the the "root" element? (For example, if "text-one" had a height of 50 and "text-two" had a height of 20, it would know that the true height is 50)
I imagine there's some kind of logic to work out all the descendant elements' heights and calculate if they're floated etc etc and give me a final figure...but I'm not smart enough to work that out.
Thanks in advance.
EDIT: Please note changing the HTML (to include a "clear", for example) is not an option. I need to be able to tell the height of this div as it is.
That's because the height is zero. Try viewing this
<html><head><title>test</title></head><body>
<div id="root" style="border:1px solid red">
<div class="header"></div>
<div class="body">
<div class="text-left" id="text-one" style="float: left;">
<p>Some text taking up multiple lines</p>
</div>
<div class="text-right" id="text-two" style="float: right;">
<p>Other text</p>
</div>
</div>
</div></body>
Header is empty, and body only contains elements floated out of the layout, so it also counts as empty, leaving root bereft of content to hold it open.
Also by the same reasoning, the body element is zero height; which you can verify by adding <body style="border:1px solid blue">
If all #root's children (strictly speaking, descendants) are floated, then it does indeed have a height of zero. Try setting a background colour on it to prove that it occupies no vertical space.
If you get the heights of the two floated elements, then you can take the greater of those:
var height = Math.max(leftHeight, rightHeight);
How about a function that reads all inner divs and stores the maximum height value from the two divs?
I dont think is very correct but here is try:
var max_height = 0;
$.each( $('#root div'), function(x, y){
var yHeight = $(y).height();
max_height = ( yHeight > max_height) ? yHeight : max_height;
});
console.log(max_height); //should have the height value.
Working Demo
I deleted an answer because I missed out on what a lot of others has already pointed out: the height is, quite literally, 0, and everything is working. What you need to do to get the height that, in your words, the root div 'seems' to have, is to make that div actually have that height, which can easily be achieved by simply clearing the floats at the end of the div.
<div id="root">
<div class="header"></div>
<div class="body">
<div class="text-left" id="text-one">
<p>Some text taking up multiple lines</p>
</div>
<div class="text-right" id="text-two">
<p>Other text</p>
</div>
</div>
<div style="clear: both;"></div>
</div>
As partly referenced above the problem here is a css issue, specifically clearing of floated elements. An excellent overview of which can be found at www.positioniseverything.net/easyclearing.html. As you are unable to alter the html mark-up you could take the positioniseverthing solution and apply it by adding a class to the parent of the floated elements with js/jQuery,
$('#root .body').addClass('clearfix');
Now you should be able to access the height with,
$('#root').height();
as mentioned above. Hope that helps
Set the overflow of the root element to hidden, then its height will stretch to match the inner elements. Tested with the link you posted in another comment, and it works!
#root {
background-color: lightgreen; /* for demo purposes */
overflow: hidden;
}
If using a CSS file is not an option, then you can use your jQuery to set the CSS:
$('#root').css( 'overflow', 'hidden' );
// ...then your height code

Categories

Resources