Activate Current Content Part in jQuery UI Accordion Menu - javascript

I'm trying to figure out how to dynamically activate the correct content part of a jQuery UI Accordion menu depending on the page currently being viewed. I've searched extensively and it seems like others have had issues with this in the past, but I haven't yet found a solution that works for me. I know that active can be set to open a certain index of the menu, but I need to do this dynamically.
I'm thinking that I can achieve what I want using the activate method, I just can't seem to figure it out. I'd like to stay away from setting cookies as that usually won't work with back/forward buttons and direct navigation via a specific url. Anyone have any ideas? Thanks in advance!
Here is the simplified structure of my menu:
<div id="menu">
<div id="sections">
<div class="grouping accordion">
<a id="heading1" href="#">Heading #1</a>
<div class="sub-items">
Item #1
<br />
Item #2
</div>
</div>
<div class="grouping accordion">
<a id="heading2" href="#">Heading #2</a>
<div class="sub-items">
Item #4
<br />
Item #6
</div>
</div>
</div>
</div>
And here is my jQuery Accordion init:
$('#sections').accordion({
header: '> .accordion > a',
autoHeight: false,
collapsible: true,
active: false,
animated: 'slide'
});
So if you are currently on the /item4 page for example, the group under Heading #2 should be expanded.
EDIT:
I found what seems to be a pretty good solution and posted that as an answer below, hopefully this will help someone with a similar problem!

To activate a specific tab, you'll want to use the accordion('activate', index) method. Example:
$( "#sections" ).accordion('activate', 2);
However, you will need something that defines an index key per page. You can probably even generate this dynamically. I would probably create a Pages object:
Pages = {
"heading1" : {
"id": 1,
"is_active": false,
"items": {
"item1": {
"href": "item1",
"name": "Item #1"
},
"item2": {
"href": "item2",
"name": "Item #2"
}
}
},
"heading2" : {
/* etc*/
},
}
With some hackish jQuery magic, you can loop through your headings
var active_heading_index = null;
$.each(Pages, function(heading) {
$.each(heading.items, function(item) {
if($(location).attr('href') == item.href) {
heading.is_active = true;
// or
active_heading_index = heading.id
}
});
});
if(active_heading_index) $( "#sections" ).accordion('activate', active_heading_index);
Anyhow, I'm sure there are cleaner and more efficient ways of doing it.

While working on some CSS for the active headings on the menu I stumbled on a pretty clean and easy solution. Looks like I might have been overthinking things!
Using the same HTML as in the question, here's the JavaScript that is working for me:
//accordion menu
$('#sections').accordion({
header: '> .accordion > a',
autoHeight: false,
collapsible: true,
active: '.selected',
animated: 'slide'
});
//add currentPage class to current menu item based on url
var url = window.location.href;
url = url.substr(url.lastIndexOf("/") + 1);
$("#sections").find("a[href='" + url + "']").addClass("currentPage");
//get id of header anchor tag
var headerId = $(".currentPage").parents(".accordion").children("a").attr("id");
//check if headerId is set, if so activate that id
if (headerId) {
$('#sections').accordion('option', 'animated', false);
$('#sections').accordion('activate', $('#' + headerId));
$('#sections').accordion('option', 'animated', 'slide');
}
This solution is pretty simple, it gets the current page from the url and compares it against each link in the accordion menu. If it finds a match, it gives that link a class of currentPage (which allows us to then style that link accordingly via css). Then it looks for a parent of that link with a class of .accordion, finds the first child link (the accordion header) and grabs the header's id. Assuming a header id has been found, we can then use the activate method to expand the correct section.

If you are going back to the server for every page click (standard non Ajaxy way), the server can add a "selected" class to the proper node. So you'd get back something like this at the client (I'm only writing the essential code, skipping most of the labels).
<ul id="menu">
<li>
<ul>
<li>
</li>
<li class="selected">
Menu 102
</li>
<ul>
</li>
<li>
...
</li>
<ul>
Then simply find the proper index to give to the activate property of the accordion.
$(document).ready(function() {
var index = $("li.selected").parents("li").last().index();
$("#menu").accordion({
active: index,
collapsible: true
});
});
The parents("li").last() jQuery returns the top most element. This only works if you only have one sub element with the class "selected", which should be the case for your menu.

I did it using this code:
var newsNum = parseInt(window.location.hash.slice(1));
$(document).ready(function(){
$("#menu").accordion('activate', newsNum );
});
And the url looks like example.com/index.html#1

Related

semantic ui popup working with manual/click

I need some advice on how to get this to work. My goal is to open a semantic popup manually after setting an angularjs scope variable. Let's say there are 5 images, I click each one. For every image I previously clicked, the popup doesn't open again. And then doesn't go away. I assume the best option for it not going away would be to have a timer/timeout to close it, but I am looking for a better option. I also have a table that uses the click event, and when clicking from one button to another, it just closes, and has similar issues related to not opening again.
So I am looking for features similar to:
manual open, but closes when clicking away
move popup to another control immediately on click event without closing it, but still close when clicking away from those controls.
Should I attempt inline instead? Table will have about 200 buttons, though it could have more, and this example could have even more. They are being used more like context menu.
Horrible first attempt at js fiddle: https://jsfiddle.net/3ecjecxn/22/
<div ng-repeat="page in Pages" class="item">
<div class="ui grid">
<a ng-if="page.Selected != null && page.Selected === true" class="twelve wide column active" ng-click="GetPageInfo(page.Id)"><span ng-repeat="n in range(page.Indention)"> </span>{{page.Name}}</a>
<a ng-if="page.Selected != null && page.Selected !== true" class="twelve wide column" ng-click="GetPageInfo(page.Id)"><span ng-repeat="n in range(page.Indention)"> </span>{{page.Name}}</a>
<div class="two wide column">
<!-- Settings icon by Icons8 -->
<img ng-click="SetTempPageId($event, page.Id)" class="pageCommand" src="[placeimagehere" width="20" height="20">
</div>
</div>
</div>
$(".pageCommand")
.popup({
popup: $('#PagePopup'),
on: 'manual',
delay: {
show: 0,
hide: 0
},
lastResort: 'bottom right',
movePopup: true,
closable: true,
prefer: 'opposite'
});
$scope.SetTempPageId = function ($event, id) {
$scope.EditingPageId = id;
$($event.target).popup('show');
};
Just now getting back to this, but soon after posting this answer, Instead of using semantic ui as context menu, I just used jquery contextmenu:
http://swisnl.github.io/jQuery-contextMenu/index.html
$.contextMenu({
selector: '.command',
callback: function (key, options) {
if (key == "Search") {
console.log("clicked search");
var search = $(".search").modal({ duration: 0 });
search.modal("show");
}
},
items: {
"Search": { name: "Search", icon: "search" }
}
});

Trying to do a:active to stay on untill other link is clicked

What I'm trying to do is this: I have two links hot/update. When hot is clicked it should turn red and update to be black. When update is clicked it should turn red and hot to be black.
This works on a Fiddle, but not on my website.
I was able to find various answers on SO, as this seems like a common thing to ask. I was implementing one by one, but none of them works. They seem to work fine in fiddle but not on my web.
HTML:
<div id="Space" >
<ul>
<li role="presentation" class="sort">
<a class="link" href="/?sort=score&page=1" style="text-decoration:none;">hot</a>
</li>
<li role="presentation" class="date">
<a class="link" href="/?sort=date&page=1" style="text-decoration:none;">update</a>
</li>
</ul>
</div>
JavaScript:
$(function() {
var links = $('a.link').click(function() {
links.removeClass('active');
$(this).addClass('active');
});
});
CSS:
a.link.active { color: red; }
a, a:visited { color: black }
Right now, this does what a:active does, it won't stay red.
var links = does not do what you think it does.
You are thinking it is doing this:
var links = $('a.link');
But, since you're assigning it to the actual click event, it's not resulting in that selector.
You need to revise your code as follows:
// This is a "safer" document ready, to prevent conflicts with other $ libraries
jQuery(function($) {
$('a.link').click(function() {
// Remove the class from all other links
$('a.link').removeClass('active');
// Add the class to _just this link_
$(this).addClass('active');
});
});
Or, a version that preserves the var links:
// This is a "safer" document ready, to prevent conflicts with other $ libraries
jQuery(function($) {
// Assign all links to the "links" variable
var links = $('a.link');
links.click(function() {
// Remove the class from all other links
links.removeClass('active');
// Add the class to _just this link_
$(this).addClass('active');
});
});
Here's a working fiddle: https://jsfiddle.net/cale_b/tqzt8f7s/1/
So to clarify you want certain buttons to be highlighted based on whether or not the url has a certain query. Highlight sort if url contains /?sort=score&page=1 and highlight date if url contains /?sort=date&page=1.
To do this all you need to do is search for each of those strings inside of your page's (window.location.search). The code for such a thing would be.
const highLightWhat = (window.location.search).search('sort=score') !== -1 ? 'Highlight sort' :
(window.location.search).search('sort=date') !== -1 ? 'Highlight date' :
'Highlight Nothing';
This flag then can be used as a reference to highlight one 'a' tag or another.
I hope this helped! (:
Try this javaScript once
$(function() {
$('a.link').click(function(event) {
event.preventDefault();
$('a.link').removeClass('active');
$(this).addClass('active');
});
});

Closable tab in kendo ui

I looked carefully through documentation, but could not find something that is so popular and extremely useful in many other libraries - I mean closable tabs. I wish there was something like:
$("#tabstrip").kendoTabStrip({
dataTextField: "Name",
dataContentField: "Content",
dataSource: [
{ Name: "Tab1", Content: "Tab2: content", closable: true } // <-- this is what I want
]
});
But, unfortunatelly. I could not find anything similar to that, but I hope some easy solution (without a lot of funky css and js stuff) exists.
Well here is a quick demo I have knocked up for you.
Closable tabs in Kendo
Essentially I have done two things:
1) Add a span tag with a data attribute indicating the index of the tab
<div id="tabstrip">
<ul>
<li>Tab 1 <span style="border:1px solid red;" data-tab="0">*</span></li>
<li>Tab 2 <span style="border:1px solid red;" data-tab="1">*</span> </li>
</ul>
<div>Content 1</div>
<div>Content 2</div>
</div>
2) Added a click event to the span tags to remove the tab and then re-sequence the tab number.
var tabStrip = $("#tabstrip").kendoTabStrip().data("kendoTabStrip");
$(document).ready(function(){
$("span[data-tab]").on('click',function(e){
//indicate I am removing a tab
console.log("removing tab::");
//find the tab I am removing based on click
var tabIndex = $(this).data("tab");
//show tab index 0 positioned
console.log(tabIndex);
//remove tab.
tabStrip.remove(tabIndex );
//now find any remaining tabs and reindex them.
var reIndex = $("span[data-tab]");
console.log(reIndex);
if(reIndex !== null && reIndex !== undefined && reIndex.length > 0 )
{
var counter = 0;
reIndex.each(function(item){
$(this).data('tab',counter);
counter++;
});
}
});
});
Hopefully this is the sort of thing you are looking for with kendo.

ResponsiveTabs add onclick in js file

I am working with the ResponsiveTabs module from PeteLove.com.
http://www.petelove.com/responsiveTabs/
I would like to make a change into it because I need an onclick event added to the tabs. Now this should be done I believe in the following code section.
// CREATE TAB ITEMS (VISIBLE ON DESKTOP)
//create tab list item from heading
//associate tab list item with tab panel
var $tabListItem = $('<li/>', {
'class': 'responsive-tabs__list__item',
id: 'tablist' + tablistcount + '-tab' + tabcount,
'aria-controls': 'tablist' + tablistcount +'-panel' + tabcount,
'role': 'tab',
tabindex: 0,
text: $tabHeading.text(),
keydown: function (objEvent) {
if (objEvent.keyCode === 13) { // if user presses 'enter'
$tabListItem.click();
}
},
click: function() {
//Show associated panel
Now I expected to see somewhere <li> so that I could do <li onclick="setBrowserFrameSource(); return false;"> but there is no <li> anywhere just the closing brackets. So I should add it to the code above. I have tried to add it as follows:
'role': 'tab',
'onclick="setBrowserFrameSource(); return false;"',
tabindex: 0,
But this broke the entire thing. Any help would be appreciated. Thanks in advance.
According to the instructions from the website petelove.com (full link in original question) you need to start the tabs with:
<div class="responsive-tabs">
Then the plugin will do the rest. So I thought instead of adding for each <li> an onclick event why not add it to the container element. Which I did and it is working. So I now have the following.
<div class="responsive-tabs" onclick="setBrowserFrameSource(); return false;">
Now every time a tab is clicked it does its functions.

How to keep the selected menu active using jquery, when the user comes back to page?

I have a typical menu structure -
<Ul class="nav">
<li>Menu1</li>
<li>menu2</li>
-------
</ul>
When I click on certain menu, as per my jquery written on load of layout.html, it selects particular menu.
<script>
jQuery(function(){
jQuery('.nav>li>a').each(function(){
if(this.href.trim() == window.location)
$(this).addClass("selected");
});
</script>
But on that page if I click on certain link which takes me on some other page and then when I come back the menu item does not remain selected.
How can I modify my jquery to achieve this?
Thanks in advance !
As SJ-B is saying, HTML5 Web Storage is a good solution.
If you don't intend to click more than one or two pages away from the page with your list menu, you could add a query to the link that takes you away form the page e.g. the id of one of your list menus.
href="somepage.html could become something like this href="somepage.html?menu_id=menu5
When using window.history.back(), you could then fish the id out of the URL using window.location.search and use id to select the list menu.
You can use simple css code. Use active attribute like
a:active
{
//Some style
}
You can use below code to achieve this.
var lastele=siteurl.substring(siteurl.lastIndexOf("/")+1);
jQuery(".nav>li> a").each(function(){
var anchorhref=jQuery(this).attr("href");
var finalhref=anchorhref.substring(anchorhref.lastIndexOf("/")+1);
if(finalhref==lastele){
jQuery(this).addClass("selected");
}
});
I would do something like this :
<ul class="nav">
<li id="home">Home</li>
<li id="contact">Contact</li>
</ul>
Javascript :
// http://mywebsite.com#home
// location.hash === '#home'
jQuery('.nav ' + location.hash).addClass('selected');
Try to use Session Object of HTML5.
sessionStorage.varName = id of selected item.
on load just check if the sessionStorage.varName has value or undefined, if not then get the value
`var value = sessionStorage.varName;` and set it.
Well there could be many ways, on which is this which i like and always use:
It works when you path name is same as your link name For e.g. yourwebsite.com/Menu1
function setNavigation() {
var n = window.location.pathname,t;
n = n.replace("/", "");
t = $("ul li:contains(" + n + ")");
t.addClass("active");
}
You can than define styling in your active class as you like.
I stumbled upon this when googling for something similar. I have a JQueryUI accordion menu. My menu is in an included script (classic asp), so it is on every page but I think it is a similar situation. I cobbled something together based on SJ-B's answer (don't know why it was down voted).
I have this:
function saveSession(id) {
if (window.sessionStorage) {
sessionStorage.activeMenu = $("#jqmenu").accordion("option", "active") ;
sessionStorage.activeLink = id ;
}
}
and this
$(function() {
//give every li in the menu a unique id
$('#jqmenu a').attr('id', function(i) {
return 'link'+(i+1);
});
var activeMenu = 0;
var activeLink = "";
if (window.sessionStorage) {
activeMenu = parseInt(sessionStorage.activeMenu);
activeLink = sessionStorage.activeLink;
}
$("#" + activeLink).parent().addClass("selectedmenu");
$("#jqmenu").accordion({collapsible: true, active: activeMenu, heightStyle: "content", header: "h3"});
$("#jqmenu a").click(function() { saveSession($(this).attr('id')); });
});
OK, a bit untidy and cobbled together from various suggestions (I'm still learning), but it seems to work. Tried on IE11 and Firefox. Chrome can't find localhost but that's another story.
add lines below
<script>
$(function(){
$("a[href='"+window.location+"']").addClass("selected");
});
</script>
var url = window.location.pathname,
urlRegExp = new RegExp(url.replace(/\/$/, '') + "$");
$('.nav li').each(function () {
if (urlRegExp.test(this.href.replace(/\/$/, ''))) {
$(this).addClass('active');
}
});

Categories

Resources