I'm making a scrolling comment section, it works by having several elements echoed by php have their top property animated with javascript. Everything seems to be working fine except when I set their position to absolute and use javascript simultaneously, this results in text-align:center only working whenever there is more than one line in the text. Here is my code:
HTML (Roughly goes like this, is echoed through PHP, also apologies for the inline styling)
<div id="element0" style="position:absolute;text-align:center;">Hello world!</div>
<div id="element1" style="position:absolute;text-align:center;">Hello world!</div>
<div id="element2" style="position:absolute;text-align:center;">Hello world!</div>
<div id="element3" style="position:absolute;text-align:center;">Hello world!</div>
Javascript
var offset = 0;
var i = 0;
for(i = 0; i < 3; i++) {
obj = document.getElementById("element" + i);
obj.style.top = offset + "px";
offset += obj.clientHeight;
}
function moveComments() {
var i1 = 0;
for(i1 = 0; i1 < 3; i1++) {
obj = document.getElementById("element" + i1);
obj.style.top = parseInt(obj.style.top) - 1 + 'px';
if(parseInt(obj.style.top) <= -offset)
obj.style.top = offset + 100 + "px";
}
}
setInterval(moveComments, 10);
position: absolute causes the element's width to automatically shrink to fit its content.
text-align: center centers text within the bounds of the block element.
If the block element is not wider than the text, it won't do anything.
You need to give it a larger width.
Related
There is one div element positioned absolutely in a relative container. It is initially positioned under one of four buttons. Based on which button is clicked, I calculate with JS the x coordinate of the button and move the div element underneath that button. Here's my markup and JS:
<div id='container-of-four-buttons' style="width: 100%; position: relative;">
<button>Foo</button>
<button>Buzz</button>
<button>Foo</button>
<button>Buzz</button>
</div>
<div id='followAlong-container' style="width: 100%; position: relative;">
<div class='followAlong-div' style="position:absolute; width: 15px; height: 13px;">Some stylized arrow</div>
</div>
var initialDiv = /* selected the second button to be initial */
var followAlongDiv = document.querySelector('followAlong-div');
var buttons = document.querySelectorAll('button');
followAlongDiv.style.left = initialDiv + 89 + 'px';
buttons.forEach(function(btn) {
btn.addEventListener('click', function() {
let xCoord = 0;
xCoord += (div.offsetLeft - div.scrollLeft + div.clientLeft);
followAlongDiv.style.left = xPos + 17 + 'px';
});
});
However, if I resize the browser, the four button elements shrink towards eachother, but the followAlongDiv stays at the same spot because it is positioned absolutely in its relative container.
How do I calculate the amount of width the browser has resized and update the position of the followAlongDiv?
I will use window.addEventListener('resize', updatePosition), but I just don't know how to approach the formulation of the updatePosition function.
First, 'followAlong-div' is a class (needs '.' before the className ):
var followAlongDiv = document.querySelector('.followAlong-div');
Second, I do not understand why you have this line:
xCoord += (div.offsetLeft - div.scrollLeft + div.clientLeft);
For resizing just needs:
window.onresize = ()=>{
var xCoord = 0;
xCoord += (selectedButton.offsetLeft);
followAlongDiv.style.left = xCoord + 'px';
}
Based on your code, I think this is what you want: https://jsfiddle.net/vua4eLhc/
Hope it helps!
Banging my head trying to sort out the correct logic for adding simple parallax behavior.
I would like to have a number of elements on a page which start out with their top offset a certain distance (e.g. 300px). Then as you scroll down the page, once the top of the element is revealed it will slowly shift upwards (tied to scroll) until the top of element reaches middle of viewport at which time it's top offset is 0 and it remains in place.
I tried using third party script (Scroll Magic, Stellar, etc), but when I couldn't get it right now I'm trying custom code:
https://jsfiddle.net/louiswalch/5bxz8fku/1/
var $Window = $(window);
var offset_amount = 400;
var window_height = $Window.height();
var window_half = (window_height/2);
var sections = $('SECTION.reveal');
sections.each(function() {
var element = $(this);
// Make sure we always start with the right offset
element.css({top: offset_amount});
$Window.bind('scroll', function() {
var viewport_top = $Window.scrollTop();
var viewport_middle = viewport_top + (window_height/2)
var viewport_bottom = viewport_top + window_height;
var element_top = element.offset().top;
if (element_top > viewport_top && element_top <= viewport_bottom) {
var distance_to_middle = (element_top - viewport_middle);
var amount_to_middle = (distance_to_middle / window_half);
console.log(amount_to_middle);
if (amount_to_middle >= 0) {
element.css({top: (offset_amount * amount_to_middle)+ 'px'});
} else {
// ? Lock to end position ?
}
}
});
});
jsBin demo 1. (margin space effect on both enter and exit)
jsBin demo 2. (preserve 0 margin once touched)
Instead of targeting the section elements, (create and) target their first child elements,
otherwise you'll create a concurrency mess trying to get the top position but simultaneously modifying it.
Also, you cannot rely on fixed 300px margin (i.e: if window height is less than 500px, you're already missing 100px). That space can vary when the screen height is really small, so you also need to find the idealMarg value.
var $win = $(window),
$rev = $('.reveal'),
winH2 = 0,
winSt = 0;
function reveal() {
winSt = $win.scrollTop();
winH2 = $win.height()/2;
$rev.each(function(i, el){
var y = el.getBoundingClientRect().top,
toMiddleMax = Math.max(0, y-winH2),
idealMarg = Math.min(300, toMiddleMax),
margMin = Math.min(idealMarg, idealMarg * (toMiddleMax/winH2));
$(">div", this).css({transform: "translateY("+ margMin +"px)"});
});
}
$win.on({"load resize scroll" : reveal});
*{box-sizing:border-box; -webkit-box-sizing:border-box;}
html, body{height:100%; margin:0;}
section > div{
padding: 40px;
min-height: 100vh;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<section>
<div style="background-color:red">1</div>
</section>
<section class="reveal">
<div style="background-color: yellow">2</div>
</section>
<section class="reveal">
<div style="background-color: orange">3</div>
</section>
<section class="reveal">
<div style="background-color: pink">4</div>
</section>
I've used in HTML just a <div> logically, that has to be the one and only first child of a section parent.
You're welcome to tweak the above code to make it more performant.
Hey so here is my go at an awnser.
http://jsbin.com/wibiferili/edit?html,js,output
The jist of it is as follows.
JS
var $Window = $(window),
parallaxFactor = 2;
$('.parallaxblock').each(function(a,b){
var element = $(b);
element.css("top",element.data("pOffset") + "px");
$Window.bind('scroll', function() {
var pos =
// Base Offset
element.data("pOffset")
// parallaxFactor
- ($Window.scrollTop() / parallaxFactor);
pos = pos < 0 ? 0 : pos;
element.animate({"top": pos + "px"},10);
return;
});
});
Styles
body{
height: 4000px;
}
.parallaxblock{
position:fixed;
background:#999;
opacity:.5;
}
Example Usage
<div class="parallaxblock" data-p-offset=100>Im A Block</div>
<div class="parallaxblock" data-p-offset=200>Im Also Block</div>
<div class="parallaxblock" data-p-offset=1500>Im Another Block</div>
So by checking the offest its never lower then 0 we can lock it at the top of the screen once it reaches it.
I get the offset amount of the data tag on the div.
If you wanted to change the rate of scroll in different posistions you could change the parallax factor at a certain percentage of screen height.
Hope this helps.
I have a 5*5 grid, what i want to do is to imitate drawing action than when i press(with my finger, it is suppose to be a mobile app) on a square it changes its background color.
this part i have managed to do and it works fine.
what I would like to do now is that when I move the finger over the screen it will change the color of each of the squares my finger is pressing(enters its surface) just like drawing.
i know that there is a touchenter event but i don't understand how can i use it
i read some tutorials and articles and everywhere it says that the touchenter event dosen't bubbles...
how can I get the id of the element that i am touchmove over?
https://jsfiddle.net/uLfm5szz/2/
any help will be more than great!
html
<div id="demo"></div>
css
.b{
width: 50px;
height: 50px;
display: inline-block;
border: red 1px solid;
}
js
createLoop();
$('.b').bind('touchmove',StartDragSelect);
function createLoop(){
var length = 30;
var text = "";
var demo = $("#demo")
for (i = 0; i < length; i++) {
var rowElement = $('<div class="a"></div>');
demo.append(rowElement);
for(var x = 0; x < length; x++){
createGridItem(rowElement,i,x);
}
}
}
function createGridItem(rootElement, i, x){
var pix = 10;
var currItem = $('<div class="b" id="a'+i+x+'" style="top:' + i*pix +'px; left: ' + x*pix +'px; background-position-x: -' + x*pix +'px ; background-position-y:-' + i*pix +'px";"></div>');
$(rootElement).append(currItem);
}
function StartDragSelect(obj)
{
obj = obj.currentTarget;
$(obj).css({"background-color":"blue"});
}
how can i check if i am above the element? which parameter should i
use to check it?
Here is a function to get the position of an element(a gridview cell for you). With the x and y coordinates, you can add the height and width to them to calculate if your current touch position is above the element.
function getPosition(element) {
var xPosition = 0;
var yPosition = 0;
while (element) {
xPosition += (element.offsetLeft - element.scrollLeft + element.clientLeft);
yPosition += (element.offsetTop - element.scrollTop + element.clientTop);
element = element.offsetParent;
}
return { x: xPosition, y: yPosition };
}
To use this function you can do like this
var y = getPosition(document.getElementById('cell1')).y;
var x = getPosition(document.getElementById('cell1')).x;
Take a look at https://api.jquerymobile.com/swipe/
This is a jQuery lib for doing that.
I'm trying to create a div 'floater' which acts similar to a fixed div (stuck in a specific position regardless of scrolling), but when it hits the boundaries of the div it is within, it stops being fixed.
When the scrollbar is at the top, it should have the div placed at 0 within the containing div (positioned say 100 pixels from the top) and when the scrollbar reaches the bottom, it should prevent the floater from going outside the container. The height of the floater would be static, but the container height would be dynamic.
I've seen this type of this all over the place, but can't figure out how to find a good example for it.
I'd like to avoid jQuery if possible, as I imagine it should only require some simple JavaScript to determine the current position relative to the div it is within.
Thank you.
Okay folks, here is a complete solution. I've only tested this in Firefox and IE, but it should work across the board (I think). This is straight JavaScript and jQuery is not used. The first JS function makes sure the height returned works in various browsers.
Edit - I improved on this, see below.
<html>
<head>
<style type="text/css">
* {margin:0;padding:0;}
#header {height:300px;width:100%;background:#888;}
#main {height:800px;width:70%;background:#eee;float:left;}
#side {width:30%;height:auto;background:#ddd;float:left;position:relative;}
#floater {height:400px;width:90%;background:#dcd;top:0px;position:absolute;}
#footer {height:300px;width:100%;background:#888;clear:both;}
</style>
<script>
function getPageY() {
var height = 0;
if(typeof(window.pageYOffset) == 'number') {
height = window.pageYOffset;
}
else if(document.body && document.body.scrollTop) {
height = document.body.scrollTop;
}
else if(document.documentElement && document.documentElement.scrollTop) {
height = document.documentElement.scrollTop;
}
return height;
}
onload=function() {
window.onscroll = scroll;
function scroll() {
ybox.value = "this: "+getPageY();
var f = document.getElementById("floater");
var y = getPageY()-300; // minus header height
var divh = document.getElementById("main").offsetHeight;
if (divh > 400) { // greater than floater height
divh -= 400; // minus floater height
if (y < 0) y = 0;
else if (y > divh) y = divh;
f.style.top = y+"px";
}
}
}
</script>
</head>
<body>
<div id="header"></div>
<div id="main"></div>
<div id="side"><div id="floater">Float Content<br />
<input name="ybox" id="ybox"></div></div>
<div id="footer"></div>
</body>
</html>
This works, but with images it is extremely jumpy. I modified it to use a fixed position when it should be stuck in a position. Replace the three matching lines with this for a smoother result:
if (y < 0) {y = 0;f.style.position = "absolute";}
else if (y > divh) {y = divh;f.style.position = "absolute";f.style.top = divh+"px";}
else {f.style.position = "fixed";f.style.top = 0;}
I've implemented this and its pretty good. http://net.tutsplus.com/tutorials/html-css-techniques/creating-a-floating-html-menu-using-jquery-and-css/. But this is done using jquery only. Ill let you know if icome across any links with just plain javascript.
All,
A total newbie here but could someone please review this code and let me know where I am going wrong?
What effect I am trying to achieve: I have about 9 divs on the webpage, consisting of images and text, the text comes into focus when the user hovers over the image inside the div. I want these divs to 'appear' to be floating around the page.
So what I did: I absolutely positioned the divs using CSS on the webpage. Now I am using JS to move the divs from their position to set positions on the page (will do this for each div) and try to give the effect of random movement to the divs. Here is the code:
<script language="javascript">
var x = document.getElementById("cr001").style.left;
var y = document.getElementById("cr001").style.top;
var d_x = 75;
var d_y = 100;
var interval = 2; //move by only 2px...
function moveImage() {
if(x < d_x) x = x + interval;
if(y < d_y) y = y + interval - 1; //move y by only 1px
document.getElementById("cr001").style.left = x+'px';
document.getElementById("cr001").style.top = y+'px';
if ((x + interval < d_x) && (y + interval < d_y)) {
window.setTimeout('moveImage()',100);
}
}
</script>
</head>
<body onload="moveImage()">
<div id="blackhole"><img src="img/bimg.png" alt="blackhole" /></div>
<div id="container">
<div id="cr001" class="twinkles">
<a href="#">
<img src="img/cr.png" alt="Co is about your freedom" />
<span>Co is about your freedom</span></a>
</div>
</body>
Could someone please explain where I am going wrong?
Cheers,
Based on the refined post, I now see that you are trying to access body content in the head with var x = document.getElementById("cr001").style.left;
This won't work because when the head is loaded, the body is not ready. You should make an init() function that looks like:
function init(){
window.x = document.getElementById("cr001").style.left;
window.y = document.getElementById("cr001").style.top;
moveImage();
}
and then attach that to the body onload.
EDIT: ok, here is some modified code that does what you want. You can stick this in a file named index.html and launch it in Firefox. I broke it down for you:
<html>
<head>
<script language="javascript">
var d_x = 75;
var d_y = 100;
var interval = 2;
//init is used for getting things up and running once the page is loaded
function init(){
//optimization: only get the element once
var el = document.getElementById("cr001")
x = parseInt(el.style.left);
if(isNaN(x)){
//parseInt("") == NaN
x = 0;
}
y = parseInt(el.style.top);
if(isNaN(y)){
//ditto
y = 0;
}
//call the nuts of this script
moveImage();
}
//this is mostly unchanged
function moveImage() {
if(x < d_x){
x = x + interval;
}else{
//lets keep looping just for fun!
x = 0;
}
if(y < d_y){
y = y + interval - 1; //move y by only 1px
}else{
y = 0;
}
//optimization: only get the element once
var el = document.getElementById("cr001")
el.style.left = x + 'px'; //dont forget to add 'px' back in
el.style.top = y + 'px';
//loop, don't use strings in setTimeout since this is basically eval...eval is evil
setTimeout(moveImage, 100);
}
</script>
</head>
<body onload="init()">
<div id="container">
<!-- IMPORTANT: POSITION IS ABSOLUTE -->
<div id="cr001" style="position:absolute; width:10px; height:10px; background-color:black"></div>
</div>
</body>
The problem is here:
document.getElementById("cr001").style.left
This actually returns the css value, which is a string for example '100px' or '10%' etc. Yet, later on your code, you use this value as if it was an integer.
You have an unclosed div. You open <div id="container"> and <div id="cr001" class="twinkles"> but only close one of them