Highlighting image & text for navbar - javascript

so I currently have a nav bar that consists of text, and an image above that text. When I hover on the text, the image is highlighted, and vice versa. Say, I hover on the 'Home' image, it should also highlight the image. Now, this works just fine, but my problem is that, if you move the mouse around too fast, either the text or the image will remain highlighted, which is slightly annoying. I'm just wondering if there's anything that I can do about this, if not, it's not like it's a huge deal.
My code, which is unfortunately, a bit hackey:
<script>
function handleEnter(elem) {
elem = elem.target;
var location = -1;
var image_elem = null;
if ($(elem).hasClass('menutext')) {
location = $(elem).parent().parent().index() + 1
image_elem = $('.menuimgwrap:nth-child('+ location +')')
$(elem).parent().parent().addClass('hovering');
$(image_elem).addClass('hovering');
} else if ($(elem).hasClass('menuimgwrap')) {
location = $(elem).index() + 1
image_elem = $('.menuitem:nth-child('+ location +')')
$(elem).addClass('hovering');
$(image_elem).addClass('hovering');
}
}
function handleLeave(elem) {
elem = elem.target;
var location = -1;
var image_elem = null;
if ($(elem).hasClass('menutext')) {
location = $(elem).parent().parent().index() + 1
image_elem = $('.menuimgwrap:nth-child('+ location +')')
$(elem).parent().parent().removeClass('hovering');
$(image_elem).removeClass('hovering');
} else if ($(elem).hasClass('menuimgwrap')) {
location = $(elem).index() + 1
image_elem = $('.menuitem:nth-child('+ location +')')
$(elem).removeClass('hovering');
$(image_elem).removeClass('hovering');
}
}
$('.menuitem, .menuimgwrap').hover(handleEnter, handleLeave);
</script>
When the text is highlighted, it's handled by the menutext selector, and when the image is highlighted, it's handled by the menuimgwrap selector. It then figures out which navbar element was highlighted, and then decides which image or text the said element matches up with, and highlights that one too.
How can I fix this, so that it doesn't stay highlighted if the mouse is moved too fast over the navbar?
Thanks

Change this to use CSS instead. The basic hover would be like the following:
<style>
.menuItem:hover {
background-color: red;
}
</style>
<a href='#' class='menuItem'>
<img src='image.png' />
Home
</a>

Related

Detect weather user clicked on text or white space inside textarea

I have a textarea that can be draged around in which text should still be selectable by draging over it. In order to distinguish a "over text drag" from a "move drag" I have to know weather the point where the user started its drag (i.e. mousedown position) was white space or text.
The only thing I can come up with to figure this out is calculating using character width and line height, which I would like to avoid.
Not really sure what you're asking, but here's my attempt to translate the insanity into working code:
let doc, htm, bod, I; // for use on other loads
addEventListener('load', ()=>{
doc = document; htm = doc.documentElement; bod = doc.body; I = id=>doc.getElementById(id);
// magic under here
const test = I('test');
function whiteStart(string){
if(string.match(/^\s+/)){
return true;
}
return false;
}
test.oncopy = test.ondragstart = function(){
let s = getSelection().toString();
if(whiteStart(s)){
console.log('"'+s+'" starts with one or more white spaces');
}
else{
console.log('"'+s+'" starts without a white space');
}
}
}); // end load
<div id='test'>I&apos;m just going to put some text in here so we can run a very basic test. I hope this helps!</div>

How do I recalculate the section's height on scroll for a fixed navigation that changes class past certain anchors?

Context
I am working on a one-page website where the fixed navigation's class changes as it scrolls through the different sections in order to match the section's background color. To achieve this effect, I used and modified the 2nd solution listed here.
Issue
While it works great most of the time, the navigation code breaks when I resize the browser (or leave the page and click back). More specifically, the navigation's background color changes too early or too late and no longer matches the section's background.
I'm guessing that this happens because the section's height are calculated on page load. Ideally, they would be recalculated on every scroll - but I am a novice and that's just a guess. Any help to solve this issue would be appreciated.
JavaScript
FYI: there are four sections in the websites (Hero, Work, About, Contact). Navigation's bg color should be transparent in Hero, white in Work and Contact, and teal in About.
var afterhero = $('#hero-section').offset().top + $('#hero-section').height();
var afterwork = afterhero + $('#work-section').height();
var afterabout = afterwebsites + $('#about-section').height();
$(window).on('scroll', function() {
stop = Math.round($(window).scrollTop());
if (stop > afterabout) {
$('header').removeClass('teal');
$('header').addClass('white');
} else if (stop > afterwork) {
$('header').addClass('teal');
} else if (stop > afterhero) {
$('header').removeClass('teal');
$('header').addClass('white');
} else {
$('header').removeClass('teal');
$('header').removeClass('white');
}
});
Just try adding all your size variables into your scroll event handler:
$(window).on('scroll', function() {
var afterhero = $('#hero-section').offset().top + $('#hero-section').height();
var afterwork = afterhero + $('#work-section').height();
var afterabout = afterwebsites + $('#about-section').height();
stop = Math.round($(window).scrollTop());
if (stop > afterabout) {
$('header').removeClass('teal');
$('header').addClass('white');
} else if (stop > afterwork) {
$('header').addClass('teal');
} else if (stop > afterhero) {
$('header').removeClass('teal');
$('header').addClass('white');
} else {
$('header').removeClass('teal');
$('header').removeClass('white');
}
});
Now afterhero, afterwork and afterabout should all be recalculated on a page scroll.

Javascript: Document.URL.indexOf issue

Hello Guys I have a little issue with document.URL.indexOf in Javascript. I have a lounge page where I want to make the background transparent if there is "lounge" in the URL and I want to make the background different when I am viewing a single lounge but the URL still contains "lounge" cause the full link to a lounge is "lounge/view/1" How can I make it work so when I am in "view" to have the background I want and when I am in lounge to have it transparent.
This is the code I have for now:
if (document.URL.indexOf("lounge") > -1)
{
body.delay(400).css('background-color', 'transparent');
}
else
{
body.delay(400).css('background', '#b4b7b8');
}
I tried adding anothger "else if" saying if indexOF is "view" to go to the one I want but it didn't work.
Any suggestions ?
You can check both if lounge is in the URL and view is not:
if (document.URL.indexOf('lounge') > -1 &&
document.URL.indexOf('view') == -1) {
// your code...
}
How about
var color = document.URL.indexOf('lounge/view') > -1?'#b4b7b8':'transparent';
body.delay(400).css('background', color);
or another colour per view:
var color = 'transparent', url = document.URL;
var views = 'lounge/view';
if (url.indexOf(views) > -1) {
var idx = parseInt(url.split(views)[1],10);
color = ["",'#b4b7b8','#99b7b8','#eeb7b8'][idx]; // view/1, view/2, view/3
}
body.delay(400).css('background', color);

Image highlight (hover state) on active section while scrolling?

I have these icons above each section on my page (the largish circular icons, please see example: http://pftest.fhero.net) with colored hover states... what I would really love to do is have them change to the active hover states as the user scrolls to each section (preferably with a simple fade transition) - much like the effect of highlighting the active links/section in the navigation.
There are many tutorials, plugins and questions on this site and so forth for highlighting active sections in a navigation however, but doesn't seem to be much that I can find relating to applying the effect to another div or image on the page...
I'm definitely not any kind of jQuery expert but I'm wondering if one of the myriad of scripts/plugins available which are typically used for highlighting active states in navigation could simply be adapted to this scenario somehow to achieve the same effect? Perhaps even the one I am currently using on my page?
Here is the script I'm using for highlighting the active section in the navigation on my page:
/* Scroll Navigation highlight */
$("#work-section1").parent().addClass('active');
var main = main = $('#mainmenu ul');
$('.scroll').click(function(event) {
event.preventDefault();
var full_url = this.href,
parts = full_url.split('#'),
trgt = parts[1],
target_offset = $('#'+trgt).offset(),
target_top = target_offset.top;
$('html, body').animate({scrollTop:target_top}, 500);
/* Remove active class on any li when an anchor is clicked */
main.children().removeClass();
/* Add active class to clicked anchor's parent li */
$(this).parent().addClass('active');
});
$(window).scroll(function(event) {
if($("#work-section").offset().top < $(window).scrollTop() + $(window).outerHeight()){
$("#work-section1").parent().addClass('active');
$("#about-section1").parent().removeClass('active');
$("#footer-section").parent().removeClass('active');
$("#services-section1").parent().removeClass('active');
$("#process-section1").parent().removeClass('active');
}
if($("#about-section").offset().top < $(window).scrollTop() + $(window).outerHeight()) {
$("#about-section1").parent().addClass('active');
$("#work-section1").parent().removeClass('active');
$("#footer-section1").parent().removeClass('active');
$("#services-section1").parent().removeClass('active');
$("#process-section1").parent().removeClass('active');
}
if($("#services-section").offset().top < $(window).scrollTop() + $(window).outerHeight()){
$("#services-section1").parent().addClass('active');
$("#about-section1").parent().removeClass('active');
$("#work-section1").parent().removeClass('active');
$("#footer-section1").parent().removeClass('active');
$("#process-section1").parent().removeClass('active');
}
if($("#process-section").offset().top < $(window).scrollTop() + $(window).outerHeight()){
$("#process-section1").parent().addClass('active');
$("#about-section1").parent().removeClass('active');
$("#work-section1").parent().removeClass('active');
$("#footer-section1").parent().removeClass('active');
$("#services-section1").parent().removeClass('active');
}
if($("#footer-section").offset().top < $(window).scrollTop() + $(window).outerHeight()){
$("#footer-section1").parent().addClass('active');
$("#about-section1").parent().removeClass('active');
$("#work-section1").parent().removeClass('active');
$("#services-section1").parent().removeClass('active');
$("#process-section1").parent().removeClass('active');
}
});
and the HTML:
<nav id="mainmenu" name="mainmenu">
<ul>
<li><a class="scroll" id="work-section1" href="#work-section">Works</a></li>
<li><a class="scroll" id="about-section1" href="#about-section">About</a></li>
<li><a class="scroll" id="services-section1" href="#services-section">Services</a></li>
<li><a class="scroll" id="process-section1" href="#process-section">Process</a></li>
<li><a class="scroll" id="footer-section1" href="#footer-section">Contact</a></li>
</ul>
</nav>
<section id="about-section" data-anchor-offset="90">
<section id="work-section" data-anchor-offset="90">
...ect...
Could this somehow be adapted to accomplish the effect I am looking for? Or any other/better methods, or plugins I should be looking at?
I should add that the icons use the sprites method which could make the CSS side of things a little trickier, although I would be willing to change them to non-sprite images if necessary...
You could use a small little function for this, that checks if a element is on screen. I set up a little JSFiddle for you: http://jsfiddle.net/LHrkB/1/
Code:
function isElementVisible(elementToBeChecked)
{
var TopView = $(window).scrollTop();
var BotView = TopView + $(window).height();
var TopElement = $(elementToBeChecked).offset().top;
var BotElement = TopElement + $(elementToBeChecked).height();
return ((BotElement <= BotView) && (TopElement >= TopView));
}
$(window).scroll(function () {
isOnView = isElementVisible(".inview");
if(isOnView){
//What to do when element is visible
$(".inview").css({"background":"#ccc"});
}else{ // If not visible
}
});
Ok, so i have changed the JSFiddle a bit, now it uses a fadeIn on a invisible element when it comes into view: http://jsfiddle.net/LHrkB/2/
Ok, i changed the JSFiddle once again. When you scroll in the results pane, and you play around with it a bit you can see the element change class as it comes on screen and also when it goes away again. I commented the JS so you can see what it does and where it does it. http://jsfiddle.net/LHrkB/4/
Thanks to the help of Veritas87 (who is super awesome), managed to get it all working with the following code:
function isElementVisible(elementToBeChecked)
{
var TopView = $(window).scrollTop();
var BotView = TopView + $(window).height();
var TopElement = $(elementToBeChecked).offset().top;
var BotElement = TopElement + $(elementToBeChecked).height();
return ((BotElement <= BotView) && (TopElement >= TopView));
}
$(window).scroll(function () {
isOnView = isElementVisible(".about-icon");
if(isOnView){
//What to do when element is visible
$('.about-icon').addClass('about-icon-active');
}else{ // If not visible
$('.about-icon').removeClass('about-icon-active');
}
isOnView = isElementVisible(".works-icon");
if(isOnView){
//What to do when element is visible
$('.works-icon').addClass('works-icon-active');
}else{ // If not visible
$('.works-icon').removeClass('works-icon-active');
}
isOnView = isElementVisible(".services-icon");
if(isOnView){
//What to do when element is visible
$('.services-icon').addClass('services-icon-active');
}else{ // If not visible
$('.services-icon').removeClass('services-icon-active');
}
isOnView = isElementVisible(".process-icon");
if(isOnView){
//What to do when element is visible
$('.process-icon').addClass('process-icon-active');
}else{ // If not visible
$('.process-icon').removeClass('process-icon-active');
}
});
with the "...icon-active" classes of course containing the style for the icon hover states.

HTML javascript bookmark user viewing position

I have a html webpage. It contains a very long text passage.
User can use internet browser to read the passage. Since the passage is long, users need to scroll the page to read the whole passage.
I would like to add a floating box button for user to click. After clicking the button, I can capture the current viewing portion of the passage.
So that users can log in later and continue reading.
I think I need to add some javascript, but after hours of online searching, I failed to find relevant information.
Please kindly suggest the possible solution to do so?
Use a position:fixed box/button. Clicking it stores (or updates, if it already exists) a localStorage item or cookie with the current position. On page load, if that item exists, ask the user if they want to return to that spot.
There are two ways of doing this:
Save position as a pixel value. This works perfectly if the user's display will not change size (switching computers, switching monitors, changing screen resolution setting, etc.). However, if any of those changes do occur, the absolute pixel value of the saved position is not consistent with the position on the page.
Demo. To run: click "Save position", scroll anywhere, then reload the page.
Save position as a percentage of total height. This works exactly as solution (1), but handles all cases in which screen size changes as well. (Use this one.) The code provided below pertains to this solution.
Demo. To run: click "Save position"; change the width of the "Result" quadrant; without changing any code, click "Run" again.
The saved item is removed regardless of the user's choice (to return to the last spot or not), so that the prompt doesn't show up every time the page is reloaded (which can get annoying).
This is pure JS; it's very modular; it demonstrates simple usage of localStorage and falls back gracefully to cookies.
HTML
<div id="save">
<button id="saveButton">Save position</button>
<span id="saved">Saved!</span>
</div>
<div id="content">
<!-- Disgustingly long content -->
</div>
CSS
#save {
position:fixed;
top:30px;
left:10px;
width:20%;
}
#saved {
visibility:hidden;
color:green;
}
#content {
width:60%;
margin:auto;
}
JS
function checkStorageSupport() {
var test = "test";
try {
localStorage.setItem(test, test);
localStorage.removeItem(test);
return true;
} catch(e) {
return false;
}
}
function getTotalHeight() {
return document.body.clientHeight;
}
function getSavedPercent() {
var percent = storageSupported ? loadFromStorage() : loadFromCookie();
return (percent == null || percent == "") ? 0 : percent;
}
/******* Save *******/
function saveInStorage() {
localStorage.setItem("scrollPercent", (document.documentElement.scrollTop / getTotalHeight()));
}
function saveCookie() {
var expDate = new Date();
expDate.setDate(expDate.getDate() + 7); // start over if it's been more than ___ days
document.cookie = "scrollPercent=" + (document.documentElement.scrollTop / getTotalHeight())
+ "; " + expDate;
}
/******* Load *******/
function loadFromStorage() {
return localStorage.getItem("scrollPercent");
}
function loadFromCookie() {
return document.cookie.replace(/(?:(?:^|.*;\s*)scrollPercent\s*\=\s*([^;]*).*$)|^.*$/, "$1");
}
/******* Remove *******/
function removeFromStorage() {
localStorage.removeItem("scrollPercent");
}
function removeCookie() {
document.cookie = "scrollPercent=''";
}
/******* Handler *******/
var saveButton = document.getElementById("saveButton"),
saved = document.getElementById("saved");
saveButton.onclick = function() {
storageSupported ? saveInStorage() : saveCookie();
saved.style.visibility = "visible";
setTimeout(function() {
saved.style.visibility = "hidden";
}, 1500);
};
/******* Logic *******/
var storageSupported = checkStorageSupport(),
percent = getSavedPercent();
if (percent > 0) {
if (confirm("Would you like to continue reading where you left off?")) {
document.documentElement.scrollTop = percent * getTotalHeight();
}
storageSupported ? removeFromStorage() : removeCookie();
}
Note: to get back to the code that produces solution (1), copy the code from that demo. In the case JSFiddle goes down, here are manual instructions:
Remove every instance of / getTotalHeight() in a "Save" function
In the "Logic" section, replace position * getTotalHeight() with position
Remove getTotalHeight(), since it's not used
Replace instances of "percent" with "position" to be more semantically accurate
Basic idea is..
create a floating bookmark button on the page like:
#mybookmark{
position: fixed;
top:30px;
right:0;
}
Now in jquery.. retrieve the position of this floating bookmark when clicked on it..
$('#mybookmark').click(function(){
var bookmark_loc = $('#mybookmark').offset().top();
});
Store this bookmark_loc data in your preferred storage for the user.
then when they clicks on a button, you can scroll to the stored offset value in your storage.. in jquery
$('#scroll_to_bookmark').click(function{
var bookmark_loc = //Fetch bookmark
$('body').animate({ scrollTop: bookmark_loc; });
});

Categories