Single page app reload - javascript

I am writing a single page app with several divs that have the attribute data-roll="page". Pushing buttons fires ajax queries and the user is redirected to divs down the document like this
<body>
<div data-role="page" id="menu">
//bunch of nav buttons like <a href="#faculty">
</div>
<div data-role="page" id="faculty" data-theme="b">
//dynamicly loaded list of faculty
</div>
and so on.
I want to return to the menu div on refresh but no amount of scrolling
seems to work. Here is my JS with two attempts at getting back to the menu page on page load.
document.ready = init;
function init(){
var button = $('#facultyButton')
,facList = $('#facultyList')
,search = $('#facSearch')
,monikerBox = $('.monikerBox')
,events = $('#events')
,ajaxString = "http://stage.webscope.com/veith/dev/ajax.pl?"
,html = "";
//executed on init
$('html').scrollTop(0);
//events
$(window).on('load',function(){
$('html').scrollTop(0);
});
button.click(function(){
var value = "a";
search.html( "" );
facultyAjax(value);
});
I also tried window.location= menu url (home) in various functions with disastrous results!

Set the window.location you want the user to view with the location object on the load event.
I put this in the html.
<body onload="location.href='#menu'">

Related

How to open a hidden div from url with #anchor

I have a page that has a grid of staff bios, when the bios are clicked additional information is displayed in a modal. I would like to be able to display the content of specific staff when linked from another page. I would like to use plain javascript and add a #anchor in the url.
When I was building this set up I seemed to have stumbled apon this on accident, but now it won't work. The closest I have gotten is from this post: How to open a hidden div when a hash is on the URL?
/*To open the details window when the ID # is used in the url*/
var hash = window.location.hash.replace('#', '');
if (hash) {
document.getElementById(hash).classList.add("bio-open");
}
Here is my markup:
<div class="bio-tile">
<div id="close" class="anchor"></div>
<div class="tile-inner" onclick="speakerDetails('open')">
//Thumbnail content here
</div>
</div>
<div id="open" class="speaker-details">
<div class="speaker-details-wrapper">
<span onclick="speakerDetailsClose('open')" class="speaker-close">×</span>
//details content here
</div>
</div>
Here are the scripts on the page:
/* To Allow Body and HTML scroll on load in class to be toggled */
window.addEventListener('DOMContentLoaded', (event) => {
document.body.classList.add("allow-overflow");
document.documentElement.classList.add("allow-overflow");
});
var speaker;
/*To open the details window when the ID # is used in the url*/
var hash = window.location.hash.replace('#', '');
if (hash) {
document.getElementById(hash).classList.add("bio-open");
}
/* To open Speaker Bio Pop Up and prevent body/html scroll*/
function speakerDetails(slug) {
speaker = document.getElementById(slug);
speaker.classList.add("bio-open");
document.body.classList.add("no-overflow");
document.documentElement.classList.add("no-overflow");
document.documentElement.classList.remove("allow-overflow");
}
/*To Close Speaker Bio Pop Up When X close button is clicked and allow body/html scroll*/
function speakerDetailsClose(slug) {
speaker.classList.remove("bio-open");
document.body.classList.remove("no-overflow");
document.documentElement.classList.remove("no-overflow");
document.documentElement.classList.add("allow-overflow");
}
/*To Close Staff Bio Pop Up when clicked outside of the bio container and allow body/html scroll*/
window.onclick = function(event) {
if(event.target == speaker) {
speaker.classList.remove("bio-open");
document.body.classList.remove("no-overflow");
document.documentElement.classList.remove("no-overflow");
document.documentElement.classList.add("allow-overflow");
}
}
I would like to have the page load using a www.site.com/page#open url, to display one of the bio details divs on load and then be able to close it to access the other bios on the page.
You're close. Basically when you are selecting things in the DOM you need to know the elements are there. What's happening is that the code inside of your if statement around the hash is getting executed before the DOM is loaded so the element doesn't existing and is returning null.
Here is what I did to work around that; just move your the hash var and the if statement into your DOMContentLoaded event listener.
document.addEventListener('DOMContentLoaded', function(event) {
//the DOMContentLoaded event occurred, which means the DOM is done loading.
/*To open the details window when the ID # is used in the url*/
var hash = window.location.hash.replace('#', '');
if (hash) {
// you don't have to do this extra save to a var, but it's clearer
var elem = document.getElementById(hash);
elem.classList.add("bio-open");
}
});
I have figured it out! Thought I would share for the rest of the SO world and thanks to bgaynor78 for getting me headed towards the right idea.
I used document.addEventListener('DOMContentLoaded', function(event) { twice, which I am not sure if that is totally best practice.
var speaker;
var hash = window.location.hash.replace('#', '');
var tag;
/* To Allow Body and HTML scroll on load in class to be toggled */
window.addEventListener('DOMContentLoaded', (event) => {
document.body.classList.add("allow-overflow");
document.documentElement.classList.add("allow-overflow");
});
/*To open the details window when the ID # is used in the url*/
window.addEventListener('DOMContentLoaded', (event) => {
if (hash) {
tag = document.getElementById(hash);
tag.classList.add("bio-open");
document.body.classList.add("no-overflow");
document.documentElement.classList.add("no-overflow");
document.documentElement.classList.remove("allow-overflow");
}
});
I then added some IF statements to reference in the scripts to close the window:
function speakerDetailsClose(slug) {
if (hash) {
tag.classList.remove("bio-open");
speaker.classList.remove("bio-open");
document.body.classList.remove("no-overflow");
document.documentElement.classList.remove("no-overflow");
document.documentElement.classList.add("allow-overflow");
}
else {
// the rest of the script

hide back menu button if page was opened as a blank

How to hide a back button (in nav menu) if current page was opened with target="_blank".
in usual case this page is called as:
<a href="/about_us/" class="nav-li" >About Us</a>
in another case it is called with:
<a href="/about_us/" class="nav-li" target="_blank" >About Us</a>
The code at the target page for the back button is:
<label class="nav-li" for="back">Back</label>
<input class='Back' id = "back" type=button value="Back" onClick="history.go(-1)">
How to hide this button if opened as blank ???
Whole project is on Django
Just hide the button if the history object has a length of null less than 2 . This could be done with a css-class, pure css or direct with JS
[EDIT]:
I would add this to the onload event of the new form.
function init(){
if(history.length < 2){
document.getElementById('Back').style.display = none;
}
}
[...]
<body onload="init()">
[...]
You should heck the history object if the length is less or equal to 1 so it haven't a history, so you can hide your btn
window.onload = function (){
var hasHistory = history.length <= 1; //if has an history;
document.getElementById('cacca').style.display = hasHistory ? "none" : "block";
}

How to store active class of a div when page reloads using local storage

I am not able to save active class for a div on page reload, when I click button in first div then its active class is removed and next class is made active. But when the page reloads in second div, how to save active class for second div when page is reloaded . i tried using local storage but i dunno that.
<div class="divs active" id="first">
<h1> first div</h1>
<a class="btn-link" href="javascript:void(0);" id="btn-first">Next - 2</a>
</div>
<div class="divs" id="second">
<h1> second div</h1>
<a class="btn-link" href="javascript:void(0);" id="btn-second"/>Next -3 </a>
</div>
<div class="divs" id="third">
<h1> third div</h1>
<a class="btn-link" href="javascript:void(0);" id="btn-third"/>Next -1</a>
</div>
<script>
$(document).ready(function(){
$('#btn-first').click(function(){
$('.divs').removeClass('active');
var activeID = $('#second').addClass('active');
console.log(activeID);
localStorage.setItem("activeDIV", activeID);
//var reloadactiveDIV = localStorage.getItem("activeDIV");
// var activeID = $('#second');
// localStorage.setItem('activeTab', $activeID );
// var activeTab = localStorage.getItem('activeTab');
// if (activeTab) {
// $('.divs').removeClass('active');
// $('#second').addClass('active');
// }
});
$('#btn-second').click(function(){
$('.divs').removeClass('active');
$('#third').addClass('active');
});
$('#btn-third').click(function(){
$('.divs').removeClass('active');
$('#first').addClass('active');
});
});
</script>
To achieve this you can store the index of the active div in local storage, instead of the entire jQuery object, and then re-set the active class on the element within the index of localStorage when the page is next loaded.
Also note that you can DRY up the logic by using a single event handler for all the buttons. You can find the parent .divs and retrieve the next one, looping back to the first if there is no next sibling. Try this:
$(document).ready(function() {
// set active on click:
$('.btn-link').click(function(e) {
e.preventDefault();
var $parentDiv = $(this).closest('div');
var $nextDiv = $parentDiv.next('div');
var $divs = $('.divs').removeClass('active');
if (!$nextDiv.length)
$nextDiv = $divs.first();
$nextDiv.addClass('active');
localStorage.setItem("activeDiv", $nextDiv.index('.divs'));
});
// set active on load:
var activeIndex = localStorage.getItem("activeDiv");
if (activeIndex)
$('.divs').removeClass('active').eq(activeIndex).addClass('active')
});
Working Example
Note that I couldn't place a working example in a SO Snippet as it has restrictions in place on accessing localStorage.

How to run .evaluate .then multiple times in nightmare

I tried to scrape web page generated by AJAX. On the web page inside <div class='main'> are several <a class='classLinks'> elements and after click on one of them is being content generated in the same <div class='main'> and <a class='classLinks'> elements are replaced with one <a class='back'> back button.
My task is grab content generated after click on all <a class='classLinks'> elements inside <div class='main'> and write it to console log.
I put all <a class='classLinks'> to the array of selectors but problem is I don't know how to run sequence ".click, .wait, .evaluate., .click" inside for cycle.
Steps are:
goto http://example.com
click on subpage
get all "a" elements
content = ""
for (i=0; i < a.lenght; i++)
{
click on a[i]
content = content + div.innerHTML;
click on "a.back"
}
console.log content;
My code looks:
var content
nightmare
.goto('http://example.com')
.wait('.firstpage')
.click('a.subpage')
.wait('.main')
.evaluate(function(){
var links = document.querySelectorAll('a.classLinks');
for (i = 0; i < links.length; ++i) {
links[i].click();
// now i need to wait for <div class='main'>
.wait('.main')
// and do evaluate again
.evaluate(function(){
//content is glogal variable
content = content + document.querySelector('div.main').innerHTML;
// and click on 'back' link becaus all a.classLinks disappeared
document.querySelector('a.back').click();
})
})
return content;
.end()
.then(function(content) {
console.log(content);
})
Please how to process several evaluations inside for cycle in nightmare?

More then one event in an onclick print event

I have an onclick print event, its working fine but now i have some div's i want to print out, so my question is, how can i make this script working with all id="PrintElement" Or id="PrintElement1" / id="PrintElement2" and so on, so i can add the ID to the div's i want to print out on one paper.
I have this Javascript, thats work with One div called id="PrintElement".
<script type="text/javascript">
//Simple wrapper to pass a jQuery object to your new window
function PrintElement(elem){
Popup($(elem).html());
}
//Creates a new window and populates it with your content
function Popup(data) {
//Create your new window
var w = window.open('', 'Print', 'height=400,width=600');
w.document.write('<html><head><title>Print</title>');
//Include your stylesheet (optional)
w.document.write('<link rel="stylesheet" href="add/css/layout.css" type="text/css" />');
w.document.write('<link rel="stylesheet" href="add/css/main.css" type="text/css" />');
w.document.write('</head><body>');
//Write your content
w.document.write(data);
w.document.write('</body></html>');
w.print();
w.close();
return true;
}
</script>
Then i have a div
<div id="PrintElement">
SOME CODE.....SHORT/LONG
</div>
And to activate the function i have
<a onclick="PrintElement('#PrintElement')">Print</a>
Working fine now i just want it to work with more then one div called id="PrintElement" or if easier i can call the divs ID PrintElement and a number... so it just print out the div's with the ID's
<div id="PrintElement">
SOME CODE.....SHORT/LONG
</div>
<div>
SOME CODE.....SHORT/LONG
</div>
<div id="PrintElement">
SOME CODE.....SHORT/LONG
</div>
<div>
SOME CODE.....SHORT/LONG
<div id="PrintElement">
SOME CODE.....SHORT/LONG
</div>
<div>
SOME CODE.....SHORT/LONG
</div>
</div>
Hope u understand..
You should replace id="PrintElement" with class="PrintElement" in your HTML
And then change your <a onclick="PrintElement('#PrintElement')">Print</a> with <a onclick="PrintElement('.PrintElement')">Print</a>
And then:
function PrintElement(elem){
$(elem).each(function() {
Popup($(this).html());
});
}
This will open a new window for every PrintElement though...
You can collect data with a var and then call Popup at the end of the loop.
EDIT: The code above is using jQuery... so you'll need the library.
EDIT2: If you want to collect data and open only one popup
function PrintElement(elem){
var data = '';
$(elem).each(function() {
data = data + $(this).html();
});
Popup(data);
}
Without jQuery, first move the code that enumerates target IDs to a function, don't embed it in the HTML:
<a onclick="PrintElements()">Print</a>
And in JS:
function PrintElements() {
printElement('#PrintElement1')
printElement('#PrintElement2')
}
There's a better approach, however. You can use classes (<div class="PrintElement">) in your HTML to mark print targets and then pick them up from PrintElements using document.getElementsByClassName.
function PrintElements() {
targets = document.getElementsByClassName('PritnElement')
[].forEach.call(targets, function(x) {
PrintElement(x)
})
}

Categories

Resources