Previous and Next Sibling JavaScript - javascript

Okay so I've been studying the book JavaScript and jQuery interactive front end development by "Jon Duckett"
Im on page 210 "Previous and Next Sibling" how do i change the li.a attributes in the navigation drop down sub menu, i have removed all white space so that it does not pick up any unwanted textNodes in the HTML like so.
<ul>
<li>
Web Development
</li>
<li>
Graphic Design
</li>
<li>
Prototypes
</li>
<li>
Fun Stuff
</li>
</ul>
I added the JavaScript from the book to change the value of the class attributes but I am having trouble with this, it does not work but when I change the id to the <li>, the previous and next siblings disappear. i am confused as the code looks correct and it works on a different web page when i give the <li> an id. But does not seem to be working here which is strange. Any help to get this working would be great thanks
/*Javascript
Previous and Next Sibling for portfolio subLinks,
=====================================================================*/
var startItem = document.getElementById('subGraph');
var prevItem = startItem.previousSibling;
var nextItem = startItem.nextSibling;
/*change the value of the siblings class Attributes
=====================================================================*/
prevItem.className = 'checkIcon';
nextItem.className = 'altSubLinks1';
/*CSS
============================*/
.checkIcon{
background-color: teal;
color:#FFF;
text-shadow: 2px 2px 1px #3b6a5e;
border-top:1px solid #7ee0c9;
border-top: 1px solid #3b6a5e;
content: '\f00c';
position: absolute;
font-family: fontAwesome;
right: 5px;
line-height:50px;
color:#FFF;
}
.altSubLinks1{
background-color: #FFF;
color: #000;
}

The fact that your markup is all packed up and unindented (due to the textNodes i know) makes it hard to see that the element you are matching has no siblings.
Take a look at the indented markup:
<ul>
<li>Web Development</li>
<li>Graphic Design</li>
<li>Prototypes</li>
<li>Fun Stuff</li>
</ul>
Note that subGraph is the <a> tag that has no siblings. Only the <li> have siblings.
Therefore you must either set the ids on the <li> tags or navigate to them with parentElement.
Example with parentElement:
var startItem = document.getElementById('subGraph');
var prevItem = startItem.parentElement.previousSibling;
var nextItem = startItem.parentElement.nextSibling;
prevItem.className = 'checkIcon';
nextItem.className = 'altSubLinks1';
.checkIcon {
color:red;
}
.altSubLinks1 {
color:green;
}
<ul><li>Web Development</li><li>Graphic Design</li><li>Prototypes</li><li>Fun Stuff</li></ul>

Related

How can i detect class name of an element using template literals inside querySelector

I have two navigation boxes where first one has a CSS Class .one and Second one is blank. For first navigation box, I given a border with JavaScript by detecting the class name .one. But I getting border for second navigation box too eventhough it don't have a class. Here i use template literals approach. I know that i can fix this using class name directly inside the querySelectorAll method as follows let li = document.querySelectorAll(".one > ul li");. But I need template literals solution which is most usefull for me to use some other projects too. Mainly i need to represent class name as a variable. Following is my code. Can anyone help me on this. Thanks in Advance!
let parents = document.querySelector(".one");
let li = document.querySelectorAll(`${parents.tagName} > ul li`);
li.forEach((elem)=>{elem.style.border="1px solid red"});
nav {font-family:arial;width:15rem;}
nav ul {list-style:none;padding:0;margin:1rem;padding-left:.5rem;}
nav ul a {color:#777;text-decoration:none;padding:.5rem;}
<nav class="one">
<ul>
<li>Home</li>
<li>About
<ul>
<li>Vision</li>
<li>Mission</li>
</ul>
</li>
<li>Contact</li>
</ul>
</nav>
<br>
<nav>
<ul>
<li>Home</li>
<li>About</li>
<li>Contact</li>
</ul>
</nav>
Try replacing this line:
let li = document.querySelectorAll(`${parents.tagName} > ul li`);
with this one:
let li = parents.querySelectorAll(`ul li`);
The reason it doesn't work for you as you expected, is because you are matching all the elements with the query selector nav > ul li within the document, and you are completely ignoring the class name of the nav tag you have selected in parents variable.
Otherwise, you can simply do this instead:
let li = document.querySelectorAll(`.one > ul li`);
li.forEach((elem)=>{elem.style.border="1px solid red"});
or just use the CSS:
.one > ul li {
border: 1px solid red;
}
or if you want to select the first element (I don't know what are your intentions, but I'm guessing according to your code):
.one:first-child > ul li {
border: 1px solid red;
}
Don't need JavaScript. It can be possible by only CSS.
.one > ul > li { border: 1px solid red}
or in your JS change
let li = document.querySelectorAll(`${parents.tagName} > ul > li`);

Change the selected list element in a navigation list using plain JavaScript

I have trouble in writing a script to change the appearance of the clicked tab in a webpage navigation list. In other words, I want to make the clicked tab appear as the selected (in code). I tried to do that by changing its id to selected_link and restoring the id of the previously selected tab.
EDIT: Following jamespaned's suggestion, I replaced element IDs with classes.
My tabs appear like in this picture:
So, when I click to "bio", I want it to appear as "home" and "home" to appear as the other tabs.
As I'm a newbie in JavaScript coding, I didn't managed to accomplish that. Here is what I've done:
The HTML code for the (inline) navigation list:
<nav>
<ul id="navlist">
<li class="selected"> home </li>
<li class=""> bio </li>
<li class=""> publications </li>
<li class=""> software </li>
<li class=""> contact </li>
</ul>
</nav>
its respective CSS:
nav ul {
list-style:none;
padding:0;
margin:0;
}
nav li {
background-color:black;
display:inline;
border:solid;
border-width:1px 1px 0 1px;
margin:0 5px 0 0;
}
nav li a {
color:white;
padding:0 10px;
}
.selected {
background-color:white;
padding-bottom: 1px;
}
.selected_link{
color:blue;
}
and the JavaScript which I've designed to accomplish this task, but it didn't worked:
function changeSelected(clickedId)
{
var ulist = document.getElementById("navlist");
var elems = ulist.getElementsByTagName("class");
for (var i = 0; i < elems.length - 1; i++)
{
var sel = elems[i].getAttribute("class");
if (sel == selected)
{
var selli = elems[i];
break;
}
}
selli.setAttribute("class", "");
selli.lastElementChild.setAttribute("class", "");
var clicked = document.getElementById(clickedId);
clicked.setAttribute("class", "selected_link");
clicked.parentNode.setAttribute("class", "selected");
}
How could I do that using only plain JavaScript?
This Javascript will do what you want:
function changeSelected(clickedId)
{
var selli = document.getElementById("selected");
var sela = document.getElementById("selected_link");
sela.setAttribute("id", "");
selli.setAttribute("id", "");
var clicked = document.getElementById(clickedId);
clicked.setAttribute("id", "selected_link");
clicked.parentNode.setAttribute("id", "selected");
}
That said, here are some ideas that might help your Javascript education:
You are using Javascript to set your IDs, but the Javascript won't work on the next page after you've clicked on one of the links. You'll probably need to do some backend (PHP/Ruby, etc) coding to get your styles to change.
IDs are normally used to refer to a unique element on the page that doesn't change, such as a #header or #sidebar_banner. You might want to use a class instead, such as ".selected_link".
You don't need both #selected_link and #selected. You could do ".selected" and ".selected a" to change the CSS so you only need to change one element.
Hope that helps!

How to represent a breadcrumb child?

I represent the breadcrumb in a table as follow:
<ol class="breadcrumb" data-sly-use.breadcrumb="myModel.js">
<output data-sly-unwrap data-sly-list="${breadcrumb}">
<li itemscope itemtype="http://data-vocabulary.org/Breadcrumb">
<a href="${item.href}" itemprop="url">
<span itemprop="title">${item.label}</span>
</a>
</li>
</output>
</ol>
How to represent the breadcrumb child in this structure?
It seems like you are using apache sling, which I haven't used myself, but for setting up a simple breadcrumb, it can be done just with CSS. Here is one which I set up using display: inline on the the li.
jsfiddle
I'm sure you could use some pretty nice styling on it, but this is a simple example using a triangle for the arrows on the breadcrumb.
html
<div id="menu">
<ul>
<li>
<a href="#" itemprop="url">
<span itemprop="title">item 1</span>
</a>
</li>
<div class="arrow-right"></div>
<li>
<a href="#" itemprop="url">
<span itemprop="title">item 2</span>
</a>
</li>
</ul>
</div>
css
.arrow-right {
width: 0;
height: 0;
border-top: 0.5em solid transparent;
border-bottom: 0.5em solid transparent;
border-left: 0.5em solid black;
display: inline-block;
}
#menu ul{
list-style: none;
}
#menu li{
display: inline;
}
I'm not entirely sure what your question is. What do you mean by "breadcrumb child"? In the Sightly example you give each item is one of the elements of the breadcrumb, so that is what I would assume the "child" is, but that doesn't seem to be what you mean.
If the question is about what myModel.js might look like, it would simply have to implement the javascript Use API and return a list of objects. For example
"use strict";
use(function () {
var crumbs= [];
crumbs.push({href: '/home/path', label: 'Home'});
crumbs.push({href: '/section/path', label: 'Section'});
return crumbs;
});
Rather than hard coding the crumbs you can use the objects that Sling gives you to get the parents of the current page, but this works as a simple example.
note: At this point you should probably use the Java API, rather than the javascript API for production code. See the comparison chart from Adobe's Sightly Intro

CSS doesn't effect dynamically created list on Phonegap

similar to my question is this one
and this one
however, still haven't sorted any solution..
i have in the <body> an unordered list <ul> each element of which is added after performing a query to a database..So according to the result, i have the corresponding <li> tags created..
Ther problem is, that although i have some css to seperate <li> to "odd" and "even" so that i can apply some different styles, and i have confirmed, that the "odd" and even" attibute has passed as an attribute (classname) to <li> still the corresponding css rules, do not apply
here is some of my code.. first the html part
<div id="sqldiv">
<ul class="test" id="attempt">
</ul>
</div>
and the javascript part..
for (var i=0; i<len; i++){
var somevariable = results.rows.item(i).dbvariable;
if (i%2==0)
lt='Even';
else
lt='Odd';
var newLI = document.createElement("LI");
newLI.className = lt;
var htmlcontainer = ("<div>my text :" + my variables + "</div><div>my text :</div><div>" my variables + "</div>");
newLI.innerHTML = htmlcontainer ;
var gl = document.getElementById("attempt");
gl.appendChild(newLI);
}
and the css
li {
background: #8258FA;
list-style-type:none;
list-style-image:none;
margin: 5px 5px;
border-radius: 15px;
}
li.odd {
border-bottom :1px dotted #ccc;
list-style-type:none;
list-style-image:none;
margin: 5px 5px;
background: #000000;
}
the li styling does apply, but the styling by class (li.odd) doesn't
after spending last 24 hours searching..i tried sth that didn't cross my mind..!!!!
in javascript i name class Even and Odd..and on css i have .even and .odd rules.. and this worked great on another project..!!!
but, for some reason, in this case there seemed to be a "case sensitive" issue.. since i changed css rule to .Even and .Odd, they were applied successfully..
before reaching this, i had also tried assigning dynamic css rules using jquery..and after some attempts, i ended up to the case sensitive..

Change link color of the current page with CSS

How does one style links for the current page differently from others? I would like to swap the colors of the text and background.
HTML:
<ul id="navigation">
<li class="a">Home</li>
<li class="b">Theatre</li>
<li class="c">Programming</li>
</ul>
CSS:
li a{
color:#A60500;
}
li a:hover{
color:#640200;
background-color:#000000;
}
With jQuery you could use the .each function to iterate through the links with the following code:
$(document).ready(function() {
$("[href]").each(function() {
if (this.href == window.location.href) {
$(this).addClass("active");
}
});
});
Depending on your page structure and used links, you may have to narrow down the selection of links like:
$("nav [href]").each ...
If you are using URL parameters, it may be necessary to strip these:
if (this.href.split("?")[0] == window.location.href.split("?")[0]) ...
This way you don't have to edit each page.
a:active : when you click on the link and hold it (active!).
a:visited : when the link has already been visited.
If you want the link corresponding to the current page to be highlighted, you can define some specific style to the link -
.currentLink {
color: #640200;
background-color: #000000;
}
Add this new class only to the corresponding li (link), either on server-side or on client-side (using JavaScript).
It is possible to achieve this without having to modify each page individually (adding a 'current' class to a specific link), but still without JS or a server-side script. This uses the :target pseudo selector, which relies on #someid appearing in the addressbar.
<!DOCTYPE>
<html>
<head>
<title>Some Title</title>
<style>
:target {
background-color: yellow;
}
</style>
</head>
<body>
<ul>
<li><a id="news" href="news.html#news">News</a></li>
<li><a id="games" href="games.html#games">Games</a></li>
<li><a id="science" href="science.html#science">Science</a></li>
</ul>
<h1>Stuff about science</h1>
<p>lorem ipsum blah blah</p>
</body>
</html>
There are a couple of restrictions:
If the page wasn't navigated to using one of these links it won't be
coloured;
The ids need to occur at the top of the page otherwise the
page will jump down a bit when visited.
As long as any links to these pages include the id, and the navbar is at the top, it shouldn't be a problem.
Other in-page links (bookmarks) will also cause the colour to be lost.
JavaScript will get the job done.
Get all links in the document and compare their reference URLs to the document's URL. If there is a match, add a class to that link.
JavaScript
<script>
currentLinks = document.querySelectorAll('a[href="'+document.URL+'"]')
currentLinks.forE‌​ach(function(link) {
link.className += ' current-link')
});
</script>
One Liner Version of Above
document.querySelectorAll('a[href="'+document.URL+'"]').forEach(function(elem){elem.className += ' current-link'});
CSS
.current-link {
color:#baada7;
}
Other Notes
Taraman's jQuery answer above only searches on [href] which will return link tags and tags other than a which rely on the href attribute. Searching on a[href='*https://urlofcurrentpage.com*'] captures only those links which meets the criteria and therefore runs faster.
In addtion, if you don't need to rely on the jQuery library, a vanilla JavaScript solution is definitely the way to go.
a:link -> It defines the style for unvisited links.
a:hover -> It defines the style for hovered links.
A link is hovered when the mouse moves over it.
include this! on your page where you want to change the colors save as .php
<?php include("includes/navbar.php"); ?>
then add a new file in an includes folder.
includes/navbar.php
<div <?php //Using REQUEST_URI
$currentpage = $_SERVER['REQUEST_URI'];
if(preg_match("/index/i", $currentpage)||($currentpage=="/"))
echo " class=\"navbarorange/*the css class for your nav div*/\" ";
elseif(preg_match("/about/*or second page name*//i", $currentpage))
echo " class=\"navbarpink\" ";
elseif(preg_match("/contact/* or edit 3rd page name*//i", $currentpage))
echo " class=\"navbargreen\" ";?> >
</div>
N 1.1's answer is correct. In addition, I've written a small JavaScript function to extract the current link from a list, which will save you the trouble of modifying each page to know its current link.
<script type="text/javascript">
function getCurrentLinkFrom(links){
var curPage = document.URL;
curPage = curPage.substr(curPage.lastIndexOf("/")) ;
links.each(function(){
var linkPage = $(this).attr("href");
linkPage = linkPage.substr(linkPage.lastIndexOf("/"));
if (curPage == linkPage){
return $(this);
}
});
};
$(document).ready(function(){
var currentLink = getCurrentLinkFrom($("navbar a"));
currentLink.addClass("current_link") ;
});
</script>
Best and easiest solution:
For each page you want your respective link to change color to until switched, put an internal style in EACH PAGE for the VISITED attribute and make each an individual class in order to differentiate between links so you don't apply the feature to all accidentally. We'll use white as an example:
<style type="text/css">
.link1 a:visited {color:#FFFFFF;text-decoration:none;}
</style>
For all other attributes such as LINK, ACTIVE and HOVER, you can keep those in your style.css. You'll want to include a VISITED there as well for the color you want the link to turn back to when you click a different link.
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html><head>
<style type="text/css"><!--
.class1 A:link {text-decoration: none; background:#1C1C1C url(..../images/menu-bg.jpg) center top no-repeat; border-left: 4px solid #333333; border-right: 4px solid #333333; border-top: 3px solid #333333; border-bottom: 4px solid #333333;}
.class1 A:visited {text-decoration: none; background:#1C1C1C url(..../images/menu-bg.jpg) center top no-repeat; border-left: 4px solid #333333; border-right: 4px solid #333333; border-top: 3px solid #333333; border-bottom: 4px solid #333333;}
.class1 A:hover {text-decoration: none; background:#1C1C1C url(..../images/menu-bg.jpg) center top no-repeat; border-left: 3px solid #0000FF; border-right: 3px solid #0000FF; border-top: 2px solid #0000FF; border-bottom: 2px solid #0000FF;}
.class1 A:active {text-decoration: none; background:#1C1C1C url(..../images/menu-bg.jpg) center top no-repeat; border-left: 3px solid #0000FF; border-right: 3px solid #0000FF; border-top: 2px solid #0000FF; border-bottom: 2px solid #0000FF;}
#nav_menu .current {text-decoration: none; background:#1C1C1C url(..../images/menu-bg.jpg) center top no-repeat; border-left: 3px solid #FF0000; border-right: 3px solid #FF0000; border-top: 2px solid #FF0000; border-bottom: 2px solid #FF0000;}
a:link {text-decoration:none;}
a:visited {text-decoration:none;}
a:hover {text-decoration:none;}
a:active {text-decoration:none;}
--></style>
</head>
<body style="background:#000000 url('...../images/bg.jpg') repeat-y top center fixed; width="100%" align="center">
<table style="table-layout:fixed; border:0px" width=100% height=100% border=0 cellspacing=0 cellpadding=0 align=center><tr>
<td style="background: url(...../images/menu_bg-menu.jpg) center no-repeat;" "border:0px" width="100%" height="100%" align="center" valign="middle">
<span class="class1" id="nav_menu">
<font face="Georgia" color="#0000FF" size="2"><b> Home </b></font>
<font face="Georgia" color="#0000FF" size="2"><b> FAQs page </b></font>
<font face="Georgia" color="#0000FF" size="2"><b> About </b></font>
<font face="Georgia" color="#0000FF" size="2"><b> Contact </b></font>
</span>
</td></tr></table></body></html>
Note: the style goes in between the head tag (<head> .... </head>) and the class="class1" and the id="nav_menu" goes in the ie: (-- <span class="class1" id="nav_menu"> --).
Then the last class attribute (class="current") goes in the hyper-link code of the link in the page that you want the active current link to correspond to.
Example: You want the link tab to stay active or highlighted when it's correspondent page is whats currently in view, go to that page itself and place the class="current" attribute by it's link's html code. Only in the page that corresponds to the link so that when ever that page is at view, the tab will stay highlighted or stand out different from the rest of the tabs.
For the Home page, go to the home page and place the class in it. example: <a href="http://Yourhomepage-url.com/" class="current" target="_parent">
For the About page, go to the about page and place the class in it. example: <a href="http://Yourhomepage-url.com/youraboutpage-url.php_or_.html" class="current" target="_parent">
For the Contact page, go to the contact page and place the class in it. example: <a href="http://Yourhomepage-url.com/youraboutpage-url.php_or_.html" class="current" target="_parent">
etc ......
Notice the example Table above;- Lets assume this was the Home page, so on this page, only the Home url link section has the class="current"
Sorry for any meaning-less error, am not a prof. but this worked for me and displays fine in almost all the browsers tested, including ipad, and smart phones. Hope this will help some-one out here because is very frustrating to want to and not able to. I had tried so had to get to this, and so far it's good for me.
#Presto
Thanks! Yours worked perfectly for me, but I came up with a simpler version to save changing everything around.
Add a <span> tag around the desired link text, specifying class within. (e.g. home tag)
<nav id="top-menu">
<ul>
<li> <span class="currentLink">Home</span> </li>
<li> About </li>
<li> CV </li>
<li> Photos </li>
<li> Archive </li>
<li> Contact</li>
</ul>
</nav>
Then edit your CSS accordingly:
.currentLink {
color:#baada7;
}
You do not need jQuery just to do this! All you need is a tiny and very light vanilla Javascript and a css class (as in all the answers above) :
First define a CSS class in your stylesheet called current.
Second add the following pure JavaScript either in your existing JavaScript file or in a separate js script file (but add script tage link to it in the head of the pages) or event just add it in a script tag just before the closing body tag, it will still work in all these cases.
function highlightCurrent() {
const curPage = document.URL;
const links = document.getElementsByTagName('a');
for (let link of links) {
if (link.href == curPage) {
link.classList.add("current");
}
}
}
document.onreadystatechange = () => {
if (document.readyState === 'complete') {
highlightCurrent()
}
};
The 'href' attribute of current link should be the absolute path as given by document.URL (console.log it to make sure it is the same)
Use single class name something like class="active" and add it only to current page instead of all pages. If you are at Home something like below:
<ul id="navigation">
<li class="active">Home</li>
<li class="">Theatre</li>
<li class="">Programming</li>
</ul>
and your CSS like
li.active{
color: #640200;
}
You can add an id in addition to the class name. Styles referring to the id will override the styles referring to the class. You might call the id: #active and add it to the link of the html page you are currently on:
HTML of href="/" (Home):
<ul id="navigation">
<li id="active "class="a">Home</li>
<li class="b">Theatre</li>
<li class="c">Programming</li>
</ul>
Css:
li a{
color:#A60500;
}
li a:hover{
color:#640200;
background-color:#000000;
}
#active {
color:#640200;
background-color:#000000;
}
So for example if you are trying to change the text of the anchor on the current page that you are on only using CSS, then here is a simple solution.
I want to change the anchor text colour on my software page to light blue:
<div class="navbar">
<ul>
<li>Home</li>
<li>Useful Sites</li>
<li class="currentpage">Software</li>
<li>The Workbench</li>
<li>Contact</li></a>
</ul>
</div>
And before anyone says that I got the <li> tags and the <a> tags mixed up, this is what makes it work as you are applying the value to the text itself only when you are on that page. Unfortunately, if you are using PHP to input header tags, then this will not work for obvious reasons.
Then I put this in my style.css, with all my pages using the same style sheet:
.currentpage {
color: lightblue;
}

Categories

Resources