Making Active Page styling different on certain page with jquery/ghost - javascript

http://i.stack.imgur.com/Q9OMB.png
Here's a little problem of mine. Basically I'm doing a theme for Ghost CMS but I've ran into a problem that has been bugging me for a few hours now and I can't solve this myself and haven't found a source of same kind of problem from google/sof neither.
My goal is to make a active page styling with different styles per page(home being red, about being blue etc) using jquery as I couldn't accomplish it in Ghost itself because it wants to rotate a single loop with same styles for all links.
Jquery Code so far
$(function(){
$('a').each(function() {
if ($(this).prop('href') == window.location.href) {
$(this).addClass('homeCurrent');}
});
});
Relevant HTML of navbar
<ul class= "nav navbar-nav navbar-left">
<li id="home" class="home hvr-sweep-to-top-home ">Home</li>
<li id="about" class="about hvr-sweep-to-top-about">About</li>
</ul>
I've tried running different kinds of IF-statements with jquery but without success.
The logic of the code would go like :
if page is home = li style is homeCurrent
<ul class= "nav navbar-nav navbar-left">
<li id="home" class="home hvr-sweep-to-top-home homeCurrent">Home</li>
<li id="about" class="about hvr-sweep-to-top-about ">About</li>
</ul>
if page is about = li style is aboutCurrent
<ul class= "nav navbar-nav navbar-left">
<li id="home" class="home hvr-sweep-to-top-home">Home</li>
<li id="about" class="about hvr-sweep-to-top-about aboutCurrent">About</li>
</ul>
Anyone?
Hopefully I included everything relevant.

Honestly, I would avoid using window.location.href comparisons as it just screams potential for problems to me.
What I would personally do would be to add to the CONTENT of the about page:
$(document).ready(function () {
$('.about').addClass('aboutCurrent');
});
You add that code to each page you wish to have a xxxCurrent class added.
This avoids you having to dynamically do it as above which will run into problems depending on the url and browsers

Try with a switch statement:
$(function () {
$('a').each(function () {
var link = $(this).prop('href');
if (link == window.location.href) {
switch (link) {
case "home":
$(this).addClass('homeCurrent');
break;
case "about":
$(this).addClass('aboutCurrent');
break;
default:
$(this).addClass('nothingactive');
}
}
});
});
Edit*
If you really want to stick with this method of checking up the URL you could go for something like this:
$(function () {
$('a').each(function () {
var base = "http://www.yourdomain.com/";
var link = base + $(this).prop('href');
if (link == window.location.href) {
switch (link) {
case "http://www.yourdomain.com/home" :
$(this).addClass('homeCurrent');
break;
case "http://www.yourdomain.com/about" :
$(this).addClass('aboutCurrent');
break;
default:
$(this).addClass('nothingActive');
}
}
});
});

Related

Add element after specific list item

I have a list of tabs set up like this. All tabs have a class tab_<number> and the active tab also has an extra class tab_active
Below these tabs there is a div that shows the dynamic content based on which tab is active
<div class="tab_content">xxx</div>
What I'm trying to do is insert the div tab_content below the active tab.
This works, but only on the second click on the tab, which I don't understand why.
The second script I tried, was looping through the different tabs and trying to insert the div like this, but this only works on the last item, because it just loops through it.
/*
// I tried two solutions, this was my first
jQuery(".tabs li").click(function() {
jQuery(".tab_content").insertAfter(jQuery(".tab_active"));
});
*/
// second
var i;
for (i = 0; i < jQuery('.tabs li').length - 1; i++) {
jQuery(".tab_" + i).click(function() {
jQuery(".tab_content").insertAfter(jQuery(".tab_" + i));
});
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul class="tabs">
<li class="tab_0 tab_active">1</li>
<li class="tab_1">2</li>
<li class="tab_2">3</li>
<li class="tab_3">4</li>
<li class="tab_4">5</li>
</ul>
<div class="tab_content">xxx</div>
Can you guys/gals see what I'm doing wrong?
Much appreciated!
this can be done in something like following way.
Note though that if there are more tab_* elements in page then update the selector to be more stricter as needed to prevent selecting unexpected element.
$("[class^=tab_]").click(function(){
$(this).append($(".tab_content"));
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul class="tabs">
<li class="tab_0 tab_active">1</li>
<li class="tab_1">2</li>
<li class="tab_2">3</li>
<li class="tab_3">4</li>
<li class="tab_4">5</li>
</ul>
<div class="tab_content">xxx</div>

jQuery each run function on every other element

I'm working on a basic dropdown element in HTML and jQuery and I'm trying to get better at understanding JavaScript and jQuery so this questions is a bit about code refactoring as well.
So here is what I've gotten so far:
HTML
<li class="nav-item">
<a class="nav-link" href="#">Foo</a>
<div class="subnav">
...
</div>
</li>
JavaScript
const navLink = $('.nav-link');
navLink.each(function () {
let $this = $(this);
$this.click(function (e) {
let hasSubnav = $this.parent().find('.subnav');
if(hasSubnav.length !== 0) {
e.preventDefault();
$this.toggleClass('dropdown-active');
}
hasSubnav.stop(true, true).slideToggle(200);
})
});
This solutions works fine. So what I want to do next is to check if another element in my loop is active, close is accordingly and then open the one I just clicked.
I thought about just putting a default click function before the each function like this:
navLink.click(function () {
$('.subnav').slideUp();
});
navLink.each(function () {
let $this = $(this);
$this.click(function (e) {
let hasSubnav = $this.parent().find('.subnav');
if(hasSubnav.length !== 0) {
e.preventDefault();
$this.toggleClass('dropdown-active');
}
hasSubnav.stop(true, true).slideDown(200);
})
});
But this does not seem to work. So my question is, is there a pretty way to achieve this maybe even inside of the each function? I've red about .not(this) in this post, which will maybe work (haven't tried it yet) but I thought that this would be duplicated code and that there might be a better way to get this to work.
Your code is now looping through every single nav-link and adding a click handler to them one by one. It is possible to remove the each loop, since you can just add a click handler to all nav-links at once.
All you have to do is add a click handler to the nav-link and then remove the active class and slide up all open dropdowns before executing your logic. See working code example below for reference:
// Collapse all initially
$(".subnav").slideUp();
// Add click handler to all nav-links
const navLink = $('.nav-link');
navLink.click(function(e) {
// Remove active classes on other elements & slide up
const otherLinks = navLink.not(this);
otherLinks.removeClass('dropdown-active');
otherLinks.parent().find('.subnav').slideUp();
// Slide down the subnav of selected element
let hasSubnav = $(this).parent().find('.subnav');
if (hasSubnav.length !== 0) {
e.preventDefault();
$(this).addClass('dropdown-active');
}
hasSubnav.stop(true, true).slideToggle(200);
})
<script src="https://code.jquery.com/jquery-3.3.1.min.js" integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8=" crossorigin="anonymous"></script>
<li class="nav-item">
<a class="nav-link" href="#">Foo</a>
<div class="subnav">
Link1
Link2
Link3
</div>
</li>
<li class="nav-item">
<a class="nav-link" href="#">Foo</a>
<div class="subnav">
Link1
Link2
Link3
</div>
</li>

Load dynamic content in div from different navbars

On one page, alphabet.php, in my project I have a sidebar further down on the page that loads diverse php-pages in a Content div. Like this:
HTML SideMenu
<nav id="sideMenu">
<ul class="list-unstyled components">
<li id="a">A</li>
<li id="b">B</li>
<li id="c">C <span class="caret"></span>
<ul>
<li id="c1">C1</li>
<li id="c2">C2</li>
</ul>
</li>
</ul>
</nav>
<div id="Content">
<h2>Lorem bla bla</h2>
<p>lorem bla bla </p>
</div>
JS
$(function() {
'use strict';
var newHash = '',
$content = $("#Content");
$("#sideMenu").delegate("a", "click", function() {
window.location.hash = $(this).attr("href");
return false;
});
$(window).bind('hashchange', function() {
newHash = window.location.hash.substring(1);
$content.load(newHash);
console.log(newHash);
});
});
The same content should be loaded also when you click the topmenu and footer navigation. And at the same time scroll to the Content div.
HTML MainMenu
<li class="dropdown"><a href="#alpha" class="dropdown-toggle" data-
toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">
Alphabet <span class="caret"></span></a>
<ul class="dropdown-menu dropdown-menu-left" role="menu" id="alpha">
<li>A
</li>
<li>B
</li>
<li>C
<ul class="dropdown-menu dropdown-menu-left" role="menu">
<li>C1</li>
<li>C2</li>
</ul>
</li>
</ul>
</li>
I solved the JS for the main-menu with this code
$(function() {
'use strict';
if(location.hash) $('#Content').load(location.hash.substring(1));
$('#alphaa').click(function() {
$('#Content').load(this.hash.substring(1));
});
});
EDIT: I changed the URL in MainMenu to alphabet.php#a.php etc., and it loads the content into the div IF you are on the current page (alphabet.php). Not if you're on another page.
EDIT 2: Solution for the main-menu JS. Now everything works fine but I guess you could make it prettier without two different js functions for the main-menu and the side-menu, but for now I'm pleased with this. It works!
Here is how i am able to do the navigation
i wrote the links like:
<a class="nav-link" href="javascript:void(0);" data-href="/page1.html #div1">Page 1</a>
<a class="nav-link" href="javascript:void(0);" data-href="/page2.html #div2">Page 2</a>
<a class="nav-link" href="javascript:void(0);" data-href="/page3.html #div3">Page 3</a>
If you use javascript:void(0) in your href= then you don't need to call the event.preventDefault.
then in my scripting side i wrote:
$(window).on('load', function () {
$('.nav-link').on('click', function () {
var linkPage = $(this).attr('data-href');
if (linkPage !== undefined)
{
$('#content').load(linkPage);
}
});});
Note
One thing you need to make sure is that domain of the calling page and pages from which the data has to come should be the same or else you will have the cross-domain issue.
Edit 1
The #div1,#div2,.#div3 are basically the ids of the div on their respective pages from which the data has to be fetched.
for example if i have some content on my pages like this:
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title> Page 1</title>
</head>
<body>
<div id="div1">
hi i am the content of page 1
</div>
</body>
</html>
So, when someone clicks on the menu links the load function will go to the particular page (which is in our case the page1.html or any other) and return the HTML contents of div with id as div1 and load the data to the particular div(i.e. div with id content).
Edit 2
The JQuery's Load() is better explained on this Jquery Load you can use this to understand more about it.
So, what i think you are doing is you are creating a request to a /page1.html from the domain www.example.com, in that case load function will call the www.example.com/page.html and will load the contents of the page but if you make a request to other any other page let say /page11.html from the domain www.example.com/page2.html then the load() will create this www.example.com/page2.html/page11.html url which is not correct and hence it will not load any content.
So,what you can do is either you can put the whole url on the of the page i.e. www.yourdomain.com/page.html #divid in the attribute data-href or you can create the particular url on the javascript calling funciton like:
$(window).on('load', function () {
$('.nav-link').on('click', function () {
var linkPage = $(this).attr('data-href');
if (linkPage !== undefined)
{
var pageUrl = window.location.origin+'any other seperation for the pages
if any'+linkPage;
$('#content').load(pageUrl);
}
});
});
Here the window.location.origin is going to give you the domain on which the website is running regardless of hashes or slashes and then it will concate it with the linkPage and will make the proper url for the called page.

SlideUp slideDown

i have this javascript code:
var x="#wrapper"
//var xyz;
$(document).ready(function(){
$("#about").click(function(){
if (!(x=="#about")){
$(x).slideUp("slow",function(){
$("#aboutus").slideDown("slow");
});
x="#aboutus";
}
});
});
$(document).ready(function(){
$("#home").click(function(){
if(!(x=="#wrapper")){
$(x).slideUp("slow", function(){
$("#wrapper").slideDown("slow");
});
dd="#wrapper";
}
});
});
with this "menu"
<nav>
<div class="menu">
<ul class="ul">
<h6>
<li id="home" >Home</li >
<li id="about">About</li >
<li >performance</li >
<li >testimonials</li >
<li >faqs</li >
<li >forum</li >
<li onclick="slideUpDown()">Contact </li >
</ul>
</h6>
</div>
</nav>
I must use the the li tags as links and when I click the about "link" the home div must slide up slowly and the about div is supposed to come down slowly.
please help!
thank you in advance
In the last line of your code, set x to #wrapper not dd:
var x="#wrapper"
//var xyz;
$(document).ready(function(){
$("#about").click(function(){
if (!(x=="#about")){
$(x).slideUp("slow",function(){
$("#aboutus").slideDown("slow");
});
x="#aboutus";
}
});
$("#home").click(function(){
if(!(x=="#wrapper")){
$(x).slideUp("slow", function(){
$("#wrapper").slideDown("slow");
});
x="#wrapper";
}
});
});
I came on this nice one a while ago. It is simple and works.
function toggleForm(x) {
if ($('#'+x).is(":hidden")) {
$('#'+x).slideDown(200);
} else {
$('#'+x).slideUp(200);
}
}
Then to call it ...
onmousedown="javascript:toggleForm('div_ID');
and to not change your URL add this in front on the same call
onclick="return false"
with this, you can use one script to call as many slid operations as you want. The div to be targeted is the one that has its ID in the call.
EDIT: sorry ... Just noted that it is jQuery, but should not affect anything. I used it where other jQuery did not. So does not seem to conflict anywere.

Comparing URL to links

I have the following HTML:
<ul class="vertical_menu no_select">
<li class="edge_top"> </li>
<!-- Menu Items Here -->
<li class="not_selected"><a class="selection_link" href="index.htm">Home</a></li>
<li class="not_selected"><a class="selection_link" href="index.htm">Subitem 1</a></li>
<li class="not_selected"><a class="selection_link" href="index.htm">Subitem 2</a></li>
<!-- Menu Items End Here -->
<li class="edge_bottom"> </li>
</ul>
Now, the links with the class "selection_link" need to have the li element (their parent) to have a new class "selected" if the current url matches the href value inside of the anchor tag. I can get the full URL but I don't know how to use that to help seeing as there could be more than one page with the same name at different directory levels.
Thanks if you can help! I'm using jQuery with all of this so feel free to provide me with jQuery examples!
Check out the jsFiddle. This should do the trick:
$("ul.vertical_menu li a").each(function() {
if (this.href == window.location.href) {
$(this).parent().toggleClass("not_selected selected");
}
});
$('.selection_link').each(function() {
if($(this).attr('href') === window.location.pathName.substring(1)) {
$(this).parent().attr("class", "selected");
}
});
not tested, but it'll it should start you off. substring is because pathname starts with '/' you could just put that in your href's too
or this...
$('.vertical_menu a').each(function() {
if (location.href.search(this.attr('href')) != -1) {
$(this).parent().addClass('selected');
}
});

Categories

Resources