Changing div styles at scroll position without JQuery - javascript

I am relatively new to web design and am not yet ready to dive into JQuery but I am beginning to use Javascript as needed. I am unable to figure out how to change the background color of a div menubar at a certain scroll position.
CSS
.mainMenu {
position: fixed;
top: 0px;
left: 0px;
height: 80px;
padding: 20px;
transition: all 0.2s;
}
Javascript
var scrollHeight = window.pageYOffset;
if (scrollHeight >= 100) {
document.getElementById("mainMenu").style.backgroundColor = "green";
}
From what I can tell as a noob, the if statement only runs on load and the var scrollHeight isn't updating as the user scrolls. I appreciate any help making this work! I will get around to learning JQuery but I would like to understand the language better before dabbling in libraries.

Right – you need to setup something that continues to check the scroll position and update accordingly:
function checkPosition() {
// Continue calling this function:
requestAnimationFrame(checkPosition);
// Check your position here
}
// Initial Call:
checkPosition();
Better yet, read up on Scroll Events.
Edit:
Also, instead of manipulating styles directly, I'd recommend adding or removing classes:
element.classList.add("newClass");
(By the way, jQuery is actually easier than 'regular' javascript.)

Related

jQuery: Move div to the left on click and bring it back to its original position (with the same button)

Here I am again, drowning in my noobness. I have been searching for literally HOURS to solve this problem! I am totally a beginner in jQuery/Javascript so I need some help.
This is what I want to do:
I have a navigation bar that when you click on a button, it hides it, then when you click again, it toggles it back, so the navigation bar is visible again. I have done this with jQuery and it works perfectly.
Now what happens is that, when you click that button and hide the navbar, I want the div content to slide to the left a few pixels and take up the full width (thus growing a bit bigger and filling up the useless whitespace, I especially want this for mobile-users). Again, this works perfectly.
However...if I click back on the famous button, the navigation bar comes back but the div content is still to the left, slightly hidden by the navbar. Whereas I want that when to navigation comes back, the div content comes back to its original place and width aswell.
Thus I have tried many many different codes but nothing seems to work! It either stays left or it just does not do anything. Although interesting and fun, it gets kind of frustrating after a few hours.
Here are a few things I have tried:
-toggle
-animate/stop
-if/else
-Get x position
I did not save any jQuery/javascript code but if need be, I shall provide a snippet. The reason I do not want to provide any code is because it is insanely LONG and confusing and complex!
As such, thank you very much in advance for your help! =)
Ah one last thing: Again, please keep in mind that you are talking to a beginner! So may you please be very specific and methodical (and keep it simple if possible ^^'), I would very much appreciate it since I have been searching for hours on Google and stackoverflow.
Oh woops I forgot! I do not use pixels for my units. I use "%" for the sake of responsiveness...I don't know if that actually works with jQuery...Enlighten me!
**ALRIGHT! Here is my super complicated fiddle...Somehow the jQuery is not working in my fiddle but it is working on my browser.
<html>Some super random code because it won't let me post fiddle without it but all my code is in the fiddle...</html>
https://jsfiddle.net/czcvucxL/1/**
you can get it done toggling a class from .content1 instead of using jquery
Demo
$(document).ready(function(){
$("#CharaCircle a").click(function(){
$("#Header").animate({width:'toggle'},350);
$("#Sidebar, #Sidebar ul li").animate({height:'toggle'},250);
$(".content1").toggleClass("fullwidth");
return false;
});
});
add this class
.fullwidth {
width: 95%;
left: 0;
margin-left: 0;
}
add these to .content1 so the div starts with 10% on the left and allow the animation(transition)
.content1{
left: 10%;
-webkit-transition: left 0.2s ease-in, width 0.2s ease-in;
transition: left 0.2s ease-in, width 0.2s ease-in;
}
EDIT: if you want it only with jquery Demo
$(document).ready(function () {
$("#CharaCircle a").click(function () {
$("#Header").animate({
width: 'toggle'
}, 350).toggleClass("hidden");
$("#Sidebar, #Sidebar ul li").animate({
height: 'toggle'
}, 250);
var properties;
var $content = $(".content1");
//build your set of properties width and marginleft
//are the ones you need to change
if ($("#Header").hasClass("hidden")) {
properties = {
width: "100%",
marginLeft: "0"
};
} else {
properties = {
width: "62%",
marginLeft: "19.4%"
};
}
$content.animate(properties, 250);
return false;
});
});

JS launches before CSS

This is currently happening in chrome, in firefox I haven't had this issue (yet).
Here is a VERY simplified version of my problem.
HTML:
<div class="thumbnail">
Click me!
</div>
CSS:
div {
width: 200px;
height: 300px;
background-color: purple;
}
a {
position: absolute;
}
#media (max-width: 991px) {
div {
height: 200px;
}
}
Javascript:
$(document).ready(function () {
var $parent = $('#clickMe').parent();
function resize() {
$('#clickMe').offset({
top: $parent.offset().top + $parent.height()-$('#clickMe').height()
});
}
$(window).on('resize', resize);
resize();
});
The problem:
So what does this give when I resize (without dragging)? Well javascript launches first and sets the position of the <a></a> , then CSS applies the height change if we are < 992 px.
Logically the button is now visually at the outside of the div and not on the border like I had originally defined it to be.
Temporary solution proposed in this post.
jQuery - how to wait for the 'end' of 'resize' event and only then perform an action?
var doit;
$(window).on('resize', function(){ clearTimeout(doit); doit = setTimeout(resize, 500); });
Temporary solution is not what I'm looking for:
However, in my situation I don't really need to only call 'resize' when the resizing event is actually done. I just want my javascript to run after the css is finished loading/ or finished with it's changes. And it just feels super slow using that function to 'randomely' run the JS when the css might be finished.
The question:
Is there a solution to this? Anyone know of a technique in js to wait till css is completely done applying the modifications during a resize?
Additional Information:
Testing this in jsfiddle will most likely not give you the same outcome as I. My css file has many lines, and I'am using Twitter Bootstrap. These two take up a lot of ressources, slowing down the css application (I think, tell me if I'm wrong).
Miljan Puzović - proposed a solution by loading css files via js, and then apply js changes when the js event on css ends.
I think that these simple three steps will achieve the intended behavior (please read it carefully: I also suggest to read more about the mentioned attributes to deeply understand how it works):
Responsive and fluid layout issues should always be primarily (if not scrictly) resolved with CSS.
So, remove all of your JavaScript code.
You have positioned the inner a#clickMe element absolutely.
This means that it will be positioned within its closest relatively positioned element. By the style provided, it will be positioned within the body element, since there is no position: relative; in any other element (the default position value is static). By the script provided, it seems that it should be positioned within its direct parent container. To do so, add position: relative; to the div.thumbnail element.
By the script you provided, it seems that you need to place the a#clickMe at the bottom of div.thumbnail.
Now that we are sure that the styles added to a#clickMe is relative to div.thumbnail, just add bottom: 0px; to the a#clickMe element and it will be positioned accordingly, independently of the height that its parent has. Note that this will automatically rearrange when the window is resized (with no script needed).
The final code will be like this (see fiddle here):
JS:
/* No script needed. */
CSS:
div {
width: 200px;
height: 300px;
background-color: purple;
position: relative; //added
}
a {
position: absolute;
bottom: 0px; //added
}
#media (max-width: 991px) {
div {
height: 200px;
}
}
If you still insist on media query change detection, see these links:
http://css-tricks.com/media-query-change-detection-in-javascript-through-css-animations/
http://css-tricks.com/enquire-js-media-query-callbacks-in-javascript/
http://tylergaw.com/articles/reacting-to-media-queries-in-javascript
http://davidwalsh.name/device-state-detection-css-media-queries-javascript
Twitter Bootstrap - how to detect when media queries starts
Bootstrap: Responsitive design - execute JS when window is resized from 980px to 979px
I like your temporary solution (I did that for a similar problem before, I don't think half a second is too long for a user to wait but perhaps it is for your needs...).
Here's an alternative that you most likely have thought of but I don't see it mentioned so here it is. Why not do it all through javascript and remove your #media (max-width.... from your css?
function resize() {
var width = (window.innerWidth > 0) ? window.innerWidth : screen.width;
if(width<992){
$("div").each(function(e,obj){$(obj).height(200);});
}
$('#clickMe').offset({
top: $parent.offset().top + $parent.height()-$('#clickMe').height()
});
}
In the html page, put the link to css file in head section; next, put the link to js file just before the /body tag and see what happens. In this way css will load always before js.
Hope this help you.
Did you try to bind the resize handler not to the window but to the object you want to listen to the resize ?
Instead of
$(window).on('resize', resize);
You can try
$("#clickMe").on('resize', resize);
Or maybe
$("#clickMe").parent().on('resize', resize);
var didResize = false;
$(window).resize(function() {
didResize = true;
});
setInterval(function() {
if (didResize) {
didResize = false;
console.log('resize');
}
}, 250);
I agree with falsarella on that you should try to use only CSS to do what you are trying to do.
Anyway, if you want to do something with JS after the CSS is applied, I think you can use requestAnimationFrame, but I couldn't test it myself because I wasn't able to reproduce the behavior you explain.
From the MDN doc:
The window.requestAnimationFrame() method tells the browser that you
wish to perform an animation and requests that the browser call a
specified function to update an animation before the next repaint. The
method takes as an argument a callback to be invoked before the
repaint.
I would try something like this:
var $parent = $('#clickMe').parent();
function resize(){
$('#clickMe').offset({
top: $parent.offset().top + $parent.height()-$('#clickMe').height()
});
}
window.onresize = function(e){
window.requestAnimationFrame(resize);
}
window.requestAnimationFrame(resize);
Anyone know of a technique to wait till css is completely done loading?
what about $(window).load(function() { /* ... */ } ?
(it executes the function only when the page is fully loaded, so after css loaded)

Using addClass() and CSS transition on render function in Backbone app not working correctly

In my backbone.js application, I'm trying to fade in the view element after it's been appended. However it doesn't work.
Live example here: http://metropolis.pagodabox.com
var itemRender = view.render().el;
$('#items-list').append(itemRender);
$(itemRender).addClass('show');
However if I add a small setTimeout function, it works.
var itemRender = view.render().el;
$('#items-list').append(itemRender);
setTimeout(function(){
$(itemRender).addClass('show');
},10);
Using fadeIn() also works but I prefer to use straight CSS for the transition as it's more efficient, and prefer not to use any setTimeout "hacks" to force it to work. Is there a callback I can use for append? Or any suggestions? The full code is below:
itemRender: function (item) {
var view = new app.ItemView({ model: item }),
itemName = item.get('name'),
itemRender = view.render().el;
$('#items-list').append(itemRender);
$(itemRender).addClass('show');
app.itemExists(itemName);
}
CSS/LESS:
#items-list li {
padding: 0 10px;
margin: 0 10px 10px;
border: 1px solid #black;
.border-radius(10px);
position: relative;
.opacity(0);
.transition(opacity)
}
#items-list li.show {.opacity(1)}
This "hack" you mention (or some variant of it) is occasionally necessary for web development, simply due to the nature of how browsers render pages.
(NOTE: This is all from memory, so while the overall idea is right please take any details with a small grain of salt.)
Let's say you do the following:
$('#someElement').css('backgroundColor', 'red');
$('#someElement').css('backgroundColor', 'blue');
You might expect to see the background color of #someElement flash red for a brief moment, then turn blue right? However, that won't happen, because browsers try to optimize rendering performance by only rendering the final state at the end of the JS execution. As a result, the red background will never even appear on the page; all you'll ever see is the blue.
Similarly here, the difference between:
append
set class
and:
append
wait 1ms for the JS execution to finish
set class
Is that the latter allows the element to enter the page and AFTER the JS is executed have its style change, while the former just applies the style change before the element gets shown.
So while in general window.setTimeout should be avoided, when you need to deal with these ... complications of browser rendeering, it's really the only way to go. Personally I like using the Underscore library's defer function:
var itemRender = view.render().el;
$('#items-list').append(itemRender);
_(function(){
$(itemRender).addClass('show');
}).defer();
It's the same darn thing, but because it's encapsulated in a library function it feels less dirty to me :-) (and if the "post-render" logic is more than a line or two I can factor it in to a Backbone View method and do _(this.postRender).defer() inside my render method).
You can use CSS animations
#keyframes show {
0% { opacity: 0; }
100% { opacity: 1; }
}
#items-list li {
padding: 0 10px;
margin: 0 10px 10px;
border: 1px solid #black;
.border-radius(10px);
position: relative;
}
#items-list li.show {
animation: show 1s;
}

Sliding a div in windows8

i have created a Windows 8 app using HTML & JavaScript.
Here i want to slide a div[contains two textbox and a button] from right side of the screen towards left.
hopes the question is clear.
jQuerys $.animate is fine for that, see here.
However, using jQuery in Windows 8 Apps is problematic due to security restrictions, I've written a blog post on that and provided a windows 8 ready jQuery version there, take a look: http://www.incloud.de/2012/08/windows-8-using-jquery-for-app-development/
Here's an example of using CSS transitions.
/* CSS */
#myDiv {
width:300px;
height:300px;
box-sizing:border-box;
position:relative;
left:-300px;
border:2px solid;
transition:1s;
}
Then in JavaScript you simply set the left property programmatically. In my case I did it in response to a button click.
// js
element.querySelector("#go").onclick = function(e) {
element.querySelector("#myDiv").style.left = "0px";
};
And there you have it. Hardware accelerated and everything.
Consider using the WinJS native animations library. For your can WinJS.UI.Animation.enterContent or WinJS.UI.Animation.showPanel could be useful.
Problem solved by using the following piece of code:
CSS:
position: fixed;
right: 0px;
top: 0px;
width: 308px;
height: 100%;
color: white;
background-color: bisque;
opacity: 0;
z-index: 1;
Then in JavaScript I have just set the opacity property to one.
JS:
(function () {
"use strict";
var page = WinJS.UI.Pages.define("/default.html", {
ready: function (element, options) {
btnname.addEventListener("click", togglePanelUI, false);
myPanel = element.querySelector("#divname"); } //div name is name of div which u wants to slide
});
var animating = WinJS.Promise.wrap();
var myPanel;
function togglePanelUI() { // If element is already animating, wait until current animation is complete before starting the show animation.
animating = animating
.then(function () {
// Set desired final opacity on the UI element.
myPanel.style.opacity = "1";
// Run show panel animation.
// Element animates from the specified offset to its actual position.
// For a panel that is located at the edge of the screen, the offset should be the same size as the panel element.
// When possible, use the default offset by leaving the offset argument empty to get the best performance.
return WinJS.UI.Animation.showPanel(myPanel);
});
}
})();
for more information regarding animations of windows 8, have a look at here

Making a DOS-style window in ASP.net

I'm trying emulate the MS-DOS command prompt on my website. I don't need to accept keystrokes, but I'd like to append data at the bottom and optionally scroll upwards.
At first I looked at the asp:TextBox and asp:Label, but the flicker of using postbacks seemed to be too much. I'm now considering DIV tags and Javascript where I simply update the InnerHTML property, but there too I get flicker, and have issues with scrolling.
What solution would you recommend in this situation? Essentially I'm trying to count to infinity, with a 1 sec delay, only need the most current 300 or so entries, with the most current entry at the bottom of the screen.
Is this even possible with JS/CSS?
Do you wish to make it a little more stylous ? :)
see this page...
http://www.klaus.dk/Some_unknown_page
or this one
http://www.harryovers.com/404.html?aspxerrorpath=/Account/LoginPartial
here is the javascript source code.
http://code.google.com/p/c64-404-page/
With a little change, you can append your text on this code :)
I just built something very similar using jQuery. You can use the append method to add content to the bottom of your DIV. You can then set the scrollTop attribute to keep things scrolled to the bottom as follows:
$("#someDiv").attr({ scrollTop: $("#someDiv").attr("scrollHeight") });
I think "DOS-style window" is a bit misleading considering all you want to do is append text to a div and make sure it stays scrolled to the bottom.
function addLine(text) {
var box = document.getElementById('DOSBox') //teehee
var line = document.createElement('p');
line.innerHTML = text;
box.appendChild(line);
box.scrollTop = box.scrollHeight;
}
And style it as such
#DOSBox {
overflow: auto;
display: block;
height: 400px; width: 500px; /* or whatever */
/* and if you want it to look DOS-like */
background: #000;
color: rgb(192, 192, 192);
font-family: fixedsys;
}
#DOSBox p {
margin: 0;
}

Categories