HTML buttons and event listeners - javascript

I wanted to make a dynamic table view where a button was clicked to reveal a Table Row however, I get an error when I try to change the text of the button.
window.onload = () => {
const buttons = document.getElementsByTagName("button")
console.log(buttons)
const info = document.getElementsByTagName("tr")
// let a = 1
for (let elem in info) {
if (info.id != "info") continue
else info.splice(info.indexOf(elem), 1)
}
for (i = 0; i < buttons.length; i++) {
buttons[i].addEventListener("click", function onClick(a = 1) {
if (a % 2 == 0) {
info[i].style.visibility = "hidden"
buttons[i].innerText = "View More" // wrong
} else {
info[i].style.visibility = "visible"
buttons[i].innerText = "View Less" // wrong
}
a++
})
}
}
<button>Show Contents</button>
<table>
<tr id="info" style="visibility:hidden;">
<td width="80%">
<p style="width:80%;text-align:center; margin-left:1%">
The Planetarium is located on the first floor of the Science Centre. The planetarium has a shape of a sphere, 16.30 meters in diameter, the dome could also be used for extreme-wide-projections and other enhanced multi-media shows. It has a seating capacity
of 140 the digital theatre of Planetarium facilitates the observation of planets, moon, stars, nebula, displayed on full dome through an advance technology and thus Astronomy Secrets will be shared with the students and general public. High resolution
projectors operated through Digester 3 technology with digital audio system will provide a dazzling shows and that would be unforgettable experience. The shows will be in 3 languages Gujarati, Hindi and English.
</p>
</td>
</table>
Error:
Uncaught TypeError: Cannot set properties of undefined (setting 'innerText')
at HTMLButtonElement.onClick

Suggestions:
Use "display" style, instead of "visibility", to don't let the space occupied on the page when it's not visible;
It's not good idea have multiple elements with the same id (like "info"), because that breaks the rules of HTML;
To show and hide, use read directly info from css, instead of use a auxiliary variable;
The document.getElementsByTagName returns an object, not an array. The way to navigate is using the classic way.
Next, your code with some fixes:
window.onload = () => {
const buttons = document.getElementsByTagName("button")
//console.log(buttons)
const info = document.getElementsByTagName("tr")
// let a = 1
let newInfo = [];
for (let i = 0; i < info.length; i++) {
if (info[i].id === "info"){
newInfo.push(info[i]);
}
}
for (let i = 0; i < buttons.length; i++) {
buttons[i].addEventListener("click", function onClick() {
if (newInfo[i].style.visibility !== "hidden") {
newInfo[i].style.visibility = "hidden"
// Suggestion: use "display" style, instead of "visibility", to don't let the space ocupied on the page, when it's not visible
//newInfo[i].style.display = "none"
buttons[i].innerText = "View More" // wrong
}
else {
newInfo[i].style.visibility = "visible"
buttons[i].innerText = "View Less" // wrong
//newInfo[i].style.display = ""
}
})
}
}
<button>Show Contents</button>
<table>
<tr id="info" style="visibility:hidden;">
<td width="80%">
<p style="width:80%;text-align:center; margin-left:1%">
1 - The Planetarium is located on the first floor of the Science Centre. The planetarium has a shape of a sphere, 16.30 meters in diameter, the dome could also be used for extreme-wide-projections and other enhanced multi-media shows. It has a seating capacity of 140 the digital theatre of Planetarium facilitates the observation of planets, moon, stars, nebula, displayed on full dome through an advance technology and thus Astronomy Secrets will be shared with the students and general public. High resolution projectors operated through Digester 3 technology with digital audio system will provide a dazzling shows and that would be unforgettable experience. The shows will be in 3 languages Gujarati, Hindi and English.
</p>
</td>
</table>
<button>Show Contents</button>
<table>
<tr id="info" style="visibility:hidden;">
<td width="80%">
<p style="width:80%;text-align:center; margin-left:1%">
2 - The Planetarium is located on the first floor of the Science Centre. The planetarium has a shape of a sphere, 16.30 meters in diameter, the dome could also be used for extreme-wide-projections and other enhanced multi-media shows. It has a seating capacity of 140 the digital theatre of Planetarium facilitates the observation of planets, moon, stars, nebula, displayed on full dome through an advance technology and thus Astronomy Secrets will be shared with the students and general public. High resolution projectors operated through Digester 3 technology with digital audio system will provide a dazzling shows and that would be unforgettable experience. The shows will be in 3 languages Gujarati, Hindi and English.
</p>
</td>
</table>

Related

How to fix function to where it allows the next function to correctly compute?

hope everyone is doing well. I am new to JavaScript and trying to do a little exercise but having trouble. When I load the page, and click the Blue button, the orange text and red text disappear like I want to, but if I click the Red button after. All of it disappears. I am trying to create something where if I click on one of the colors, the colors that isn't clicked on disappear and only the colored text remains. I want to be able to do it endlessly.
I've tried various websites but haven't been able to get the help I want.
JavaScript
function blueChange() {
var firstHidden = document.getElementById('orange');
firstHidden.style.display = "none";
var secondHidden = document.getElementById('red');
secondHidden.style.display = "none";
}
function redChange() {
var thirdHidden = document.getElementById('blue');
thirdHidden.style.display = "none";
var fourthHidden = document.getElementById('orange');
fourthHidden.style.display = "none";
}
document.getElementById('blueButton').addEventListener("click",
blueChange);
document.getElementById('redButton').addEventListener("click",
redChange);
HTML
<section>
<button id="blueButton">
Blue
</button>
<button id="orangeButton">
Orange
</button>
<button id="redButton">
Red
</button>
</section>
<section id="allParagraphs">
<p style="color:orange" id="orange" class="colors">
So far, authorities are still in the process of collecting
information, and details on exact numbers or the cause of the die off
have been scarce. Several turtle species live in the area—hawksbills,
leatherbacks, olive ridleys, and green turtles.
</p>
<p style="color:red" id="red" class="colors">
In both of these previous cases, red tide was found to be the
cause of the turtles' deaths. "Red tide" is a term that commonly refers
to when colonies of algal blooms grow out of control. Sometimes,
depending on the specific organisms and conditions, they can become toxic
for marine life. Flair ups can occur in fresh and salt water, and they
can be exacerbated by runoff from chemicals like pesticides or untreated
sewer water. For turtles, ingesting the toxic blooms can be deadly.
</p>
<p style="color:blue" id="blue" class="colors">
Mike Liles has lived in El Salvador for the past decade working
on turtle conservation as the director of the country's branch of the
Eastern Pacific Hawksbill Initiative. From his sources on the ground,
Liles has learned that as many as 300 additional dead turtles may have
been found in an area called Isla Tasajara 30 miles west of Jiquilisco
Bay. El Salvador's environmental ministry has yet to confirm this.
</p>
The problem is that you never reset the color that matches the button. So for example, when you click the Blue button, that correctly hides the Orange and Red text. Then if you click the Red button, again, it correctly hides the Orange and Blue text. But the Red text is still hidden from the first time you clicked the Blue button -- you never un-hide that text!
Try adding code to each event listener to reset the color that matches the button clicked. For example:
function blueChange() {
var firstHidden = document.getElementById('orange');
firstHidden.style.display = "none";
var secondHidden = document.getElementById('red');
secondHidden.style.display = "none";
// reset blue.
var blueElement = document.getElementById('blue');
blueElement.style.display = "block";
}
As explained in srk's answer above, you need to reset the display property each time.
In addition, i would suggest that you create a general function like bellow:
function toggleColorDisplay(color){
let colors = ['red', 'orange', 'blue']; // you can add any color you want
colors.forEach(col => {
let elem = document.getElementById(color);
if(col == color) elem.style.display = 'block' // or whatever the original display property is
else elem.style.display = 'none';
})}
Then you call that function:
document.getElementById('blueButton').addEventListener("click", function() {
toggleColorDisplay('blue');
};
Repeat this call for each button, just change the argument to the appropriate color

Expanding all details tags

Anyone know if there is a way to create an expand all link for pages that use the semantic <details> tag? I managed to create a link that would auto-open closed details: Link to details section that expands details section as well
Now I'm trying to add a link that will expand all <details>.
I'm guessing you can do it with javascript but I'm weak there. Something to the effect of clicking a link that initiates a script that finds all "<details in the html and inserting the word "open" before displaying the html. Little help would be appreciated.
So far I'v got
<button onclick="openAll()">Expand All</button>
<script>function openAll() {
var x = document.getElementsByTagName("details");
var i;
for (i = 0; i < x.length; i++) {
x[i].setAttribute("open", "true");
}
</script>
The below works for the first <details> tag but I guess my loop in the above is not correct ...
<script>
function openAll() {
document.getElementsByTagName("details")[0].setAttribute("open", "true");
}
</script>
The below is the dummy html that I'm testing on
<details>Hello World<summary>summary</summary>lost</details>
<details>another<summary>good night moon</summary>find me</details>
To toggle all details elements in the page from JavaScript:
// Toggle open all details elements, onload
// Regardless of their initial status
document.body.querySelectorAll('details')
.forEach((e) => {(e.hasAttribute('open')) ?
e.removeAttribute('open') : e.setAttribute('open',true);
console.log(e.hasAttribute('open'))
})
<details> <!-- Initial status: closed -->
<summary>Details</summary>
Something small enough to escape casual notice.
</details>
<details> <!-- Initial status: closed -->
<summary>Details</summary>
Something small enough to escape casual notice.
</details>
<details> <!-- Initial status: closed -->
<summary>Details</summary>
Something small enough to escape casual notice.
</details>
To close all other details, when one is opened (only one at a time):
document.body.querySelectorAll('summary').forEach((e) => e.addEventListener("click", (e) => {
document.body.querySelectorAll('details').forEach((e) => (e.hasAttribute('open')) ? e.removeAttribute('open') : '')
}))
<details>
<summary>Details</summary>
Something small enough to escape casual notice.
</details>
<details>
<summary>Details</summary>
Something small enough to escape casual notice.
</details>
<details>
<summary>Details</summary>
Something small enough to escape casual notice.
</details>
To toggle every details all at once, when one is opened or closed:
document.body.querySelectorAll('summary').forEach((e) => e.addEventListener("click", (e) => {
e.preventDefault()
document.body.querySelectorAll('details').forEach((e) => (e.hasAttribute('open')) ? e.removeAttribute('open') : e.setAttribute('open', true))
}))
<details>
<summary>Details</summary>
Something small enough to escape casual notice.
</details>
<details>
<summary>Details</summary>
Something small enough to escape casual notice.
</details>
<details>
<summary>Details</summary>
Something small enough to escape casual notice.
</details>
UPDATES
05/31/22 nucleon informed that the open attribute value isn't coerced into a boolean so even a "false" is treated strictly as a string which defaults to a truthy value. The correct way to handle it is to remove open instead. The change is located at the bottom of both snippets:
obj.open = false;
obj.removeAttribute('open');
Thanks, nucleon
04/12/21 trigger-segfault mentioned that should #expAll have any descendants there's a chance that the user could click it making it e.target which would foul up the class switching. Even though in the examples it's not a concern, trigger-segfault makes a good point, so in Snippet 1 e.target is replaced with e.currentTarget which always points to the element that listens for the event (#expAll):
e.currentTarget.classList.toggle('exp');
e.currentTarget.classList.toggle('col');
//...
if (e.currentTarget.classList.contains('exp')) {//...
In Snippet 2 the alternate solution is used -- e.target replaced with this. this also points to the element registered to event(s):
this.classList.toggle('exp');
this.classList.toggle('col');
//...
if (this.classList.contains('exp')) {//...
Thanks trigger-segfault
03/27/17 OP requested that the first 6 <detail>s be excluded. Swapped out .forEach() method for for loop.
See Snippet 2
Use the open attribute of <details>. It's true if open false if closed.
Details commented in Snippet.
SNIPPET 1
// Reference the toggle link
const xa = document.getElementById('expAll');
// Register link on click event
xa.addEventListener('click', function(e) {
/* Toggle the two classes that represent "state"
|| determined when link is clicked
*/
e.currentTarget.classList.toggle('exp');
e.currentTarget.classList.toggle('col');
// Collect all <details> into a NodeList
const details = document.querySelectorAll('details');
/* Convert NodeList into an array then iterate
|| through it...
*/
Array.from(details).forEach(function(obj, idx) {
/* If the link has the class .exp...
|| make each <detail>'s open attribute true
*/
if (e.currentTarget.classList.contains('exp')) {
obj.open = true;
// Otherwise remove [open]
} else {
obj.removeAttribute('open');
}
});
}, false);
<a href='#/' id='expAll' class='col'>Expand All</a>
<details>Hello World
<summary>summary</summary>lost</details>
<details>another
<summary>good night moon</summary>find me</details>
SNIPPET 2
// Reference the toggle link
const xa = document.getElementById('expAll');
// Register link on click event
xa.addEventListener('click', function(e) {
/* Toggle the two classes that represent "state"
|| determined when link is clicked
*/
this.classList.toggle('exp');
this.classList.toggle('col');
// Collect all <details> into a NodeList
const details = document.querySelectorAll('details');
/* Convert NodeList into an array then iterate
|| through it...
*/
const D = Array.from(details);
/* Start a for loop at 6 instead of 0
|| Now 0 - 5 details are excluded
*/
for (let i = 6; i < D.length; i++) {
/* If the link has the class .exp...
|| make each <detail>'s open attribute true
*/
if (this.classList.contains('exp')) {
D[i].open = true;
// Otherwise remove [open]
} else {
D[i].removeAttribute('open');
}
}
}, false);
<a href='#/' id='expAll' class='col'>Expand All</a>
<details>Hello World
<summary>summary 0</summary>lost</details>
<details>another
<summary>good night moon 1</summary>find me</details>
<details>Hello World
<summary>summary 2</summary>lost</details>
<details>another
<summary>good night moon 3</summary>find me</details>
<details>Hello World
<summary>summary 4</summary>lost</details>
<details>another
<summary>good night moon 5</summary>find me</details>
<details>Hello World
<summary>summary 6</summary>lost</details>
<details>another
<summary>good night moon</summary>find me</details>
<details>Hello World
<summary>summary</summary>lost</details>
<details>another
<summary>good night moon</summary>find me</details>
<details>Hello World
<summary>summary</summary>lost</details>
<details>another
<summary>good night moon</summary>find me</details>
<details>Hello World
<summary>summary</summary>lost</details>
<details>another
<summary>good night moon</summary>find me</details>
<details>Hello World
<summary>summary</summary>lost</details>
<details>another
<summary>good night moon</summary>find me</details>
<details>Hello World
<summary>summary</summary>lost</details>
<details>another
<summary>good night moon</summary>find me</details>
<details>Hello World
<summary>summary</summary>lost</details>
<details>another
<summary>good night moon</summary>find me</details>
<details>Hello World
<summary>summary</summary>lost</details>
<details>another
<summary>good night moon</summary>find me</details>
<details>Hello World
<summary>summary</summary>lost</details>
<details>another
<summary>good night moon</summary>find me</details>
The solutions didn't work for me. So, I altered #testing123 solution to get it to work with a complete example.
function openAll() {
var elems = document.getElementsByTagName("details");
document.getElementById("btnExpandHideAllDetails").innerHTML = "Hide All Details on page";
document.getElementById("btnExpandHideAllDetails").setAttribute( "onClick", "javascript: closeAll();");
for (var i = 4; i <= elems.length; i++){
elems[i].setAttribute("open", "true");
}
}
function closeAll() {
var elems = document.getElementsByTagName("details");
document.getElementById("btnExpandHideAllDetails").setAttribute( "onClick", "javascript: openAll();" );
document.getElementById("btnExpandHideAllDetails").innerHTML = "Expand All Details on Page";
for (var i = 4; i <= elems.length; i++){
elems[i].removeAttribute("open");
}
}
<button id="btnExpandHideAllDetails" onclick="openAll()" style="color:white;background-color:green;">Expand All Details on Page</button>
<details>
<summary>0</summary>
</details>
<details>
<summary>1</summary>
</details>
<details>
<summary>2</summary>
</details>
<details>
<summary>3</summary>
</details>
<details>
<summary>Expand me.</summary>
Hello World!
</details>
Here is my solution:
const expandElements = shouldExpand => {
let detailsElements = document.querySelectorAll("details");
detailsElements = [...detailsElements];
if (shouldExpand) {
detailsElements.map(item => item.setAttribute("open", shouldExpand));
} else {
detailsElements.map(item => item.removeAttribute("open"));
}
};
Here how you could use it:
<button onClick="expandElements(true)">Expand</button>
<button onClick="expandElements(false)">Collapse</button>
So zer00ne's solution seems to sometimes work in the browsers (Chrome / Firefox). Sometimes on the second click it works. Sometimes on the first. Sometimes not at all. Maybe because the details tag is still not fully supported?
I went with the solution below ... just has an absolute endpoint at 31 instead of stop at end.
<button id="expand" onclick="openAll()">Expand All +</button>
var elems = document.getElementsByTagName("details");
function openAll() {
for (var i = 4; i <= 31; i++){
elems[i].setAttribute("open", "true");
}
document.getElementById("expand").setAttribute( "onClick", "javascript: closeAll();" );
document.getElementById("expand").innerHTML = "Collapse All -";
}
function closeAll() {
for (var i = 4; i <= 31; i++){
elems[i].removeAttribute("open");
}
document.getElementById("expand").setAttribute( "onClick", "javascript: openAll();" );
document.getElementById("expand").innerHTML = "Expand All +";
}
I wanted something for my own use so I don't care if it works in all browsers.
My approach was to create the expand/close button in each heading of every section of the page containing details elements. The button as an inline block sits at the end of each section heading without me having to add them in manually.
The code goes through the page detail elements to find the closest parent that is either a section, an aside, an article, the main or a div. A unique array of those parent grouping elements is then used to add the buttons to their respective headings. It does not matter whether those headings are h1 - h6, whatever the first one is in each section will have the heading amended with an 'expand' button.
The button itself updates to show 'close' when 'expanded' and visa-versa, therefore behaving like a toggle.
Because I want to be able to search content on the page I have also included a 'expand all' button after the first heading in the main element. This explains that you need to 'expand all' to search in the page.
This 'expand all' updates the daughter 'expand' buttons in each section to show 'close'. It also toggles to 'close all'.
In my opinion this approach is necessary only if you are working with structured content that is using the semantic elements and have a lot of content on the page.
A failing of the details element is that it does hide content from on page search, this is my best effort to work around that for content that is likely to be search, such as technical notes where you might want to hide code snippets and lengthy instructions for setting up software yet still want to search for a given keyword.
document.addEventListener("DOMContentLoaded", function (t) {
var groups = ["section", "aside", "article", "main", "div"], headings = ["h1", "h2", "h3", "h4", "h5", "h6"],
parents = [],
details = document.querySelectorAll("details");
for (var detail of details) for (var group of groups) {
var parent = detail.closest(group);
if (parent) {
if (!parents.includes(parent)) for (var heading in parents.push(parent), headings) {
var location = parent.getElementsByTagName(headings[heading]);
if (location.length) {
var button = document.createElement("button");
button.classList.add("details-helper"),
button.setAttribute("type", "button"),
button.textContent = "Expand",
button.style.display = "inline-block",
location[0].appendChild(button),
button.addEventListener("click", expandGroup(parent));
}
}
break;
}
}
if (parents.length) {
var nav = document.createElement("nav");
nav.classList.add("text-search");
var button = document.createElement("button");
button.classList.add("search-helper"),
button.setAttribute("type", "button"),
button.textContent = "Expand All",
button.style.display = "inline-block",
nav.appendChild(button),
button.addEventListener("click", expandAll());
var p = document.createElement("p");
p.style.display = "inline-block";
var em = document.createElement("em");
em.textContent = "Press before searching this page with CTRL+F";
p.appendChild(em);
nav.appendChild(p);
for (heading of headings) {
if (location = document.querySelector("main " + heading)) {
location.parentNode.insertBefore(nav, location.nextSibling);
break;
}
}
}
function expandGroup(group) {
return function () {
this.classList.contains("close-details") ? (this.classList.remove("close-details"), this.textContent = "Expand", state = false) : (this.classList.add("close-details"), this.textContent = "Close", state = true);
var details = group.getElementsByTagName("details");
Array.from(details).forEach(function (detail) {
detail.open = state;
})
}
}
function expandAll() {
return function () {
this.classList.contains("close-all-details") ? (this.classList.remove("close-all-details"), this.textContent = "Expand All", state = false) : (this.classList.add("close-all-details"), this.textContent = "Close All", state = true);
var buttons = document.querySelectorAll('.details-helper');
Array.from(buttons).forEach(function (button) {
if(!state) {
button.classList.remove("close-details");
} else {
button.classList.add("close-details");
}
button.textContent = state ? "Close" : "Expand";
for (var group of groups) {
var parent = button.closest(group);
if (parent) {
var details = parent.querySelectorAll("details");
Array.from(details).forEach(function (detail) {
detail.open = state;
})
}
}
})
}
}
});
This can be included in a document with a script tag - 'details-helper.js' - and the created buttons include styles.
To keep buttons consistent with the default styling of details elements:
.search-helper,
.details-helper {
font-size: .66em;
margin: 0 1em;
outline: none;
padding: 0.25em;
text-transform: uppercase;
vertical-align: text-bottom;
width: 8em;
}
.search-helper {
width: 10em;
}
.search-helper::after,
.details-helper::after {
content: ' ▶';
}
.close-all-details::after,
.close-details::after {
content: ' ▼';
}
Your mileage may vary with this solution but hopefully you may find some of it useful. Assumptions are made that your page has a main and logical structure to the content. This has not been tested on a page where every element is nested in lots of divs and there are no articles or sections.

change target of javascript to div

I have some img tags with id's but through validating my code I realized that the tags were missing a src. The only problem is, is that in my javascript these img id's are targeted and when I changed them to a div instead the images disappeared.
Basically this page is staff profiles with images and content, the user clicks an arrow and it goes to the next profile. How the code works is that the images are in an external javascript file and when I click something on page and inspect the html I saw that the image appears within the image tags in HTML.This javascript was given to me so I am not sure what to change, I don't know much about javascript. Let me know if any clarification or code is needed, this is very difficult to explain as I don't understand what is going on.
HTML -the problem
<img id='staff_image' class='staff_image'></img>
<img id='staff_name' class='staff_name'></img>
HTML -the page
<div id='staff_slider' class='slider'>
<div class='staff_container'>
<img id='staff_image' class='staff_image' src"#" alt="image"
</div>
<img id='staff_name' class='staff_name' src"#" alt="image"></div>
<div id='staff_details' class='staff_details'></div>
</div>
<div class='slider_navigation'>
<img class='navLeft' src='../assets/images/staff_profile/slider/navLeft.png' alt= "nav left" onclick='navigate(-1);'/>
<img class='navRight' src='../assets/images/staff_profile/slider/navRight.png' alt="nav right" onclick='navigate(1);'/>
</div>
</div>
<script src="staff_profiles.js"></script>
<script src="slider.js"></script>
<script>
navigate(0);
</script>
JAVASCRIPT- slider.js (this is for two arrow buttons that scroll through the profiles)
var slider_index = 0;
function navigate(direction){
slider_index += direction;
if(slider_index < 0)
{
slider_index = profiles.length - 1;
}
else if(slider_index == profiles.length)
{
slider_index = 0;
}
loadProfile(profiles[slider_index]);
}
function loadProfile(profile)
{
var staff_image = document.getElementById('staff_image');
staff_image.src = imgPath + profile.img;
var staff_name = document.getElementById('staff_name');
staff_name.src = titlePath + profile.title;
var staff_details = document.getElementById('staff_details');
staff_details.innerHTML = profile.details;
}
JAVASCRIPT - staff_profiles.js (seperate file, these are the links to the images needed for the profiles, the content are in strings)
var imgPath = "../assets/images/staff_profile/staff/";
var titlePath = "../assets/images/staff_profile/titles/";
var profiles =
[
//
{
img:"fin.jpg",
title:"fin.png",
details:"<p>Stunt pilot with the Red Arrows (UK airforce stunt team), has served in combat choppers in 3 recent wars, and fears nothing except small dogs and single women.</p>" +
"<p>Owns an Extra EA-200 for the ultimate full stunt flight experience, and flies all our other fixed wing craft much more sedately when required. And, yes, that is his real name. He's Irish and he doesn't want to talk about it.</p>"
},
//
{
img:"hans.jpg",
title:"hans.png",
details:"<p>Hans has flown almost everything there is to fly. Hanshas has flown almost everything there is to fly. He first took the controls of a small plane at 12 years old, and flew solo when he was 14. After a few years flying anything anywhere he settled into a series of test pilot jobs but left that because he prefers company when hes in the air.</p>"
},
//
{
img:"john.jpg",
title:"john.png",
details:"<p>With over 10,000 hours piloting helicopters in the bush and mountains of the Southern Alps for deer recovery and mountain rescue operations, Doc is well qualified to land you and your friends in remote parts of the country that only he knows about. He ll help you plot your route, drop extra provisions where you want them, and pick you up when your done.</p>"
},
{
img:"wendy.jpg",
title:"wendy.png",
details:"<p>13 years commercial pilot in Africa, Russia and South America, during which she survived 3 crashes (none her own fault, she maintains). Owns a Cessna-172Skyhawk P that is ideal for low level sight seeing, rides a Harley and is a ski instructor during the seas</p>"
}
];
You need to change the following lines in the loadProfile function
var staff_image = document.getElementById('staff_image');
var myimg = staff_image.getElementsByTagName('img')[0];
myimg.src = imgPath + profile.img;
The HTML could be like this
<div id='staff_image'>
<img src"#" alt="image"/>
</div>
Hope it's useful to you

Trying to add two values from different javascript arrays

I am deriving two different values from these scripts.
Script #1...
//JS for Potential Gen Ed TOC
$(function($) {
$('#CourseMenu select').change(function() {
var sum = 0;
$('#CourseMenu select').each(function(idx, elm) {
sum += parseFloat(elm.value, 10);
});
$('#total_potential').html(Math.min(sum,72).toFixed(2));
});
});
Script #2...
//JS for Potential Gen Ed TOC from Electives only
$(function($) {
$('#CourseMenu_Electives select').change(function() {
var sum = 0;
$('#CourseMenu_Electives select').each(function(idx, elm) {
sum += parseFloat(elm.value, 10);
});
$('#total_potential').html(Math.min(sum,33).toFixed(2));
});
});
However, I'd like to pull the data from both of these and have the result display in the following HTML...
<p><fieldset id="PotentialTOC">
<legend style="font-weight: bold; font-size: 140%;">Potential TOC Evaluation Results</legend>
<div id="Results" style="text-align:left; font-family: 'Century Gothic', Gadget, sans-serif; font-size:14px;"><br />
<div>
<h2><span id="span"></span>
Potential Gen Ed TOC: <span id="total_potential"></span>
<br />
Potential Money Saved: $<span id="total_money"></span>
<br />
Potential Class Time Saved: <span id="total_time"></span> weeks
</fieldset></p>
Here's a jsfiddle to show what I've done so far... I can't transfer more than 33 elective credits and no more than 72 credits overall. I have the scripts laid out well, but again, need them combined to spit out one value.
The first thought that came to mind was to store the result of each function in a hidden div (or even displayed, so a user can see the weight of each choice). Then update the total value by just adding the two columns that contribute to it after the new credit total has been calculated for the new choice.
It will be a minor change, just alter where the current values are being inserted and add an additional line or two to each change callback that pulls in those two values, parses them, adds them, and then updates the total div.
I thought about doing it altogether, just using the previous value from the div, but the problem I ran into was that you weren't sure what the previous contribution was so it made it hard to "zero" the div before adding in the new choice since the choices are not cumulative. One select box should only make one contribution to the final value.
Edit:
So I fiddled with the fiddle and went with the state object approach: http://jsfiddle.net/MCg2d/1
COURSE['Non-electives'] = Math.min(sum, 72).toFixed(2);
var total = (parseFloat(COURSE['Non-electives'], 10) || 0) + (parseFloat(COURSE['Electives'], 10) || 0)
$('#total_potential').html(total);
});
It's very rough but it probably makes more sense than my ramblings above.

Jquery: Count node separation in xml

I'm loading an xml document using JavaScript (Jquery $.ajax).
I need to be able to count the number of branches (b) separating 2 text nodes (s).
E.g.
<b n="Archaea">
<s>Archaea</s>
<b n="Eubacteria">
<s>Cyanobacteria</s>
<s>Spirochaete</s>
<b n="Seaweeds">
<s>Red rags</s>
<s>Calliblepharis</s>
</b>
</b>
<b n="Land plants">
<s>Liverwort</s>
<s>Moss</s>
<s>Bracken fern</s>
<b n="Seed plants">
<s>Scots pine</s>
<s>Ginko</s>
<s>Welwitschia</s>
</b>
</b>
</b>
So, how many branches is 'Scots pine' away from 'Calliblepharis', for example. In this case, the answer would be 4 (Seed plants > Land plants > Archaea > Eubacteria > Seaweeds).
I also need to calculate the 'closest common ancestor' between 2 elements. For example, between 'Scots pine' and 'Ginko' it would be 'Bracken fern' (because Bracken fern is the closest species to the branch that contains 'Scots pine' and 'Ginko'). I'm really not sure how this would work when the 2 elements are very far from each other in different branches.
Sorry if I'm using the wrong language here. Hope it makes sense.
Sorry about the late reply.
I've set up a a demo at jsbin
Hopefully it's fairly self explanatory but if not ask me.
For the xhr bit you need to have an file.xml in the same directory as the page.
This is the main function that gets the distance between the branches
function elementDistance(elem1, elem2) {
var steps = 0;
//the parent elements are the branches
var first = elem1.parentElement;
var second = elem2.parentElement;
//if the elements are at different depths you need to even them up
//and count each time as a step
if (elem1.depth() > elem2.depth()) {
while (first.depth() > second.depth()) {
first = first.parentElement;
steps++;
}
}
else if (elem1.depth() < elem2.depth()) {
while (first.depth() < second.depth()) {
second = second.parentElement;
steps++;
}
}
while (first !== second) {
steps += 2;
first = first.parentElement;
second = second.parentElement;
}
return steps;
}
p.s. the demo doesn't work in firefox or IE

Categories

Resources