wanted: simple HTML file that does disclosure triangle <div> hide/reveal - javascript

I have a program that produces a text report. I want it to make an HTML report with multiple disclosure triangles, so that when you click a triangle more of the report shows or hides. I am okay with embedding JavaScript inside the file, but I really want it all in a single file, with no additional files. Is there an easy way to do this with modern browsers?

If you don't care about compatibility with Internet Explorer, you could use the html tag: http://www.w3schools.com/tags/tag_details.asp
Its a very quick way to prototype disclosure triangles.
For example:
<details>
<summary>The contents of the summary tag is always visible</summary>
<p>Everything else inside the details tag will be hidden in a disclosure triangle</p>
</details>

The simplest way is something like this:
<html>
<head>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js" type="text/javascript"></script>
<style>.wrapper div { display:none;}</style>
<script>
$(function() {
$('.wrapper h2').click(function() { $(this).next().toggle();});
});
</script>
</head>
<body>
<div class="wrapper">
<h2>Example header 1</h2>
<div>bodytext 1</div>
</div>
<div class="wrapper">
<h2>Example header 2</h2>
<div>bodytext 2</div>
</div>
<div class="wrapper">
<h2>Example header 3</h2>
<div>bodytext 3</div>
</div>
</body>
</html>
I have made a simple working example here: http://jsfiddle.net/NXuQt/1/
It isn't pretty but should give you the simple template you need.
Note that in this solution, the entire header is click-able... I figure adding an image and changing it as part of the click event is something you can take care of yoruself, otherwise let me know :)
Note: The javascript is based on the inclusion of the jQuery library.
EDIT: I updated the answer to copy/paste ready working code, the reason you couldn't make it work as it was, was because i had only taken the essentials from the fiddle example. The fiddle automatically ran the click handler initialization at DOMready, which the updated example now has built in :)

With straight HTML, no. That's not what it's for. You will need to use a scripting language, either JavaScript or VBScript, most likely.
This is a script I've used in the past (not mine, but I don't have the URI of the original):
var timerlen = 5;
var slideAniLen = 250;
var timerID = new Array();
var startTime = new Array();
var obj = new Array();
var endHeight = new Array();
var moving = new Array();
var dir = new Array();
function slidedown(objname)
{
if(moving[objname])
return;
if(document.getElementById(objname).style.display != "none")
return; // cannot slide down something that is already visible
moving[objname] = true;
dir[objname] = "down";
startslide(objname);
}
function slideup(objname)
{
if(moving[objname])
return;
if(document.getElementById(objname).style.display == "none")
return; // cannot slide up something that is already hidden
moving[objname] = true;
dir[objname] = "up";
startslide(objname);
}
function startslide(objname)
{
obj[objname] = document.getElementById(objname);
endHeight[objname] = parseInt(obj[objname].style.height);
startTime[objname] = (new Date()).getTime();
if(dir[objname] == "down")
{
obj[objname].style.height = "1px";
}
obj[objname].style.display = "block";
timerID[objname] = setInterval('slidetick(\'' + objname + '\');',timerlen);
}
function slidetick(objname)
{
var elapsed = (new Date()).getTime() - startTime[objname];
if (elapsed > slideAniLen)
{
endSlide(objname)
}
else
{
var d =Math.round(elapsed / slideAniLen * endHeight[objname]);
if(dir[objname] == "up")
d = endHeight[objname] - d;
obj[objname].style.height = d + "px";
}
return;
}
function endSlide(objname)
{
clearInterval(timerID[objname]);
if(dir[objname] == "up")
obj[objname].style.display = "none";
obj[objname].style.height = endHeight[objname] + "px";
delete(moving[objname]);
delete(timerID[objname]);
delete(startTime[objname]);
delete(endHeight[objname]);
delete(obj[objname]);
delete(dir[objname]);
return;
}
function toggleSlide(objname)
{
if(document.getElementById(objname).style.display == "none")
{
// div is hidden, so let's slide down
slidedown(objname);
}
else
{
// div is not hidden, so slide up
slideup(objname);
}
}
You would assign a call to toggleSlide() to the onclick() event of the element you want to toggle.

CSS:
.hidden {
display: none;
}
Javascript:
function createSection(section, hidden) {
var triangle = section.children[0]; // assumes the triangle image is the first child of a section (see HTML)
var contents = section.children[1];
triangle.onclick = function() {
if (contents.className.indexOf("hidden") != -1) { // the section is hidden
contents.className = contents.className.replace("hidden", "");
} else { // the section wasn't hidden
contents.className += " hidden";
}
}
if (hidden) {
contents.className += " hidden";
}
}
// Create the sections when window loads
window.onload = function() {
createSection(document.getElementById("section1"));
createSection(document.getElementById("section2"), true);
}
HTML:
<div id="section1">
<img src="triangle.jpg"></img>
<div>This is the section content</div>
</div>
<div id="section2">
<img src="triangle.jpg"></img>
<div>this section is hidden by default</div>
</div>
Obviously you would have to change some things to your own html file

Well, after some fiddling around, I was able to make a file that does what I want using the switchcontent.js and switchicon.js javascript files I found at http://www.dynamicdrive.com/dynamicindex17/switchcontent2.htm
Here's my code, based on editing down theirs:
<!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" lang="en" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Dynamic Drive DHTML scripts- Switch Content Script II (icon based)</title>
<script type="text/javascript" src="switchcontent.js" ></script>
<script type="text/javascript" src="switchicon.js"></script>
<style type="text/css">
/* Specifies title style */
.iconspan{
margin: 3px;
cursor:hand;
cursor:pointer;
font-weight: bold;
}
</style>
</head>
<body>
<span id="faqtable1-title" class="iconspan"></span>
How hot is our Sun?<br/>
<div id="faqtable1" class="icongroup2">
The surface of the Sun is around 5800 Kelvin, while the core reaches over 15 million Kelvin.
</div>
<br>
<span id="faqtable2-title" class="iconspan"></span>
How big is our Sun in terms of mass? <br/>
<div id="faqtable2" class="icongroup2">
The contains more than 99.8% of the total mass of our Solar System.
</div>
<script type="text/javascript">
var faqtable=new switchicon("icongroup2", "div")
faqtable.setHeader('▼', '▶') //Set header HTML
faqtable.collapsePrevious(false) //Allow more than 1 content to be open simultanously
faqtable.setPersist(true, 7) //Enable persistence to remember last switch content states for 7 days
faqtable.init()
</script>
</body>
</html>
It looks like this when closed:
▶ How hot is our Sun?
▶ How big is our Sun in terms of mass?
And this when opened:
▼ How hot is our Sun?
The surface of the Sun is around 5800 Kelvin, while the core reaches over 15 million Kelvin.
▼ How big is our Sun in terms of mass?
The contains more than 99.8% of the total mass of our Solar System.

Related

Javascript loading speed issue as variable increases

I am having an issue with page loading time. Currently right now I am running UBUNTU in Oracle Vm Virtual Box. I am using mozilla firefox as my browser and I am working on an etchasketch project from "The odin project".
My problem is the page loading time. The code takes a prompt at the start and generates a grid for the etch a sketch based on that prompt. I have not given it the minimum and maximum values (16 and 64) respectively, however any number when prompted at the beginning that is beyond 35 doesn't load or takes ages to load.
How do I speed up the process time? / why is it moving so slow? / how can I avoid this ? / is there a fix that I am over looking that can make this work a lot faster? / feel free to tackle any and all of those questions!
This is my HTML CODE:
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" type="text/css" href="style.css">
<meta charset="utf-8"/>
<title>
</title>
</head>
<body>
<div class="etchhead">
<p> Choose your grid size </p>
<input type = "text"></input>
<button id="startOver"> Clear Grid </button>
<p> Change color </p>
</div>
<div id="grid">
</div>
<script src="eas.js"></script>
</body>
</html>
And this is my CSS code:
p {
color: blue;
display: inline;
}
#grid {
display: grid;
width: 800px;
max-width: 800px;
height: 800px;
max-height: 800px;
line-height: 0;
}
.gridBox {
border: 1px solid black;
background-color: lightgrey
}
And this is my JAVASCRIPT code:
gridStart();
function gridStart(){
var boxes = 0
var selectBody = document.querySelector("#grid");
var addBox = document.createElement("div");
var boxCountStart = prompt("enter a number between 16 and 64");
var boxDimensions = (boxCountStart * boxCountStart);
function rowsAndColumns() {
var selectBody = document.querySelector("#grid");
var gridTemplateColumns = 'repeat('+boxCountStart+', 1fr)';
selectBody.style.gridTemplateColumns= gridTemplateColumns;
selectBody.style.gridTemplateRows= gridTemplateColumns;
};
function hoverColor(){
var divSelector = selectBody.querySelectorAll("div");
divSelector.forEach((div) => {
div.addEventListener("mouseover", (event) => {
event.target.style.backgroundColor = "grey";
});
});
};
rowsAndColumns();
for (boxes = 0; boxes < boxDimensions ; boxes++) {
var selectBody = document.querySelector("#grid");
var addBox = document.createElement("div");
addBox.classList.add("gridBox");
addBox.textContent = (" ");
selectBody.appendChild(addBox);
hoverColor();
};
};
There are two components to your issue. One is that you are repeatedly modifying the DOM in a loop. You can fix it by appending all your boxes to a DocumentFragment and then adding that to the DOM after your loop finishes. You are also calling hoverColor(); inside your loop which results in adding tons of event listeners that all do the same thing (since inside hoverColor you are adding a listener to every single div). You can fix both those issues like this:
var fragment = document.createDocumentFragment( );
for (var i = 0; i < boxDimensions ; i++) {
var addBox = document.createElement("div");
addBox.classList.add("gridBox");
addBox.textContent = (" ");
fragment.appendChild(addBox);
}
document.querySelector("#grid").appendChild( fragment );
hoverColor();
Here is a JSFiddle with your original code, and here is one with the modification.
You could also benefit from only having one event listener total. You don't need to loop and add an event listener to every div. Just add one to #grid and use event.target (like you already do, to find the div that the event originated from). Something like this:
function hoverColor(){
document.querySelector("#grid").addEventListener( 'mouseover', function ( event ) {
event.target.style.backgroundColor = "grey";
} );
}

Auto Click all Links In Div ID

I have a WP blog page which shows recent posts using category shortcodes
On that page, i have a list of links leading to their posts.
I can't edit the links to add id or class to them, so i am manually using a div to wrap the shortcode and a javascript which makes the links open to new tab upon click, is there a way i can open all the links to new tabs open single click? (REMEMBER, I CANT EDIT THE LINKS)
Here is my codes
<!--- i cant edit the links below ----->
<div id="boss" class="boss">
Example 1
Example 2
Example 3
Example 4
</div>
JAVASCRIPT
<script type="text/javascript">
window.onload = function(){
var a = document.getElementById('boss').getElementsByTagName('a');
for (var i=0; i<a.length; i++){
a[i].setAttribute('target', '_blank');
}
}
</script>
am trying to load all the links to their new tabs upon click
<div onclick="boss();">Something To Click On</div>
ITS NOT WORKING, ANY HELP PLS?
Fullcode example:
<!DOCTYPE html>
<!--
To change this license header, choose License Headers in Project Properties.
To change this template file, choose Tools | Templates
and open the template in the editor.
-->
<html>
<head>
<title>TODO supply a title</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script type="text/javascript">
function boss() {
var a = document.getElementById('boss').getElementsByTagName('a');
for (var i = 0; i < a.length; i++) {
a[i].setAttribute('target', '_blank');
openNewTab(a[i], "click");
}
}
function openNewTab(obj, evtName) {
try {
if (obj.dispatchEvent !== null && obj.dispatchEvent !== undefined) {
//var event = new Event(evtName);
var event = document.createEvent("MouseEvents");
event.initMouseEvent(evtName, true, true, window,
0, 0, 0, 0, 0, false, false, false, false, 0, null);
obj.dispatchEvent(event);
} else if (obj.fireEvent !== null && obj.fireEvent !== undefined) {
event = document.createEventObject();
event.button = 1;
obj.fireEvent("on" + evtName, event);
obj.fireEvent(evtName);
} else {
obj[evtName]();
}
} catch (e) {
alert(e);
}
}
</script>
</head>
<body>
<div onclick="boss();">Something To Click On</div>
<div id="boss">
Example 1
Example 2
Example 3
Example 4
</div>
</body>
</html>
That would be easy with jQuery. You can use .each() and .attr() to achieve it.
NOTE
Try this script in your WordPress. Since the below output is a iframe, it won't work!
$ = jQuery;
$(document).ready(function(){
$("#boss > a").each(function(){
$(this).attr("target","_blank");
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="boss" class="boss">
Example 1
Example 2
Example 3
Example 4
</div>
Good Luck :)

.innerHTML: Cannot set property 'innerHTML' of null

First, I am completely new to coding and have been using self-teaching tools to learn Javascript in my free time. I've learned enough to start building my own projects. My first attempt is to build a randomizer (in this case, random restaurant names). The Javascript works through my tests in the console as do the buttons. However, I cannot seem to get the .innerHTML to work and I'm not sure what I'm missing. I've done several searches here and none of the solutions I've found seem to be working.
The error I'm getting is listed in the title and it is appearing at line 29.
Here is Javascript:
var randomRestaurant = {
restaurantName: [],
findRestaurant: function() {
var restaurantName = Math.random();
if (restaurantName < 0.20) {
this.restaurantName.push("China Taste");
}
else if (restaurantName < 0.40) {
this.restaurantName.push("Pizza Johns");
}
else if (restaurantName < 0.60) {
this.restaurantName.push("Liberatore's");
}
else if (restaurantName < 0.80) {
this.restaurantName.push("Bill Bateman's");
}
else {
this.restaurantName.push("R&R Taqueria");
}
},
clearRestaurant: function() {
randomRestaurant.restaurantName.splice(0, 1);
}
};
var randomRestaurantButton = document.getElementById('randomRestaurantName');
randomRestaurantButton.addEventListener('click', function() {
randomRestaurant.findRestaurant();
document.getElementById("restaurantNameDisplay").innerHTML = randomRestaurant.restaurantName[0]; //<--line 29
});
var randomRestaurantButton = document.getElementById('refreshRestaurant');
randomRestaurantButton.addEventListener('click', function() {
randomRestaurant.clearRestaurant();
randomRestaurant.findRestaurant();
document.getElementById("restaurantNameDisplay").innerHTML = randomRestaurant.restaurantName[0];
});
And here is my HTML:
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div><h1>Random Restaurant!</h1>
<button id="randomRestaurantName">Click me for a random restaurant!</button>
</div>
<br>
<h2="restaurantNameDisplay"></h2="restaurantNameDisplay">
<div>
<br>
<button id="refreshRestaurant">Nah. Give me another one.</button>
</div>
</body>
<script src="script.js"></script>
</html>
Thanks for your help and hopefully it's not due to something stupid like a typo.
There are some problems here.
the h2 tag id should be
<h2 id="restaurantNameDisplay"></h2>
your buttons are set on the same variable name, change the second to
var refreshRestaurantButton = document.getElementById('refreshRestaurant');
refreshRestaurantButton.addEventListener('click', function () {
randomRestaurant.clearRestaurant();
randomRestaurant.findRestaurant();
document.getElementById("restaurantNameDisplay").innerHTML = randomRestaurant.restaurantName[0];
});
If it's still not working, you should call your script after the page load event.
so insert your javascript code to a function (e.g. "myFunc()") and change your html body tag to:
body onload="myFunc()">
Most probably this line <h2="restaurantNameDisplay"></h2="restaurantNameDisplay"> should be
<h2 id="restaurantNameDisplay"></h2>

My javascript "slideshow" isnt working

Here is a small part of a website that I'm experimenting with. Anyway I'm learning Javascript and I decided to experiment by making an extremely simple "slideshow", but whenever I run this in the browser (Mozilla Firefox 42), the browser crashes. I'm wondering if anyone could tell me whats wrong or possibly give me a better way of making this(I'm sure there is but I couldn't find one). Also I know I can make this in jQuery but I want to try this out with pure Javascript.
I have also tried this on Chrome and Opera.
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript">
//I will use javascript to make the "slideshow" on mainSection
function loop() {
var BACKGROUND = document.getElementById("Introduction");
var SECTION1 = document.getElementById("mainSection");
var SECTION2 = document.getElementById("section2");
var SECTION3 = document.getElementById("section3");
var i = 1;
while (i <= 3) {
i = i + 0.0001;
SECTION1.style.display="block";
SECTION2.style.display="none";
SECTION3.style.display="none";
}
while (i <= 6) {
i = i + 0.0001;
SECTION1.style.display="none";
SECTION2.style.display="block";
SECTION3.style.display="none";
}
while (i <= 9) {
i = i + 0.0001;
SECTION1.style.display="none";
SECTION2.style.display="none";
SECTION3.style.display="block";
}
while (i = 9) {
i = 1;
}
}
</script>
</head>
<body onload="loop();">
<header id="Introduction">
<section id="mainSection">
<h1>Welcome to the Ipsum Hotel.</h1>
<p>This is where thought and precision goes<br />
towards the comfort of our customers.<br /></p>
</section>
<!--This will be used to make a slideshow-->
<section id="section2">
<p><strong>Free Wifi!</strong></p>
<p>Free wifi is included in all of our guest<br />
packages from Economy to Deluxe<br /></p>
</section>
<section id="section3">
<p><strong>Free Hot Breakfast</strong></p>
<p>Included with any of our guest packages is<br />
a hearty breakfast. You can also get a personalized<br />
omelet at our omelet bar.<br /></p>
</section>
</header>
</body>
</html>
Try using setInterval. As mentioned in the comments, a while loop will block all page operations and tax your CPU. setInterval is designed specifically for handling timing operations in a more resource-friendly manner.
var SECTION1 = document.getElementById("mainSection");
var SECTION2 = document.getElementById("section2");
var SECTION3 = document.getElementById("section3");
var sections = [SECTION1, SECTION2, SECTION3];
var activeSection = 0;
setInterval(function() {
// If we are past the end of list, reset to first element
if (activeSection >= sections.length) {
activeSection = 0;
}
// Mark only the activeSection as visible
sections.forEach(function(section, idx) {
section.style.display = activeSection === idx ? 'block' : 'none';
});
activeSection += 1;
}, 3000);
This will loop over each section every three seconds (at the least, see https://developer.mozilla.org/en-US/docs/Web/API/WindowTimers/setInterval for more info about how timers work in the browser). Once the last section is reached, it resets to the first section.

IE8 display overlap occurs using insertBefore

I'm attempting to move div elements from one section to another using node.insertBefore and order the insertion alphabetically. Upon clicking (in this case clicking A) to reorder I have a problem with elements overlapping as seen in the image below:
The code I'm using to produce this follows; I'm sorry it's a little long, but if you copy it into an html file in it's entirety you'll easily see my problem.
<!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>
<script type="text/javascript">
var moveUp, moveDown;
var moveUp = function() {
var e = window.event.srcElement;
var firstBlock = document.getElementById('firstBlock');
var moved = false;
for (var i=0; i<firstBlock.childNodes.length; i++) {
if (firstBlock.childNodes[i].innerText > e.innerText) {
firstBlock.insertBefore(e, firstBlock.childNodes[i]);
moved = true;
break;
}
if (!moved) firstBlock.appendChild(e);
}
e.onclick = moveDown;
};
var moveDown = function() {
var e = window.event.srcElement;
var secondBlock = document.getElementById('secondBlock');
var moved = false;
for (var i=0; i<secondBlock.childNodes.length; i++) {
if (secondBlock.childNodes[i].innerText > e.innerText) {
secondBlock.insertBefore(e, secondBlock.childNodes[i]);
moved = true;
break;
}
if (!moved) secondBlock.appendChild(e);
}
e.onclick = moveUp;
};
</script>
<title>Test</title>
</head>
<body>
<div id="firstBlock" style="background-color:#dddddd;">
<div onclick="moveDown()">A</div>
<div onclick="moveDown()">B</div>
<div onclick="moveDown()">C</div>
<div onclick="moveDown()">D</div>
</div>
<div id="secondBlock">
<div onclick="moveUp()">E</div>
<div onclick="moveUp()">F</div>
<div onclick="moveUp()">G</div>
<div onclick="moveUp()">H</div>
</div>
</body>
</html>
Am I doing something wrong/odd? Can this be fixed/worked around? Thanks in advance for your help!
Edit:
I can't currently test in any other browsers.
I notice that once one section fills up, the highlighting no longer readjusts itself when items move between sections.
Edit 2: Result of jsfiddle posted by Jared
Happened to come back to this question now. In case anyone else is having this problem, I ended up having to replace the div list with a table and rearrange table rows. Another option may be to use a list.

Categories