I am trying to maintain state in my JQuery accordion menu, I'd like to avoid any server-side processing or unnecessary variable passing if possible.
Here is my code:
<ul class="accordion">
<li>
Autos
<div class="slide">
<ul>
<li>Cars</li>
<li>Motorbikes</li>
</ul>
</div>
</li>
<li>
Pets
<div class="slide">
<ul>
<li>Cats</li>
<li>Dogs</li>
</ul>
</div>
</li>
</ul>
<script type="text/javascript">
$(document).ready(function() {
var accordion = $('ul.accordion');
var show_link = '/cats';
active = FIND_SECTION_TO_OPEN_BASED_ON_URL;
accordion.accordion('activate', active );
});
</script>
By hardcoding
accordion.accordion('activate', 0 );
I can have the "Autos" menu open when the page loads, but I want to be about to dynamically find which menu or ul to open based on the URL, I'm pretty new to JavaScript and where I am stuck is on this line:
active = FIND_SECTION_TO_OPEN_BASED_ON_URL.to_int;
Does anyone know how to implement this?
(I've done a lot of research on this and have not been able to find a solution which works here)
You can use the location.hash property to get the menu to open from the URL. You would pass the menu number in a hash tag like this:
URL: http://www.domainname.com/page.html#1
And then use the JS to get it and pass it to the script:
<script type="text/javascript">
$(document).ready(function() {
var accordion = $('ul.accordion');
var show_link = '/cats';
var active = window.locatioh.hash.replace("#", "");
accordion.accordion('activate', active );
});
</script>
First off you need to pass the current page via the anchor like so (What you pass doesn't really matter, just that it's unique):
Autos
...
Pets
Then you can base the index off of the resultant hash
active = $(".opener[href='"+location.hash+"']").parents("li").index();
Here's what I did for my page. My URLS are in the format site.com/#page/accordion/tab. I also made it so that when the user clicks on an accordion or tab, the hash changes. That way if you were to navigate to the URL somewhere else, you would go to the accordion you were just looking at.
I did run into a problem though with the hashchange event. Since it's a hash, if the user goes from site.com/#page/accordion-one to site.com/#page/accordion-two, that's a hashchange not a pageload, so I put the below code in a function and bound it to the hashchange event. Problem is I have to unbind it when I change the hash in the below code, and I'm having some trouble with it still catching the hashchange event when I rebind it.
See my question here.
var hash = window.location.hash;
hash = hash.replace(/#/, "");
hash = hash.split("/");
if(typeof hash[1] !== 'undefined'){
//select campus accordion
//first disable the animation and the function that changes the hash:
$("#accordion").accordion("option", "animated", false);
$('.ui-accordion').unbind('accordionchangestart');
$("#accordion").accordion("activate", $("#accordion-"+hash[1]));
$("#accordion").accordion("option", "animated", 'slide');
$('.ui-accordion').bind('accordionchangestart', function(event, ui) {
var hash = window.location.hash;
hash = hash.replace(/#/, "");
hash = hash.split("/");
var name = $(ui.newHeader).attr("name");
var val = hash[0]+"/"+name;
sessionStorage.setItem("accordion", val);
hashChange(val);
});
}
if(typeof hash[2] !== 'undefined'){
//select tab
$(".ui-tabs").tabs("select", "#tabs-"+hash[2] );
}
My new library does this. Check it out.
Related
Firs of all I wanted to say that I have read a lot about it online and all the solutions found I could not implement them properly, some repaired some problems but created others. Another thing is that I cannot comment on other posts because of low reputation (noob), if I could do that I would not be posting a new question.
I am creating a website with a navbar with different pages for each part of the website: Home.html, AboutUs.html...
I implemented the navbar, but I think is not a good solution to paste the same code of the navbar in each page so I looked for a way to optimizing it.
For now I created another site (Navbar.html) and added it into the other pages and it looks good:
<script>
$(function(){
$("#navbar").load("Navbar.html");
});
</script>
and inside the body:
<div id="navbar"></div>
The problem occurred when trying to automatize the "active" class. For that I tried both data-toggle='tab' and data-toggle='pill' but in both cases the active changed but when clicking the button the webite didn't change.
There is the code:
<ul class="nav navbar-nav" >
<li class="menuText"><a href="Home.html" data-toggle="tab" >Home</a></li>
<li class="menuText"><a href="AboutUs.html" data-toggle="tab" >About Us</a></li>
<li class="menuText"><a href="Donate.html" data-toggle="tab" >Donate</a></li>
<li class="menuText"><a href="Volunteer.html" data-toggle="tab" >Volunteer</a></li>
<li class="menuText"><a href="Contact.html" data-toggle="tab" >Contact</a></li>
</ul>
I also tried redirecting it with a .js file:
$('#home').load('Home.html');
$('#aboutus').load('AboutUs.html');
$('#donate').load('Donate.html');
$('#volunteer').load('Volunteer.html');
$('#contact').load('Contact.html');
it worked perfectly and it changed pages when the button was clicked, but I found that if I scrolled down there was the first page I opened constantly there below the changing page. (hard to explain this, hope you understood)
I also tried adding lots of functions found online but I didn't really know if they were working. I think I didn't implemented them correctly or in the wrong place. I'm a noob in html. I don't really know how to call the function :S
Example:
$(function(){
var hash = window.location.hash;
hash && $('ul.nav a[href="Home.html"]').tab('show');
$('.nav-tabs a').click(function (e) {
$(this).tab('show');
var scrollmem = $('body').scrollTop();
window.location.hash = this.hash;
$('html,body').scrollTop(scrollmem);
});
});
Is there anyway I can do it, or another way to automatize the "active" class in each page?
Thank you for your time
This should give you what you want:
$(function() {
var mynavbar = $("#navbar"); //cache it
mynavbar.load("Navbar.html");
// remove any current active if found in markup:
mynavbar.find('ul.nav li').removeClass('active');
var url = window.location;// get location
// add the active class to current url detected href
// Will work for absolute hrefs, might have to adjust for others
mynavbar.find('ul.nav li').find('a').filter(function() {
return (url.href.indexOf(this.href) != -1);
}).parent().addClass('active');
// put the click handler for the navigation in place
mynavbar.on('click', 'ul.nav li', function() {
var myhref = $(this).find('a').attr('href');
// just for debug alert("proceed to: " + myhref);
window.location.href = myhref;
});
});
NOTE: IF you want to simply use the current page, loading content in a hashed area, that is different. In that case you will need to rework this and change this line:
window.location.href = myhref;
For example:
$('#mycontentcontainer').load(myhref);
IF you want to use tabbed content and load the content only on the click, that can also be done (but you said you wanted to navigate to the NEW page so I did not include that)
EDIT: NOTE: Looking ahead, the solution above with load might not work in all cases (load slow)...so use this instead: Only process the `nav after it is loaded.
function addActiveNavbar(mynavbar) {
// remove any current active if found in markup:
mynavbar.find('ul.nav li').removeClass('active');
var url = window.location; // get location
// Will work for absolute hrefs, might have to adjust for others
mynavbar.find('ul.nav li').find('a').filter(function() {
return (url.href.indexOf(this.href) != -1);
}).parent().addClass('active');
}
$(function() {
var mynavbar = $("#navbar"); //cache it
addActiveNavbar(mynavbar);
$.get("Navbar.html")
.done(function(data) {
mynavbar.html(data);
// add the active class to current url detected href
addActiveNavbar(mynavbar);
});
// put the click handler for the navigation in place
mynavbar.on('click', 'ul.nav li', function() {
var myhref = $(this).find('a').attr('href');
// un-comment for debug alert("proceed to: " + myhref);
window.location.href = myhref;
});
});
I've been able to easily use the history.pushState to change the content of my div and have the address bar reflect a fake url. However, whenever I push the back/forward buttons the url changes back but the content remains the same. Typing in the url comes up with an error. It seems I have the first part of the history API down, but need help doing state changes.
I'm a fairly new programmer and trying to build my website in jQuery and keep the code as concise as possible.
HTML code:
<ul>
<li><button class="navButton" id="signUp" href="./content/registration.php" name="registration" title="Registration">Sign Up</button></li>
<li><button class="navButton" id="settings" href="./content/account_settings.php" name="settings" title="settings">Settings</button></li>
<li><button class="navButton" id="about" href="./content/about.php" name="about" title="About">About</button></li>
</ul>
<div id="mainContent"></div>
Javascript code:
$(document).ready(function() {
// INITIAL CONTENT ON FIRST LOAD
$("#mainContent").load('./content/start.php');
// CODE FROM HISTORY.JS
(function(window, undefined) {
var History = window.History;
if (!History.enabled) {
return false;
}
History.Adapter.bind(window, 'statechange', function() {
var State = History.getState();
History.log(State.data, State.title, State.url);
});
// EVENT LISTENER FOR NAVBUTTON CLASS TO REPLACE CONTENT IN MAINCONTENT DIV
$('.navButton').click(function(e) {
e.preventDefault();
pageurl = $(this).attr('name');
$("#mainContent").fadeOut().load($(this).attr("href")).fadeIn();
if (pageurl != window.location) {
history.pushState('', $(this).attr('title'), $(this).attr('name'));
}
});
})(window);
});
I have installed history.js but if I don't need to use it, that would be preferred. I would love to have this code corrected so the back button refreshes and this works!
So I solved this by adding an if statement under the popstate to compare the url and determine the content loaded in the mainContent div. Works!.. but discovered my original pushstate is pushing several popstates the more you click the navButtons. That question is posted Cannot find where I have a popstate loop creating multiple history entries
window.addEventListener('popstate', function() {
//WHEN BACK/FORWARD CLICKED CHECKS URL PATHNAME TO DETERMINE WHICH CONTENT TO PLACE IN DIV
if (location.pathname == "/index.php") {
$("#mainContent").load("./content/start.php");
} else {
$("#mainContent").load("./content" + location.pathname + ".php");
}
});
Advice: use the built html5 history state, to pass in objects or params or so on...
Action when you are pushing a state into browser:
history.pushState('{url:location}', $(this).attr('title'), $(this).attr('name'));
Action when your clicked back or front using the browser:
$(window).on('popstate', function(e){
if(e.originalEvent.state != null){
console.log("url to render"+e.originalEvent.state.url)
}else{
console.log("nothing in the state, do nothing")
}
I have a question that will be found very often. The problem is that nowhere can be found an explicit solution.
I have two problems regarding anchors.
The main goal should be to get a nice clean url without any hashes in it while using anchors to jump on a page.
So the structure of the anchors is:
<ul>
<li>One</li>
<li>Two</li>
<li>Three</li>
</ul>
<div class="wrap">
<a name="one">text 1</a>
<a name="two">text 2</a>
<a name="three" class="box">text 3</a>
</div>
Okay, if you will click one of the links the url will automatically change to
www.domain.com/page#1
At the end this should be just:
www.domain.com/page
So far, so good. Now the second thing is, when you search the internet for that problem you will find javascript as a solution.
I have found this function:
function jumpto(anchor){
window.location.href = "#"+anchor;
}
and calling that function with:
<a onclick="jumpto('one');">One</a>
what will be the same like before. It will add the hash to the url. I also added
<a onclick="jumpto('one'); return false;">
without success. So if there is someone who could tell me how to solve this I really would appreciate.
Thanks a lot.
You can get the coordinate of the target element and set the scroll position to it. But this is so complicated.
Here is a lazier way to do that:
function jump(h){
var url = location.href; //Save down the URL without hash.
location.href = "#"+h; //Go to the target element.
history.replaceState(null,null,url); //Don't like hashes. Changing it back.
}
This uses replaceState to manipulate the url. If you also want support for IE, then you will have to do it the complicated way:
function jump(h){
var top = document.getElementById(h).offsetTop; //Getting Y of target element
window.scrollTo(0, top); //Go there directly or some transition
}
Demo: http://jsfiddle.net/DerekL/rEpPA/
Another one w/ transition: http://jsfiddle.net/DerekL/x3edvp4t/
You can also use .scrollIntoView:
document.getElementById(h).scrollIntoView(); //Even IE6 supports this
(Well I lied. It's not complicated at all.)
I think it is much more simple solution:
window.location = (""+window.location).replace(/#[A-Za-z0-9_]*$/,'')+"#myAnchor"
This method does not reload the website, and sets the focus on the anchors which are needed for screen reader.
I don't have enough rep for a comment.
The getElementById() based method in the selected answer won't work if the anchor has name but not id set (which is not recommended, but does happen in the wild).
Something to bear in mind if you don't have control of the document markup (e.g. webextension).
The location based method in the selected answer can also be simplified with location.replace:
function jump(hash) { location.replace("#" + hash) }
Because when you do
window.location.href = "#"+anchor;
You load a new page, you can do:
One
<script>
function getPosition(element){
var e = document.getElementById(element);
var left = 0;
var top = 0;
do{
left += e.offsetLeft;
top += e.offsetTop;
}while(e = e.offsetParent);
return [left, top];
}
function jumpTo(id){
window.scrollTo(getPosition(id));
}
</script>
I have a button for a prompt that on click it opens the display dialogue and then I can write what I want to search and it goes to that location on the page. It uses javascript to answer the header.
On the .html file I have:
<button onclick="myFunction()">Load Prompt</button>
<span id="test100"><h4>Hello</h4></span>
On the .js file I have
function myFunction() {
var input = prompt("list or new or quit");
while(input !== "quit") {
if(input ==="test100") {
window.location.hash = 'test100';
return;
// else if(input.indexOf("test100") >= 0) {
// window.location.hash = 'test100';
// return;
// }
}
}
}
When I write test100 into the prompt, then it will go to where I have placed span id="test100" in the html file.
I use Google Chrome.
Note: This idea comes from linking on the same page using
Test link
which on click will send to the anchor. For it to work multiple times, from experience need to reload the page.
Credit to the people at stackoverflow (and possibly stackexchange, too) can't remember how I gathered all the bits and pieces. ☺
The first suggested solution of accepted solution did not work for me entirely. The main problem was when it was already jumped to hash, and hash already in url, jump did not happen again. I propose here, for the sake of completeness, somewhat more elaborate solution which works (tested in Chrome and FF). el is element with anchor tag.
el.addEventListener('click', function(ev) {
ev.preventDefault();
const href = ev.target.getAttribute('href');
const hashIndex = href.indexOf('#');
if (hashIndex !== -1) {
const hashPart = href.substring(hashIndex);
if (location.hash === hashPart) {
document.querySelector(hashPart).scrollIntoView();
}
else {
location.hash = hashPart;
}
}
})
I have a web page that contains two articles. Upon loading this page, jQuery is used to hide the two articles and slide down the first one. User can click on the navigation tab to view the second article. Then go back to the first article by clicking the back button using the onhashchange event. The following is my HTML code:
<nav>
<a href='#1'>Article 1</a>
<a href='#2'>Article 2</a>
</nav>
<article id=1>
The first article.
</article>
<article id=2>
The second article.
</article>
And here is the javascript code:
function change(hash)
{
$('article:visible').slideUp();
if(hash != '')
{
$(hash).slideDown();
}
else
{
$('article').first().slideDown();
}
}
$('nav a').click(function(){
var id = $(this).attr('href');
change(id);
});
$('article').hide();
change(location.hash);
window.onhashchange = change(location.hash);
What was observed is that the page remains on the second article despite clicking the back button. I am using firefox 12.0 browser and don't know what is causing it not to work. Any help is appreciated. Thanks.
You might want to try:
window.onhashchange = change;
//and read location.hash in the change function instead
function change(){
var hash = location.hash;
...
}
or
window.onhashchange = function(){
change(location.hash);
}
window.onhashchange = change(location.hash);
If my JS ain't rusty, this fails because
calls change()
functions that have no return return undefined
you are assigning undefined to window.onhashchange - which is wrong because you're supposed to assign a function to an event.
I have two (or more) links. For example: http://google.com and http://yahoo.com.
How can I make them both open when I click on a single link?
For example, a link entitled "click here" which, when clicked, will open two different blank windows.
HTML:
Click Here
JS:
$('a.yourlink').click(function(e) {
e.preventDefault();
window.open('http://yoururl1.com');
window.open('http://yoururl2.com');
});
window.open also can take additional parameters. See them here: http://www.javascript-coder.com/window-popup/javascript-window-open.phtml
You should also know that window.open is sometimes blocked by popup blockers and/or ad-filters.
Addition from Paul below: This approach also places a dependency on JavaScript being enabled. Not typically a good idea, but sometimes necessary.
I did it in a simple way:
<a href="http://virtual-doctor.net" onclick="window.open('http://runningrss.com');
return true;">multiopen</a>
It'll open runningrss in a new window and virtual-doctor in same window.
You might want to arrange your HTML so that the user can still open all of the links even if JavaScript isn’t enabled. (We call this progressive enhancement.) If so, something like this might work well:
HTML
<ul class="yourlinks">
<li><a href="http://www.google.com/"></li>
<li><a href="http://www.yahoo.com/"></li>
</ul>
jQuery
$(function() { // On DOM content ready...
var urls = [];
$('.yourlinks a').each(function() {
urls.push(this.href); // Store the URLs from the links...
});
var multilink = $('Click here'); // Create a new link...
multilink.click(function() {
for (var i in urls) {
window.open(urls[i]); // ...that opens each stored link in its own window when clicked...
}
});
$('.yourlinks').replaceWith(multilink); // ...and replace the original HTML links with the new link.
});
This code assumes you’ll only want to use one “multilink” like this per page. (I’ve also not tested it, so it’s probably riddled with errors.)
You can open multiple windows on single click... Try this..
<a href="http://--"
onclick=" window.open('http://--','','width=700,height=700');
window.open('http://--','','width=700,height=500'); ..// add more"
>Click Here</a>`
You need to unblock the pop up windows for your browser and the code could work.
chrome://settings/contentExceptions#popups
I created a bit of a hybrid approach between Paul & Adam's approach:
The link that opens the array of links is already in the html. The jquery just creates the array of links and opens each one when the "open-all" button is clicked:
HTML:
<ul class="links">
<li></li>
<li></li>
</ul>
<a id="open-all" href="#">OPEN ALL</a>
JQUERY:
$(function() { // On DOM content ready...
var hrefs = [];
$('.links a').each(function() {
hrefs.push(this.href); // Store the URLs from the links...
});
$('#open-all').click(function() {
for (var i in hrefs) {
window.open(hrefs[i]); // ...that opens each stored link in its own window when clicked...
}
});
});
You can check it out here:
https://jsfiddle.net/daveaseeman/vonob51n/1/
Here is a basic implementation in javascript - I separated it into an external file
HTML
Click To Open Links
JS
var myLinks = [
"https://google.com",
"https://www.w3schools.com/jsref/met_win_open.asp",
"https://developer.mozilla.org/en-US/docs/Web/API/Window/open"
]
function openMultipleLinks(links) {
for (var i = 0; i < links.length; i ++) {
window.open(links[i]);
}
}
Note that the user will have to enable pop-ups for the pages to open.
Here it is in action: https://jsfiddle.net/cuppajoeman/rjavuhcg/
If you prefer to inform the visitor which links will be opened, you can use a JS function reading links from an html element. You can even let the visitor write/modify the links as seen below:
<script type="text/javascript">
function open_all_links() {
var x = document.getElementById('my_urls').value.split('\n');
for (var i = 0; i < x.length; i++)
if (x[i].indexOf('.') > 0)
if (x[i].indexOf('://') < 0)
window.open('http://' + x[i]);
else
window.open(x[i]);
}
</script>
<form method="post" name="input" action="">
<textarea id="my_urls" rows="4" placeholder="enter links in each row..."></textarea>
<input value="open all now" type="button" onclick="open_all_links();">
</form>