Strange Progress Bar Behavior offsetwidth - javascript

I started developing a simple progress bar using vanilla JavaScript. As far as grabbing a width set in CSS the only way I found with JS is to use .offsetWidth - The following is the code for the functionality demo I was beginning to setup. The fiddle link is at the bottom of the question.
HTML:
<section id="box"></section>
<p>
<section id="box2"></section>
CSS:
#box, #box2 {
height: 10px;
width: 5px;
background-color: lightBlue;
}
#box2 {
width: 4px;
}
JavaScript (onload) :
var savedwidth = document.getElementById("box").offsetWidth;
alert("box 1 width " + savedwidth);
savedwidth = document.getElementById("box2").offsetWidth;
alert("box 2 width " + savedwidth);
While testing it out to see if it grabbed the property accurately I noticed that when the width was set to 5px it returned 6px. Everything else seems fine.
4px = 4px, 6px = 6px.
I was curious if anyone knew why that happened? It's minimal enough where it won't affect what I'm trying to do seemingly, but the more you know the better off you'll be.
FIDDLE : http://jsfiddle.net/5yk9e5du/

Related

jQuery isn't working to make navigation icons appear after scrolling past 1vh

I work in a web development environment that uses WordPress. The theme we use is ThemeCo's Pro.
I'm still learning javascript (so please forgive me if I'm really far off), and I'm trying to use jQuery to write a piece of code that will allow an element to appear after scrolling 1vh of the page. Can anyone help me understand why this isn't working? I can't tell if it's my code, or my theme might not be allowing it. The theme itself uses jQuery on the front end, but has a javascript file I may edit, but for the most part, the frontend editor is pretty reliable for code.
I'm using pieces from this question to help me write it, as well as referencing the jQuery library.
$(window).scroll(function() {
var scroll = $(window).scrollTop();
var minH = $(window).height() * 1;
if (scroll >= minH) {
$("#circle-menu").fadeTo(500, 1);
}
else {
$("#circle-menu").fadeTo(500, 0);
}
});
Just to make sure I understand what you're trying to do, I'll quickly reiterate what your code does: Basically, minH is supposed to be 1vh, and if scroll is >= minH, you want #circle-menu to fade in.
That being said, I think we have to look at a couple potential issues with the code above:
1vh is really just 1/100 of the viewport height, which can be calculated as:
// this is 1vh, which is what you're going for
$(window).height() / 100
As opposed to:
// this is 100vh
$(window).height() * 1
The second would be that you're using fadeTo. The difference between fadeIn/fadeOut and fadeTo is that fadeTo doesn't affect an element's display property. It only affects an element's opacity property. This means that if the theme's default value for the menu's display property is set to "none", fadeTo is not going to make it fade into sight. To get around this, in my opinion, it would be better to use fadeIn and fadeOut instead, especially since it doesn't seem like you're trying to control different levels of opacity (which is what fadeTo is really needed for).
I made a quick code snippet to demonstrate the above fixes.
$(window).scroll(function() {
var scroll = $(window).scrollTop();
var vh = $(window).height() / 100;
var minH = vh;
if (scroll >= minH) {
$("#circle-menu").fadeIn(500);
}
else {
$("#circle-menu").fadeOut(500);
}
});
p {
margin-top: 10vh;
height: 150vh;
border: 2px solid #666;
}
#circle-menu {
font-family: 'Segoe UI', verdana, sans-serif;
font-size: 20px;
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 50px;
box-shadow: 1px 2px 3px rgba(50,50,50,0.1);
z-index: 1;
display: none;
background-color: steelblue;
color: white;
padding-left: 20px;
padding-top: 10px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="circle-menu">Menu</div>
<p></p>

Javascript issue with id and class combination within R shiny

I am working on a project and am stuck with one of my final steps. I am developing a shinyApp and have done stuff like the following within my ui.R file, at the end of my tags$body section:
tags$script(HTML('
window.onscroll = function() {myFunction()};
var sidebar = document.getElementById("sidebar");
var title = document.getElementById("title");
var titleHeight = title.offsetHeight;
function myFunction() {
if (window.pageYOffset >= titleHeight) {
if ($(window).width() > 1280) {
sidebar.classList.add("sticky-wide");
} else if ($(window).width() > 780) {
// This is the final issue:
sidebar.classList.add("sticky");
//sidebarWell.classList.add("stickyWell");
} else {
sidebar.classList.add("sticky-narrow");
}
} else {
if ($(window).width() > 1280) {
sidebar.classList.remove("sticky-wide");
} else if ($(window).width() > 780) {
sidebar.classList.remove("sticky");
//sidebarWell.classList.remove("stickyWell");
} else {
sidebar.classList.remove("sticky-narrow");
}
}
}'))...
Note that "sidebar" is the id name given to my shiny element "sidebarPanel()". So that when I scroll beyond the title at the top of the page, my sidebar becomes sticky based on the following code in my css file (note the very last element I am pretty sure is from my predecessor's previous code and I believe is some global style options assigned to a class that shiny labels automatically):
.stickyWell {
box-sizing: border-box;
width: calc(33% - 30px);
}
.sticky {
box-sizing: border-box;
width: calc(33% - 30px);
/*width: inherit;*/
position: fixed;
top: 0;
height: 100vh;
}
.sticky-narrow {
width: 100%;
}
.sticky-wide {
box-sizing: border-box;
width: calc(426.67px - 30px);
position: fixed;
top: 0;
height: 100vh;
}
/*Change style options of a singular selectInput box by first defining a class for it:*/
.my_class .selectize-input {
border-top-left-radius: 0px;
border-top-right-radius: 0px;
}
#ss-connect-dialog {
opacity: 1 !important;
padding: 1em;
position: fixed;
top: 50px;
bottom: auto;
left: 50px;
padding-left: 45px;
padding-right: 18px;
width: 300px;
height: auto;
z-index: 99999;
background-color: #404040;
color: white;
border-radius: 3px;
font-size: 0.9em;
box-shadow: rgba(0, 0, 0, 0.3) 3px 3px 10px;
}
Update: Note the if statements have been updated and now work properly. This is the closest I have gotten the code to working, but the second case in the nested if statement does not adjust the width properly.
The following was one solution I used in the past but seems incompatible with the window.onscroll feature:
#media only screen and (max-width: 1280px) and (min-width: 780px) {
#sidebar.well {
box-sizing: border-box;
width: calc(33% - 30px);
/*position: fixed;*/
overflow-y: scroll;
height: 80vh;
}
}
This used to be in my CSS file and adjusted the width the appropriate amount (note the 33% is due to column = 4 for sidebarPanel and the 30px is twice the border of the sidebarPanel, set by default, later I can make this more robust). So ideally I need to figure out a way to implement this in my javascript section of ui.R (one of my attempts being connected to the commented lines involving "stickyWell" in the first code bluck, which calls a similar looking thing, to the #media above, in the first block of css code).
Remaining portions of original post follows and can be ignored
The issue is that the width of my sidebar becomes too large when scrolling down the page. I found a solution to this earlier, but it runs into the issue of the sidebar width changing before and after I scroll beyond the title.
One way I figured out to get around this was to use:
#sidebar.well {
box-sizing: border-box;
width: calc(33% - 30px);
}
in my css file as well (where the class name "well" is assigned automatically by R shiny and specifically using the id-class name combo correctly sizes things). But this only fixes the width after scrolling beyond the title (when the sidebar gets the position:fixed property) and screws up the width prior to scrolling beyond the title.
So now what is left to do is to only enable the above css snippet when I scroll beyond the title. I have tried such things as:
var sidebarWell = document.getElementById("sidebar").getElementsByClass("well")[0];
and then within the proper if statement (in the first block of code) I tried adding things like:
sidebarWell.setAttribute("style", "box-sizing: border-box;");
sidebarWell.setAttribute("style", "width: calc(33% - 30px);");
or
sidebarWell.classList.add("stickyWell");
After first renaming "#sidebar.well{}" in the css file to "stickyWell{}".
I am new to javascript, what am I missing or doing wrong? Please note that I think I am very limited with id and class names because of how shiny labels things, and I have tried applying the above style changes to just id="sidebar" but it does not work how I think it should.
In response to the first comment:
Firstly, I figured I would include any relevant parts of the code that may create conflicts. First the way the sidebarPanel is defined:
sidebarLayout(
sidebarPanel(id="sidebar",
width=4,
...
with nothing else major in that section of ui.R (mainPanel is defined with width=8. Then in the beginning of ui.R, I have
shinyUI(fluidPage(
includeCSS("extrahtmlfunc.css"),
tags$head(
# 2018-06-19: Fixes issue where a slider that appears at certain zoom levels for figures using splitLayout (only shows up on Chrome):
tags$style(HTML(".shiny-split-layout > div { overflow: visible; }")),
# The following makes it so the UI doesn't look to weird in super-wide browsers
tags$style(type="text/css",
".container-fluid { max-width: 1280px; }"
),
...
That should be all that is relevant, the rest is minor color styles or similar tweaks. Note that this last thing is what makes some easier fixes for my solution more difficult, because I need separate cases for different page widths (I am updating the first block of code to reveal the full details of these cases in the function myFunction(), which I removed to shorten my post; note the second case of the nested if statement is the only one not working properly).
I also updated the second block of code with the rest of my css file as per request.
Found a workaround:
First off, I was able to incorporate my previous css code that fixed the issue but I was previously unable to incorporate with the window.onscroll feature. This was one of the main ways to solve my question, and there are likely other solutions which may be better.
Recall the snippet from my original CSS file that gave the correct sizing:
#media only screen and (max-width: 1280px) and (min-width: 780px) {
#sidebar.well {
box-sizing: border-box;
width: calc(33% - 30px);
/*position: fixed;*/
overflow-y: scroll;
height: 80vh;
}
}
Note that the #media... connects to the second case of the nested if statement in my javascript portion of my ui.R. It was hard to tell if I was able to replicate this with things like:
.stickyWell {
box-sizing: border-box;
width: calc(33% - 30px);
}
in conjunction with
var sidebar = document.getElementById("sidebar");
var sidebarWell = sidebar.getElementsByClassName("well")[0];
if(...){
if(...) {
...
} else if (...) {
...
sidebarWell.classList.add("stickyWell");
}...
because the "33%" seemed to not work within javascript (perhaps someone knows why). I even found and tried a way to transform the first block of CSS code directly into my javascript section:
$("#sidebar.well").css("box-sizing", "border-box");
$("#sidebar.well").css("width", "calc(33% - 30px)");
but this did not work (I even inspected the element when running the app and it did not accept the second portion of the style above).
However, once learning how to implement css code directly into javascript, I realized I might be able to replace the 33% with a precise number of pixels as that worked in the ".sticky-wide" portion of my original question. Here is the resulting solution:
shinyUI(fluidPage(
includeCSS("extrahtmlfunc.css"),
tags$head(
... ,
tags$script(HTML('
window.onscroll = function() {myFunction()};
var sidebar = document.getElementById("sidebar");
var title = document.getElementById("title");
var titleHeight = title.offsetHeight;
function myFunction() {
if (window.pageYOffset >= titleHeight) {
if ($(window).width() > 1280) {
sidebar.classList.add("sticky-wide");
} else if ($(window).width() > 780) {
sidebar.classList.add("sticky");
$("#sidebar.well").css("box-sizing", "border-box");
$("#sidebar.well").css("width", "calc(" + $(window).width()/3 + "px - 30px)");
} else {
sidebar.classList.add("sticky-narrow");
}
} else {
if ($(window).width() > 1280) {
sidebar.classList.remove("sticky-wide");
} else if ($(window).width() > 780) {
sidebar.classList.remove("sticky");
$("#sidebar.well").css("box-sizing", "");
$("#sidebar.well").css("width", "");
} else {
sidebar.classList.remove("sticky-narrow");
}
}
}
'
)
) # Closes tag$script
) # Closes tag$head
... # Rest of ui.R
)
) # Closes shinyUI
I hope this ends up helping someone else.

show/hide div on click with JS and introduction

I'm fairly new to the front-end web developing sphere and I have only studied HTML/CSS for ~ a month and a half and just about 1 week or less into JS. Since I want to practice what I learn from different websites I make my own to test my knowledge. I want to apologize in advance if I am asking too many questions, but there aren't any people I know that I can share coding issues with.
So I wanted to make ( just for testing ) a show/hide div which is activated when you click a button with JS. I can make it show, but I wanted to try to make it hide/show with an "if/else" function. I thought my code was right but it doesn't seem to work and I can't find a solution. I'll share with you my code ( the part of it which I have problems with actually) and will be very grateful if you can help me find a solution.
HTML :
<button type="button" onclick="slide()" >Click Me</button>
<div class="divtest" id="dropdown">
<span>If you are seeing this, then your JS worked! </span>
</div>
The CSS ( some things are pointless, I just added them in to test a bit ):
.divtest {
position: absolute;
left: 25%;
bottom: 30px;
width: 50%;
height: 100px;
border: 2px solid black;
box-sizing: border-box;
box-shadow: 5px 5px 10px 3px;
text-align: center;
padding: 40px;
margin: 0 auto;
font-family: Cooper, sans-serif;
font-weight: 100;
transition: 1s ease;
background-color: limegreen;
color: black;
display: none;
}
button {
position: absolute;
width: 50%;
left: 25%;
bottom: 130px;
padding: 10px;
border: 2px solid black;
background-color: limegreen;
box-shadow: 5px 5px 50px 3px;
color: black;
cursor: pointer;
font-family: Cooper, sans-serif;
font-weight: 100;
}
the JS:
<script>
function slide() {
var drop = document.getElementById("dropdown"); // declares the element with id="dropdown" as a var
var dropSetting = drop.style.display; // declares that the variable "drop"'s display property is also a variable
if (dropSetting == "none") { // if the current value of display = "none" ( which it is as u can see in the CSS)
dropSetting == "block"; // Then set it to "block"
}
else { // if the value of display != none
dropSetting == "none"; // then set it to "none"
}
}
</script>
If you have any questions towards the code or anything, please feel free to ask as this is a separate feature contained in my test website so it is not connected in any way to other elements/attributes. I tried this code first in another way (without declaring dropSetting as a var, just adding in a few lines in the if/else function ) but it still did not work.I don't think JS recognizes the "style.display" as a property because Brackets doesn't highlight it. Thank you very much for your time in advance, and I hope that soon I too will be able to help some people out with what I know!
Also - a side question - What are your thoughts on treehouse? I have heard very good things about them and I'm thinking about signing up to further my knowledge.
Have a nice day!
For code compatibility, try to use methods, no shortcuts, for attributes use:
var drop = document.getElementById("dropdown");
drop.setAttribute('style', 'display: block');
var display = drop.getAttribute('display'); //Here is all the inline css, better do like below:
And it is much better for a clean and faster code, make all css clases you need:
.hide{
display:none;
}
JS:
drop.classList.add('hide');
drop.classList.remove('hide');
drop.classList.toggle('hide');
Never used Treehouse, but for myself the best teacher is a good IDE for web like Atom of VScode, google Chrome console (F12), and those are your books:
-http://www.w3schools.com/js/js_examples.asp
-https://developer.mozilla.org/en-US/docs/Web/API/Element
And this is your teacher for questions:
stackoverflow.com
You dont need anything more.
PD: Your logic is ok, just don't get used to code shortcuts, they may not work in all environments. (like elem.attribute instead of elem.getAttribute(''))
Your code doesn't works because you didn't assign display property to appropriate value (block / none). you have used comparison operator("==") instead of equals ("=").
if (dropSetting == "none") { // if the current value of display = "none" ( which it is as u can see in the CSS)
dropSetting = "block"; // Then set it to "block"
}
else { // if the value of display != none
dropSetting = "none"; // then set it to "none"
}
"==" operator in your code will just return true/false without changing display property of the div.
The problem is that your dropSetting is not an object, just string. When you change it (if change) you don't change the object (style in this case). Try something like this:
var drop = document.getElementById("dropdown"); //get reference to the object
drop.style.display = drop.style.display == 'none' ? 'block' : 'none'; //if(...){do something}else{do something else}
Another possibility:
var dropStyle = document.getElementById("dropdown").style;
if(dropStyle.display == 'none'){
dropStyle.display = 'block';
}else
dropStyle.display = 'none';

How to resize a div to clients viewport height?

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/

Highlight lines of text on mouseover [duplicate]

This question already has answers here:
How can I highlight the line of text that is closest to the mouse?
(3 answers)
Closed 8 years ago.
I'm currently working on a website which will feature a bunch of stories for people to read (basically a blog). I want to make them as easy to read as possible and I figured it would be useful to 'highlight' lines of text with the cursor. Kinda like following the lines of text with your finger when reading a book.
I stumbled upon this answer, however I can't seem to get it to work for my page. It's also a pretty old answer so maybe there's an improved version of this?
If anyone could help me out I'd be forever grateful!
Wrote some jQuery code that, atleast to me, both looks and works better than the code in the post that you are referring to. Hope it fits your needs :)
There's also a live demo up at http://jsfiddle.net/gFTrS/2/
HTML
<div class="textWrapper">
<div class="highlight"></div>
<p>Your text goes here</p>
</div>
CSS
.textWrapper
{
position: relative;
width: 600px;
padding: 0px 10px;
margin: 0 auto;
cursor: default;
}
.textWrapper p
{
font: normal 12px Arial;
color: #000000;
line-height: 18px;
padding: 0;
margin: 0;
}
.highlight
{
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 18px;
background: yellow;
z-index: -1;
display: none;
}
jQuery
$(document).ready(function()
{
var lineHeight = 18;
$('.textWrapper').hover(function()
{
$('.highlight', this).show();
$(this).mousemove(function(e)
{
var relativePos = e.pageY - this.offsetTop;
var textRow = (Math.ceil(relativePos / lineHeight) * lineHeight) - lineHeight;
if (textRow => 0)
{
$('.highlight', this).css('top', textRow + 'px');
}
});
}, function()
{
$('.highlight', this).hide();
});
});
Most of the answers and suggestions in the older post on SO you reffered to try to manipulate the DOM by adding spans or divs for each line. But that's actually not a waterproof approach since it is not cross- browser compatble, especially not with mobile browsers. You should use a dynamically jquery controlled div that jumps behind the lines. The div should be dynamically be positioned with a jquery function triggered on mousemove calculating the div jumping on line-height depending on mouse cursor position

Categories