start with active menu item javascript - javascript

Hi I'm new and not sure if I'm doing this correctly.
I use Javascript that will decorate an active link after it's been clicked.
Question is, how can I load the page with one of the menu items already active?
Example: http://moschalkx.nl/
Javascript code:
function hlite_menu(obj){
var lnk=document.getElementById('menu').getElementsByTagName('A');
for(var i in lnk){
lnk[i].className=(lnk[i]===obj)?'menu_active':'menu_idle';
}
}
function set_menu(){
var lnk=document.getElementById('menu').getElementsByTagName('A');
for(var i in lnk){
lnk[i].className='menu_idle';
lnk[i].onclick=function(){
hlite_menu(this);
}
}
}
window.onload=set_menu;
CSS:
a.menu_idle {color:#333333; text-decoration:none;}
a.menu_active {color:#333333; text-decoration:underline;}
a:visited {color:#333333; text-decoration:none;}
a:hover {color:#333333; text-decoration:underline;}

You already have your hlist_menu function that sets a particular link to be active, so I would just call that from your set_menu function for whichever link is supposed to be active to begin with
function set_menu(){
var lnk=document.getElementById('menu').getElementsByTagName('A');
for(var i in lnk){
lnk[i].className='menu_idle';lnk[i].onclick=function({hlite_menu(this);}}
if (lnk[i] /* ??? how do you know whether this is the link to activeate up front? */ ) {
hlist_menu(lnk[i]);
}
}
Also, this
lnk[i].onclick=function({hlite_menu(this);}}
can be simplified to just
lnk[i].onclick = hlite_menu;
assuming you change it to
function hlite_menu(){
var lnk= document.getElementById('menu').getElementsByTagName('A');
for(var i in lnk){
lnk[i].className = (lnk[i] === this) ? 'menu_active':'menu_idle';
}
}

Related

Javascript - Deleting a list item

How do you properly delete list item by clicking on it?
I have been using the following line for code to delete an item but instead this deletes the entire list itself:
var list = document.getElementById("shoppinglist");
list.onclick = function() { list.parentNode.removeChild(list);}
I have been searching online on how to do this and the same kind of code keeps appearing and I am not sure how to solve this. I assumed that the list item generated was a child of the "shoppinglist".
I am very new to Javascript and I know this is a rookie mistake but I would really appreciate any help. Thank you.
<!doctype html>
<html dir="ltr" lang="en-gb">
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<style>
body {
/* Sets the width then uses the margin auto feature to centre the page in the browser */
width:800px;
margin: 0px auto; /*0px top/bottom auto left/right */
font-size:10px; /* By default fonts are usually 16px but may not be in some browsers */
}
p, li {
font-size:1.5em; /* Set all text to be 1.5 * overall font size = 15 pixels */
}
section {
/* each of the two sections will use just under half the width of the width of the body */
width:395px;
display:block;
}
#choices {
/* float the choices list to the left of the page */
float:left;
background-color: #FFFF99;
}
#cart {
/* float the shopping cart to the right of the page */
float:right;
background-color: #7FFF00;
}
.cartlist {
/* Simplify the display of the lists, removing default bullet points and indentation */
list-style-type:none;
margin:0px;
padding:0px;
width:inherit;
}
.cartlist li {
/* Set each list item to be 2* the height of the text */
height:2em;
}
.cartlist li:nth-child(odd) {
/* Colour odd list items ie first, third, fifth etc, a different colour */
background-color:#eee;
}
#outputinfo {
/* prevents the DIV from joining the floating behaviour so it displays below the lists */
clear:both;
}
</style>
</head>
<body>
<section id="choices">
<p>Available Choices</p>
<ul id="sourcelist" class="cartlist">
<li data-value="2.99">£2.99 : Chocolate</li>
<li data-value="3.49">£3.49 : Cereal</li>
<li data-value="0.98">£0.98 : Milk</li>
<li data-value="0.89">£0.89 : Bread</li>
<li data-value="3.79">£3.79 : Coffee</li>
<li data-value="2.53">£2.53 : Strawberries</li>
<li data-value="3.89">£3.89 : Cheesecake</li>
</ul>
</section>
<section id="cart">
<p>Shopping Cart</p>
<ul id="shoppinglist" class="cartlist"></ul>
</section>
<div id="outputinfo">
<p><button id="calctotal">Calculate Total</button> : <span id="totalresult"></span></p>
</div>
</body>
<script>
function getTargetElement(e) {
var targetelement=null;
targetelement=(e.srcElement || e.target || e.toElement)
return targetelement;
}
function calcTotal() {
var shoppinglist=document.getElementById("shoppinglist");
var total=0;
for(i=0;i<shoppinglist.children.length;i++) {
total+=parseFloat(shoppinglist.children[i].getAttribute("data-value"));
}
var totalresult=document.getElementById("totalresult");
totalresult.innerHTML="£"+total.toFixed(2);
}
function handleEvent(e) {
var listclicked=getTargetElement(e);
var newlistitem=document.createElement("li");
var datavalue=listclicked.getAttribute("data-value");
newlistitem.setAttribute("data-value",datavalue);
newlisttext=document.createTextNode(listclicked.innerHTML)
newlistitem.appendChild(newlisttext);
var shoppinglist = document.getElementById("shoppinglist");
shoppinglist.appendChild(newlistitem);
var list = document.getElementById("shoppinglist");
list.onclick = function() { list.parentNode.removeChild(list);}
console.log(listclicked);
}
function removeItem(e){
var listclicked=getTargetElement(e);
var node = document.getElementById('shoppinglist');
listclicked.parentNode.removeChild(listclicked);
}
document.onreadystatechange = function(){
if(document.readyState=="complete") {
var sourcelist=document.getElementById("sourcelist");
for(i=0;i<sourcelist.children.length;i++) {
if(document.addEventListener) {
sourcelist.children[i].addEventListener("click", handleEvent, false);
} else {
sourcelist.children[i].attachEvent("onclick", handleEvent);
}
var totalbutton=document.getElementById("calctotal");
if(document.addEventListener) {
totalbutton.addEventListener("click",calcTotal,false);
} else {
totalbutton.attachEvent("onclick",calcTotal);
}
}
}
}
</script>
</html>
You don't want to remove the entire list, just the clicked LI element.
As you don't seem to have nested elements, event delegation becomes a little easier
var list = document.getElementById("shoppinglist");
list.addEventListener('click', function(evt) {
list.removeChild(evt.target);
},false);
FIDDLE
For the future, if you wanted nesten elements, you could use element.closest()
var list = document.getElementById("shoppinglist");
list.addEventListener('click', function(evt) {
var p = evt.target.closest('li');
list.removeChild(p);
}, false);
Note the somewhat lacking support in older browsers for closest(), but there are several polyfills available if needed.
Also note that you're binding event handlers inside event handlers, which is a big no-no, your code does the equivalent of
var sourcelist = document.getElementById("sourcelist");
for(i = 0; i < sourcelist.children.length; i++) {
sourcelist.children[i].addEventListener("click", handleEvent, false);
...
// and then
function handleEvent(e) {
var list = document.getElementById("shoppinglist");
list.addEventListener('click', function(evt) {
list.removeChild(evt.target);
},false);
....
so every time you add another list item to the list, you bind a new event handler, and it adds up, but you only need one single event handler, having multiple event handlers will just try to remove the same element over and over again, but it's removed the first time.
list.onclick = function() { list.parentNode.removeChild(list);}
list is the whole list (<ul id='list'>). You're listening for a click on the whole list. Then grabbing the whole list's parent node with list.parentNode ( which gives you <section id="cart">) and deleting the list from it.
Your code is doing exactly what you told it to do.
Like this:
list.removeChild(list.childNodes[indexToRemove])
You need to specify what node to remove. You can test this in chrome by opening up the console and pasting the following:
var list = document.getElementById("shoppinglist");
console.log('List:', list)
console.log('List children:', list.childNodes)
var indexToRemove = 0;
list.removeChild(list.childNodes[indexToRemove]);
console.log('List:', list)
console.log('List children:', list.childNodes)
You can use this:
var list = document.getElementById("shoppinglist");
list.onclick = function(e) { e.target.parentNode.removeChild(e.target);}
You can read more about target and currentTarget and checkout this example http://fiddle.jshell.net/hidoos/Lpz917vo/

does javascript remove event listeners?

On a test webpage I have, there is a link like so:
HOME
The style for it is like so:
nav > a {
text-decoration: none;
color: #0000aa;
display: inline-block;
width: 80px;
padding: 0 10px;
}
nav > a:hover {
background-color: #eeeeee;
}
and switchf() (switch field) is like so:
function switchf(field,tab) {
document.getElementById("home").style.display = "none";
document.getElementById("about").style.display = "none";
document.getElementById("account").style.display = "none";
document.getElementById("contact").style.display = "none";
document.getElementById("t1").style.backgroundColor = "#dddddd";
document.getElementById("t2").style.backgroundColor = "#dddddd";
document.getElementById("t3").style.backgroundColor = "#dddddd";
document.getElementById("t4").style.backgroundColor = "#dddddd";
document.getElementById(field).style.display = "inline-block";
tab.style.backgroundColor = "#cccccc";
}
The link basically acts as a tab, to show a different thing. There are three others like it.
The JavaScript works fine switching tabs, but when I hover over a tab after I've used switchf(), it doesn't change color anymore.
Is there something wrong with my code?
thanks.
EDIT
this is how I fixed mine:
first, I added class="tab" to all the links, so they looked like this:
HOME<br />
second, I changed the javascript so that the function switchf() was like this:
function switchf(field,tab) {
document.getElementById("home").style.display = "none";
document.getElementById("about").style.display = "none";
document.getElementById("account").style.display = "none";
document.getElementById("contact").style.display = "none";
var t = document.getElementsByClassName("tag"); // here is different
for(var i = 0; i < t.length; i++) {
t[i].style.backgroundColor = "#dddddd";
t[i].addEventListener("mouseover");
t[i].addEventListener("mouseout");
}
document.getElementById(field).style.display = "inline-block";
tab.style.backgroundColor = "#cccccc";
}
and it worked.
Inline CSS takes precedence over stylesheets. Once you click on a link, it will set the background-color property for all links, hence all links will not change color when you hover over it.
A better alternative than hard-coding the style in your elements, you can try adding a CSS class to your links (like page-active) and style those elements as needed.
Yet another alternative that saves you from clearing old classes is adding a class or ID to the page and use that to hide/show links as needed.
<style>
nav > a {
display: none;
}
#page-about nav > a#link-home {
display: inline-block;
}
<body id="page-about">
<nav>
Home
About
</nav>
</body>
This should give you a general idea, polishing it is an exercise for the reader.

Show hide multiple tables

I was wondering if someone could help me out with a command;
If have the following script:
<script type="text/javascript">
function show_table(id){
document.getElementById('table1').style.display='none';
document.getElementById('table2').style.display='none';
document.getElementById('table3').style.display='none';
document.getElementById('table4').style.display='none';
document.getElementById('table6').style.display='none';
document.getElementById('table'+id).style.display='block';
}
</script>
And it shows the tables just fine that I have, but now I want to use a command to open two tables at the same time, so with one click on the below reference link;
Table6
Is it possible to use it with a double onclick="" command? I would like to open as example table(6) and table(2). What should I write? By the way I can only use javascript, no PHP.
I tried something like this, but is does not do the job
Table6 and Table2
Try this version, which can take a number or an array:
function show_table(id) {
var ix;
for (ix = 1; ix <= 6; ++ix) {
document.getElementById('table' + ix).style.display='none';
}
if (typeof id === "number") {
document.getElementById('table'+id).style.display='block';
} else if (id && id.length) {
for (ix = 0; ix < id.length; ++ix) {
document.getElementById('table'+ix).style.display='block';
}
}
}
Then you can say show_table([1, 2]) instead of just show_table(1).
function show_table(ids) {
var idArr = ids.split(",");
document.getElementById('table1').style.display='none';
document.getElementById('table2').style.display='none';
document.getElementById('table3').style.display='none';
document.getElementById('table4').style.display='none';
document.getElementById('table6').style.display='none';
for(var i = 0; i< idArr.length; i++) {
document.getElementById('table'+idArr[i]).style.display='block';
}
}
<a href="#" onclick="show_table('6,2')">
If you prefer minimum force aproach, try this:
function hide_all_tables(){
document.getElementById('table1').style.display='none';
document.getElementById('table2').style.display='none';
document.getElementById('table3').style.display='none';
document.getElementById('table4').style.display='none';
document.getElementById('table6').style.display='none';
}
function show_table(id){
document.getElementById('table'+id).style.display='block';
}
And then use the code this way:
Table6 and Table2
I have never used a 'double onclick command' and to be honest don't think they work, or are good practice. Why don't you just house both show table comands in a javascript function and call the function onclick?
If i am understanding you correctly.
You can change them all at once without looping, if the tables have logical associations (they must, right?).
The idea is to assign them a class (or multiple classes) and change the whole class at once:
<script>
function f(classname, show)
{
var mysheet=document.styleSheets[0];
/* Each class in the styleSheet is called a 'rule' */
var myrules=mysheet.cssRules;
var value = show ? '' : 'none'; /* show or hide? */
for (i=0; i<myrules.length; i++){
/* find the class we want to change */
if(myrules[i].selectorText==classname){
/* change the rule */
myrules[i].style.display = value;
}
}
}
</script>
<style type="text/css" >
.hasPets { color: green; display: none; }
.hasCats { font-weight: bold; display: none; }
</style>
​<button onclick="f('.hasPets', true)">Show Pets</button>
​<button onclick="f('.hasCats', true)">Show Cats</button>
​<button onclick="f('.hasPets', false)">Hide Pets</button>
​<button onclick="f('.hasCats', false)">Hide Cats</button>
<div class="hasPets">Pets</div>
<div class="hasCats hasPets">Cats</div>
In this example, Show Pets shows both, Hide Cats hides only Cats. You can't show only Cats -- Pets overrides it.
Note: I've kept this short for clarity. In practice you'll have to add a few more lines because not all versions of IE support the .cssRules property, I think they called it .rules.
This function allows for any number of tables to show.
function show_table(){
for(var i = 1; i < 7; i++) // change 7 to the amount of tables
if(document.getElementById('table'+i))
document.getElementById('table'+i).style.display='none';
for (var i = 0; i < arguments.length; i++)
if(document.getElementById('table'+arguments[i]))
document.getElementById('table'+arguments[i]).style.display='block';
}
To show tables with ids of table3 and table5 then:
show_table(3,5);

Setting CSS color with javascript onclick

Hi i am trying to make my menu link go red when i am on that page and its not working.
Html:
<li><a id="home" onclick="changeClass('home')" href="index.php">Home</a></li>
CSS:
#topMenu li{
display:inline;
margin-right:60px;
font-size:12px;
font-weight:bold;
color:#000;
text-decoration:none;
}
#topMenu li a{
color:#000;
text-decoration:none;
}
#topMenu li a:hover{
color:#666;
text-decoration:underline;
}
.topMenuon{
color:#F00
}
Javascript:
function changeClass(id)
{
var element = document.getElementById(id);
element.className = element.className + ”topMenuon”;
}
Any ideas on how i could get this to work?
You might want to do that server side, but if for some reason you cannot
and you cannot use jQuery:
function changeClass (id) {
var el = document.getElementById(id);
if (el.href == location.pathname) el.className += 'topMenuon';
};
It's simpler to Include Jquery, and do this:
$('#home').on('click',function(){
$(this).addClass('topmenuon');
});
However, it won't work like that if you are going to another page. You must detect what page you are on somehow in javascript/jquery (using something in the url, or using identifier on the page such as the section title), and then add your class while you are on that page (or,do it server side and don't call it at all if server renders directly). Can't use onclick like that if you're leaving the page anyway, new page has no way of knowing if you are doing full postback rather than ajax!
Plain js
window.onload = function(){
document.getElementById("home").onclick = function(){
this.className +=" topMenuon" ;
}
}
Edit
You are probably going to a new page on the click of the link. Hence the above code would not change the class of the link since you are now on a new page.
You may need to add the class to the link using php(i assume you are using it).
Apply as
var element = document.getElementById('home');
element.setAttribute("className", newClass);
function changeClass()
{
var element = document.getElementById('home');
element.className += 'topMenuon';
}
<li><a id="home" onclick="changeClass();" href="#">Home</a></li>
use jquery - this in the <head>...
<script src="yourPath/jquery_1.8.0_min.js" type="text/javascript"></script>
then...
$(document).ready(function(){
$("#home").addClass('topMenuon');
}
that'll do it...
S

Hiding list items with a "show more" button

I have an issue. I am getting data from a MySQL database, and make a list of it. That's all good, and works fine, but the list is now over 100 items long if I don't limit it.
I've tried Googling how to shorten list, and found some things with jQuery and JavaScript, but that didn't work too well.
What I'm looking for is a way to make the list limit itself on 10 items, with a [More] button under it. When pressed, the next 10 items show, and when pressed again, 10 more etc.
I have my list in normal <li> and <ul> bits.
If there's any more information needed, please ask me. This is the webpage it's about: http://lolmewn.nl/stats/
A bit of my PHP code:
echo "<li><a href=\"?player=" . $row['player'] . "\">" . $row['player'] .
"</a></li>\n";
Maybe you can try this. In this example I used 2 items instead of 10. I used css to hide all li elements starting from the 3rd li element inside the ul. I used jQuery to reveal additional 2 lis every time show more is clicked.
Hope this helps
Updated Link Again...
EDIT
$(function () {
$('span').click(function () {
$('#datalist li:hidden').slice(0, 2).show();
if ($('#datalist li').length == $('#datalist li:visible').length) {
$('span ').hide();
}
});
});
ul li:nth-child(n+3) {
display:none;
}
ul li {
border: 1px solid #aaa;
}
span {
cursor: pointer;
color: #f00;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<ul id="datalist">
<li>dataset1</li>
<li>dataset1</li>
<li>dataset2</li>
<li>dataset2</li>
<li>dataset3</li>
<li>dataset3</li>
<li>dataset4</li>
<li>dataset4</li>
<li>dataset5</li>
<li>dataset5</li>
</ul>
<span>readmore</span>
One method is to use ajax to load the list items & restrict them to 10 items using mysql limit.
Otherwise, if you load all at once, you can do the following: (write the code yourself)
Load all of them in a ul and make the display of all none.
Then using jquery eq selector display the first 10 li elements.
on clicking more, just toggle those li which you want to display.
If you want this is pure javascript I made a example on jsfiddle
Javascript
function showMore() {
var listData = Array.prototype.slice.call(document.querySelectorAll('#dataList li:not(.shown)')).slice(0, 3);
for (var i=0; i < listData.length; i++)
{
listData[i].className = 'shown';
}
switchButtons();
}
function showLess() {
var listData = Array.prototype.slice.call(document.querySelectorAll('#dataList li:not(.hidden)')).slice(-3);
for (var i=0; i < listData.length; i++)
{
listData[i].className = 'hidden';
}
switchButtons();
}
function switchButtons() {
var hiddenElements = Array.prototype.slice.call(document.querySelectorAll('#dataList li:not(.shown)'));
if(hiddenElements.length == 0)
{
document.getElementById('moreButton').style.display = 'none';
}
else
{
document.getElementById('moreButton').style.display = 'block';
}
var shownElements = Array.prototype.slice.call(document.querySelectorAll('#dataList li:not(.hidden)'));
if(shownElements.length == 0)
{
document.getElementById('lessButton').style.display = 'none';
}
else
{
document.getElementById('lessButton').style.display = 'block';
}
}
onload= function(){
showMore();
}
HTML
<ul id="dataList">
<li class="hidden">One</li>
<li class="hidden">Two</li>
<li class="hidden">Three</li>
<li class="hidden">Four</li>
<li class="hidden">Five</li>
<li class="hidden">Six</li>
<li class="hidden">Seven</li>
<li class="hidden">Eight</li>
<li class="hidden">Nine</li>
<li class="hidden">Ten</li>
<li class="hidden">Eleven</li>
</ul>
<input id="moreButton" type="button" value="More" onclick="showMore()"/>
<input id="lessButton" type="button" value="Less" onclick="showLess()"/>
CSS
.shown{
display:block;
}
.hidden{
display:none;
}
Have you ever try jquery datatable yet?
Simple solution in pure javascript:
var ul = document.getElementsByTagName("ul")[0], //Your <ul>
readmore = document.createElement("li"),
lisColl = ul.getElementsByTagName("li"),
len = lisColl.length,
lis = [],
pos = 0;
readmore.textContent = "Read more";
for (var i = 0; i < len; i++) {
lisColl[i].style.display = "none";
lis.push(lisColl[i]);
}
readmore.onclick = function () {
if (this.parentNode) {
this.parentNode.removeChild(this);
}
for (var c = 0; pos < len; pos++) {
if ((c++) === 10) {
ul.insertBefore(this, lis[pos + 1]);
break;
}
lis[pos].style.display = "";
}
}
readmore.onclick.call(readmore);
If you want to limit the number of results from the database, add LIMIT 10 (or any number) to the MySQL query.
If you want to actually hide the lists, but leave them available, you will need CSS to initially hide them, and Javascript/Jquery to unhide them. (CSS3 might let you unhide them without Javascript/Jquery, but it isn't fully supported everywhere yet).
Assuming all the list items have the same CSS class then a javascript loop like the following may work:
function unhide(number) {
var items = document.getElementsByClassName('tagnamehere');
var shown=0;
for (var i=0; shown<number && i<items.length; i++) {
if (items[i].style.display=="" || items[i].style.display=="none") {
items[i].style.display="list-item";
shown+=1;
}
}
}
In the CSS, all you need to add is .tagnamehere {display:none;}
Feel free to substitute with your own tags.

Categories

Resources