Javascript Target link state - javascript

I've got a bit of javascript that toggles two divs with two separate links, I wanted to add a little image next to the selected link say for instance if you select div 1 to be viewed the link would have a litle bullet next to it and if you select div 2 the div 2 would have a bullet on it. Heres the script can anyone help please :)
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<style type='text/css'>
</style>
<script type='text/javascript' src='http://code.jquery.com/jquery-1.6.2.js'></script>
<script type='text/javascript'>//<![CDATA[
$(window).load(function(){
$(function(){
$('a[id^="link"]').click(function(){
var vid_id = $(this).attr("id").replace("link", "#testVid");
$('div[id^="testVid"]').hide();
$(vid_id).show();
});
$('span[id^="close"]').click(function(){
var vid_id = $(this).attr("id").replace("close", "#testVid");
$(vid_id).hide();
});
});
});//]]>
</script>
</head>
<body>
<div>
Click Link 1<br />
Click Link 2<br />
<div id="testVid1" style="background:pink; height:300px">Test Vid Div 1<br /><br /><span id="close1">CLOSE 1</span></div>
<div id="testVid2" style="display:none;background:pink; height:300px">Test Vid Div 2<br /><br /><span id="close2">CLOSE 2</span></div>
</div>
</body>
</html>

You can do this in various ways. I can think of three off the top of my head, and I'm sure there are more.
Background images and padding
content:before
Altering the DOM dynamically (not recommended)
The idea in #1 and #2 is to change the CSS style of the selected element. For #1, you would define styles something like this:
.selected {
background-image: url(myselectedimage.png);
background-repeat: no-repeat;
background-position: left center;
padding-left: 20px; /* or whatever the size of your image is */
}
For #2, you would use the following:
.selected:before {
content: "\u2219"; /* bullet */
}
Then, you can do something like this to remove the .selected class from everything, and add it to the selected link, when a link is clicked:
$('a[id^="link"]').click(function(e){
$('a[id^="link"]').removeClass('selected');
$(e.currentTarget).addClass('selected');
...
});
$('span[id^="close"]').click(function(){
$('a[id^="link"]').removeClass('selected');
...
});
The advantage to approach #1 is that almost all modern browsers support it without trouble. The advantage to #2 is that it's more flexible -- you can add text, images, attributes, all kinds of things, but be warned that browser support can be inconsistent. Since you're already using CSS3 selectors (^=), you're probably OK. See CSS Tricks for more info.
Approach #3 involves inserting and removing HTML from before the link. It's possible, but clunky. It's how we used to do things before CSS2 and 3 came along. :) I wouldn't recommend it, but occasionally it's the only way to get things done in a reliably cross-browser fashion (probably not in this case). In order to do that, insert a <span> tag before each link, with an ID that is computable from the link ID (or you could use CSS selectors to find the sibling). Then use JQuery's .html() method to insert HTML into it, e.g.:
<span id="bullet-link1"></span>Click Link 1<br />
...
<script lang="text/javascript">
$('a[id^="link"]').click(function(e) {
$('span[id^="bullet-"]').html('');
$('#bullet-' + e.currentTarget.id).html('•');
...
});
</script>

Related

How to craft a more elegant implementation

I've made an interface for my students where they click an image and hear the description pronounced via text-to-speech, and the text description appears in a div.
Currently I'm calling the text from the image because the onclick event for the speech only works if it's on the div, and since it's a (this) event I don't understand how to combine the two.
First, is it possible, or "better" - to have a single click on the div trigger both functions, rather than splitting them between the div and the image as I've done? This is the only way I could figure out how to get it all working. So that's the first thing.
Second, I'm re-stating this code every time
jQuery(this).articulate('speak')" data-articulate-append=
How can I make this more economical? In reality I have hundreds of items, and there are a bunch more settings in between the jQuery and data-articulate. I've shortened it for this post but in reality it's much longer and repeated hundreds of times.
Last, is it possible to draw the content for the innerHTML from the data-articulate-append part of the TTS command, since it's the same in every case?
Many thanks, I've spent quite a while constructing what I have so far as I'm new to JS. I'm learning and I've tried to answer these questions myself but it's not yet within my skillset, and sorry if I'm not using all correct terminology in my post. I'm including a stripped-down version of the page here, with just the essentials. Any input is greatly appreciated.
<!doctype html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title></title>
<script src="http://www.clients.brettcolephotography.com/test/jquery-3.1.1.min.js"></script>
<script src="http://www.clients.brettcolephotography.com/test/articulate.min.js"></script>
<link href="http://www.clients.brettcolephotography.com/test/style.css" rel="stylesheet" type="text/css">
</head>
<body>
<div>
<div onclick="jQuery(this).articulate('speak')" data-articulate-append="elephant">
<img onclick="elephant()" src="http://www.clients.brettcolephotography.com/test/01.jpg">
</div>
<div onclick="jQuery(this).articulate('speak')" data-articulate-append="camel">
<img onclick="camel()" src="http://www.clients.brettcolephotography.com/test/02.jpg">
</div>
<div onclick="jQuery(this).articulate('speak')" data-articulate-append="bear">
<img onclick="bear()" src="http://www.clients.brettcolephotography.com/test/03.jpg">
</div>
</div>
<div id="word">
</div>
<script>
function elephant() {
document.getElementById("word").innerHTML ="elephant";
}
function camel() {
document.getElementById("word").innerHTML ="camel";
}
function bear() {
document.getElementById("word").innerHTML ="bear";
}
</script>
</body>
</html>
You can accomplish this by:
Giving each div a class, for my example its speak. Then add an eventlistener for speak elements. Then in that event listener, you can run multiple functions. You can also get rid of the image's onclick handler.
<div class="speak" data-articulate-append="elephant"><img src="http://www.clients.brettcolephotography.com/test/01.jpg"></div>
<div class="speak" data-articulate-append="camel"><img src="http://www.clients.brettcolephotography.com/test/02.jpg"></div>
<div class="speak" data-articulate-append="bear"><img src="http://www.clients.brettcolephotography.com/test/03.jpg"></div>
$(document).ready(function(){
$(".speak").on("click",function(){
$(this).articulate('speak');
$("#word").html($(this).data("articulate-append"));
});
});

Retrieving the actual DOM/css state of a web page through javascript

As you know, a web page is the union of a html file, one or more css files and one or more javascript files: the first two elements are parsed by the browser to generate the DOM and other data structures useful for the rendering of the page .
Javascript files are executed by an engine, and they can change the value of the DOM or of the data structures related to css, so that, after the execution of a javascript, the "actual status" of a web page can be different from what was statically described by the original html and css code.
I need to develop a firefox add-on that grabs the "actual status" of a web page and stores it to disk, as a couple html + css file.
For the html file is quite easy, i need to serialize the DOM. My concerns are about the css: I can traverse the DOM and for each element get its stylesheet, but it will be
extremely slow and produces a not optimized css code.
Let's make an example
I have this html code:
<html>
<head>
<title>Test</title>
<link type="text/css" rel="stylesheet" href="style.css" />
<script type='text/javascript' src="changebackground.js" > </script>
</head>
<body>
<div class="divclass" >
<form>
<h2>click to change the background</h2>
<input type="button" value="version" onclick="changebg()" />
</form>
</div>
</body>
Style.css has this definitions:
.divclass{
margin: .5in;
height: 400px;
}
body{
background-color: white;
color: blueviolet;
}
and changebackground has this code:
function changebg() {
document.body.style.backgroundColor = 'black';
}
Obviously, after clicking the button the background's color becomes black.
My goal is to write an add-on that , after this change, gives me back the css with the style's modification, i.e.:
.divclass{
margin: .5in;
height: 400px;
}
body{
background-color: black;
color: blueviolet;
}
Any ideas?
You don't actually need to traverse anything. Inline styles are already part of the, so you get that for free, e.g.:
elem.style.width = "100px";
elem.outerHTML == '<elem style="width: 100px;>";
So to produce a "dump" of the current DOM, incl. inline styles, etc. do:
var html = document.documentElement.outerHTML;
You may also want to serialize document.doctype.
In the unlikely event that a script actually messes with external stylesheets (<link rel="stylesheet">, you may do something like what I described in "Get text of a modified stylesheet" to get the current set of rules. Again, inline styles (<style> and style= attributes) are already present in .outerHTML.
EDIT: What you ask now is not possible, because this is not how inline styles work.
Consider the following html fragment:
<div>first div</div>
<div>second div</div>
Now the following code runs:
document.querySelector("div").style.background = "black";
This will cause the first div to have an inline style:
<div style="background: none repeat scroll 0% 0% black;">first div</div>
<div>second div</div>
Demo Fiddle
How would that rule look like? div { background: black; } is obviously wrong, as this would affect all divs.
You could generate new classes and/or ids, but then you need to manipulate and store the DOM, and could have used my original answer in the first place.

Javascript to rotate between pages within ONE HTML page

I would like some help displaying contents (to different pages) within one HTML page using JavaScript.
This is a sample of what I have found so far: http://www.swan10.nl/stuff/test.htm however instead of displaying "FAQ question #blabla" in the box every time a link is clicked, I would like to display words and images like a normal content. Is there a way to do this?
I tried removing the CreateDiv function and replacing it with HTML codes but it doesn't work.
Thank you in advance :)
Umm, well you would need to use AJAX to pull the data into the page and display it in whatever method you choose. If you want to use a framework look into JQuery. It has nice AJAX functions. Otherwise read HERE
After re-reading your post I think you might just want to choose which div is displayed on a form at one time. This you can achieve by placing all of your divs in the same container. Then toggle their display css property.
Using jQuery it's as simple as
$('#divname').load('/path/to/file.html');
Note that the result should probably not include <html> and <head> tags (although you don't seem like you care about well formed HTML code).
I should probably also mention that you shouldn't make the client load content for you, that's what server side code is for.
Personally I would use the innerHTML property on one of your elements. It will allow you to add markup to that element. Check it out here: http://www.w3schools.com/jsref/prop_html_innerhtml.asp
<html>
<head>
<title>Multiple DIV</title>
<style type="text/css">
DIV#db {
border : 1px solid blue;
width : 400px;
height : 400px;
}
</style>
<script type="text/javascript">
var Content = new Array();
Content[0] = '<i>test1</i>';
Content[1] = '<b>test2</b><br><img src =http://www.w3schools.com/images/w3schoolslogo.gif>';
Content[2] = '<u>test3</u>';
Content[3] = '<s>test4</s>';
function Toggle(IDS) {
document.getElementById('db').innerHTML = Content[IDS];
}
</script>
</head>
<body onLoad="Toggle(0,10)">
FAQ #1
FAQ #2
FAQ #3
FAQ #4
<p />
<div id="db"></div>
</body>
</html>
I updated it to work all javascripty with the innerHTML

ul Component Won't Hide

I've done a simple menu using some HTML, CSS and Javascript. The main idea is that it should be hided until the user click on it, but the problem is that it won't start the page hidden and nothing happens when I click, just like if the Javascript won't active. Here is part of my files:
index.html
<head>
<link rel="stylesheet" type="text/css" href="style/sample.css" />
</head>
<body>
<script src="js/menu.js" type="text/javascript"></script>
<div id="container">
<div id="header">
<center>
<div class="leftMenu" onclick="toggleMenu()">Menu</div>
<h1>Test</h1>
</center>
<ul>
<li>About</li>
<li>Blog</li>
<li>Contact</li>
</ul>
</div>
</div>
</body>
menu.js
$(document).ready(function() {
$('#header ul').addClass('hide');
$('#header').append('<div class="leftMenu" onclick="toggleMenu()">Menu</div>');
});
function toggleClass() {
$('#header ul').toggleClass('hide');
$('#header .leftMenu').toggleClass('pressed');
}
sample.css
#header ul.hide {
display: none;
}
#header div.pressed {
-webkit-border-image: url(graphics/button_clicked.png) 0 8 0 8;
}
What I'm making wrong and how I can correct it?
I think at least part of the problem is that the menu toggle div you're creating is using the function toggleMenu() and not toggleClass().
EDIT: I made a jsfiddle that shows the changes I would propose to make it work properly: http://jsfiddle.net/avidal/dDDKz/
The key is to remove the onclick attributes, and use jQuery to handle the event binding for all current, and future matching elements:
$(document).ready(function() {
$('#header ul').addClass('hide');
$('#header').append('<div class="leftMenu">Menu</div>');
$('#header div.leftMenu').live('click', toggleClass);
});
function toggleClass() {
$('#header ul').toggleClass('hide');
$('#header .leftMenu').toggleClass('pressed');
}
Ok, a few things:
Make sure you have a doctype. You said this was just part of your code, so perhaps you do, but just to be sure, I'll point this out anyway. You can just use the html5 doctype (it is compatible with IE6 if that's a worry):
<!DOCTYPE html>
<html>
<head>...head stuff here </head>
<body> ...Body stuff here</body>
</html>
Make sure you are loading the jquery library. Again, maybe you already are, but just making sure your bases are covered here. I'd suggest putting it in your HEAD. You should also move menu.js out of the head and just below the closing BODY tag.
If you want the UL to start off hidden, you should have the default CSS for it display none. Otherwise, even if your script was working, you would see the ul for a moment before it became hidden as the page would first load and then the JS would apply the class. In that gap between page loading and JS applying your class, the UL will be visible.
Your scripts could really be optimized, and I apologize for not being more specific (shouldn't write these when I'm trying to get ready for bed), but I'll at least point out the most obvious fix here - make sure that you are calling the correct method. I see that in the HTML snippet you are appending, you are calling toggleMenu(), but in your actual JS, your function is called toggleClass. Change one of those so they match.

Is there a HTML opposite to <noscript>?

Is there a tag in HTML that will only display its content if JavaScript is enabled? I know <noscript> works the opposite way around, displaying its HTML content when JavaScript is turned off. But I would like to only display a form on a site if JavaScript is available, telling them why they can't use the form if they don't have it.
The only way I know how to do this is with the document.write(); method in a script tag, and it seems a bit messy for large amounts of HTML.
Easiest way I can think of:
<html>
<head>
<noscript><style> .jsonly { display: none } </style></noscript>
</head>
<body>
<p class="jsonly">You are a JavaScript User!</p>
</body>
</html>
No document.write, no scripts, pure CSS.
You could have an invisible div that gets shown via JavaScript when the page loads.
I don't really agree with all the answers here about embedding the HTML beforehand and hiding it with CSS until it is again shown with JS. Even w/o JavaScript enabled, that node still exists in the DOM. True, most browsers (even accessibility browsers) will ignore it, but it still exists and there may be odd times when that comes back to bite you.
My preferred method would be to use jQuery to generate the content. If it will be a lot of content, then you can save it as an HTML fragment (just the HTML you will want to show and none of the html, body, head, etc. tags) then use jQuery's ajax functions to load it into the full page.
test.html
<html>
<head>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
<script type="text/javascript" charset="utf-8">
$(document).ready(function() {
$.get('_test.html', function(html) {
$('p:first').after(html);
});
});
</script>
</head>
<body>
<p>This is content at the top of the page.</p>
<p>This is content at the bottom of the page.</p>
</body>
</html>
_test.html
<p>This is from an HTML fragment document</p>
result
<p>This is content at the top of the page.</p>
<p>This is from an HTML fragment document</p>
<p>This is content at the bottom of the page.</p>
First of all, always separate content, markup and behaviour!
Now, if you're using the jQuery library (you really should, it makes JavaScript a lot easier), the following code should do:
$(document).ready(function() {
$("body").addClass("js");
});
This will give you an additional class on the body when JS is enabled.
Now, in CSS, you can hide the area when the JS class is not available, and show the area when JS is available.
Alternatively, you can add no-js as the the default class to your body tag, and use this code:
$(document).ready(function() {
$("body").removeClass("no-js");
$("body").addClass("js");
});
Remember that it is still displayed if CSS is disabled.
I have a simple and flexible solution, somewhat similar to Will's (but with the added benefit of being valid html):
Give the body element a class of "jsOff". Remove (or replace) this with JavaScript. Have CSS to hide any elements with a class of "jsOnly" with a parent element with a class of "jsOff".
This means that if JavaScript is enabled, the "jsOff" class will be removed from the body. This will mean that elements with a class of "jsOnly" will not have a parent with a class of "jsOff" and so will not match the CSS selector that hides them, thus they will be shown.
If JavaScript is disabled, the "jsOff" class will not be removed from the body. Elements with "jsOnly" will have a parent with "jsOff" and so will match the CSS selector that hides them, thus they will be hidden.
Here's the code:
<html>
<head>
<!-- put this in a separate stylesheet -->
<style type="text/css">
.jsOff .jsOnly{
display:none;
}
</style>
</head>
<body class="jsOff">
<script type="text/javascript">
document.body.className = document.body.className.replace('jsOff','jsOn');
</script>
<noscript><p>Please enable JavaScript and then refresh the page.</p></noscript>
<p class="jsOnly">I am only shown if JS is enabled</p>
</body>
</html>
It's valid html. It is simple. It's flexible.
Just add the "jsOnly" class to any element that you want to only display when JS is enabled.
Please note that the JavaScript that removes the "jsOff" class should be executed as early as possible inside the body tag. It cannot be executed earlier, as the body tag will not be there yet. It should not be executed later as it will mean that elements with the "jsOnly" class may not be visible right away (as they will match the CSS selector that hides them until the "jsOff" class is removed from the body element).
This could also provide a mechanism for js-only styling (e.g. .jsOn .someClass{}) and no-js-only styling (e.g. .jsOff .someOtherClass{}). You could use it to provide an alternative to <noscript>:
.jsOn .noJsOnly{
display:none;
}
In the decade since this question was asked, the HIDDEN attribute was added to HTML. It allows one to directly hide elements without using CSS. As with CSS-based solutions, the element must be un-hidden by script:
<form hidden id=f>
Javascript is on, form is visible.<br>
<button>Click Me</button>
</form>
<script>
document.getElementById('f').hidden=false;
</script>
<noscript>
Javascript is off, but form is hidden, even when CSS is disabled.
</noscript>
You could also use Javascript to load content from another source file and output that. That may be a bit more black box-is than you're looking for though.
Here's an example for the hidden div way:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<style>
*[data-when-js-is-on] {
display: none;
}
</style>
<script>
document.getElementsByTagName("style")[0].textContent = "";
</script>
</head>
<body>
<div data-when-js-is-on>
JS is on.
</div>
</body>
</html>
(You'd probably have to tweak it for poor IE, but you get the idea.)
My solution
.css:
.js {
display: none;
}
.js:
$(document).ready(function() {
$(".js").css('display', 'inline');
$(".no-js").css('display', 'none');
});
.html:
<span class="js">Javascript is enabled</span>
<span class="no-js">Javascript is disabled</span>
Alex's article springs to mind here, however it's only applicable if you're using ASP.NET - it could be emulated in JavaScript however but again you'd have to use document.write();
You could set the visibility of a paragraph|div to 'hidden'.
Then in the 'onload' function, you could set the visibility to 'visible'.
Something like:
<body onload="javascript:document.getElementById(rec).style.visibility=visible">
<p style="visibility: visible" id="rec">This text to be hidden unless javascript available.</p>
There isn't a tag for that. You would need to use javascript to show the text.
Some people already suggested using JS to dynamically set CSS visible. You could also dynamically generate the text with document.getElementById(id).innerHTML = "My Content" or dynamically creating the nodes, but the CSS hack is probably the most straightforward to read.

Categories