scrollTop always returns 0 in safari - javascript

the code below works perfectly in chrome, but does not work in safari (desktop & mobile)
const messageBody = document.querySelector(`.chatContainer`);
messageBody.scrollTop = messageBody.scrollHeight;
messageBody is a div with overflow-y: scroll
Every time an item is added to the div, it scrolls to the bottom.
Any idea how to make it work in safari?

I have found to problem, it was a problem in my react code.
Every time I added a new element to my array, all of my components were rerendered. This was because I was overwrittin the existing id I gave them.
The code that worked in chrome did not work in safari, because safari executed the code before all of the components were rendered.

ScrollPosition.prototype.restore = function () {
if (this.readyFor === 'up') {
this.node.scrollTop = this.node.scrollHeight -
this.previousScrollHeightMinusTop;
}
}
this.previousScrollHeightMinusTop = this.node.scrollHeight-this.node.scrollTop;
reference-
http://kirbysayshi.com/2013/08/19/maintaining-scroll-position-knockoutjs-list.html

Related

Apple iOS browsers randomly won't render HTML objects loaded dynamically

We have a problem that is only evident on iOS browsers (iOS 12.0) with our SPA application that uses HTML object tags to load widgets (HTML/CSS/JS files) through JavaScript onto the page.
The issue is an intermittent one when the page is loaded some of the widgets don't display/render on the screen, yet are loaded into the DOM and can be viewed/highlighted with full element properties in the Safari Web Inspector. but are “invisible” to their user. The problem will occur about 50% of the time if there are 4 widgets to load on a page, 2 typically won't display and it will be different widgets not displaying each time, with no detectable pattern.
The widget javascript load events run properly and there are no errors in the console. In the Safari Web Inspector, we can see some of the HTML elements from the non-rendering object are loaded at position 0,0 but their style is correct in the DOM (left and top set correctly, display: inline, etc.).
Here is the code that loads the widgets (the fragment is added to the DOM after all widgets are setup):
function loadWidget(myFrag, widgetName) {
var widgetObj = document.createElement("object");
widgetObj.data = "widgets/" + widgets[widgetName].type + ".html"; // location of widget
widgetObj.className = "widget unselectable";
widgetObj.id = widgetName;
widgetObj.name = widgetName;
myFrag.appendChild(widgetObj); // build widgets onto fragment
widgetObj.addEventListener("load", widgetLoaded, false); // Run rest of widget initialisation after widget is in DOM
widgetObj.addEventListener("error", badLoad, true);
}
Here is the code in the load event that configures the widget once loaded (we work around a Chrome bug that also affects Safari where the load event is fired twice for every object loaded):
function widgetLoaded(e) {
var loadObj = e.target;
if (loadObj === null) {
// CHROME BUG: Events fire multiple times and error out early if widget file is missing so not loaded (but this still fires), force timeout
return;
}
var widgetName = loadObj.id;
// CHROME BUG: Workaround here is to just set the style to absolute so that the event will fire a second time and exit, then second time around run the entire widgetLoaded
if ((parent.g.isChrome || parent.g.isSafari) && !widgets[widgetName].loaded) {
widgets[widgetName].loaded = true; // CHROME: WidgetLoaded will get run twice due to bug, exit early first time.
loadObj.setAttribute("style", "position:absolute"); // Force a fake style to get it to fire again (without loading all the other stuff) and run through second time around
return;
}
var defView = loadObj.contentDocument.defaultView; // Pointer to functions/objects inside widget DOM
loadObj.setAttribute("style", "position:absolute;overflow:scroll;left:" + myWidget.locX + "px;top:" + myWidget.locY + "px;z-index:" + zIndex);
loadObj.width = myWidget.scaleX * defView.options.settings.iniWidth; // Set the width and height of the widget <object> in dashboard DOM
loadObj.height = myWidget.scaleY * defView.options.settings.iniHeight;
}
The code performs correctly in Chrome (Mac/Windows), IE and Safari (Mac), however, presents the random invisible loading issue in iOS Safari and also in iOS Chrome.
Any ideas what causes this and what the workaround could be?
We couldn't find the exact source of this issue after a lot of investigation and are fairly sure this is a webkit bug. However there is an acceptable workaround, which is to replace the object tag with an iframe tag, and it looks to be working exactly the same way (replace .data with .src) with a bonus it doesn't exhibit the chrome bug where onload events are fired twice, so Chrome runs our app faster now.

Setting Page Scroll Cross-Browser

I've been working on a project for work where I need to create a Javascript "jump-menu" within a page.
(Q:Wait, a jump-menu? Why don't you just use a elements and namespaces to navigate within your page?
A: Because that would defeat the purpose! So please, don't provide answers like that. I need to do this with Javascript (AND I'M NOT USING JQUERY!!!))
So, here is what I do:
I make a list at the top of the page, and a list at the bottom of the page.
I add an event listener to each list item at the top of the page and I attach a reference to that list items corresponding content item within the page.
When the link at the top is clicked, I grab to offsetTop of the item I want to scroll to, and I set either the document.body.scrollTop or the window.pageYOffset.
I've never actually needed the window.pageYOffset, but somewhere told me it would work and I never removed it from my code. Either way, this appears to work with the document.body.scrollTop in Chrome, Safari, and Opera, yet it doesn't work in Firefox or IE. Why?
Here is the code block where I set the document.body.scrollTop:
if(elem.jump_ref)
{
if(document.body.scrollTop || document.body.scrollTop === 0)
{
document.body.scrollTop = elem.jump_ref.offsetTop - page_top_padding;
}
else if(window.pageYOffset || window.pageYOffset === 0)
{
window.pageYOffset = elem.jump_ref.offsetTop - page_top_padding;
}
}
And Heres The Project In JSFIDDLE
I've stepped through and found that "Yes, I am grabbing the right element." and "Yes, I am setting the document.body.scrollTop, and "No, I am not setting the document.body.scrollTop to zero." and yet it still doesn't work! Please help! My webpage is supposed to go public on Tuesday!
Well, I believe I have found my answer. So far, it appears to work in Chrome, Firefox, IE, Opera, and Safari (these were the only ones I was able to test). I don't know what type of mobile support this feature will have (if any), but my page already has an entirely different functionality for mobile anyway.
Either way, here's the fix. Its the window.scrollTo method!:
this.jump = function(evt)
{
var elem = evt.srcElement || evt.currentTarget;
var page_top_padding = 100;
if(elem.jump_ref)
{
window.scrollTo(0, (elem.post_ref.offsetTop - page_top_padding));
}
}.bind(this);
And like I said, it works great in nearly everything! Everything except JSFiddle. lol. I don't quite get it, but luckily no one is going to be visiting my webpage in JSFiddle.

Safari Scrolling issue with jQuery .remove()

I'm developing a plugin for a website building program, and am building the preview page for it. It's sort of a parallax scrolling plugin and the issue I'm having is that in Safari, when you scroll down to a certain point, it wont allow you to scroll any further. It's fine in firefox and chrome, but I saw the same issue in opera. I've managed to narrow it down to the function that's causing it, but I have no idea why or how to fix it.
When I comment out this function, the page scrolls fine, but it doesn't remove the empty divs like I need it to do:
function removeStuff() {
$('.conP').each(function(){
var divDad = $(this),
divses = $(this).children();
if (divses.hasClass('empty'))
divDad.remove();
});
}
here's the preview page where the issue can be observed:
http://reveriesrefined.com/myftp/dack_stev/
//////////EDIT:
I've simplified the code to this:
$('.conP_%id% > .empty').parent().remove();
however, it's still causing scrolling issues in safari and opera, but not the other browsers.
Any help is VERY VERY appreciated!
Actually, I found the issue already. Somehow even though commenting out the function mentioned above seemed to solve it, it was actually a line of code in another function.
I had this function:
function autoPlay() {
var backDiv = $('#outterLax div:first');
backDiv.hide();
$('.conP').hide();
backDiv.remove();
$('#outterLax').append(backDiv);
backDiv.show();
}
but the line:
$('.conP').hide();
was unnecessary as that was already being accomplished elsewhere in my code.

window.scrollBy only works in Firefox?

In my website I have this javascript code, adding a vertical offset when in the url a specific section of the page is specified (#):
if (!!window.location.hash)
window.scrollBy(0,-60);
However this only works in Firefox... I'm pretty sure window.location.hash works in all browsers, that is, the symbol "sharp" is correctly detected in the url.
However, the -60 offset only works in Firefox... this is the url, could you give me some insight ?
http://patrickdiviacco.co.cc/#432
thanks
It seems to me that the default behavior is applied in a different order. So your code runs first, then the browser aligns the window according to the #hash. Push it to the event queue to run it afterwards.
if (typeof window.location.hash == "string") {
setTimeout(function(){ window.scrollBy(0, -60); }, 1);
}
I tested it in IE 7 and it works, also in FireFox and Chrome...
If this really don't work try using this:
function jumpScroll(amount) {
document.body.scrollLeft += amount;
}
jumpScoll(100);
or value which you want...

assigning dynamic cursor style to element using jquery in Opera

I'm trying to dynamically change the cursor style when the mouse is over an element. The cursor should be either "move" or "default" depending on a boolean returned by a method.
The code is something like this:
$("#elemId").mousemove(function(event) {
if(cursorShouldBeMove()) {
$(this).css({'cursor':'move'});
} else {
$(this).css({'cursor':'default'});
}
}
This code works like a charm in IE8,FF3,Chrome and Safari.
Only Opera fails to handle it correctly.
I'm using Opera 9.6.4
Does anyone have an idea how to solve this?
I prepared a sample for testing;
var cursorStatus = true;
setInterval(function() { cursorStatus = !cursorStatus; }, 500);
function cursorShouldBeMove() {
return cursorStatus;
}
$(function() {
$("#elemId").mousemove(
function(event) {
$(this).css("cursor", cursorShouldBeMove() ? "move" : "default");
}
);
});
If you move your mouse from outside of #elemId to inside of it for a few times you will see that the cursor will change. But if you position your mouse in #elemId and move your mouse, cursor not changes.
The code is very simple. I think it's a bug of Opera.
I tested this code also with;
Firefox 3.5.1 (worked)
Internet Explorer 7 (worked)
Google Chrome 2.0 (worked)
Safari 3.2 (worked)
(Windows versions)
Opera is real funny with cursors. I find that you have to move the mouse over the element twice before it actually works.
Can see here that you need to hover over the Hello World twice to get the cursor to change.
Same issue described here

Categories

Resources