HTML\CSS\JavaScript: How can I build a menu dynamically? - javascript

I am using the W3.CSS animated drop-down (https://www.w3schools.com/w3css/w3css_dropdowns.asp).
But I cannot figure out how can I populate the menu items dynamically according to a list of item names.
I guess some Javascript should be involved here, so I try in this forum 🙂
<link rel="stylesheet" href="https://www.w3schools.com/w3css/4/w3.css">
<div class="w3-dropdown-click">
<button onclick="showMenu()" class="w3-button">Team1</button>
<div id="Demo" class="w3-dropdown-content w3-bar-block w3-animate-zoom">
Link 1
Link 2
Link 3
</div>
</div>
<script>
async function getTeams() {
try{
(async () => {
const response = await fetch('http://localhost:8088/teams')
var teamsArrObj = await response.json()
console.log(teamsArrObj);
return teamsArrObj;
})()
}catch{
console.log("error");
}
}
function showMenu() {
var x = document.getElementById("Demo");
if (x.className.indexOf("w3-show") == -1) {
x.className += " w3-show";
} else {
x.className = x.className.replace(" w3-show", "");
}
}
</script>
Thanks!

Assuming that you're using a regular js array of text, you can loop over that array and insertAdjacentHTML into the dropdown.
for (let text of /*insert array name here*/) {
document.getElementById('Demo').insertAdjacentHTML('beforeend', `${text}`
Here we use the modern for...of loop, and do insertAdjacentHTML. Check the MDN docs if you are not familiar with the function. We also use the ES6 template strings to insert.

Because W3 Schools has so much wrong in their demo that you've linked to, I've recreated their example (the right way) and shown how the CSS would be done (instead of relying on their pre-made CSS that you don't get to see).
You'll note that the actual hiding/showing of the menu is accomplished with a single line of JavaScript instead of all that outdated string related stuff that W3 Schools uses.
And, you'll see how you can dynamically load the menu items from an array of object data.
<!DOCTYPE html>
<html>
<head>
<title>W3.CSS</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
button {
background-color:black;
color:white;
padding:5px;
border:none;
font-size:1.1em; /* 10% bigger than normal */
}
#Demo {
position:relative;
box-shadow:0 0 20px #808080;
padding:6px;
margin-top:3px;
height:auto;
width:75px;
transform-origin: center; /* Make effect work from center outward */
transition:all .5s; /* Make changes to all CSS happen over 1 second */
}
/* The style of the menu when it's hidden */
#Demo.hidden {
transform:scale(0,0); /* Scale it to 0 by 0 pixels */
}
.menuItem {
display:block; /* Each item on its own line */
text-decoration:none; /* no underline on the links */
padding:3px;
font-family:Arial;
}
.menuItem:hover {
background-color:#e0e0e0;
}
</style>
</head>
<body>
<div>
<h1>Animated Dropdown</h1>
<div class="w3-dropdown-click">
<button>Click me</button>
<div id="Demo" class="hidden"></div>
</div>
</div>
<script>
let items = [
{ text: "Link 1", path: "https://example.com"},
{ text: "Link 2", path: "https://hbo.com"},
{ text: "Link 3", path: "https://cbs.com"},
];
const demo = document.getElementById("Demo");
// Loop over the items array
items.forEach(function(item){
// Create a new anchor element and configure it:
let link = document.createElement("a");
link.classList.add("menuItem");
link.href = item.path;
link.textContent = item.text;
// Append the new link to the menu
demo.appendChild(link);
});
document.querySelector("button").addEventListener("click", function(){
demo.classList.toggle("hidden"); // Toggle the display of the menu
});
</script>
</body>
</html>

Related

How to make sure every div of a class has the same amount of a specific element?

ok,maybe its my noobness,but i cant wrap my head around this particular problem
In this test we have a button with id #add-div which purpose is to append the same div with class .container to body on every click.
We also have another button with id #add-boxes which purpose is to append a red box with class .redbox to every div with the .container class.
the .container div has a button inside which does the same thing as the #add-boxes button.
Lets say we have a scenario where we throw a couple of divs there,and we also fill them with 2 boxes each like this :
and then we add another div which is empty like this :
what is the logic i should follow to make sure the new div will appear with the same amount of red boxes inside it as the previous ones like this : ?
snippet to visualize my concept :
$(document).on('click', '#add-div', function () {
$("body").append("<div class=containers><button>ADD BOXES</button></div>")
});
function redBoxObj(){
var box = document.createElement("div");
box.className = "redbox"
return box
}
$(document).on('click', '.containers button,#add-boxes', function () {
$(".containers").each(function(){
$(this).append(redBoxObj())
});
});
*{
box-sizing: border-box;
margin:2px;
}
button{
position:relative;
float:left;
clear:both;
}
.containers{
position:relative;
float:left;
padding:3px;
border: 1px solid black;
background-color:lightcyan;
clear:both;
}
.redbox{
position:relative;
float:left;
border:none;
width:30px;
height:30px;
background:red;
}
<!DOCTYPE html>
<html>
<head>
<script src="https://code.jquery.com/jquery-3.1.0.js"></script>
</head>
<body>
<button id="add-boxes">ADD BOXES</button><button id="add-div">ADD DIV</button>
</div>
</body>
</html>
What you need to do is cloning the existing "container div" when there is one, like this:
$(document).on('click', '#add-div', function() {
if ($('.containers').length) {
$("body").append($('.containers').first().clone());
} else {
$("body").append("<div class=containers><button>ADD BOXES</button></div>")
}
});
I created a fiddle for you:
https://jsfiddle.net/adamcai/y3ekjzLs/2/

Tabulator rendering issue using responsive layout

ISSUE:
Everything pretty much works if I stick to layout: "fitColumns" anything else I try seems to result in rendering (if that is the correct term) issues. I am not using a framework (a bridge too far in the timeframe). When the table is displayed after the page is fully loaded, regardless of the layout I choose - it always starts off displaying as it would for "fitColumns". If I set it to "fitDataFill" for example, it loads and displays as for "fitColumns". When I click to another tab and back again
it then displays the data as it should for fitDataFill.
REVISED:
Rough order of steps:
Load a specific file which contains meta data about the rest of the files to load into tables, the names of those tables, the columns in each table and the text to display as float over help on the column headers
Load the rest of the data and build the table config object which contains the meta data
Add a table specific div for each table and append to the csv-tab-buttons div
Build the table on the newly created div
Add the button which will toggle which table gets display via the css active class and the setTab function
The setTab function includes two redraws (to be sure, to be sure).
If you see code that resembles something you wrote here then thanks to you, much of what I wrote I gleaned from others.
Tabulator version is 4.8
Code is created using Visual Studio Code using the Live Server extension to reload the page after every save
Browser is Chrome Version 85.0.4183.121 (Official Build) (64-bit)
I rewrote based on the suggestions of #mirza to ensure the data is read in entirely before the tables are built and each table is stored independently of the others so I don't pass the same table to setTab every time
fitColumns works but does not allow me to resize columns individually (which may be by design)
fitData seems to work ok
fitDataFill and fitDataStretch do not work on the first render, or subsequent renders of the same table until I click away and back again
I have attempted to follow the logic in the tabulator.js via the debugger and although I can see what is happening, there is way too much going on in there for me to grasp where the issue might be
HTML:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<!-- CSS -->
<link rel="stylesheet" href="./scripts/dist/css/tabulator.min.css">
<link rel="stylesheet" href="./styles/style.css">
<!-- Scripts -->
<script type="text/javascript" src="./scripts/dist/js/tabulator.min.js"></script>
<script type="text/javascript" src="./scripts/dist/js/papaparse.min.js"></script>
<title>My Team</title>
</head>
<body>
<!-- Wrapper -->
<div class="wrapper">
<section class="container">
<!-- Header -->
<header id="header" class="header">
<h1>Reporting</h1>
</header>
<!-- Tabs -->
<div id="csv-tab-buttons" class="tab">
</div>
<!-- Tables on each tab -->
<div id="csv-tabs">
</div>
<!-- Footer -->
<footer class="footer">
<p>My Team © 2020</p>
</footer>
</section>
</div><!-- Wrapper Ends-->
<script src="./scripts/dist/js/miscsv.min.js"></script>
</body>
</html>
REVISED Javascript:
//*******************************************************************************************************
// Global variables
//*******************************************************************************************************
var file = 'DS.PPTE.DB2.VIARACF.VARLEGND.CSV'
var tables = []
var tableDivs = []
var tabConfig = {}
//*******************************************************************************************************
// Global functions
//*******************************************************************************************************
let onlyUnique = (value, index, self) => {
return self.indexOf(value) === index
}
//*******************************************************************************************************
// Async functions
//*******************************************************************************************************
// Set the tab to whichever button was clicked
async function activateTab(target) {
// hides all tabs
document.querySelectorAll(".tabcontent").forEach(tabContent => tabContent.style.display = "none");
// Remove the active class from all tab links
document.querySelectorAll('.tablinks').forEach(tabLink => tabLink.className.replace("active", ""));
// Remove the active class from the active tab
document.querySelectorAll(".active").forEach(activeTab => activeTab.classList.remove("active"))
// Activate the selected tab
document.querySelector(`#${target.textContent}`).style.display = "block"
target.classList.add("active");
}
async function setTab(target) {
console.log("Activate the tab")
await activateTab(target)
console.log("Redraw the table")
// Redraw the table
tableDivs[`${target.textContent}`].redraw(true);
}
// Read a CSV file
const readCSV = async (file) => {
return new Promise(resolve => {
Papa.parse(`data/${file}`, {
header: true,
download: true,
skipEmptyLines: true,
complete: results => {
console.log(`${file} loaded - ${results.data.length} records.`)
resolve(results)
}
})
})
}
// Get all the data first
async function getData() {
// Read the meta data file with the data and table config
let parseMeta = await readCSV(file)
tabConfig = {
// Get the names of the tables to present
tabs: parseMeta.data.map((data) => data['TABLE-NAME']).filter(onlyUnique).sort(),
// Find the file name for each table
files: parseMeta.data.map((data) => `${data['TABLE-NAME']}-${data['CSV-FILE-NAME']}`).filter(onlyUnique)
.map((entry) => {
let tmpEntry = entry.split('-')
return { table: `${tmpEntry[0]}`, file: `${tmpEntry[1]}` }
}),
// Save the float over help for each column by table name
help: parseMeta.data.map((data) => {
return { key: `${data['TABLE-NAME']}-${data['VARIABLE']}`, helpText: data['VAR-DESCRIPTION'] != '' ? data['VAR-DESCRIPTION'] : data['VARIABLE'] }
}),
data: tables,
divs: tableDivs,
}
// Read in the files which contain the table data
for (const tabName of tabConfig.tabs) {
let file = tabConfig.files.filter(entry => entry.table == tabName)[0].file
tables[tabName] = await readCSV(file)
tableDivs[tabName] = `csv-table-${tabName}`
}
}
// Master function to do everything in the right order
async function doAll() {
// Get all the data and build the table config
await getData()
// Store the buttons and tabs anchor divs
let buttonsDiv = document.getElementById("csv-tab-buttons")
let tabsDiv = document.getElementById("csv-tabs")
// Add the buttons and tables
for ([idx, tabName] of tabConfig.tabs.entries()) {
// Add tabs to hold the tables to the page
const elemTabDiv = document.createElement('div')
const elemTableDiv = document.createElement('div')
elemTabDiv.id = tabName
elemTabDiv.className = "tabcontent"
elemTableDiv.id = `csv-table-${tabName}`
elemTableDiv.className = "table"
elemTabDiv.appendChild(elemTableDiv)
tabsDiv.appendChild(elemTabDiv)
// Define header context menu
let headerMenu = [
{
label:"Hide Column",
action:function(e, column){
column.hide()
},
},
]
// Create the table
tableDivs[tabName] = new Tabulator(`#csv-table-${tabName}`, {
data:tabConfig.data[tabName].data,
layout:"fitData",
responsiveLayout:"collapse",
tooltips:true,
pagination:"local",
paginationSize:20,
resizableColumns:true,
movableColumns:true,
resizableRows:true,
autoColumns: true,
autoColumnsDefinitions: function(definitions) {
definitions.forEach((column) => {
let helpText = tabConfig.help.find(key => key.key === `${tabName}-${column.field}`).help
// Add float over help based on column name
column.headerTooltip = helpText
column.headerMenu = headerMenu
column.headerFilter = true
column.headerSort = true
column.headerFilterLiveFilter = false
})
return definitions
},
renderStarted:function(){
console.log("Render started")
},
renderComplete:function(){
console.log("Render complete")
},
})
// Add tab buttons to page
const elemTabButton = document.createElement('button')
elemTabButton.id = `button-${tabName}`
if ( idx == 0 ) {
elemTabButton.className = "tablinks active"
} else {
elemTabButton.className = "tablinks"
}
elemTabButton.onclick = function() { setTab(this) }
elemTabButton.textContent = tabName
buttonsDiv.appendChild(elemTabButton)
}
document.querySelector(".active").click();
}
doAll()
CSS:
:root {
--shadow: 0 1px 5px rgba(104, 104, 104, 0.8);
--raisin: #262730;
--vermillion: #d33f49;
--cadet: #576c75;
--navyboy: #8db2c2;
--space-cadet: #363457;
--baby-powder: #f0f4ef;
--ice: rgb(245, 247, 253);
}
html {
box-sizing: border-box;
font-family: Arial, Helvetica, sans-serif;
color: var(--dark);
}
body {
background: var(--baby-powder);
margin: 10px 10px;
line-height: 1.4;
}
/* .wrapper {
display: grid;
grid-gap: 10px;
} */
.container {
display: grid;
grid-gap: 10px;
grid-template-areas:
'header'
'csv-tab-buttons'
'footer';
margin: auto;
width: 98%;
overflow: auto;
padding: 1rem 1rem;
}
header {
background: var(--raisin);
color: var(--vermillion);
font-size: 150%;
line-height: 1;
padding: 0.1rem;
text-align: center;
box-shadow: var(--shadow);
}
.tab {
background-color: var(--ice);
box-shadow: var(--shadow);
}
/* Style the buttons that are used to open the tab content */
.tab button {
background-color: inherit;
/* float: left; */
border: none;
outline: none;
cursor: pointer;
/* padding: 14px 16px; */
padding: 1rem 1.1rem;
transition: 0.3s;
}
/* Change background color of buttons on hover */
.tab button:hover {
background-color: var(--cadet);
color: var(--ice);
}
/* Create an active/current tablink class */
.tab button.active {
background-color: var(--vermillion);
color: var(--ice);
}
/* Style the tab content */
.tabcontent {
/* overflow: hidden; */
display: none;
/* padding: 6px 12px; */
/* border-top: none; */
}
/* Override Tabulator header background */
.tabulator-col-content {
background-color: var(--ice);
}
.table {
overflow: hidden;
box-shadow: var(--shadow);
}
.footer {
background: var(--cadet);
color: white;
padding: 0rem 2rem;
line-height: 1;
box-shadow: var(--shadow);
}
EDIT:
I made some changes to the order of everything so I could keep the table object in scope when the setTab function is called and I could issue the redraw when the tab button is clicked. The first time I click through every tab it appears to be filling to the width of the data. When I click through each tab again it is properly wrapping columns that would be off screen to the next line. I put multiple table redraws in the setTab routine and it makes no difference to the rendering of the table. It does however change the attributes of the table in some way. I observed in the debugger that tableWidth changed from 0 prior to the first redraw to 2734, the to 2786 after the second redraw and it stayed at the value. If I click away and back again it wraps as expected.
Tabulator table does not properly render if the element is not visible when creating the table.
To properly render the table, you have to redraw the table when the element is visible.
See Here
From the website:
If the size of the element containing the Tabulator changes (and you are not able to use the in built auto-resize functionality) or you create a table before its containing element is visible, it will necessary to redraw the table to make sure the rows and columns render correctly.
You can redraw the table by
table.redraw();
Or
table.redraw(true); //trigger full rerender including all data and rows

how do Replace div to another div from div's it self in Javascript

I have this code and I want to replace every div whenever i click the div
function show(par, param_div_id) {
document.getElementById(par).innerHTML = document.getElementById(param_div_id).innerHTML;
}
<div id="main_place1" style="display:none" onclick="show('main_place1','one')">
main
</div>
<div id=one style="display:none" onclick="show('one','two')">
one
</div>
<div id=two style="display:none" onclick="show('two','three')">
two
</div>
<div id=three style="display:none" onclick="show('three','main_place1')">
three
</div>
the problem is div cannot replace from "one" to "two" or "two" to "three"
it only works from "main_place1" to "one"...
how to make it works??
i need somebody help
Don't set up events with HTML event attributes. Here's why.
Also, don't use inline styles when you can use classes. Classes are reusable and don't clutter up the code. They also are easier to work with in JavaScript.
See comments inline for additional details:
// Get all the div elements to be cycled through into a node list
var divs = document.querySelectorAll(".cycle");
// Loop through each div in the array...
for(let i = 0; i < divs.length; i++) {
// Assign a callback function for the click event of the div
divs[i].addEventListener("click", function(){
divs[i].classList.toggle("hidden"); // Hide the current div
// Check to see if there is another div after the current one
if(i < divs.length -1){
divs[i+1].classList.toggle("hidden"); // Hide the next div
} else {
divs[0].classList.toggle("hidden"); // Hide the first div
}
});
}
/* Everything that should not be seen by default
should have this class set up on it in the HTML */
.hidden { display:none; }
/* Just for fun */
.cycle {
background-color:aliceblue;
font-family:Arial, Helvetica, sans-serif;
font-size:2em;
box-shadow:2px 2px #e0e0e0;
width:50%;
padding:1em;
user-select:none;
cursor:pointer; /* Let user know they can click on the element */
}
<div id="main_place1" class="cycle">main</div>
<div id="one" class="hidden cycle">one</div>
<div id="two" class="hidden cycle">two</div>
<div id="three" class="hidden cycle">three</div>
Now, depending on what the content of each div is supposed to be, it may be simpler to use just one div that is always visible, but upon each click, just replace the contents of that div. The content could be stored in an array. This would not only be simpler in terms of not having to worry about toggling the display of the various div elements, but it would be more efficient.
/* This code should be placed inside of a <script> element that comes
just before the closing body tag (</body>) */
// Content for the div is stored here:
var content = ["main", "one", "two", "three"];
// Get reference to the div that will hold the content
var div = document.querySelector(".cycle");
var contentIndex = 0; // Represents which element in the array is currently displayed
// Initialize the default content of the div
div.textContent = content[contentIndex];
// Assign a callback function for the click event of the div
div.addEventListener("click", function(){
// Increment the contentIndex unless we are at the end of the array
contentIndex = (contentIndex < content.length - 1) ? ++contentIndex : 0;
// Set the content to the appropriate value
div.textContent = content[contentIndex];
});
/* Just for fun */
.cycle {
background-color:aliceblue;
font-family:Arial, Helvetica, sans-serif;
font-size:2em;
box-shadow:2px 2px #e0e0e0;
width:50%;
padding:1em;
user-select:none;
cursor:pointer; /* Let user know they can click on the element */
}
<div id="main_place1" class="cycle"></div>

jquery failing to update background-color css

I have a grid generator, it uses Javascript and jQuery to generate blocks in a grid that are displayed with HTML and CSS. I am trying to set up a button that will change the :hover behavior of the blocks (specifically, change their background-color). I am unable to do this and I'm not sure why my code is not working. I will copy and paste it here and I apologize that it is very long. You can see it in action here: http://codepen.io/anon/pen
HTML
<html>
<head>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js">
</script>
<script type="text/javascript" src="script.js"></script>
<title> Odin #2 by Max Pleaner </title>
<link rel="stylesheet" type="text/css" href='stylesheet.css'>
</head>
<body>
<p> Welcome to my Odin Project #2 page. This is me showing off my basic JS and jQuery skills. If you move your mouse through the blocks you can see frogs come out of hiding. If you press the clear button below you can select a new number of blocks to fill the same space.</p>
<button id="button"> Generate a number of blocks of your liking that will position themselves to all fit in the 960px by 960px grid. </button>
<button id="button2"> <strike> Click here to generate new blocks and make hovering on blocks produce random colors.</strike> Why isn't this button working?! It's drawing new blocks fine, but not changing the :hover style as intended. </button>
<div id="square_holder">
</div>
<img src="Q6w802v.jpg" alt="froggy" ></img>
</body>
</html>
CSS
body {
background-color: grey;
}
p {
color: aqua;
}
#square_holder {
width: 960px;
}
.block {
background-color: green;
display:inline-block;
border: 1px solid black;
width: 232px;
height: 232px;
}
.block:hover {
background-color: blue;
//background-image:url("Q6w802v.jpg");
background-size: contain;
}
JS
$(document).ready(function(){
draw_grid(4);
$('#button').click(function(){
get_input();
});
$('#button2').click(function(){
get_input();
$('.block:hover').css("background-image", "none").css("background-color", get_random_color());
});
});
var draw_grid = function (blocks) {
var totalno = Math.pow(blocks, 2);
var dimension = (960 - 1 -(blocks * 2))/blocks;
for(var i = 0; i < totalno; i++){
$("#square_holder").append("<div class='block' id=" + i + "></div>");
};
$(".block").css("height", dimension).css("width", dimension);
}
var get_input = function(){
alert('Do you want to change the number of boxes?<b></b>');
$('#square_holder').empty();
var user_entry = prompt("What number do you choose?");
alert("Watch in awe as the grid fills ..... ");
draw_grid(user_entry);
}
var get_random_color = function() {
var letters = '0123456789ABCDEF'.split('');
var color = '#';
for (var i = 0; i < 6; i++ ) {
color += letters[Math.round(Math.random() * 15)];
}
return color;
};
You need to use background, not background-color. Taken from the MDN page for background-image:
The CSS background-image property sets one or several background images for an element. The images are drawn on successive stacking context layers, with the first specified being drawn as if it is the closest to the user. The borders of the element are then drawn on top of them, and the background-color is drawn beneath them.
This translates into a declaration of background-image at all (even as none) will sit on top of background-color. Therefore, if you set background instead of background-color, it will supercede all other property-specific declarations.

Change menu ul style while arriving to a div

the code I'm searching for is very simple, simply I have divs and menu and I want that when I arrive to the first div by scrolling, the first ul in menu change its style automatically, then when I scroll to the second div the second url style change to another style, and like that... I got the answer for my question and I have the code but I don't like it because it's very tall and it contain codes for every div I got.
As I know I can find ONE short code that does the job for the WHOLE divs in jQuery.
What I want is exactly as in this code(I'm not able to let it work through http://jsfiddle.net/ if anybody knows how to load jquery there please load it and give me the url)
<html>
<style>
#menu {
background-color:#ccc;
position:fixed;
width:100%;
}
.menutext {
padding:25 40 30 !important;
display:inline-block;
}
.menutext2 {
padding:25 40 0 !important;
display:inline-block;
color:red;
}
.alldivs {
width:300px;
height:200px;
background-color:a9a9a9;
}
</style>
<div id="menu">
<div class="menutext" linkId="DIV1">Change the style of me to .mebutext2 on arriving to DIV1</div>
<div class="menutext" linkId="DIV2">Change the style of me to .mebutext2 on arriving to DIV2</div>
<div class="menutext" linkId="DIV3">Change the style of me to .mebutext2 on arriving to DIV3</div>
</div>
<br><br><br><br><br><br><br>
<div class="alldivs"><div class="contentDiv" id="DIV1">DIV1</div></div>
<br><br><br><br><br><br><br><br>
<div class="alldivs"><div class="contentDiv" id="DIV2">DIV2</div></div>
<br><br><br><br><br><br><br><br>
<div class="alldivs"><div class="contentDiv" id="DIV3">DIV3</div></div><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.min.js"></script>
<script>
$(function(){
var menu=$('#menu'),
menuText=menu.find('.menuText'),
DIV1=$('#DIV1'),
DIV2=$('#DIV2'),
DIV3=$('#DIV3'),
DIV1Top=DIV1.offset().top,
DIV2Top=DIV2.offset().top,
DIV3Top=DIV3.offset().top;
$(window).scroll(function(e) {
var win=$(this),
scrollTop=$(this).scrollTop();
//to make nav menu selected according to scroll
var start=scrollTop;
menuText.filter('.menutext2').removeClass('menutext2').addClass('menutext');
if(start>DIV3Top){
menuText.filter('[linkId="DIV3"]').removeClass('menutext').addClass('menutext2');
}
else if (start>DIV2Top){
menuText.filter('[linkId="DIV2"]').removeClass('menutext').addClass('menutext2');
}
else if(start>DIV1Top){
menuText.filter('[linkId="DIV1"]').removeClass('menutext').addClass('menutext2');
}
});
});
</script>
Something like this :
$(function(){
var offsets = [],
menuText = $('#menu .menuText');
$("div.contentDiv").each( function(i, div) {
offsets.push({ id: div.id, offset: $(div).offset().top });
});
$(window).scroll(function(e) {
var start = $(this).scrollTop();
for ( var div = 0; div < offsets.length; div++ ) {
if ( start > offsets[div].offset ) {
menuText.removeClass('menutext2').addClass('menutext');
menuText.filter('[linkId="'+offsets[div].id+'"]').addClass('menutext2').removeClass('menutext');
}
}
if ( start === 0 ) { menuText.removeClass('menutext2').addClass('menutext'); }
});
});
http://jsbin.com/ijiwom/2/edit
EDIT :
http://jsbin.com/ijiwom/3/edit
EDIT 2 :
http://jsbin.com/ijiwom/4/edit
EDIT 3 :
http://jsbin.com/ijiwom/5/edit
dringchev gave you a working example.
what you are describing is sometimes called a "scroll spy", for example here in bootstrap:
http://twitter.github.io/bootstrap/javascript.html#scrollspy
you could also implement it using jquery waypoints
http://imakewebthings.com/jquery-waypoints/
See https://ux.stackexchange.com/questions/17375/what-is-the-navigation-concept-bootstrap-uses-called for a discussion of this UX pattern

Categories