I have a webpage where there is scroll happening to next section within the webpage on click of a button. Can someone please suggest how to capture that scroll? Code is with in the anchor tag and href is pointing to # to scroll to next section in page. I am not sure how to validate if scroll actually worked?
You could check that the anchor is scrolled at the top of the window by checking the positon relative to the viewport with getBoundingClientRect() :
browser.get('https://www.w3.org/TR/webdriver');
$("[href='#capabilities']").click();
// assert that the position of the anchor relative to the top border of the window is less than 16 pixels.
var anchor = $('#h-capabilities');
var isCloseToTop = browser.executeScript(e => !(e.getBoundingClientRect().top >> 4), anchor);
expect(isCloseToTop).toBeTruthy();
Note that if the anchor is at the very bottom of the document, the anchor will not be at the top of the window, but somewhere within.
So you should also consider this case with a more generic solution:
browser.get('https://www.w3.org/TR/webdriver');
$("[href='#informative-references']").click();
expect(isScrolledTop($('#h-informative-references'))).toBeTruthy();
function isScrolledTop(element) {
return browser.executeScript(function(elem) {
var doc = elem.ownerDocument,
viewHeight = doc.defaultView.innerHeight,
docBottom = doc.documentElement.getBoundingClientRect().bottom,
box = elem.getBoundingClientRect();
return box.top > -1 && (box.top < 25 || (docBottom - viewHeight) < 25);
}, element);
}
You can assert/check few things in this case:
the current URL to point to the correct # section:
expect(browser.getCurrentUrl()).toEqual("https://url.com/mypage#myparagraph");
check the scrollTop position of the body element (assuming it is what is scrolled - or the other scrollable container):
var body = $("body");
expect(body.getCssValue("scrollTop")).toEqual("someValue"); // or apply the "greater than" check
check the current active element (assuming there is an element focused once the "anchor" paragraph is becoming active)
solution based on your suggestion to use window.pageYOffset - compare the value before and after the click:
browser.executeScript('return window.pageYOffset;').then(function (offsetBefore) {
offsetBefore = parseInt(offsetBefore);
button.click();
browser.executeScript('return window.pageYOffset;').then(function (offsetAfter) {
offsetAfter = parseInt(offsetAfter);
expect(offsetAfter).toBeGreaterThan(offsetBefore);
});
});
Related
I'm using the similar code to retain cursor position for ckeditor.
var range = null;
editor.on( 'blur', function() {
range = editor.getSelection().getRanges()[ 0 ];
});
someElement.on('click',function() {
var editor = CKEDITOR.instances.editor1;
if(editor){
editor.focus();
range.select();
}
});
I'm able to retain cursor position but the scrollbar scrolls to the top.
How can i keep/retain the scrollbar at same position as of cursor's?
range.select().scrollIntoView() helped me out!!
I have several editors on a long page, and scrollIntoView() never did exaclty what I wanted: either it scrolled laso the container page, or it doesn't, or it puts the elemnt to show just one line after the viewport... so, since my need was simply to return to the previous position after a small change in the HTML with setData(), I could do the following:
let window = editor.document.getWindow().$ ;
let scrollX = window.scrollX ;
let scrollY = window.scrollY ;
[...]
editor.setData(contents, {
callback: function() {
editor.document.getWindow().$.scrollTo(scrollX, scrollY) ;
}
}) ;
I don't think that CKEditor (at least, not the 4.x series) has the proper APIs for this, so I had to go to the underlying DOM.
I have 2 divs on my webpage. first div is "#pattern" (red one), and second on is "#projets".(blue one)
when use scrolls for the first time, the window scrolls automaticaly to the the second div "#projets". I'm using jquery scroll-To plugin.
it works nice, even if when the users scroll with a large amount of scroll there could be on offset from the "#projets" div... If someone has an idea to correct this would be nice, but that's not my main trouble...
Now i'm trying to scroll back to the top of the page ("#pattern" div) as soon as "#pattern" div reappears when scrolling, the red one. so basically it should be as soon as the offset from the top of my screen of my div "#projets" is supperior to 1.
I've tried so many solutions without results, using flags, multiple conditions... it can be the same kind of thing as on this page, but user should be abble to scroll freely inside the page, not scrolling from hash to hash :
http://www.thepetedesign.com/demos/onepage_scroll_demo.html
here is my html :
<div id="pattern"></div>
<div id="projets"></div>
my css :
#pattern {
height:300px;
width: 100%;
background-color:red
}
#projets {
height:800px;
width: 100%;
background-color:blue
}
and my jquery :
var flag=0 ;
$(window).on('scroll',function(){
var top_projets_position = $("#projets").offset().top - $(window).scrollTop();
if((flag==0) && $(window).scrollTop()>1){
$(window).scrollTo('#projets', 500);
flag=1;
}
if($(window).scrollTop()==0){
flag=0;
}
});
here is jsfiddle :
http://jsfiddle.net/jdf9q0sv/
hope someone can help me with this, I can't figure out what I'm doing wrong, maybe a wrong method ! thanks
It looks like you need to track 3 things:
The scroll direction occurs.
The area you are currently viewing.
If scroll animation is currently happening (we need to wait until it's done, or problems will occur).
http://jsfiddle.net/vx69t5Lt/
var prev_scroll = 0; // <-- to determine direction of scrolling
var current_view ="#pattern"; // <-- to determine what element we are viewing
var allowed = true; // <-- to prevent scrolling confusion during animation
var top_projets_position = $("#projets").offset().top + 1;
$(window).on('scroll',function(){
var current_scroll = $(window).scrollTop();
if(current_scroll < top_projets_position && current_view=="#projets" && current_scroll < prev_scroll){
scrollToTarget("#pattern");
}
if($(window).height() + current_scroll > top_projets_position && current_view=="#pattern" && current_scroll > prev_scroll){
scrollToTarget("#projets");
}
prev_scroll = current_scroll;
});
function scrollToTarget(selector){
if(allowed){
allowed = false;
$(window).scrollTo(selector, {
'duration':500,
'onAfter': function(){ allowed = true; current_view = selector;}
});
}
}
This is just a quick solution based on your original code. A better solution would be to do something more Object Oriented (OOP) and track values in an object. Perhaps take an array of elements on object creation, grab all the boundaries and use the boundaries in your scroll handler to determine when to scroll to the next div.
My table consists of two column: name of object and object. Name is just one word. Object can occupy several screens. I want to hold name on top of visible part of its cell. In this case when user scrolls page down he can see name of the object until the object is hidden. How can I do this? Are there plugins to do so?
It's only a couple lines of jQuery. http://jsfiddle.net/VuRvs/
Attach a handler to the window scroll event, find your "sticky" heading, position them based on the current scroll position make sure they stay inside of their parent element (the TD).
$(window).on("scroll", function() {
var y = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop;
$(".sticky").each(function() {
var elm = $(this);
var td = elm.parent("td");
var tdTop = td.offset().top;
var tdBot = tdTop + td.height() - elm.outerHeight();
if(y <= tdBot && y >= tdTop) {
// set a placeholder
if(td.children().length == 1)
td.append(elm.clone().removeClass("sticky").css("visibility", "hidden"));
elm.css("position", "absolute");
elm.css("top", y + "px");
}
});
});
What you are describing, is a persistant header, or a freeze pane like Excel.
Check this link, it's nicelly explained.
I want to slide a DIV with contents out -- within a defined page area; within a long vertical 1 page website.
I have it setup with 6 DIV blocks;
Block 5 I have a CSS3 / jQuery animation wrapped in a DIV -- that I would like to SLIDE out into the page (from either left or right) with jQuery.
I'm thinking determining the point of slide from a defined anchor point; put within the the mark-up of the area that I'd like the DIV to slide into.
How could I write this;
..something like -- if anchor tag; SlideIn?
Something like;
slideLeftHide: function() {
return this.each(function() {
$(this).hide('slide', {direction: 'left'}, 1000);
});
http://jsfiddle.net/SZ8uH/2/
Try something like this:
var animInTriggeredAt = $("a#slidein").offset().top; //show when the anchor comes on stage
var animOutTriggeredAt = animInTriggeredAt + $(window).height(); //hide when it leaves the stage
var animActive = false;
// handle scroll event
$(window).scroll(checkScrollCues);
function checkScrollCues(){
var scrollY = $(window).scrollTop();
if (scrollY > animInTriggeredAt && scrollY < animOutTriggeredAt && !animActive){
animActive = true;
$("#myAnimatedDiv").show(); //put whatever animation code you want in here
} else if ((scrollY < animInTriggeredAt || scrollY > animOutTriggeredAt) && animActive){
animActive = false;
$("#myAnimatedDiv").hide(); //put whatever animation code you want in here
}
}
I am having this problem where i have a set of 6 UL's having a common class x.Each of them consist of a specific section of the page.Now i have 6 menus that are related to each of the section.What i have to do is highlight the menu when its related section is in users view.
For this i thought that may be jQuery position(); or offset(); could have helped but they give the top and left of the element.I also tried using jQuery viewport plugin but apparently view port is big it can show more than one UL at a time hence i cant apply element specific logic here.I am not familliar to this but does anything changes of an element on scrolling?If yes then how to access it?
Please share your views.
Regards
Himanshu Sharma.
Is very easy to do it using jQuery and a dummy fixed HTML block that helps you find the current position of the viewport.
$(window).on("scroll load",function(){
var once = true;
$(".title").each(function(ele, index){
if($(this).offset().top > $("#viewport_helper").offset().top && once){
var index = $(this).index(".title");
$(".current").removeClass('current')
$("#menu li").eq(index).addClass('current')
once = false;
}
});
})
Check out a working example: http://jsfiddle.net/6c8Az/1/
You could also do something similar with the jQuery plugin, together with the :first selector:
$(window).on("scroll load",function(){
$(".title:in-viewport:first").each(function(){
var index = $(this).index(".title");
$(".current").removeClass('current')
$("#menu li").eq(index).addClass('current')
});
})
You can get the viewport's width and height via $(document).width() and $(document).height()
You can get how many pixels user scrolls via $(document).scrollTop() and $(document).scrollLeft
Combining 1 and 2, you can calculate where the viewport rectangle is
You can get the rectangle of an element using $(element).offset(), $(element).width() and $(element).height()
So the only thing left to you is to determine whether the viewport's rectangle contains (or interacts) the elements's rectangle
So the whole code may look like:
/**
* Check wether outer contains inner
* You can change this logic to matches what you need
*/
function rectContains(outer, inner) {
return outer.top <= inner.top &&
outer.bottom >= inner.bottom &&
outer.left <= inner.left &&
outer.right >= inner.right;
}
/**
* Use this function to find the menu related to <ul> element
*/
function findRelatedMenu(element) {
return $('#menu-' + element.attr('id'));
}
function whenScroll() {
var doc = $(document);
var elem = $(element);
var viewportRect = {
top: doc.scrollTop(),
left: doc.scrollLeft(),
width: doc.width(),
height: doc.height()
};
viewportRect.bottom = viewportRect.top + viewportRect.height;
viewportRect.right = viewportRect.left + viewportRect.width;
var elements = $('ul.your-class');
for (var i = 0; i < elements.length; i++) {
var elem = $(elements[i]);
var elementRect = {
top: elem.offset().top,
left: elem.offset().left,
width: elem.width(),
height: elem.height()
};
elementRect.bottom = elementRect.top + elementRect.height;
elementRect.right = elementRect.left + elementRect.width;
if (rectContains(viewportRect, elementRect)) {
findRelatedMenu(elem).addClass('highlight');
}
}
}
$(window).on('scroll', whenScroll);
Let's see if i understood well. You have a page long enough to scroll, and there is an element that when it appears in the viewport, you wanna do something with it. So the only event that's is triggered for sure on the time the element gets in the viewport is the 'scroll'. So if the element is on the page and the scroll is on the viewport, what you need to do is bind an action to the scroll event to check if the element is in the view each time the event is trigger. Pretty much like this:
$(window).scroll(function() {
check_element_position();
});
Now, in order for you to know if the element is in the viewport, you need 3 things. The offset top of that element, the size of the viewport and the scroll top of the window. Should pretty much look like this:
function check_element_position() {
var win = $(window);
var window_height = win.height();
var element = $(your_element);
var elem_offset_top = element.offset().top;
var elem_height = element.height();
var win_scroll = win.scrollTop();
var pseudo_offset = (elem_offset_top - win_scroll);
if (pseudo_offset < window_height && pseudo_offset >= 0) {
// element in view
}
else {
// elem not in view
}
}
Here, (elem_offset_top - win_scroll) represent the element position if there was no scroll. Like this, you just have to check if the element offset top is higher then the window viewport to see if it's in view or not.
Finally, you could be more precise on you calculations by adding the element height (variable already in there) because the code i just did will fire the event even if the element is visible by only 1 pixels.
Note: I just did that in five minutes so you might have to fix some of this, but this gives you a pretty darn good idea of what's going on ;)
Feel free to comment and ask questions