I am using Awesome Tables (which I will refer to as AT) to take data from a Google Sheets document and present the data in a format I can embed into a website. I have used a HTML template in the sheets to display the data in the AT form, which utilises inline CSS formatting. The template is only for the table output and as such, only the <body> element exists for that table - i.e. I have no access to <head> section, etc.
I have a piece of data (${"Status"}) pulled in from Google Sheets that can insert one of three text outputs: Active, Delivered or Cancelled. This is called to the output by:
<div style="display:inline-block;color:rgb(87, 87, 87);font-size: 14px;padding: 10px 10px 10px 0;flex-shrink: 0;margin-right: auto;text-transform: capitalize;">
<p><b>Name:</b> ${"Name"}</p>
<p><b>Start Date:</b> ${"Start Date"}</p>
<p><b>Completed Date:</b> ${"Completed Date"}</p>
<p><b>Status:</b> ${"Status"}</p>
</div>
I would like to color format the output text of ${"Status"} so that "Active" = orange, "Cancelled" = red and "Delivered" = green but not 100% sure how to do this. I have read that I probably need to use some sort of JavaScript to achieve this, but to be honest, do not know where to start.
Any help appreciated.
So, following on from the response received, here is my first attempt of writing JavaScript after a bit of online research. Am I heading along the right track?
var jobStatus = "${"Status"}";
if (jobStatus = "Delivered") {
document.getElementById("status").style.color = "green";
} else if (jobStatus = "Active") {
document.getElementById("status").style.color = "orange";
} else {
document.getElementById("status").style.color = "red";
}
If you can edit the html template, I would suggest to use css classes to apply the colors. Therefore just apply the value also as the css class and create a bit of css to format your text (or what ever) how you want it:
<div style="display:inline-block;color:rgb(87, 87, 87);font-size: 14px;padding: 10px 10px 10px 0;flex-shrink: 0;margin-right: auto;text-transform: capitalize;">
<p><b>Name:</b> ${"Name"}</p>
<p><b>Start Date:</b> ${"Start Date"}</p>
<p><b>Completed Date:</b> ${"Completed Date"}</p>
<p class="${"Status"}"><b>Status:</b> ${"Status"}</p>
</div>
The css is static. You can put it in the header section of your document (I understood, you do not have dynamic access to that, is that assumption correct?). Otherwise some js to append it to the body would work as well.
.Active {
color: orange;
}
.Cancelled {
color: red;
}
.Delivered {
color: green;
}
Related
so I finished a coding bootcamp a little while ago and I'm still pretty novice to Javascript. I'm having issues finding a solution to creating dynamic code. Basically I have an email Icon under every employee on the team and when hovering over the icon I want it to show their email. I can hard code this but we have multiple team pages with a different amount of employees on them.
<div class="member">
<img class="member-img" src="/assets/images/signage/example.png" alt="">
<h5 class="member-details">example</h5>
<img onmouseover="showEmail()" onmouseleave="hideEmail()" class="email-icon" id="emailIcon2" src="/assets/images/email-asset-128-fix.png" alt="">
<h5 class="email-txt" id="emailTxt">example#email.com</h5>
</div>
Specifically on this page I have 3 other of these divs for each team member. I have put both the Icons and Email texts h5s into arrays with the code below.
const allIcons = [];
$('.email-icon').each(function() {
allIcons.push(this);
});
console.log(allIcons);
const allEmails = [];
$('.email-txt').each(function() {
allEmails.push(this);
})
console.log(allEmails);
Being newer to Javascript I'm struggling to figure out what I should do here and I can't find a similar solution to this online. I want it be when I hover over Icon 1 it shows Email 1 and so forth, same goes for onmouseleave I just want to hide the h5 again. My css for the email-text is below.
.email-txt {
color: #474747;
margin: 0;
padding: 3px;
transform: translateY(-260%);
border-style: solid;
border-radius: 5px;
border-color: #474747;
background-color: darkgray;
color: black;
display: none;
}
I've tried this solution Change Color of Icon When Hovering Over Adjacent Text With jQuery
I don't know if I'm just not doing it right or what but can't get it to work.
Feel free to judge my code too, the more advice the better :). Thanks!
Assuming that the email addresses are in an array, all you need to do is generate a new image with its title attribute set to the email address for each array entry:
["1#2.com", "3#4.com", "4#5.com", "5#6.com"].forEach(function(item){
let link = document.createElement("a"); // Create dynamic anchor
link.href = "mailto:" + item; // Set link to go to array item
let img = document.createElement("img"); // Create dynamic image
img.alt = item; // Set the required alt attribute
img.src = "https://illustoon.com/photo/dl/2751.png"; // Set image source
img.title = item; // Set the tooltip for the image to the array item
link.append(img); // Put the image in the anchor
document.body.append(link); // Put the anchor on the page
});
img { width: 30px; }
<p>Hover over each icon to see the email address
NOTES:
Don't store HTML elements in an array - - they are already in the DOM so there's no reason to maintain a second list of them. Just store the data you want to work with in the array.
Don't use headings (<h1>...<h6>) because of how the text is styled by the browser. Headings are to define document structure and are essential for those who use assistive technologies (like screen readers) to browse the web. An <h5> would only ever be used to sub-divide an existing <h4> section. And an <h4> should only be used to sub-divide an <h3> section, and so on.
You are using JQuery in your code. While there's nothing inherently wrong with JQuery, it's widely overused to solve simple coding scenarios. Your situation here is very simple and really doesn't warrant JQuery. Learn JavaScript very well before learning JavaScript libraries and frameworks.
You could use CSS to handle the hovering effect, when possible CSS is preferrable over JS to handle these scenarios:
const employees = [{
email: "member1#email.com",
img: "👮"
}, {
email: "member2#email.com",
img: "👷"
}, {
email: "member3#email.com",
img: "💂"
}, {
email: "member4#email.com",
img: "🕵"
}]
employees.forEach(d => {
const html = ` <div class="member">
<div class="member-img">${d.img} </>
<h5 class="member-details">${d.email.match(/.*(?=#)/)}</h5>
<div class="email-icon">✉️<h5 class="email-txt" id="emailTxt">${d.email}</h5></div>
</div>`
root.innerHTML += html
})
#root {
display: flex;
justify-content: center;
}
.member {
display: flex;
flex-direction: column;
align-items: center;
}
.email-icon {
position: relative;
font-size: 3rem;
cursor: pointer;
}
.email-txt {
display: none;
position: absolute;
top: 0;
left: 0;
transform: translateX(-50%);
}
.email-icon:hover .email-txt {
display: block;
}
<div id="root"></div>
I'm sure this has to be documented somewhere, but I'm so new at html that I can't figure out where to look, so feel free to just direct me to the correct reading if it's something obvious. As a note, I code in several languages, but mostly things like python or LaTeX, nothing like html. I have included my attempt at the bottom, but tried to include what I could in terms of my design setup and what problems I am running into. Any solutions to any of the listed problems would be appreciated :)
The setup;
I need to form gigantic table of information that will be populated based on a JSON string given on another webpage. I am currently using javascript to parse the JSON string and form a single global object of my own that has all the relevant information (the JSON string that the user will plug in is huge and I only need a relatively small portion of it). The created object has the following form;
cruData = {hero:[{"cruID":0,"EP":0,"Owned":"No","GearName1":"Empty","GearRarity1":"Empty","GearName2":"Empty","GearRarity2":"Empty","GearName3":"Empty","GearRarity3":"Empty"}]}
With the cruID iterating from 0 to 103 (plans to make it at least a couple hundred higher at some point). All the strings will be populated with strings, and EP/ID are true numbers.
Proposed Setup:
My original plan was to pre-make the (blank) table structure on the separate web page, and then after grabbing the JSON file and parsing it into the cruData object, to populate that table with relevant info (technically ID 1 to 103 for now, no 0 ID in this table) upon page-load when the user goes to it.
The Problems:
1) My concern with this method of forming the table upon page load is that the table is sizable and I'd really rather not have the table get formed on every page load. Is there a way to save this locally so that it gets formed once and then it's in cache?
2) Assuming pre-formatting the table really is a good idea (feel free to tell me I'm stupid for thinking so heh), I will have some 350+ cells (all the 'rarity' cells) that are all identical dropdown boxes. Thus I'd like to make a class type for cells that are a drop-down selection list, but can't figure out how to do that in the style section. I can get a specific td to work, but not a class of td to work. Again, I'm sure this is because I just don't really understand how defining classes or the style section works (I haven't used a class-inheritance system coding before).
To be specific, I would like there to be a drop-down box in 3 different cells of every row of this 100+ row table. They are all identical drop-down selections. To do this, would a form be better? Is there a way to define the drop-down selections one time in a class, and then just point to the class in each cell so that I don't have to re-add the selection options to 3 cells of every single row?
3) I would like each of the rarity cells and the EP cell for each row to be editable by the human, having the new value saved for calculations elsewhere. My idea for this would be to copy the cruData object to a cruComp object that is used for computations, then have that get overwritten by player input; that way I can add a "reset" button on the table page to fix everything back after user remorse kicks in :)
4) I want to color row blocks in the table that correspond to something in the game I'm recording data for. Right now I need every 5 rows to be blocked together in a color after the heading, but that 5 may universally change to another number. Is there a way to set a dynamic variable for this so that I can change one number instead of a bunch? Also in my attempt below it works for the first like 50-70 rows and then starts having all kinds of weird behavior, but I can't figure out why?
[ Solved, found the thead tbody tags which was the problem ]
5) Not a real problem but, is there a way to just have x rows get created without each one being created by hand? The only wrinkle is that the ID numbers in the example given below will have all the numbers 1-103+ but not in that order. I figured I could do some sort of vector that has the numbers in the correct order and then pull the consecutive numbers from that vector in order to number them in order, but I don't know if you can create rows using a FOR loop.
Thanks for the help!
My Attempt: Warning, I'm sure this will make anyone that knows what they are doing die inside, as I keep saying I really have little to no idea what I'm doing in this language. Hence me starting with a silly project to learn by doing :)
<!DOCTYPE html>
<html>
<head>
<title>COTLI Calculator and Ref</title>
<!-- <link rel="stylesheet" href="StyleRef.css"> -->
<script>
function Load_Data() {
var i = 0;
/*
<td>The Bush Whacker</td>
<td id="CrEP_1">Blank</td>
<td id="CrGN1_1">Blank</td>
<td id="CrGR1_1">Blank</td>
<td id="CrGN2_1">Blank</td>
<td id="CrGR2_1">Blank</td>
<td id="CrGN3_1">Blank</td>
<td id="CrGR3_1">Blank</td>
<td id="CrUnLock_1">Blank</td>
*/
for (i = 1; i < lootTable.hero.length; i++) {
"crEP_"+i = cruData.hero[i].EP;
};
}
window.onload = Load_Data;
</script>
</head>
<body style="background-color:lightgrey; text-align:center;">
<style>
<!-- Below is the color coding for the rows broken into batches of 4 bench slots at a time. The offset value is because of how the rows are counted and the "header" row. -->
<!-- tr:nth-child(35n+1) {background-color: #4682b4;} -->
<!-- tr:nth-child(21n+1) {background-color: #e36f8a;} -->
tr:nth-child(20n+2) {background-color: #4682b4;}
tr:nth-child(20n+3) {background-color: #4682b4;}
tr:nth-child(20n+4) {background-color: #4682b4;}
tr:nth-child(20n+5) {background-color: #4682b4;}
tr:nth-child(20n+6) {background-color: #4682b4;}
tr:nth-child(20n+7) {background-color: #3abda0;}
tr:nth-child(20n+8) {background-color: #3abda0;}
tr:nth-child(20n+9) {background-color: #3abda0;}
tr:nth-child(20n+10) {background-color: #3abda0;}
tr:nth-child(20n+11) {background-color: #3abda0;}
tr:nth-child(20n+12) {background-color: #e09e87;}
tr:nth-child(20n+13) {background-color: #e09e87;}
tr:nth-child(20n+14) {background-color: #e09e87;}
tr:nth-child(20n+15) {background-color: #e09e87;}
tr:nth-child(20n+16) {background-color: #e09e87;}
tr:nth-child(20n+17) {background-color: #93b881;}
tr:nth-child(20n+18) {background-color: #93b881;}
tr:nth-child(20n+19) {background-color: #93b881;}
tr:nth-child(20n) {background-color: #93b881;}
tr:nth-child(20n+1) {background-color: #93b881;}
table {
border-collapse: collapse;
border: 5px solid black;
tex-align:center;
}
th {
padding: 20px;
border: solid black 3px;
}
td {
padding: 20px;
border: solid black 1px;
}
td.rarity {
<select>
<option value="volvo">Volvo</option>
<option value="saab">Saab</option>
<option value="mercedes">Mercedes</option>
<option value="audi">Audi</option>
</select>
}
</style>
<h1>
Crusader Table
</h1>
<table align="center">
<tr style="background-color:#e36f8a; text-align:center;">
<th>Crusader Name</th>
<th>EP</th>
<th>Gear 1 Name</th>
<th>Gear 1 Rarity</th>
<th>Gear 2 Name</th>
<th>Gear 2 Rarity</th>
<th>Gear 3 Name</th>
<th>Gear 3 Rarity</th>
<th>Unlocked</th>
</tr>
<!-- Below is the master table for Crusaders. Tags are: CrEP_# for EP, CrGN1_# for Gear 1 name, CrGR1_# for Gear 1 Rarity (similarly gear 2 and 3) and CrUnlock_# for unlock, where # is Crusader ID. -->
<!-- Bench One
The Bush Whacker - 1
RoboRabbit - 38
Graham The Driver - 66
Warwick the Warlock - 75
Slisiblyp, the Alien Scientist - 89
-->
<tr>
<td>The Bush Whacker</td>
<td id="CrEP_1" value=CruData.hero[1].EP> </td>
<td id="CrGN1_1">Blank</td>
<td class="rarity" id="CrGR1_1"></td>
<td id="CrGN2_1">Blank</td>
<td id="CrGR2_1">Blank</td>
<td id="CrGN3_1">Blank</td>
<td id="CrGR3_1">Blank</td>
<td id="CrUnLock_1">Blank</td>
</tr>
Without doing it for you - here are the angles that I would solve these problems
You can cache it locally to a cookie as a string of the literal HTML, but the process really isn't that expensive. If the length is a concern - maybe think about breaking it down into rendering the first X amount of elements.
Create a class for the cell. <td class='dropdown-cell'> [your data] </td> and then in your css: .dropdown-cell{[your css rules} will format only the table cells that have the class dropdown-cell. edit: CSS classes work the same way they would if it was a <td class="custom-class"> or <select class="custom-class"> or <option class="custom-class> whatever element you put it on will inherit that styling as specified by .custom-class in the CSS.
.dropdown{
height: 50px;
width: 200px;
background-color: gray;
}
.dropdown-option{
background-color: lightgray;
}
<select class="dropdown">
<option class="dropdown-option">A</option>
<option class="dropdown-option">B</option>
<option class="dropdown-option">C</option>
</select>
If I'm understanding it right, if you want these edits to be bound to some object. You should create a class for each row, and then run a function onChange or onClick or onKeyup of these editable events and modify the related Object.
class SomeObject{
constructor(id, name, someVal){
this.id = id;
this.name = name;
this.someVal = someVal;
}
}
var numberOfObjects = 5;
var yourObjectsArray = [];
//Create i number of objects and add them to an array of your row objects
//This would be done by looping through your JSON
for(var i = 0; i < numberOfObjects; i++){
yourObjectsArray.push(new SomeObject(i, "Object " + i, "Some Value"));
}
//Build your table
for(var i = 0; i < yourObjectsArray.length; i++){
//The syntax below is Jquery - I suggest using it for event bindings and DOM manipulation
$('#output-table').append('<tr><td class="id">'+ yourObjectsArray[i].id +'</td><td>'+ yourObjectsArray[i].name +'</td><td class="change-val">'+ yourObjectsArray[i].someVal +'</td></tr>');
}
//Bind an event to a click or any jquery event handler
$(document).on('click', '.change-val', function(){
//Get the ID of the row that you clicked
var id = $(this).closest('tr').find('.id').text(); //use value or something else
//Modify the text in the table
var newVal = "New Value";
$(this).text(newVal);
//Parse the array of objects to find the one you need to modify
for(var i = 0; i < yourObjectsArray.length; i++){
if(yourObjectsArray[i].id == id){
yourObjectsArray[i].someVal = newVal;
}
}
//Prove that your object value changed not just the text
$('#output').html("<br>");//clear the output
for(var i = 0; i < yourObjectsArray.length; i++){
$('#output').append('ID: ' + yourObjectsArray[i].id + " Value: " + yourObjectsArray[i].someVal + "<br>");
}
});
table {
border-collapse: collapse;
}
table, th, td {
border: 1px solid black;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Click on a value cell below to change it
<table id="output-table">
<thead>
<tr>
<td>ID</td>
<td>Name</td>
<td>Value</td>
</tr>
</thead>
</table>
<div id="output"></div>
https://developer.mozilla.org/en-US/docs/Web/API/Document/getElementsByClassName add a class to each row and then in a for loop, add conditional formatting for row[i] modulus 5.
You can create rows using a for loop, you just have to give the Javascript the HTML formatting and then use an append to add it to the end https://www.w3schools.com/jsref/met_node_appendchild.asp
I'd recommend Jquery for your DOM manipulation as it makes drilling down to specific ID's, classes, and elements very easy.
Currently in a web cms we are building, we allow users to include any arbitrary content (be it plain text or any html content) to be displayed at any part of the web site. These blocks are called widgets (and obviously we take action to clean them up for security purpose).
I would like to be able to highlight these blocks for debugging purpose when necessary, however I cannot wrap them in any additional elements (such as div) as it may break the layout. I found several questions on this site regrading the same question yet have not any good solution yet.
It would be nice if we are allowed to use some kind of non-layout element (such as the comment tags) to wrap around block of contents to be able to do some action such as highlighting like this, but I have not found any way to do that.
I'm comfortable with any solutions (js, server based, etc) as long as it allows me to outline any block of content without breaking the layout. Please let me know if you have any suggestion.
A few example of widget contents:
Text only widget:
this is a the content of text only widget, there is also no wrapper here.
HTML widget:
<h1>Hello world </h1>
<section class="content">
The problem here is that we do not want to force the users to
always wrap their contents inside a root element.
In this example you can see that the content contains 1 h1 element
and 1 section element. To outline this whole widget we may need to
wrap it by an outer element which may break the layout.
</section>
This is not exactly what you wanted, but it might be close enough (fiddle). The script will wrap widgets with a <span class="highlight">. The span should not effect layout in any way:
.highlight {
display: block; // this will change the layout as it inserts a line break
outline: 1px dashed red;
}
When rendering the html, add a comment before and after a widget:
<!--!!!start widget!!!-->
this is a the content of text only widget, there is also no wrapper here.
<!--!!!end widget!!!-->
When you move to debug mode, run this script to add the highlight span:
var START_WIDGET = '!!!start widget!!!';
var END_WIDGET = '!!!end widget!!!';
function filter( node ) {
if ( node.nodeValue !== START_WIDGET && node.nodeValue !== END_WIDGET) { // filter all comment nodes that are not start or end widget
return( NodeFilter.FILTER_SKIP );
}
return( NodeFilter.FILTER_ACCEPT );
}
filter.acceptNode = filter;
var treeWalker = document.createTreeWalker(
document.body,
NodeFilter.SHOW_COMMENT,
filter,
false
);
var start = null;
while ( treeWalker.nextNode() ) {
if(treeWalker.currentNode.nodeValue === START_WIDGET) {
start = treeWalker.currentNode;
} else if(treeWalker.currentNode.nodeValue === END_WIDGET) {
highlight(start, treeWalker.currentNode);
start = null;
}
}
function highlight(start, end) {
var currentNode = start.nextSibling;
var span = document.createElement('span');
var temp;
span.className = 'highlight';
while(currentNode !== end) {
temp = currentNode;
currentNode = currentNode.nextSibling;
span.appendChild(temp);
}
$(span).insertAfter(start);
}
The treeWalker code is based on this article - Finding HTML Comment Nodes In The DOM Using TreeWalker
Try the style property, outline. It's like border but it's size doesn't affect layout. Wrap your widgets in <span>s as they are inline elements, which makes them perfect if you don't want to disrupt your layout. In addition to the use of outline and <span>, you can use the defaults to facilitate a smooth even layout.
CSS
/* DEFAULTS */
html {
box-sizing: border-box;
font: 400 16px/1.45'Source Code Pro';
}
*,
*:before,
*:after {
box-sizing: inherit;
margin: 0;
padding: 0;
border: 0 solid transparent;
}
/* WIDGETS */
.widget {
outline: 3px dashed orange;
}
.widget.text {
outline: 1px solid blue;
}
.widget.html {
outline: 1px solid red;
}
.widget.html > .content {
outline: 1px solid black;
background: yellow;
}
<span class="widget text">
this is a the content of text only widget, there is also no wrapper here.
</span>
<span class="widget html">
<h1>Hello world</h1>
<section class="content">
The problem here is that we do not want to force the users to
always wrap their contents inside a root element.
In this example you can see that the content contains 1 h1 element
and 1 section element. To outline this whole widget we may need to
wrap it by an outer element which may break the layout.
</section>
</span>
I have an about section, where I've split it up into multiple sections loaded by JavaScript for easier reading. I'd like the side navigation for this to have a different background color if it is both hovered over and if it is the one selected, and ALSO to have a border right with a unique color for each option. I have it working with no problems, but I'm just wondering if there is a more efficient way to do this than the way I currently am.
In a nutshell, the HTML:
<nav>
<p id="bout" onclick="bout()">About Us</p>
<p id="mish" onclick="mish()">Our Mission</p>
<p id="team" onclick="team()">The Team</p>
<p id="how" onclick="how()">How It Works</p>
<p id="poli" onclick="poli()">Policies</p>
</nav>
<div class="actual">
<div id="about">
<h2>About Us</h2>
<p>We are a conglomerate of hoodlums.</p>
</div>
</div><!-- end actual -->
And the JS:
function bout() {
document.getElementById("about").innerHTML= '<h2>About Us</h2><p>We are a conglomerate of hoodlums.</p>';
document.getElementById("bout").style.borderRight='3px solid red';
document.getElementById("mish").style.borderRight='none';
document.getElementById("team").style.borderRight='none';
document.getElementById("how").style.borderRight='none';
document.getElementById("poli").style.borderRight='none';
document.getElementById("bout").style.backgroundColor='ghostwhite';
document.getElementById("mish").style.backgroundColor='bisque';
document.getElementById("team").style.backgroundColor='bisque';
document.getElementById("how").style.backgroundColor='bisque';
document.getElementById("poli").style.backgroundColor='bisque';
}
function mish() {
document.getElementById("about").innerHTML = '<h2>Mission</h2><p>Our mission is to rid the world of dust bunnies.</p>';
document.getElementById("bout").style.borderRight='none';
document.getElementById("mish").style.borderRight='3px solid orange';
document.getElementById("team").style.borderRight='none';
document.getElementById("how").style.borderRight='none';
document.getElementById("poli").style.borderRight='none';
document.getElementById("bout").style.backgroundColor='bisque';
document.getElementById("mish").style.backgroundColor='ghostwhite';
document.getElementById("team").style.backgroundColor='bisque';
document.getElementById("how").style.backgroundColor='bisque';
document.getElementById("poli").style.backgroundColor='bisque';
}
As you can see, it's quite cumbersome to have to explicitly turn off an on each style when clicked. The main key though is to have each border-right be a different color.
Here is a jsfiddle with the whole thing, but for some reason it's not actually acknowledging the JS: http://jsfiddle.net/4CrhD/
Additional random question: Is it possible to link to this page with a different piece of content loaded than about, for example, can I link to this page with "mish()" loaded instead of whats in the HTML?
The best way would be to use CSS. Add remove a class on a parent element and have the CSS apply the right rules.
body.mish #bout{
border-right : 3px solid red,
}
body.bout #bout{
border-right : 3px solid blue,
}
Yes. You need to divide between html and styling. Use CSS!
Then you can change styles e.g. with jQuery.css():
$('#mish').css({
'border-right': '3px solid orange',
'background-color':'ghostwhite'
});
Of course you can define styles in a class. A class describes the styling definition for all elements using a class.
nav > p {
border-right: none;
background-color: bisque;
}
.active {
border-right: 3px solid red;
background-color: ghostwhite;
}
If a button is clicked you can dynamically add and remove a classes with:
$('nav > p').click(function() {
$('nav > p').removeClass('active');
$(this).addClass('active')
});
Because code duplication is bad (and I don't like to set the full innerHTML), you can create a dynamic page like:
pages = {
'bout': {
'id': 'about',
'headline': 'About Us',
'body': 'We are a conglomerate of hoodlums.'
}
}
Extend the above code to
$('nav > p').click(function() {
$('nav > p').removeClass('active');
$(this).addClass('active')
if (pages[$(this).attr('id')]) {
var page = pages[$(this).attr('id')];
$('.actual').first().empty();
var container = $('<div>', { 'id': page.id });
container.append($('<h2>', { 'html': page.headline }));
container.append($('<p>', { 'html': page.body }));
$('.actual').first().append(container);
}
});
Have look at this jsfiddle for a working example
Addressing your "random" question
Additional random question: Is it possible to link to this page with a different piece of content loaded than about, for example, can I link to this page with "mish()" loaded instead of whats in the HTML?
If you want to have links pointing to this page you can parse the window.location.hash object and link with links like page.html#mish.
To set default a "page" we extend our pages object to provide such a information: http://jsfiddle.net/Eu36g/6/
Define your classes in the CSS : bout, mish, about, poli ... For each one put the CSS you want. After that, in the javascript, you just have to change the class of the element (add class or change class, or whatever) and the new CSS will apply
example
document.getElementById("bout").className = "otherclass"
I have annotated text, and I'd like certain annotated words to be color-coded along with their annotations, but I don't want to have to do it manually. Is there a way to have javascript (or jquery) or even css make the first class="Noted" green, then the second blue, and then on the fifth go back to green, and to do the same with the corresponding class="note"s?
you can do this using :nth-child you will need something like jQuery for support for IE though.. working on that...
here's a first fiddle for a CSS only version http:http://jsfiddle.net/zhQ67/2/ ** FIDDLE updated with new code below **
CSS:
.noted:nth-child(4n+1) {
background: green;
}
.noted:nth-child(4n+2) {
background: red;
}
.noted:nth-child(4n+3) {
background: yellow;
}
.noted:nth-child(4n+4) {
background: blue;
}
final update using thirtdots updated code and including some jQuery for IE - JSBIN Page
Ok, based on your jsFiddle you could use something along these lines to get the result you're after:
p:nth-child(5n+1) .Noted, p:nth-child(5n+1) .Annotation {color: green}
as demonstarted in this modification of your jsfiddle
You can get all elements with getElementsByClass an then simply iterate through them, giving every single one and it's corresponding element class="note" a different color.
In jquery.....set the colors as you see fit. jsFiddle demo
<script type="text/javascript">
$(".Noted").each(function(i,e){
switch(i%4){
case 0: $(this).css({color:"#f00"});break;
case 1: $(this).css({color:"#0f0"});break;
case 2: $(this).css({color:"#00f"});break;
case 3: $(this).css({color:"#ff9"});break;
case 4: $(this).css({color:"#f90"});break;
}
});
</script>
First, try encapsulating your elements inside a container. It will make the children selection much easier.
<div id="parent">
<span class="note">Green</span>, <span class="note">blue</span>
then <span class="note">red</span>.
</div>
then, the js :
<script>
var children = document.getElementById('parent').getElementsByTagName('*')
,colours = ['green','blue','red','orange']
,i,j=0,max;
for (i = 0, max = children.length; i<max; i++) {
if(children[i].getAttribute('class') == 'note') {
children[i].setAttribute('style','color:' + colours[j]);
j++;
if (j>colours.length) {
j = 0;
}
}
}
</script>
If the HTML is being generated by a server side script, you could have the script assign a class based on which Annotation is being generated, then in the stylesheet, assign a color to that class, like so:
.note1 { //Corresponds to class='note1'
color: green; //or whatever you want
}
.note2 { //Corresponds to class='note2'
color: blue; //or whatever you want
}
/* and so on */
If the HTML is simply being written statically, then assign the class corresponding to how it defined in the stylesheet, depending on the color you want.
If they are children, you could use something along the lines of clairesuzy's solution.
The other option is to assign all of them as class note and then have an javascript that colors everything marked as class note based on a predefined order that you set.
That would probably be along the lines of something like this (using jQuery):
Demo here: http://jsfiddle.net/hs8Nm/
<p class="note">Note 1</p>
<p class="note">Note 2</p>
<p class="note">Note 3</p>
<p class="note">Note 4</p>
and the corresponding Javascript:
$(document).ready(function(){
var colors = ['green','blue','orange','yellow',"FFFFF0"]; //Assign your color order here.
$('.note').each(function(index){
this.css('color',colors[index%5]);
});
});
Yes, it can be done using CSS Selectors. You can get the first, second, third, and so on element in a list of matching occurences.
Here you go:
<html>
<head>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.5.1/jquery.min.js"></script>
<title>Cycle classes</title>
<style>
.blue {
background-color: blue;
}
.green {
background-color: green;
}
.yellow {
background-color: yellow;
}
</style>
<script>
$(document).ready( function() {
$(".Noted").each(function(i) {
var classes = ['green','blue','yellow'];
$(this).addClass(classes[i % classes.length])
});
})
</script>
</head>
<body>
<div class="Noted">hello</div>
<div class="Noted">world</div>
<div class="Noted">it works</div>
</body>
</html>