I'm working on a fairly extensive local website. It is not on a web server, and I am more or less restricted to HTML and JavaScript.
I have a side navigation menu on all the pages that is called with this statement:
<script type="text/javascript" src="menu/menu.js"></script>
menu.js is essentially a list of links like this:
document.write("<a href='page5.html#part1'>Part 1</a>");
In place on all the pages is a sticky header script that is making linking to anchors cumbersome. If you're currently on the page the link is linking to and ABOVE the anchor the link is linking to, it works fine. But if you're currently below the anchor on the same page, it gets glitched up. It doesn't take you to where it should.
There's probably another way to do it, but I feel like an easy-to-implement solution would be to create a link that first opened the page at the top, and THEN took you to the anchor.
I tried using #Qwerty's solution from this question ([Force page reload with html anchors (#) - HTML & JS), but it didn't work. I tried this:
document.write("<a href='page5.html#part1' onclick='location.reload()'>Part 1</a>");
I'm guessing it didn't work because of it being local and/or because of the link being read from a JS file.
Example
For simplicity's sake, let's say there are 3 pages on the site and each page has 3 anchors on it. I want this external JS menu to be on and work on all pages. It has these links:
page1.html#part1
page1.html#part2
page1.html#part3
page2.html#part1
page2.html#part2
page2.html#part3
page3.html#part1
page3.html#part2
page3.html#part3
The Snippet below is for ease of reference there's more involved with this than what is in the Snippet. If you like a live demonstration go to this PLUNKER.
The first page must be index.html as a requirement of the website, but you may name your pages however you want on your PC. Keep in mind the links do not include index.html because I'm too lazy to include it, it would mean writing code that wouldn't be useful for you.
// Code goes here
var pages = 5;
var parts = 3;
var pg = [];
var pt = [];
var menu = document.getElementById('menu');
var i, j;
for (i = 0; i < pages; i++) {
var page = 'page' + (i+1);
pg.push(page);
for (j = 0; j < parts; j++) {
var part = 'part' + (j+1);
pt.push(part);
var url = pg[i] + '.html#' + pt[j];
var anchor = document.createElement('a');
anchor.href = url;
anchor.textContent = 'Page ' +(i+1) + ' Part ' +(j+1) ;
menu.appendChild(anchor);
}
}
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="style.css">
</head>
<body>
<h1>Index</h1>
<nav id='menu'></nav>
<section id='part1'>
<h2>Part1</h2>
</section>
<section id='part2'>
<h2>Part2</h2>
</section>
<section id='part3'>
<h2>Part3</h2>
</section>
<script src="menu.js"></script>
</body>
</html>
This may either be brutally irrelevant to your question or give you an idea, how your app could be structured better. To handle your navigation needs, you don't need Javascript. But you can add it to the mix to improve this solution with nice gimmicks.
<html>
<head>
<title>one-page-app</title>
<style>
.pages {
display: none;
}
.pages:target {
display: block;
}
</style>
</head>
<body>
<nav>
<p>Main Menu:</p>
Home
FAQ
External content (other file)
</nav>
<a name="home"></a>
<div id="home" class="pages">
<h1>Home</h1>
<p>Hi. Check FAQ to see how it's working.</p>
</div>
<a name="faq"></a>
<div id="faq" class="pages">
<h1>FAQ</h1>
<ul>
<li>
<h2>How does it work?</h2>
<p>The magic of the <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/CSS/:target">:target pseudo-class in CSS</a>.</p>
</li>
<li>
<h2>What if I have more content?</h2>
<p>
I've worked with 2-3 MB html files without a problem. That's when smartphone browsers were really choking. ;) For local pages, loading time is no issue after all.</p>
</li>
<li>
<h2>What about REALLY old browsers?</h2>
<p>They will see all the content at once, but due to the anchors, the main menu will still work. Add "back to top" links to the pages if you want.</p>
</div>
<a name="external"></a>
<iframe id="external" class="pages" src="http://google.com"></iframe>
</body>
</html>
EDIT - after question-edit:
If you want to keep your current structure, you could just do:
<a name="page1_1"></a>
<iframe id="page1_1" class="pages" src="page1.html#part1"></iframe>
<a name="page1_2"></a>
<iframe id="page1_2" class="pages" src="page1.html#part2"></iframe>
and so on.
Related
I will try to summarize this in a Requirements fashioned way, I hope this simplifies the question.
When clicking on an anchor tag, the web page navigates the user to a new page, where upon page load, the page is scrolled to the element which corresponds to the aforementioned anchor tag, which was previously clicked.
As you will see in the code I am trying to make use of the CSS scroll-behaviour property.
https://developer.mozilla.org/en-US/docs/Web/CSS/scroll-behavior
So far I have tried out the code bellow, however when I run it I get an error message in the developer console stating:
TypeError: Cannot read property 'offsetTop' of undefined
Hence, I surmise that the window.onload function is not really fired on the page which I would like to load but the very same page on which I am located when clicking the anchor tag. How can I change the code so it would count for page intended.
HTML of Page A (where the anchor tag is located):
<a id="ship-it" href="services.html" class="services">
<div id="image-container_4">
<div id="image_4">
<div id="overlay_4"></div>
<h2 class="h2">We pack it and ship it</h2>
<img id=imageB src="/images/shipping.jpg" alt="">
</div>
</div>
</a>
HTML of Page B (where the target element is located):
<section id="manufacturing-section" class="section">
<img src="/images/manufacturingMelting2.jpg" alt="Magnetic Particle Inspection">
<div id="manufacturing-container">
<h2> <span>Manufacturing</span> <br> We provide high quality, low cost solutions to meet your requirements.</h2>
<p>
soemthing something something, DarkSide...
</p>
</div>
</section>
JS / CSS:
function scrollIt(element) {
window.scrollTo({
'behavior': 'smooth',
'left': 0,
'top': element.offsetTop
});
}
const serviceAnchor = document.querySelectorAll('.services');
//'serviceAnchor' is located on page A
const sections = document.querySelectorAll('.section');
// 'sections' is located on page B and represents the element the page should scroll to when the page has loaded after the corresponding anchor tag was clicked
serviceAnchor[0].addEventListener('click', () => {
window.onload = scrollIt(sections[0]);
});
serviceAnchor[1].addEventListener('click', () => {
window.onload = scrollIt(sections[1]);
});
serviceAnchor[2].addEventListener('click', () => {
window.onload = scrollIt(sections[2]);
});
serviceAnchor[3].addEventListener('click', () => {
window.onload = scrollIt(sections[3]);
});
The reason you're getting the error is it's impossible to run javascript across page loads. Assuming you're using a traditional site and not a single-page app, when the browser loads a new page, all javascript on the current page is stopped.
Browsers already support jumping to an element on page load using the www.site.com#myElementId syntax. If you want smooth scrolling, you'll need to pass the id of element to scroll in the url, or some other way like caching its id in localstorage, then run your smooth scrolling js on the pageload of the other page.
You can't navigate to a different page and then ask the browser to launch a piece of JavaScript. That would be a huge security issue, since I could make you click into a link to, let's say, my-bank.com then do a bit of JavaScript do access your secret cookies or local storage and hack into your account.
The only thing you can do is link to anchors inside the linked page, and the default scroll behavior (no smooth scrolling, for most browsers, since it's the least computationally and resources intensive) will be used:
<!-- not possible -->
<a onclick="navigateThenDoSomething()">Some link</a>
<!-- possible -->
Some link
If you own the target page, however, you can hide a target section in the query string then do a bit of magic in the target page's onload to smoothly scroll to your section:
<!-- source-page.html -->
Some link
// script running at target-page.html
const url = new URL(window.location);
const section = url.searchParams.get('section');
if (section) {
// scroll smoothly to `section` using
}
Since .scrollTo JS method with options has the same browser compatibility as scroll-behavior CSS property, and you're OK with that, you might get rid of your JS code and set:
html, body, .or-other-scrolling-container {scroll-behavior:smooth}
and use anchor links.
So HTML of Page A would be e.g.:
<a id="ship-it" href="services.html#manufacturing" class="services">
<div id="image-container_4">
<div id="image_4">
<div id="overlay_4"></div>
<h2 class="h2">We pack it and ship it</h2>
<img id=imageB src="/images/shipping.jpg" alt="">
</div>
</div>
</a>
And HTML of Page B (please note <a name="#manufacturing"> tag):
<a name="manufacturing"></a>
<section id="manufacturing-section" class="section">
<img src="/images/manufacturingMelting2.jpg" alt="Magnetic Particle Inspection">
<div id="manufacturing-container">
<h2>
<span>Manufacturing</span><br>
We provide high quality, low cost solutions to meet your requirements.
</h2>
<p>something something something, DarkSide...</p>
</div>
</section>
Working example:
html {scroll-behavior:smooth}
.long {height:100vh; background:#efc}
<a id="ship-it" href="#manufacturing" class="services">
<div id="image-container_4">
<div id="image_4">
<div id="overlay_4"></div>
<h2 class="h2">We pack it and ship it</h2>
<img id=imageB src="https://picsum.photos/50/50" alt="">
</div>
</div>
</a>
<section class="long">Placeholder to enable scroll</section>
<a name="manufacturing"></a>
<section id="manufacturing-section" class="section">
<img src="https://picsum.photos/400/220" alt="Magnetic Particle Inspection">
<div id="manufacturing-container">
<h2>
<span>Manufacturing</span><br>
We provide high quality, low cost solutions to meet your requirements.
</h2>
<p>something something something, DarkSide...</p>
</div>
</section>
Hope it helps.
I'm trying to create a drop down FAQ page with jQuery and for some reason the answers are showing when I load the page.
I have my jQuery script on my page
<script src="http://code.jquery.com/jquery-2.1.4.min.js"></script>
And my javascript page:
<script src="js/threecatsdesign.js"></script>
My full javascript is this:
$(document).ready(function() {
$("#categories h3").click(
function() {
$(this).toggleClass("minus");
if ($(this).attr("class") != "minus") {
$(this).next().hide();
}
else {
$(this).next().show();
}
$("#image").attr("src", "");
// needed for IE so a placeholder isn't displayed for the image
$("#image").attr("style", "display:none;"); }
); // end click
}); // end ready
My HTML is this code:
<main id="categories">
<h3>What is this site about?</h3>
<div>
<ul id="web_images">
<li>We are a website that holds Photoshop lessons called tutorials. Please read our about me page for more information.</li>
</ul>
</div>
<h3>If you hold contests on the site, how do I enter?</h3>
<div>
<ul id="java_images">
<li>Go to our page called contests in the nav bar and you will need to fill out the form in order to enter.</li>
</ul>
</div><p>
<h3>I have a tutorial I would like to suggest or put up my own. How do I do that?</h3>
<div>
<ul id="net_images">
<li>Please go fill out our contact form and you will be contaced with 24 hours or less on how to proceed.</li>
</ul>
</div>
You need to add some css to hide the questions to begin with.
<style>
.faq-question div {
display:none;
}
</style>
I suggest putting this in a different file, but inline styles like this work for a quick and dirty solution.
You also should wrap each question and answer in a tag like this
<div class="faq-question">
<h3>What is this site about?</h3>
<div>
<ul id="web_images">
<li>We are a website that holds Photoshop lessons called tutorials. Please read our about me page for more information.</li>
</ul>
</div>
</div>
And change your JS to reflect the change in elements.
$(".faq-question").click(
I have a page with a visiual menu system that when clicked fills the designated area with an image and approriate text. Below I have included an example of the containers and script used on the page.
There are around 20 of them in all and each has its own individual # tag. If I try to reference the page via a link like the one below. It doesn't change the content of the page to match the unique # tag. I think this is due to the script being a click event only. Can someone give me an idea of how fix this so I can use this link externally on other html pages within the site and have the appropriate # information show up.
http://jets.chiefaircraft.com/skymaster/available-models.html#af816sw
The menu html:
<div class="box">
<a href="#bh248" class="scheme-links" data-scheme="bh248">
<div class="boxinner">
<img src="http://cdn1.chiefaircraft.com/skymaster/images/gallery/bae-t1/BH248.jpg" alt=""/>
<div class="titlebox">BAE Hawk T-1 - In Stock<br />RAF 2004 Scheme
</div>
</div>
</a>
</div>
The click event:
$(document).ready(function(event){
$('.scheme-links').click(function(event){
var scheme = $(this).attr('data-scheme');
$('.gallery').hide(event);
$('#gallery_' + scheme).show(event);
});
});
The event references this information to fill the selected areas:
<div id="gallery_bh248" class="gallery">
<div class="gallery-image"><img src="http://cdn1.chiefaircraft.com/skymaster/images/gallery/bae-t1/BH248.jpg" alt=""/></div>
<div class="gallery-info">
<div class="gallery-text">
<h2><u>Skymaster PRO ARF Plus</u><br />
BAE Hawk T-1:</h2>
<h3>RAF 2004 Scheme (BH248)<br />
In Stock: Only $5,199.50 + Freight</h3>
</div>
<div class="gallery-upgrade">
<p><b>Includes the Following Upgrades:</b></p>
<ul><li>Jet Airframe: BH248 RAF 2004 Scheme</li>
<li>Scale Landing Gear: AP921</li>
<li>Speed Brake Assembly Factory Installed</li>
<li>Landing Gear & Doors Factory Installed</li>
<li>Cylinder Set for Gear Doors: AP925</li>
<li>Cockpit Details w/o Pilot: AP927</li>
<li>Exhaust Pipe (P120-P160): AP923</li>
<li>Complete Air Kit: AP921K</li>
<li>Kevlar Fuel Tank: AP922</li>
<li>Hardware Kit: AP924</li>
<li>Wing Bag</li></ul>
</div>
</div>
</div>
Is what you want?
Once the website loads, you can recognize what hash came with it, and make a proper function to load it.
Please elaborate your code further so if this isn't the correct answer, I can be of help/edit.
$(function()
{
// Moving page to hash on open
var hash = null;
if(window.location.hash)
{
hash = window.location.hash;
window.location.hash = '';
window.location = hash;
}
});
We have a single page application with two views (essentially, a list of items and a details page for the selected item). Both views are in separate html files, and we’re using sammy.js to transition/navigate between the pages. Everything was working great until we tried to add jQuery Mobile to the mix. Now, when we navigate to the second page (the details page), jQuery Mobile is not styling the page.
Our working app is not set up as described by jQuery Mobile’s multi-page template (i.e., having all page divs in the same html file and use their navigation system to load linked pages into the DOM via AJAX). But, is it possible to have separate pages, use something other than jQuery Mobile’s navigation, and still have jQuery Mobile style the second page? Or, is there a way to force jQuery Mobile to style the second page?
Here’s some code snippets that’ll hopefully help show what we’re doing. (Note: We’re also using ASP.NET razor views.)
index.cshtml
<body>
#RenderPage("Views/items.cshtml")
#RenderPage("Views/item.cshtml")
#Scripts.Render("~/bundles/jquery")
<script>
$(document).bind("mobileinit", function () {
$.mobile.ajaxEnabled = false;
$.mobile.hashListeningEnabled = false;
$.mobile.pushStateEnabled = false;
$.mobile.loader.prototype.options.text = "loading. please wait...";
$.mobile.loader.prototype.options.textVisible = true;
});
</script>
#Scripts.Render("~/bundles/jquerymobile", ...)
</body>
items.cshtml (this page gets loaded and rendered correctly)
<section id="items-view" class="view" data-role="page">
<section data-role="header">
....
</section>
<section data-role="content">
(navbars, ULs, LIs, etc. are here, with each LI a link to go to the details page)
</section>
<section data-role="footer">
....
</section>
</section>
item.cshtml (this page gets loaded but NOT rendered correctly, there is no jQuery Mobile styling)
<section id="item-view" class="view" data-role="page">
<section data-role="header">
....
</section>
<section data-role="content">
(ULs, LIs, listboxes, textboxes, etc. are here)
</section>
<section data-role="footer">
....
</section>
</section>
router.js (used to route between pages)
....
navigateTo = function (url) {
sammy.setLocation(url); // url = #/items or #/item/1234
},
....
In the js file for the item page, we’ve tried:
var $page = $("#item-view");
//$page.trigger("create");
//$page.listview("refresh");
//$page.page(); (this one kind of work but doesn’t style every object)
//$page.page("refresh", true);
but haven’t got any thing to work correctly and completely.
So, again, given our situation, is there a way to have a jQuery Mobile multi-page app with actual separate physical files and have all pages get style correctly? Or is there a programmatic way to force jQuery Mobile to style all pages correctly?
Thanks.
jquery mobile does NOT load everything from your second page.
when you require a new page with JQM (or it's ajax method), it loads parts of your page's DOMs and get all things under
<div data-role="page" id="yourPageID"></div>
so your could simply try put your stylesheet under "data-role", like this:
<div data-role="page" id="yourPageID">
<link rel="stylesheet" href="yourStyleSheetLink.css" />
</div>
then, when JQM requires a new page, your stylesheets will be loaded.
as a non-English speaker, i hope you can understand my words :)
I'm trying to make a twitter like system that scrolls through info slowly and then repeats.
I have it down(kinda) thanks to this tutorial. I have it working on its own and I added my own content but when I try adding it to my webpage it takes a c*** on me and throws all of my content all together at the top of the page. Any suggestions?
<div class="header">
<h2><span>Resteruant Consulting</span></h2>
<h1>Tasty Solutions</h1>
</div>
<div class="content">
<DIV align=center style="background:#fff">
<DIV id="tempholder"></DIV>
<SCRIPT language=JavaScript
src="dhtmllib.js"></SCRIPT>
<SCRIPT language=JavaScript
src="scroller.js"></SCRIPT>
<SCRIPT language=JavaScript
src="mydata.js"></SCRIPT>
<SCRIPT language=JavaScript>
//SET SCROLLER APPEARANCE AND MESSAGES
function runmikescroll() {
var layer;
var mikex, mikey;
// Locate placeholder layer so we can use it to position the scrollers.
layer = getLayer("placeholder");
mikex = getPageLeft(layer);
mikey = getPageTop(layer);
// Create the first scroller and position it.
myScroller1.create();
myScroller1.hide();
myScroller1.moveTo(mikex, mikey);
myScroller1.setzIndex(200);
myScroller1.show();
}
window.onload=runmikescroll
</SCRIPT>
<center><DIV id='placeholder'></DIV></div></DIV></center>
</div>
I have all the other javascript in the same directory. I have javascript enabled in my web browser, and it works on its on its just when I incorporate it into my index.html it gets screwy.
each headline has a "position:absolute", perhaps if you put those headlines in a div with
position:relative;
so the headlines at least will stay just in that div.
if I'm wrong pardon me, if I'm right let me know.