I am trying to make a responsive web page eg where the display changes with the screen size.
I have the following HTML:
<div class="responsive_menu" id="resp_Menu" onClick="fnResponsiveMenu()">
</div>
<div class="nav_wrapper">
<div class="navigation" id="navMenu1">
Contact Us
</div>
<div class="navigation" id="navMenu2">
Information
</div>
<div class="navigation" id="navMenu3">
Venue Details
</div>
<div class="navigation" id="navMenu4">
Registration & Payment
</div>
<div class="navigation" id="navMenu5">
Agenda
</div>
<div class="navigation" id="navMenu6">
Home
</div>
</div>
and the following in responsive.css:
.navigation {
width:100%;
background-color:#3171B7;
border-bottom:1px solid #ffffff;
margin:0;
text-transform:uppercase;
font-size:16px;
height:40%;
padding-top:10px;
display:none;
}
and the following in style.css:
.navigation {
float:right;
margin:30px 0px 1px 0px;
height:25px;
width:100px;
display:block;
}
.navigation a
{
font-family: Arial, Helvetica, sans-serif;
font-size: 14px;
color: #FFFFFF;
text-decoration: none;
display:block;
padding:0 5px;
height:30px;
}
and the following JavaScript:
var oNavChecker = 0;
function fnResponsiveMenu()
{
if(oNavChecker == 0 )
{
var oNav1 = document.getElementById("navMenu1");
oNav1.setAttribute('style', 'display:inline');
var oNav2 = document.getElementById("navMenu2");
oNav2.setAttribute('style', 'display:inline');
var oNav3 = document.getElementById("navMenu3");
oNav3.setAttribute('style', 'display:inline');
var oNav4 = document.getElementById("navMenu4");
oNav4.setAttribute('style', 'display:inline');
var oNav5 = document.getElementById("navMenu5");
oNav5.setAttribute('style', 'display:inline');
var oNav6 = document.getElementById("navMenu6");
oNav6.setAttribute('style', 'display:inline');
oNavChecker = 1;
return;
}
if(oNavChecker == 1 )
{
var oNav1 = document.getElementById("navMenu1");
oNav1.setAttribute('style', 'display:none');
var oNav2 = document.getElementById("navMenu2");
oNav2.setAttribute('style', 'display:none');
var oNav3 = document.getElementById("navMenu3");
oNav3.setAttribute('style', 'display:none');
var oNav4 = document.getElementById("navMenu4");
oNav4.setAttribute('style', 'display:none');
var oNav5 = document.getElementById("navMenu5");
oNav5.setAttribute('style', 'display:none');
var oNav6 = document.getElementById("navMenu6");
oNav6.setAttribute('style', 'display:none');
oNavChecker = 0;
return;
}
}
That all works fine and behaves as I want.
My problem is, once the screen has been reduced, and then the menu button pressed eg when fnResponsiveMenu() has been:
pressed to first show the menu
then pressed again to remove it
then the screen return to wide resolution,
The navMenus do not show anymore.
I am sure it is because the CSS is being over riden by the javascript eg:
oNav1.setAttribute('style', 'display:none');
So how can I resolve this and get the style.CSS to override the changes applied by the JavaScript?
If this is not possible, can anyone suggest an alternative to achieveing my aim of making a responsive menu?
I can't comment, not enought rep, so I'll ask it in the answer...
Have you read this? Remove inline css of an HTML elements
Once you remove inline styling, default from your css file will be applied again.
Related
I have a label I'm attempting to generate. It has the following structure.
.name-box { width: 400px; background-color: #efefef; border: 1px solid #000; overflow: hidden; white-space: nowrap; }
.last-name { font-size: 26px; display:inline; overflow: hidden;}
.first-name { display:inline; overflow: hidden;}
<div class="name-box">
<div class="last-name">McDonald-OrAReallySuperDuperLongLastName</div>
<div class="first-name">David</div>
</div>
What I'm wanting to do is change the text size of the first name, based on the length of the last name. If the name is "Venckus-Stringfellow" and I only have a little bit of space left I'd like the text size of the first name to be around 7px. But if the last name is "Le", then I'd want the first name to have a text size of 26px -- granted that having a text size of 26px still allows the first name to fit on the 600px that my div has to fill the label. How can I do this with HTML/CSS (if I MUST use Javascript then that's fine, was trying to avoid it though) ?
Javascript that uses the length of the last name in a mathematical equation to set the first names size. This is a very simple example and you'd need to change it if you wanted it to be exponential and you should probably set high and low bounds that it can't go below.
var lastNameText = document.querySelector('.last-name').textContent;
var firstName = document.querySelector('.first-name');
firstName.style.fontSize = (120 / lastNameText.length) + "px";
.name-box { width: 600px; }
.last-name { font-size: 26px; }
.first-name: { font-size: 26px; }
<div class="name-box">
<div class="last-name">McDonald</div>
<div class="first-name">David</div>
</div>
You're going to need javascript here, unfortunately. You can get close using viewport percentages, but that applies to the whole viewport. And it would only be for one container, not a preceding container. What you are going to need to do is create an algorithm that updates the font sizes, and run it everytime you load HTML/text into those div's.
Something like this should get you started:
function loadNames(var firstName, var lastName) {
//GET THE LENGTH OF THE LASTNAME STRING
var len = lastName.length;
var factor = .7; //CUSTOMIZE THIS TO DO YOUR SIZING BASED ON THE FONT
var fontSize = Math.ceil(factor * len); //GET THE NEW FONT SIZE, BASED ON THE LENGTH AND FACTOR, AND ROUNDED UP
//SET THE TEXT OF THE NAMES
$('firstName').Text(firstName);
$('lastName').Text(lastName);
//SET THE FONT SIZES
$('firstName').css({ 'font-size': fontSize + 'px;' });
$('lastName').css({ 'font-size': fontSize + 'px;' });
}
CSS solution unfortunately is not possible. It's not possible to select partial text inputs, and there's some calculation required that cannot be done with CSS at this point, in this age.
But javascript.. Were you looking for something like this OP?
$(document).on("ready", function(){
var ratio = 20;
$(".name").keydown(function(){
var input_length = $(this).val().length / ratio;
var new_size = (2 - input_length < 1 ? 1 : 2 - input_length);
$(this).css("font-size", new_size+"em");
});
});
input {
width: 40em;
margin: 0 auto;
display: block;
padding: 15px;
}
.main-wrapper {
width: 100%;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="main-wrapper">
<input class="name" type="text" placeholder="Enter name" />
</div>
This is another approach how You could achieve the result. Maybe it's possible to do not use table at all but each div should use display:inline-block; property.
$scalingL = $('.last-name').width();
$scalingF = $('.first-name').width();
$('.first-name').css('font-size',($scalingL / $scalingF * 26));
.name-box { width: 600px; background-color: #efefef; border: 1px solid #000; overflow: hidden; white-space: nowrap; }
.last-name { font-size: 26px; overflow: hidden; display:inline-block;}
.first-name { font-size: 26px; display:inline-block;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="name-box">
<table>
<tr>
<td>
<div class="last-name">McDonald-OrAReallySuperDuperLongLastName</div>
</td>
</tr>
</tr>
<td>
<div class="first-name">Something</div>
</td>
</tr>
</table>
</div>
Try this:
<style type="text/css">
.name-box{
width:auto;
overflow:auto;
}
#first-name{
display:inline-block;
width:auto;
clear:both;
float:left;
font-size:1px;
}
#last-name {
display:inline-block;
width:auto;
clear:both;
float:left;
font-size:26px;
}
</style>
<div class="name-box">
<div id="last-name">McDonalds</div>
<div id="first-name">David</div>
</div>
<script type="text/javascript">
var ln = document.getElementById("last-name");
var fn = document.getElementById("first-name");
for ( i = 1; ln.offsetWidth>fn.offsetWidth; i+=.5)
{
fn.style.fontSize=(i)+"px";
}
</script>
<style type="text/css">
.name-box{
width:auto;
overflow:auto;
}
#first-name{
display:inline-block;
width:auto;
clear:both;
float:left;
font-size:1px;
}
#last-name {
display:inline-block;
width:auto;
clear:both;
float:left;
font-size:26px;
}
</style>
<div class="name-box">
<div id="last-name">McDonalds</div>
<div id="first-name">David</div>
</div>
<script type="text/javascript">
var ln = document.getElementById("last-name");
var fn = document.getElementById("first-name");
for ( i = 1; ln.offsetWidth>fn.offsetWidth; i+=.5)
{
fn.style.fontSize=(i)+"px";
}
</script>
I have a Div in which I want to add another small Div's Dynamically. But small Div's strictly needs to be inside the main Div. I have added one small Div inside. But how to add all the 15 div's inside the main Div dynamically I'm not getting. Also the size of small Div's are fixed, if they are more in numbers say 20, then Main Div should have horizontal scroll bar.
Here is the HTML used:
<div id="tables" style="width:740px; height:50px; border:1px solid;margin-left:180px;">
<div id ="1" style="border:1px solid; height:44px; width:50px; margin-left:2px; margin-top:2px; margin-bottom:2px;">1</div>
</div>
And here is my fiddle link: Fiddle.
You need to loop as many times as required, create the elements and then append them to #tables. Something like this:
var $tables = $('#tables');
for (var i = 1; i <= 15; i++) {
$('<div />', { class: 'inner', text: i }).appendTo($tables);
};
Example fiddle
You can add the id property back in if needed, but I would advise against incremental id attributes as they only lead to a maintenance headache. Also, I changed the styling to use actual CSS classes for a better separation of concerns.
You can use the following code in jQuery to append a div :
smallDivWidth = (740 / 15);
for (var i = 1; i <= 15; i++) {
$('#tables').append('<div style="border:1px solid; height:44px;float:left; margin- left:2px; margin-top:2px; margin-bottom:2px;">1</div>');
$('#tables').children().css('width',(smallDivWidth-4)+'px');
};
Just as an example, see this here :
$("#btnDynamicDiv").click(function() {
var smallDivWidth = (740 / 15);
for (var i = 1; i <= 15; i++) {
$('#tables').append('<div style="border:1px solid; height:44px;float:left; margin- left:2px; margin-top:2px; margin-bottom:2px;">1</div>');
$('#tables').children().css('width',(smallDivWidth-4)+'px');
};
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js"></script>
<div id="tables" style="width:740px; height:50px; border:1px solid;margin-left:180px;">
<div id ="1" style="border:1px solid; height:44px; width:50px; margin-left:2px; margin-top:2px; margin-bottom:2px;">1</div>
</div>
<input type="button" id="btnDynamicDiv" value ="Add div dynamically"></input>
Try like this (JSFiddle demo)
HTML:
<div id="tables">
<div class="inner" id="innder-1">1</div>
</div>
<div class="inner inner-template"></div>
<br>
<button id="add-btn">Add inner</button>
CSS:
#tables {
width:200px;
height:50px;
border:1px solid;
white-space: nowrap;
overflow-x: auto;
}
.inner {
border:1px solid;
height:44px;
width:50px;
margin-left:2px;
margin-top:2px;
margin-bottom:2px;
display: inline-block;
vertical-align: top;
white-space: howrap;
}
.inner-template {
display: none;
}
JS:
var $template = $('.inner-template');
$('#add-btn').on('click', function() {
var currentID = $('#tables .inner').length + 1;
var $inner = $template
.clone()
.removeClass('inner-template')
.attr('id', 'inner-' + currentID)
.text(currentID)
.appendTo('#tables');
});
I'm setting up a reusable jQuery toggle function (for my employer) to enable show/hide of content (eg FAQs), to improve accessibility over existing inline onClick bindings.
In JSFiddle everything is fast and fluid, but when I transfer to the preview server an odd behaviour becomes apparent. Clicking the button works as normal, but on clicking the button's link text there's a noticeable delay before anything happens.
Is there anything within the script that might be causing the delay? Or anything which is an obvious candidate for conflicts of some kind?
Anyway, here's the code (based on Mike Raynham's accessible toggles):
http://jsfiddle.net/internet_man/9yKKM/2/
html:
<div class="buttons">
<ul>
<li><strong class="_toggle type noscript">This is the first toggle</strong>
<ul class="_toggle-this show-hide">
<li><strong>Option One</strong></li>
<li><strong>Option Two</strong></li>
<li><strong>Option Three</strong></li>
</ul>
</li>
<li class="bad-break"><strong class="_toggle type noscript">This is the second toggle (a bit longer than the first)</strong>
<ul class="_toggle-this show-hide">
<li><strong>Option One</strong></li>
<li><strong>Option Two</strong></li>
</ul>
</li>
<li class="bad-break"><strong class="_toggle type noscript">This is the third toggle (also somewhat longer)</strong>
<ul class="_toggle-this show-hide">
<li><strong>Option One</strong></li>
<li><strong>Option Two</strong></li>
</ul>
</li>
</ul>
</div>
Script:
var create_name = function(text) {
var name = text.toLowerCase();
name = name.replace(/^\s+|\s+jQuery|[^a-z0-9&\s-]/g, '');
name = name.replace(/&/g, 'and');
name = name.replace(/\s/g, '-');
name = name.replace(/(-)+\1/g, "jQuery1");
return name;
};
var add_link = function() {
var name = create_name(jQuery(this).text());
jQuery(this).next('.toggle-this').attr('name', name);
jQuery(this).html('' + jQuery(this).html() + '');
};
var toggle = function(event) {
event.preventDefault();
jQuery(this).toggleClass('expanded').nextAll('.toggle-this').slideToggle(100);
jQuery('.toggle-this').not(jQuery(this).siblings()).slideUp(100);
jQuery('.toggle').not(jQuery(this)).removeClass('expanded');
};
var remove_focus = function() {
jQuery(this).blur();
};
jQuery(function (){
jQuery('._toggle').removeClass('_toggle, noscript').addClass('toggle');
jQuery('._toggle-this').removeClass('_toggle-this').addClass('toggle-this');
jQuery('._expanded').removeClass('_expanded').addClass('expanded');
jQuery('.toggle:not(.expanded)').nextAll('.toggle-this').hide();
jQuery('.toggle').each(add_link);
jQuery('.toggle').click(toggle);
jQuery('.toggle a').mouseup(remove_focus);
});
CSS:
body
{
font-size:62.5%;
color:#666;
font-family:arial,Helvetica,sans-serif;
}
a
{
color:#462170;
}
ul
{
list-style-type:none;
margin-left:0;
padding-left:0;
}
strong
{
font-weight:normal;
}
div.buttons
{
width:462px;
line-height:2.2em;
margin:1.5em 0;
}
.buttons li > strong
{
font-size:1.9em;
}
.toggle, .buttons .type.noscript
{
display:block;
font-size:1.9em;
height:65px;
background:url(http://oi48.tinypic.com/dy6xf.jpg) 0 -85px no-repeat;
padding:20px 0 0 90px;
text-decoration:none;
color:#462170;
cursor:pointer;
cursor:hand;
}
.toggle a
{
text-decoration:none;
}
.toggle strong
{
display:block;
height:65px;
border:1px dotted red;
}
.toggle:hover, .toggle:focus
{
background-position:0 0;
}
.buttons .show-hide
{
border-bottom:6px solid white;
}
.buttons .show-hide li
{
margin-left:12px;
border-bottom: 2px solid white;
border-top:2px solid white;
font-size:1em;
}
.buttons .show-hide a
{
display:block;
height:15px;
text-decoration:none;
color:#462170;
background:#f1f1f1 url(http://oi46.tinypic.com/6iedtw.jpg) 5px 14px no-repeat;
padding:12px 0 15px 58px;
}
.buttons .show-hide a:hover, .connection-buttons .show-hide a:focus
{
text-decoration:underline;
color:black;
background-color:#ece8f0;
background-position:5px -41px;
}
li.bad-break a
{
padding-right:30%;
}
Notes:
Scripts on -- ._toggle becomes .toggle, ._toggle-this becomes .toggle-this, .noscript is removed and a link is inserted around (in this case) the strong element of class toggle, pointing to the next '.toggle-this' element.
Scripts off -- No toggle created but it's styled as though the accordions are expanded.
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);
}
}
if (lnk[i]) { /* ??? how do you know whether this is the link to activeate up front? */
hlist_menu(lnk[i]);
}
}
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;}
I need to put in the logic somewhere inside
if (lnk[i]) { /* ??? how do you know whether this is the link to activeate up front? */
hlist_menu(lnk[i]);
}
to let the script know which link will be active upfront. As i'm not familiar with coding, i have no clue how to do this!
Set the initially active link in your markup:
<a target="iframe1" class="menu_active" href="gallery/photo_menu.html">PHOTOGRAPHY</a>
Then in your set_menu function, set the iframe's src attribute to the href of that link:
for (i in lnk) {
if (lnk.hasOwnProperty(i)) {
//lnk[i].className = 'menu_idle'; // initial menu states are set in markup. This line is no longer necessary.
lnk[i].onclick = hlite_menu;
if (lnk[i].className === 'menu_active') {
iframe.src = lnk[i].href;
}
}
}
I would also strongly recommend re-writing your JavaScript to the following:
var hlite_menu = function hlite_menu() {
'use strict';
var lnk = document.getElementById('menu').getElementsByTagName('a'),
i = null;
//set all links to idle
for (i in lnk) {
if (lnk.hasOwnProperty(i)) {
lnk[i].className = 'menu_idle';
}
}
//set this link to active
this.className = 'menu_active';
},
set_menu = function set_menu() {
'use strict';
var lnk = document.getElementById('menu').getElementsByTagName('a'),
iframe = document.getElementById('iframe1'),
c = document.getElementById('copyright'),
i = null;
// set copyright
c.innerText = (new Date()).getFullYear();
// set onclicks and initial iframe src.
for (i in lnk) {
if (lnk.hasOwnProperty(i)) {
//lnk[i].className = 'menu_idle'; // initial menu states are set in markup. This line is no longer necessary.
lnk[i].onclick = hlite_menu;
if (lnk[i].className === 'menu_active') {
iframe.src = lnk[i].href;
}
}
}
};
window.onload = set_menu;
This avoids several long-term problems like readability/maintenance, variable hoisting, and the dreaded document.write (which you are using to set your copyright date). You'll also want to change the copyright section to this:
<div id="footer">
ALL IMAGES © <span id="copyright"></span>
</div>
You can also write your navigation like this (avoiding tables for layout):
<div id="header">
<div class="logo">
<span style="">MO SCHALKX</span>
</div>
<div id="menu">
<a target="iframe1" class="menu_active" href="gallery/photo_menu.html">PHOTOGRAPHY</a>
<a target="iframe1" class="menu_idle" href="gallery/film_menu.html">FILM</a>
<a target="iframe1" class="menu_idle" href="about.html">ABOUT</a>
<a target="iframe1" class="menu_idle" href="http://reflecture.tumblr.com">BLOG</a>
</div>
</div>
and add this to your CSS:
#header {
float: left;
display: inline-block;
margin: 1em;
text-align: center;
}
.logo, #menu {
background-color: #FFF;
}
.logo {
font-size: 40px;
font-weight: 500;
font-style: inherit;
}
#menu {
margin-top: 5px;
}
#menu > a {
padding-left: 0.25em;
}
#menu > a {
border-left: 1px solid #000;
}
#menu > a:first-child {
border-left: none;
}
which should make it look the same. You can also combine your CSS rules for menu_active and a:hover (likewise with menu_idle and a:visited) like so:
a.menu_idle, a:visited {
color: #333333;
text-decoration: none;
}
a.menu_active, a:hover {
color: #333333;
text-decoration: underline;
}
Finally, you've wrapped your iframe in a <form id="form1" runat="server"> element. You can remove this entirely. It won't affect your layout and you don't actually have a form with any input elements so it's unnecessary. Also, the runat="server" attribute doesn't do anything unless you're running this on ASP.Net (and you obviously are not) so you may want to keep that in mind.
Altogether, you should be able to change the entire document source to the following with no real visual changes (and I think you'll find that it's a lot cleaner to look at in the source):
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>Mo Schalkx Photography</title>
<script type="text/javascript">
var hlite_menu = function hlite_menu() {
'use strict';
var lnk = document.getElementById('menu').getElementsByTagName('a'),
i = null;
//set all links to idle
for (i in lnk) {
if (lnk.hasOwnProperty(i)) {
lnk[i].className = 'menu_idle';
}
}
//set this link to active
this.className = 'menu_active';
},
set_menu = function set_menu() {
'use strict';
var lnk = document.getElementById('menu').getElementsByTagName('a'),
iframe = document.getElementById('iframe1'),
c = document.getElementById('copyright'),
i = null;
// set copyright
c.innerText = (new Date()).getFullYear();
// set onclicks and initial iframe src.
for (i in lnk) {
if (lnk.hasOwnProperty(i)) {
//lnk[i].className = 'menu_idle'; // initial menu states are set in markup. This line is no longer necessary.
lnk[i].onclick = hlite_menu;
if (lnk[i].className === 'menu_active') {
iframe.src = lnk[i].href;
}
}
}
};
window.onload = set_menu;
</script>
<style type="text/css">
body {
margin: 0;
overflow: hidden;
}
#header {
float: left;
display: inline-block;
margin: 1em;
text-align: center;
}
#iframe1 {
position: absolute;
left: 0px;
top: 0px;
width: 100%;
height: 100%;
z-index: -1;
}
#footer {
font-size: 9px;
font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
text-align: center;
position: absolute;
bottom: 0px;
left: 0px;
width: 100%;
height: 20px;
visibility: visible;
display: block;
color: #000;
opacity: 0.4;
filter: alpha(opacity=40);
text-shadow: 0px 1px 0px rgba(255,255,255,.5); /* 50% white from bottom */;
}
.logo, #menu {
background-color: #FFF;
}
.logo {
font-size: 40px;
font-weight: 500;
font-style: inherit;
}
#menu {
margin-top: 5px;
}
#menu > a {
padding-left: 0.25em;
}
#menu > a {
border-left: 1px solid #000;
}
#menu > a:first-child {
border-left: none;
}
a.menu_idle, a:visited {
color: #333333;
text-decoration: none;
}
a.menu_active, a:hover {
color: #333333;
text-decoration: underline;
}
</style>
</head>
<body>
<div id="header">
<div class="logo">
<span style="">MO SCHALKX</span>
</div>
<div id="menu">
<a target="iframe1" class="menu_active" href="gallery/photo_menu.html">PHOTOGRAPHY</a>
<a target="iframe1" class="menu_idle" href="gallery/film_menu.html">FILM</a>
<a target="iframe1" class="menu_idle" href="about.html">ABOUT</a>
<a target="iframe1" class="menu_idle" href="http://reflecture.tumblr.com">BLOG</a>
</div>
</div>
<div id="footer">
ALL IMAGES © <span id="copyright"></span>
</div>
<iframe id="iframe1" frameborder="0"></iframe>
</body>
</html>
UDPATE
To apply this on http://moschalkx.nl/gallery/film_menu.html, simply include the same JavaScript and comment out the lines that involve setting the copyright in set_menu and update the id of the iframe:
var hlite_menu = function hlite_menu() {
'use strict';
var lnk = document.getElementById('menu').getElementsByTagName('a'),
i = null;
//set all links to idle
for (i in lnk) {
if (lnk.hasOwnProperty(i)) {
lnk[i].className = 'menu_idle';
}
}
//set this link to active
this.className = 'menu_active';
},
set_menu = function set_menu() {
'use strict';
var lnk = document.getElementById('menu').getElementsByTagName('a'),
iframe = document.getElementById('gallery'),
//c = document.getElementById('copyright'),
i = null;
// set copyright
//c.innerText = (new Date()).getFullYear();
// set onclicks and initial iframe src.
for (i in lnk) {
if (lnk.hasOwnProperty(i)) {
//lnk[i].className = 'menu_idle'; // initial menu states are set in markup. This line is no longer necessary.
lnk[i].onclick = hlite_menu;
if (lnk[i].className === 'menu_active') {
iframe.src = lnk[i].href;
}
}
}
};
window.onload = set_menu;
Also, since you're including jQuery on this page, you could write that in jQuery as:
$(document).ready(function () {
$('#menu a').click(function (e) {
var self = $(this),
href = self.attr('href');
$('#menu a').not(self).removeClass('menu_active').addClass('menu_idle');
self.removeClass('menu_idle').addClass('menu_active');
$('#gallery').attr('src', href);
});
});
I am writing a drop-down menu for the school intranet site and I have created a rather strange issue. The sub-menus are offset from the selected menu y position by 36px.
Here's a excerpt of the code (please excuse the quality :D)
<html>
<head>
<style>
#navagationBar {
margin: 0;
padding: 0;
z-index: 30;
}
#navagationBar li {
list-style: none;
float: left;
font: bold 12px 'Arial';
margin-left: 10px;
width: 96px;
}
#navagationBar li a {
display: block;
margin: 0 1px 0 0;
padding: 4px 10px;
width: 136px;
color: #FFFFFF;
text-align: center;
text-decoration: none;
}
#navagationBar li a:hover {
background: #796952;
}
#navagationBar div {
position: absolute;
visibility: hidden;
background: transparent;
}
#navagationBar div a {
position: relative;
display: block;
padding: 5px 10px;
width: 136px;
white-space: nowrap;
text-align: left;
text-decoration: none;
background: #796952;
color: #FFF;
font: 9px "Arial";
}
#navagationBar div a:hover {
background: #969696;
color: #FFF;
}
#navagationBar a {
color: #FFF;
}
div.navagation {
background: #2d221c;
height: 28px;
}
div.sub {
left: 156px;
}
</style>
<!-- BG COLOR: #2d221c
FORERGROUND: #3c3429
HOVER: #796952
-->
<script>
var menuItem = 0;
var subItem = 0;
var timeLimit = 250;
var closeTimer = 0;
var closeSubTimer = 0;
// open menu
function openMenu(id) {
stopTimer();
// If a layer is already open close it
if (menuItem) {
menuItem.style.visibility = 'hidden';
}
// Then set the one clicked on by the user to be shown
menuItem = document.getElementById(id);
menuItem.style.visibility = 'visible';
}
function openSub(id) {
stopSubTimer();
// If a layer is already open close it
if (subItem) {
subItem.style.visibility = 'hidden';
}
subItem = document.getElementById(id);
subItem.style.visibility = 'visible';
}
function close() {
if (menuItem) {
menuItem.style.visibility = 'hidden';
}
}
function closeSub() {
if (subItem) {
subItem.style.visibility = 'hidden';
}
}
function startTimer() {
closeTimer = window.setTimeout(close, timeLimit);
}
function startSubTimer() {
closeSubTimer = window.setTimeout(closeSub, timeLimit);
}
// Stop timing
function stopTimer() {
if (closeTimer) {
window.clearTimeout(closeTimer);
closeTimer = null;
}
}
// TODO: Make more modular
function stopSubTimer() {
if (closeSubTimer) {
window.clearTimeout(closeSubTimer);
closeSubTimer = null;
}
}
// If the user click out, close teh box
document.onclick = close();
document.onclick = closeSub();
</script>
</head>
<body>
<div class="navagation">
<ul id="navagationBar">
<li>HSIE
<div id="menu0" onMouseOver="stopTimer()" onMouseOut="startTimer()">
Business Studies
<div class='sub' id="submenu0_0" onMouseOver="openSub('submenu0_0')" onMouseOut="startSubTimer()">
<a href='view.php?id=110'>Year 11</a>
<a href='view.php?id=109'>Year 12</a>
</div>
Commerce
<div class='sub' id="submenu0_1" onMouseOver="openSub('submenu0_1')" onMouseOut="startSubTimer()">
<a href='view.php?id=112'>Year 9</a>
<a href='view.php?id=111'>Year 10</a>
</div>
Geography
<div class='sub' id="submenu0_2" onMouseOver="openSub('submenu0_2')" onMouseOut="startSubTimer()">
<a href='view.php?id=48'>Year 7</a>
<a href='view.php?id=92'>Year 8</a>
<a href='view.php?id=105'>Year 9</a>
<a href='view.php?id=70'>Year 10</a>
<a href='view.php?id=69'>Year 11</a>
<a href='view.php?id=131'>Year 12</a>
</div>
History
<div class='sub' id="submenu0_3" onMouseOver="openSub('submenu0_3')" onMouseOut="startSubTimer()">
<a href='category.php?id=89'>Junior</a>
<a href='category.php?id=90'>Senior</a>
</div>
</div>
</li>
</ul>
</div>
</body>
</html>
Try putting the sub menu divs before the corresponding a tags (instead of putting these divs after them).
For instance, try this:
<div class='sub' id="submenu0_0" onMouseOver="openSub('submenu0_0')" onMouseOut="startSubTimer()">
<a href='view.php?id=110'>Year 11</a>
<a href='view.php?id=109'>Year 12</a>
</div>
Business Studies
Instead of this:
Business Studies
<div class='sub' id="submenu0_0" onMouseOver="openSub('submenu0_0')" onMouseOut="startSubTimer()">
<a href='view.php?id=110'>Year 11</a>
<a href='view.php?id=109'>Year 12</a>
</div>
DOM Access
First, you have to make absolutely sure to not access the DOM by getElementbyId(); before the whole page has loaded.
You have to invoke the script right before the closing body tag or wrap your whole code in one function and invoke it at the end, right before the closing body tag. This is Yahoo! and Google Front-End Development best practice.
Alternatively you could use JQuery's $(document).ready() function or another JavaScript library's document-loaded function. Using a library for addressing just this issue, however would be overkill.
Global Variables
By declaring var menuItem = 0; outside the function scope, you declare the variable as a global, which is a very bad thing! It will clutter your entire Web site's namespace. Declare variables inside a function to create a closure.
Also you don't want to initialise your menuItem variable with an integer, because you will reference an object later on (a DOM object). Albeit Javascript doesn't need types to be dclared and this will work, it is creating confusion with the reader of the code. Just use var menuItem; inside the function.
CSS Block Formatting Context
Try using display: inline or display: block with your HTML elements. Make sure to read and understand the W3C CSS Visual formatting model.
You have individual IDs for each sub level so you could add styling for each.
#submenu0_0 > a {top:0px;}
#submenu0_1 > a {top:25px;}
#submenu0_2 > a {top:50px;}
#submenu0_3 > a {top:75px;}
Is this due to quirks mode?
Try using a proper doctype like this:
<!DOCTYPE HTML>
<html>
<head>
</head>
<body>
</body>
</html>