I have a website that serves content like so, using .js:
var FluidNav = {
init: function() {
$("a[href*=#]").click(function(e) {
e.preventDefault();
if($(this).attr("href").split("#")[1]) {
FluidNav.goTo($(this).attr("href").split("#")[1]);
}
});
this.goTo("home");
},
goTo: function(page) {
var next_page = $("#"+page);
var nav_item = $('nav ul li a[href=#'+page+']');
$("nav ul li").removeClass("current");
nav_item.parent().addClass("current");
FluidNav.resizePage((next_page.height() + 40), true, function() {
$(".page").removeClass("current"); next_page.addClass("current");
});
$(".page").fadeOut(500);
next_page.fadeIn(500);
FluidNav.centerArrow(nav_item);
},
centerArrow: function(nav_item, animate) {
var left_margin = (nav_item.parent().position().left + nav_item.parent().width()) + 24 - (nav_item.parent().width() / 2);
if(animate != false) {
$("nav .arrow").animate({
left: left_margin - 8
}, 500, function() { $(this).show(); });
} else {
$("nav .arrow").css({ left: left_margin - 8 });
}
},
resizePage: function(size, animate, callback) {
if(size) { var new_size = size; } else { var new_size = $(".page.current").height() + 40; }
if(!callback) { callback = function(){}; }
if(animate) {
$("#pages").animate({ height: new_size }, 400, function() { callback.call(); });
} else {
$("#pages").css({ height: new_size });
}
}};
So far so good, but the client wants a browser back button functionality integrated. I did my homework and with the help of SO and other sources found out that the pushState and popState are the best way to achieve this.
If you take a second to read the code above, you will find out the following:
If you type website.com/#team in your browser, you are going to get the front page, not the #team page. If you want to navigate to #team, you are going to have to click from there.
If you navigate to #team and then want to go back to the front page, and you press the back button, you are going to get redirected to where you were before vising the website. Kicked out so to speak.
This is done with the purpose of a smoother browsing experience.
However, I now need to achieve the following, and I am a bit lost as to what changes I am going to have to make to my .js file above:
Achieve a working back-button functionality (manipulate the
browser's history storage)
When I type website.com/#team in the
URL bar, to go to that page and not the front page.
Here is an example website built with this functionality so you can see how it functions. http://themes.two2twelve.com/site/fluidapp/light/
You might try integrating a library that handles browsers incapable of pushState (fallback to hash urls like you're describing. I've had some luck with History.js in the past. (Get it??)
NOTE: This answer was provided by the asker as an edit to the question, rather than as an answer. I have moved it here to conform to site standards.
I did the following:
Download and unzip History.js to my server as instructed here: https://github.com/browserstate/history.js/
Follow the install here: https://github.com/browserstate/ajaxify
Installed the StateRouter from here Can't understand History.js, need it simplified? and here https://github.com/aknuds1/staterouter.js/tree/master/lib
So far what has been achieved:
Now the URLs actually change with the back button, meaning:
I go to Home -> Users -> Staff and then using the Back button the URL in the URL bar will change like so: www.123.com/#staff -> www.123.com/#users -> www.123.com/#home . However, only the URl changes and not the content. Any ideas what I am missing?
Related
I'm making a basic mobile app using HTML, and part of it is remembering the last position the user was on so when they reopen the app it goes back to the same position. I'm using this script, and it works properly on a browser, but not when you close an app and restart it.
I'm not very familiar with mobile apps, so I don't know how to fix it, appreciate your help.
Here's the script I use.
<script>
function refreshPage() {
var page_y = document.getElementsByTagName("body")[0].scrollTop;
window.location.href = window.location.href.split('?')[0] + '?page_y=' + page_y;
}
window.onload = function() {
setTimeout(refreshPage, 35000);
if ( window.location.href.indexOf('page_y') != -1 ) {
var match = window.location.href.split('?')[1].split("&")[0].split("=");
window.scrollTo(0, match[1]);
}
}
</script>
Latest Update: Could find the exact JS file dealing with the sticky header.Attached the same.
I have recently started maintaining a website that already built using Drupal.
When a user visits the homepage (https://scholars.umd.edu/) and scrolls down slowly(the issue magically vanishes when we quickly scroll down), the red band at the top seems to get stuck for a while and it is only after scrolling more and more that a user is able to scroll down finally.Please go to the website and scroll down on the home page and you will understand the issue.
I am attaching the relevant Javascript file where I think the issue might be present but I am newbie in JS so not really sure whats going on with the jQuery calls etc.
Update: The issue only happens in Chrome and not in Firefox or IE. the chrome version I am using is Version 59.0.3071.115 (Official Build) (64-bit). Also, the issue happens when I use the mouse to scroll down or when i use the touchpad and scroll down slowly. If I click and drag the scroller on the right, the issue is not present.
jQuery(document).ready(function ($) {
function stickymenu() {
var $this = this,
$body = $("body"),
header = $("#header"),
headerContainer = header.parent(),
menuAfterHeader = (typeof header.data('after-header') !== 'undefined'),
headerHeight = header.height(),
flatParentItems = $("#header.flat-menu ul.nav-main > li > a"),
logoWrapper = header.find(".logo"),
logo = header.find(".logo img"),
logoWidth = logo.attr("width"),
logoHeight = logo.attr("height"),
logoPaddingTop = parseInt(logo.attr("data-sticky-padding") ? logo.attr("data-sticky-padding") : "28"),
logoSmallWidth = parseInt(logo.attr("data-sticky-width") ? logo.attr("data-sticky-width") : "82"),
logoSmallHeight = parseInt(logo.attr("data-sticky-height") ? logo.attr("data-sticky-height") : "40");
if(menuAfterHeader) {
headerContainer.css("min-height", header.height());
}
$(window).afterResize(function() {
headerContainer.css("min-height", header.height());
});
$this.checkStickyMenu = function() {
if(!menuAfterHeader) {
if($(window).scrollTop() > ((headerHeight - 15) - logoSmallHeight)) {
$this.stickyMenuActivate();
} else {
$this.stickyMenuDeactivate();
}
} else {
if($(window).scrollTop() > header.parent().offset().top) {
header.addClass("fixed");
} else {
header.removeClass("fixed");
}
}
}
$this.stickyMenuActivate = function() {
if($body.hasClass("sticky-menu-active"))
return false;
logo.stop(true, true);
$body.addClass("sticky-menu-active").css("padding-top", headerHeight);
flatParentItems.addClass("sticky-menu-active");
logoWrapper.addClass("logo-sticky-active");
logo.animate({
width: logoSmallWidth,
height: logoSmallHeight,
top: logoPaddingTop + "px"
}, 200, function() {});
}
$this.stickyMenuDeactivate = function() {
if($body.hasClass("sticky-menu-active")) {
$body.removeClass("sticky-menu-active").css("padding-top", 0);
flatParentItems.removeClass("sticky-menu-active");
logoWrapper.removeClass("logo-sticky-active");
logo.animate({
width: logoWidth,
height: logoHeight,
top: "0px"
}, 200);
}
}
$(window).on("scroll", function() {
$this.checkStickyMenu();
});
$this.checkStickyMenu();
}
stickymenu();
});
You could be seeing this due to the way Chrome is applying your wheel events. Ben Nadel explain this in more detail.
The solution to your problem most likely boils down to setting overscroll-behavior: contain on your overflow: auto container.
I am trying to write an extension that will pop-in and pop-out a side bar type view to allow for quick management of our HR help center.
Anyways, I've taken some existing stuff and modified it to do what I want. I plan to modify it even more than what I currently have, however, I want to make sure the functionality is there before I go to my boss and say LOOK! SEE!
I've gotten the basic idea to work with the browser action icon in Chrome. No issues there. The main issue comes when I try to enable a hotkey that will also open the extension. It just will not work, I've smacked my head against my desk one too many times and I need some outside assistance.
Anyhow here is the manifest section that I have handling the hotkey.
Manifest
"commands": {
"toggle-feature": {
"suggested_key": {
"default": "Ctrl+Shift+0",
"mac": "Command+Shift+0"
},
"description": "Toggle the helpcenter screen",
"global": true
},
"_execute_browser_action": {
"suggested_key": {
"windows": "Ctrl+Shift+9",
"mac": "Command+Shift+9",
"chromeos": "Ctrl+Shift+9",
"linux": "Ctrl+Shift+9"
}
}
As you can see I got pretty desperate and added hot keys for every system on the network and tried it on them all.
background.js
chrome.browserAction.onClicked.addListener(function(tab) {
chrome.tabs.sendMessage(tab.id, { action: "toggleSidebar" });
});
chrome.commands.onCommand.addListener(function(tabh) {
chrome.tabs.sendMessage(tabh.id, { action: "toggleSidebarhkey" });
});
The second line is probably totally incorrect, I've screwed with it so many times trying to pass the information to the extension. The first line correctly handles the working half of the extension.
content.js
var sidebarURL = "help center server";
var isSidebarOpen = false;
var sidebar = createSidebar();
/* Create a pop-out */
function createSidebar() {
var sb = document.createElement("iframe");
sb.id = "mySidebar";
sb.src = sidebarURL;
sb.style.cssText = ""
+ "border: 3px groove;\n"
+ "width: 50%;\n"
+ "height: 100%;\n"
+ "position: fixed;\n"
+ "top: 0px;\n"
+ "left: 0px;\n"
+ "z-index: 9999;\n"
+ "";
return sb;
}
/* Show/Hide the pop-out */
function toggleSidebar() {
if (isSidebarOpen) {
document.body.removeChild(sidebar);
} else {
document.body.appendChild(sidebar);
}
isSidebarOpen = !isSidebarOpen;
}
**HERE IS WHERE I RUN INTO TROUBLE**
I copied and pasted the above code below and added the identifier from the background.js screen. I left the rest, because it should just use the current values to decide if it wants to close it or open it.
/* Show / Hide the pop-out via hotkey */
function toggleSidebarhkey() {
if (isSidebarOpen) {
document.body.removeChild(sidebar);
} else {
document.body.appendChild(sidebar);
}
isSidebarOpen = !isSidebarOpen;
}
/* Listen for message from the background-page and toggle the SideBar */
chrome.runtime.onMessage.addListener(function(msg) {
if (msg.action && (msg.action == "toggleSidebar")) {
toggleSidebar();
}
});
**HOT KEY LISTENER**
Once again this part is probably wrong as hell, but I've messed with it so much to try to make it work I doubt any part of it is correct.
/* Listen for message from the background-page and toggle the SideBar via hotkey */
chrome.runtime.onMessage.addListener(function(msg) {
if (msg.action && (msg.action == "toggleSidebarhkey")) {
toggleSidebarhkey();
}
});
To be honest I'm totally stuck, I suppose that many of you are thinking, "take the idea as it is to the boss!" and "your boss won't know!" but I want the extra cool-factor of not having to hunt down the button and easy access to the HR stuff in the helpcenter portal. Once I get the basic functionality of "hey Look!!" then I will expand, maybe add a panel instead of the pop-out (like google keep or hangouts) who knows, but I need a proof of concept first, and I hate to leave things uncompleted in this fashion.
As the docs on chrome.command explain, the callback for onMessage listener gets the command as the parameter, not the Tab object.
So, inside the callback you need to figure out which tab is active:
chrome.commands.onCommand.addListener( function(command) {
if(command === "toggle-feature"){
chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
chrome.tabs.sendMessage(tabs[0].id, { action: "toggleSidebarhkey" });
});
}
});
My site has a fixed navbar which causes problems when using hashes (www.somesite.com/a_page#some_hash) to jump to certain elements on the page. When the page jumps to the hashed element,fixed navbar covers part of the element. I am trying to make it so the page scrolls to element with an offset:
function getHash() {
var hash = window.location.hash;
return hash;
}
$(document).ready(function(){
if (getHash()) {
$(getHash()).fadeOut(300).fadeIn(300)
.fadeOut(300).fadeIn(300)
.fadeOut(300).fadeIn(300);
scrollTo( 0, $(getHash()).offset().top + 200);
}
})
Now, this the scrollTo part is not firing for some reason. The part right above that does (the fadeOut & fadeIn part). When I use the scrollTo line, scrollTo( 0, $(getHash()).offset().top - 200);, in the console, it work just as it should. Why isn't it scrolling when I load the page with a hash in the link? Any and all input is appreciated.
How about a function that overrides the default functionality of any link who's href value begins with a hash tag? Is that something you'd be interested in?
$(document).ready(function() {
$('a[href^="#"]').on('click', function(e) {
// prevent the default behavior so your named anchors don't cause
// a parent with an overflow to 'slide-under' it's parent.
e.preventDefault();
$('html, body').animate({ scrollTop: $($(this).attr('href')).position().top }, 'slow');
});
});
Fiddle proof of concept
Hashes seemed to be causes an immense problem. Especially because a hashed link that refers to the current page does not reload the page. As a result, any new content it not loaded. I just decided to get rid of hashes and use query parameters to simplify all the issues associated with hashes.
My url's now look like this:
www.some_site.com/some_page?element=3434
Then this query to find the element and scroll to it with an offset:
function getUrlVars() {
var vars = {};
var parts = window.location.href.replace(/[?&]+([^=&]+)=([^&]*)/gi, function(m,key,value) {
vars[key] = value;
});
return vars;
}
$(document).ready(function(){
var post_url_param = getUrlVars()["element"];
var hashed_element_id = '#' + post_url_param;
if (post_url_param) {
$(hashed_post_id).fadeOut(300).fadeIn(300).fadeOut(300).fadeIn(300).fadeOut(300).fadeIn(300);
scrollTo( 0, $(hashed_post_id).offset().top - 250);
}
})
I found this post
http://www.netmagazine.com/tutorials/create-jquery-tab-system
And modified this tabs to fit my current design. The only thing I need is to make this tabs plug-in work with hashtags. For example, if user opened mydomain.com/#firstTab open this tab.
My code looks like that
var url, tabToken;
$(function() {
var indicator = $('#indicator'),
indicatorHalfWidth = indicator.width()/2,
lis = $('#tabs').children('li');
$("#tabs").tabs("#content section", {
effect: 'fade',
fadeOutSpeed: 0,
fadeInSpeed: 400,
onBeforeClick: function(event, index) {
var li = lis.eq(index),
newPos = li.position().left + (li.width()/2) - indicatorHalfWidth;
indicator.stop(true).animate({
left: newPos
}, 600, 'easeInOutExpo');
}
});
});
$(document).ready(function() {
url = document.location.href;
tabToken=url_data = url.split('#')[1];
if(tabToken){
What to do???
}
});
Please take a look at the link that I posted, and check if I can make it work with hashtags? I don't want to change this plug-in, because I will not find any plugin with similar design.
It looks like the tutorial you are referring to is using jQuery tools tab system,
It already have history options along with backbutton support
Check http://jquerytools.org/demos/tabs/history.html#tab3
$(function() {
$(".css-tabs:first").tabs(".css-panes:first > div", { history: true });
});
http://jquerytools.org/demos/tabs/history.html#tab1
http://jquerytools.org/demos/tabs/history.html#tab2
http://jquerytools.org/demos/tabs/history.html#tab3
Also Check this for internal linking
http://jquerytools.org/demos/tabs/anchors.html