My use case is very simple: I'm in a custom list form (modified NewForm.aspx, added with SharePoint Designer). I've added a button and I want that when the users clicks on it, the page scrolls back to the very top.
I've tried to following approach :
In the aspx
<button onclick="return MyScrollTop()">SCROLL TOP</button>
In the javascript
function MyScrollTop() {
//All my attemps go here
return false;
}
I'm not detailing how I'm making sure that the function is called (it can be tricky sometimes in SharePoint, with the MDS and _spBodyOnLoadFunctionNames.push, but I'm 100% certain that my function is called as I see it in the browser's debugger.
I'm using IE11, both in "10" and "Edge" modes.
Here are my attempts (I tried them one by one, not in the same function)
//attempt #1 (as seen on W3C)
document.body.scrollTop = 0;
document.documentElement.scrollTop = 0;
//attempt #2 (as seen on Stack Overflow for regular javascript)
window.scrollTo(0,0);
//attempt #3 (as seen on Stack Overflow for some corner case - desperate attempt)
window.scroll(0,0);
//attempt #4 (as seen on Stack Overflow to fight SharePoint's '_maintainWorkspaceScrollPosition' hidden control on a page reload or unload)
var scrollX = document.getElementById('__SCROLLPOSITIONX');
var scrollY = document.getElementById('__SCROLLPOSITIONY');
if (scrollX && scrollY) {
scrollX.value = 0;
scrollY.value = 0;
}
var workspaceY = document.getElementById('_maintainWorkspaceScrollPosition');
if (workspaceY) {
workspaceY.value = 0;
}
None of these work. When I click on the buttons, the breakpoints show me that my script is executed, but it's like window.scrollTo and others have no effect at all.
I've put a breakpoint in this SharePoint function from init.js to see if I can hook myself somewhere, but I'm not sure wht I should do :
if (!g_setScrollPos) {
if (browseris.firefox && browseris.firefox36up)
window.scrollTo(0, 0);
if (Boolean((ajaxNavigate.get_search()).match(RegExp("[?&]IsDlg=1")))) {
if (!isIE7 || elmWorkspace.scrollHeight < elmWorkspace.clientHeight)
elmWorkspace.style.overflowY = "auto";
}
var scrollElem = document.getElementById("_maintainWorkspaceScrollPosition");
if (scrollElem != null && scrollElem.value != null) {
elmWorkspace.scrollTop = Number(scrollElem.value);
}
g_setScrollPos = true;
}
CallWorkspaceResizedEventHandlers();
g_frl = false;
I finally managed to do it like this :
var w = document.getElementById("s4-workspace");
w.scrollTop = 0;
Related
I am running a script to show a notification within a menu with scroll, but I do not know how to detect if the device has orientation landscape to validate the script.
The call onClick="VerHayMas();" works perfectly, but if the user open the menu once, clicking on #boton-menu and with your device in portrait, after changing the orientation to landscape the script no longer meet the objective.
The script has its logic ONLY if the device is in landscape, which is
when the menu needs to show the notification.
So, is it possible that my script is only valid with (max-width:999px) and (orientation:landscape), ignoring the portrait...?
I am a beginner in JS, and I do not know how to do it, really.
Any idea?
Thanks in advance!
HTML & CSS
#mas-menu {display:none}
<div id="boton-menu" onClick="VerHayMas();">+</div>
Script:
var clicksVerHayMas = 0;
function VerHayMas() {
clicksVerHayMas = clicksVerHayMas + 1;
if (clicksVerHayMas == 1) {
document.getElementById('mas-menu').style.display = 'block';
window.setTimeout(function() {
$('#mas-menu').fadeOut('slow');
}, 4000);
}
};
EDIT:
I have tried with the following script, but it does not work. If the user makes a call to onClick="VerHayMas();" in portrait mode, the script is no longer running in landscape mode.
What am I doing wrong here?
const matchesMediaQuery = window.matchMedia('(max-width:999px) and (orientation:landscape)').matches;
if (matchesMediaQuery) {
var clicksVerHayMas = 0;
function VerHayMas() {
clicksVerHayMas = clicksVerHayMas +1;
if(clicksVerHayMas == 1){
document.getElementById('mas-menu').style.display = 'block';
window.setTimeout(function(){
$('#mas-menu').fadeOut('slow');
},4000);
}};
}
I'd keep it simple, if screen height is less than width, then the user is in landscape mode. You can grab the height and width from the global window object.
if (window.innerWidth > window.innerHeight) {
// The user is in landscape mode!
userInLanscapeFunc();
}
Reference: https://developer.mozilla.org/en-US/docs/Web/API/Window/innerHeight
You can solve this using matchMedia:
const matchesMediaQuery = window.matchMedia('(max-width:999px) and (orientation:landscape)').matches;
if (matchesMediaQuery) {
// do something
}
Make sure to note the browser support in the MDN link.
EDIT TO PROVIDE CONTEXT:
Because the user may be moving around their screen, you will want to make this evaluation inside VerHayMas, each time it is run, to determine if the main body of the script should be executed:
var clicksVerHayMas = 0;
function VerHayMas() {
var isLandscapeAndMeetsSizeRequirements = window.matchMedia('(max-width:999px) and (orientation:landscape)').matches;
if (isLandscapeAndMeetsSizeRequirements) {
clicksVerHayMas = clicksVerHayMas + 1;
if (clicksVerHayMas == 1) {
document.getElementById('mas-menu').style.display = 'block';
window.setTimeout(function() {
$('#mas-menu').fadeOut('slow');
}, 4000);
}
}
};
So VerHayMas will be run on every click, but only if the screen meets the requirements as determined by the media query string will it execute the code inside the if block.
I have a working bottom function in JavaScript to detect if the user scrolls at the bottom. However, a problem comes when the user has a strange resolution (like windows scale) or when you zoom. The function is not working anymore and can't detect the bottom.
Here is what I did :
const bottom = e.target.scrollHeight - e.target.scrollTop === e.target.clientHeight;
if (bottom) {
this.props.getNewValues();
}
Is there a way to avoid that? Even when you don't zoom, this is not working for people displaying the site on a TV or something like this (like a friend of mine did)
Thanks you
EDIT : I'm applying this on a precise element and I repeat that my solution is working except by unzooming. Unzooming provides float values that made the response not really accurate (it goes from 1 to 50px of difference based on the zoom made)
I use this function (can't take credit as someone else wrote it - sorry for no credit - it was ages ago). Maybe you can adapt this to your use case:
(function($) {
//CHECK SCROLLED INTO VIEW UTIL
function Utils() {
}
Utils.prototype = {
constructor: Utils,
isElementInView: function (element, fullyInView) {
var pageTop = $(window).scrollTop();
var pageBottom = pageTop + $(window).height();
var elementTop = $(element).offset().top;
var elementBottom = elementTop + $(element).height();
if (fullyInView === true) {
return ((pageTop < elementTop) && (pageBottom > elementBottom));
} else {
return ((elementTop <= pageBottom) && (elementBottom >= pageTop));
}
}
};
var Utils = new Utils();
//END CHECK SCROLLED INTO VIEW UTIL
//USING THE ELEMENT IN VIEW UTIL
//this function tells what to do do when the element is or isnt in view.
//var inView = Utils.isElementInView(el, false); Where FALSE means the element doesnt need to be completely in view / TRUE would mean the element needs to be completely in view
function IsEInView(el) {
var inView = Utils.isElementInView(el, false);
if(inView) {
//console.log('in view');
} else {
//console.log('not in view');
}
};
//Check to make sure the element you want to be sure is visible is present on the page
var variableOfYourElement = $('#variableOfYourElement');
//if it is on this page run the function that checks to see if it is partially or fully in view
if( variableOfYourElement.length ) {
//run function on page load
IsEInView(variableOfYourElement);
//run function if the element scrolls into view
$(window).scroll(function(){
IsEInView(variableOfYourElement);
});
}
//END USING THE ELEMENT IN VIEW UTIL
})(jQuery);
I have a bit of text that I want to change when the user scrolls a certain distance. However, when I scroll, the value of document.body.scrollTop remains at 0.
var scroll = document.body.scrollTop;
if (scroll < 50) {
document.write("A");
} else {
document.write("B");
}
When checking the log, the value of scroll never budges from 0, thus the text never switches from A to B when scrolling. Thanks for any help in advance.
EDIT: None of the first three answers seem to work for me. I suppose I should provide some context.
Building my design portfolio site. View the early build here. I'd like to be able to change the word "designer" in the banner to other descriptor words as the user scrolls down the page, but can't seem to be able to listen to the current scroll location.
Why are you placing that script inline within the banner? Why not implement your logic within your existing $(window).scroll(function () { as that event seems to be setting the opacity correctly on scroll.
Just add:
if(scrollTop < 50){
$('#banner h1').text("My name is John. I'm a designer");
} else {
$('#banner h1').text("My name is John. I'm a thinker");
}
Live Demo
if(document.attachEvent){
document.attachEvent('onscroll', scrollEvent);
}else if(document.addEventListener){
document.addEventListener('scroll', scrollEvent, false);
}
function scrollEvent(e){
var scroll = document.body.scrollTop;
var text = null;
if (scroll < 50) {
text = document.createTextNode('A');
} else {
text = document.createTextNode('B');
}
document.body.appendChild(text);
}
Though unrelated to your issue, you should stay away from document.write whenever you can. See Why is document.write considered a "bad practice"? for more detail.
this should do it. "document.documentElement.scrollTop" is an IE variant.
should work cross browsers.
window.onscroll = function() {
var scroll = window.scrollY || document.documentElement.scrollTop;
if (scroll < 50) {
document.write("A");
} else {
document.write("B");
}
}
DEMO FIDDLE
var el = $('.test');
//alert(el.scrollTop());
el.on('scroll', function(){
if(el.scrollTop()>50){
alert(el.scrollTop());
}
});
Try this.
I would like to make it so when user scrolls down and reaches a certain div, say #float, set that div to margin-top: 50px and position fixed, and if user scrolls back up undo those changes. It's hard to understand I know ))) If you go to this page and pay your attention to sidebar once scrolling up and down you will see what I mean.
As you scroll down 2nd advertisement scrolls with a page too.
How would I achieve same functionality with jQuery/CSS?
This is a way of doing it in jQuery.
This code is provided for example purposes only; there are almost certainly a handful of regularly-maintained jQuery plugins that will do this thing for you - check GitHub or DailyJS.
$(window).scroll(function() {
var styledDiv = $('#styledDiv'),
targetScroll = $('#float').position().top,
currentScroll = $('html').scrollTop() || $('body').scrollTop();
styledDiv.toggleClass('fixedPos', currentScroll >= targetScroll);
});
Here is a simple JSFiddle of the above in action.
Edit: Have now refactored this code to a more elegant solution.
Edit 2: Following an email I received about a question, I've updated the code above so that it also works in Firefox. As $('body').scrollTop() will not work in Firefox (See comments on the jQuery API page), we need to check both the html and body elements.
This is the relevant jQuery/JavaScript code use on that site.
if (window.XMLHttpRequest) {
var topGagStay = $("top-gag-stay");
var isLoggedIn = $("profile-menu") ? true : false;
var sidebarAdsTop = 1061 - 545;
var signupBtnOffset = 60;
var dockPos = 72;
if (!isLoggedIn && !GAG.isReadOnly()) {
sidebarAdsTop += signupBtnOffset
}
if (formMessageShown) {
sidebarAdsTop += formMessageOffset
}
if (topGagStay) {
if (document.documentElement.scrollTop > sidebarAdsTop || self.pageYOffset > sidebarAdsTop) {
if (topGagStay.style.position != "fixed") {
topGagStay.style.position = "fixed";
topGagStay.style.top = dockPos + "px"
}
} else {
if (document.documentElement.scrollTop < sidebarAdsTop || self.pageYOffset < sidebarAdsTop) {
topGagStay.style.position = "";
topGagStay.style.top = ""
}
}
}
}
Thank FireBug and http://jsbeautifier.org/ for the code (and 9GAG, of course).
I have tried the above answer by beardtwizzle and it worked fine. Also made it work for the case when the page is scrolled upto the bottom of the page.
see the working demo/tutorial here
Just wondering if anyone has an idea as to how I might re-create a nav bar style that I saw a while ago, I just found the site I saw it on, but am not sure how they might have gotten there. Basically want it to scroll with the page then lock to the top...
http://lesscss.org/
Just do a quick "view source" on http://lesscss.org/ and you'll see this:
window.onscroll = function () {
if (!docked && (menu.offsetTop - scrollTop() < 0)) {
menu.style.top = 0;
menu.style.position = 'fixed';
menu.className = 'docked';
docked = true;
} else if (docked && scrollTop() <= init) {
menu.style.position = 'absolute';
menu.style.top = init + 'px';
menu.className = menu.className.replace('docked', '');
docked = false;
}
};
They're binding to the onscroll event for the window, this event is triggered when the window scrolls. The docked flag is set to true when the menu is "locked" to the top of the page, the menu is set to position:fixed at the same time that that flag is set to true. The rest is just some simple "are we about to scroll the menu off the page" and "are we about back where we started" position checking logic.
You have to be careful with onscroll events though, they can fire a lot in rapid succession so your handler needs to be pretty quick and should precompute as much as possible.
In jQuery, it would look pretty much the same:
$(window).scroll(function() {
// Pretty much the same as what's on lesscss.org
});
You see this sort of thing quite often with the "floating almost fixed position vertical toolbar" things such as those on cracked.com.
mu is too short answer is working, I'm just posting this to give you the jquery script!
var docked = false;
var menu = $('#menu');
var init = menu.offset().top;
$(window).scroll(function()
{
if (!docked && (menu.offset().top - $("body").scrollTop() < 0))
{
menu.css({
position : "fixed",
top: 0,
});
docked = true;
}
else if(docked && $("body").scrollTop() <= init)
{
menu.css({
position : "absolute",
top: init + 'px',
});
docked = false;
}
});
Mu's answer got me far. I tried my luck with replicationg lesscss.org's approach but ran into issues on browser resizing and zooming. Took me a while to find out how to react to that properly and how to reset the initial position (init) without jQuery or any other library.
Find a preview on JSFiddle: http://jsfiddle.net/ctietze/zeasg/
So here's the plain JavaScript code in detail, just in case JSFiddle refuses to work.
Reusable scroll-then-snap menu class
Here's a reusable version. I put the scrolling checks into a class because the helper methods involved cluttered my main namespace:
var windowScrollTop = function () {
return window.pageYOffset;
};
var Menu = (function (scrollOffset) {
var Menu = function () {
this.element = document.getElementById('nav');
this.docked = false;
this.initialOffsetTop = 0;
this.resetInitialOffsetTop();
}
Menu.prototype = {
offsetTop: function () {
return this.element.offsetTop;
},
resetInitialOffsetTop: function () {
this.initialOffsetTop = this.offsetTop();
},
dock: function () {
this.element.className = 'docked';
this.docked = true;
},
undock: function () {
this.element.className = this.element.className.replace('docked', '');
this.docked = false;
},
toggleDock: function () {
if (this.docked === false && (this.offsetTop() - scrollOffset() < 0)) {
this.dock();
} else if (this.docked === true && (scrollOffset() <= this.initialOffsetTop)) {
this.undock();
}
}
};
return Menu;
})(windowScrollTop);
var menu = new Menu();
window.onscroll = function () {
menu.toggleDock();
};
Handle zoom/page resize events
var updateMenuTop = function () {
// Shortly dock to reset the initial Y-offset
menu.undock();
menu.resetInitialOffsetTop();
// If appropriate, undock again based on the new value
menu.toggleDock();
};
var zoomListeners = [updateMenuTop];
(function(){
var w = window,
d = document,
e = d.documentElement,
g = d.getElementsByTagName('body')[0];
var lastWidth = 0;
function pollZoomFireEvent() {
var widthNow = w.innerWidth || e.clientWidth || g.clientWidth;
if (lastWidth == widthNow) {
return;
}
lastWidth = widthNow;
// Length changed, user must have zoomed, invoke listeners.
for (i = zoomListeners.length - 1; i >= 0; --i) {
zoomListeners[i]();
}
}
setInterval(pollZoomFireEvent, 100);
})();
Sounds like an application of Jquery ScrollTop and some manipulation of CSS properties of the navbar element. So for example, under certain scroll conditions the navbar element is changed from absolute positioning with calculated co-ordinates to fixed positioning.
http://api.jquery.com/scrollTop/
The effect you describe would usually start with some type of animation, like in TheDeveloper's answer. Default animations typically slide an element around by changing its position over time or fade an element in/out by changing its opacity, etc.
Getting the "bouce back" or "snap to" effect usually involves easing. All major frameworks have some form of easing available. It's all about personal preference; you can't really go wrong with any of them.
jQuery has easing plugins that you could use with the .animate() function, or you can use jQueryUI.
MooTools has easing built in to the FX class of the core library.
Yahoo's YUI also has easing built in.
If you can remember what site it was, you could always visit it again and take a look at their source to see what framework and effect was used.