I am having a number (10) of objects which are clickable, but struggling with moving a selected one to the middle of the scroll view. You can see on the image below that number four is selected but not in the middle.
I tried to use:
myScrollView.scrollToHorizontalOffset(myScrollView.scrollableWidth / 2, true)
But it always bring the whole scroll view into the middle. Can anyone help with making it working? Thank you in advance.
Since You didn't put the Angular tag, I am assuming you are using the Typescript flavor of Nativescript.
In order to do this, you'd have to find a way keep track of your base (starting point) and your target (the one that the user just clicked) so that you can get there x offsets and animate the scroll from one to another.
Here's an example in your code behind:
export function() {
const base = page.getViewById('label1') as Label;
const target = page.getViewById('label2') as Label;
myScrollView.scrollToHorizontalOffset(target.getLocationRelativeTo(base).x, true);
}
Now, the code above will just do a minimum scroll to get to your target element (and you can use a different element other than the example label). But if you want to make it center, you can add an additional offset depending on how wide your scroll container is.
eg.
myScrollView.scrollToHorizontalOffset(target.getLocationRelativeTo(base).x + (myScrollView.width / 2), true);
Note that this is my hypothesis from something similar I've done before (just not needing to be center). So might need to play with the additional offset.
EDIT: (This is how to make it work specifically according to the OPs need)
myScrollView.scrollToHorizontalOffset(target.getLocationRelativeTo(base).x - (myScrollView.scrollableWidth / 2)), true);
Related
My web app includes dynamically built Bootstrap 5 dropdown menus that can be quite large. They need to be resized and repositioned to make the best use of screen space. So I'd like to be able to control or adjust the offset computed by Popper.js via javascript. But I haven't been make this work. The Popper.js documentation is not so clear, and I haven't found any documentation or examples of how to do this within Bootstrap 5. (The data-bs-offset attribute isn't suitable since it cannot invoke a function to provide dynamic offset values.)
Please see the code example on JSFiddle https://jsfiddle.net/Martin_ATS/cqw5mjLv/3/. I am able to access the Dropdown object both via bootstrap.Dropdown.getInstance() and via jQuery $(ddelem).dropdown(), as demonstrated in the hideDropdown() function. But I have not been able to change the offset via javascript despite a number of attempts at calling setOptions() etc.
I'd like to use Bootstrap/Popper's computed y offset, but adjust the x offset so that the menu opens closer to the left margin, and ideally leaves a right margin instead of hitting the right side of the window. The code snippet is a simplified example. In the real app, the dropdown menu contents can range from small (for which Bootstrap/Popper's normal offsets work fine) to very large (including horizontal or vertical scrolling).
Thanks!
Get the instance of the Popper (which is _popper in the dd instance), and then set the offset inside the modifers array...
var dd = bootstrap.Dropdown.getInstance(evt.relatedTarget);
console.log(`shown.bs.dropdown ${evt.relatedTarget.id}`);
var $ddelem = $(evt.relatedTarget);
dd._popper.setOptions( {modifiers: [
{
name: 'offset',
options: {
// calculate and set the offset as needed here..
offset: [30, 10],
},
},
]})
Demo
I need to make four rectangles and an arrow at the center that points toward the rectange that is hovered. See https://jsfiddle.net/Lvmf67rm/1/
$(document).ready(function(){
$('.quarter:nth-child(1)').mouseenter(function(){
$('.pointer').css('transform','rotate(-45deg)');
});
$('.quarter:nth-child(2)').mouseenter(function(){
$('.pointer').css('transform','rotate(45deg)');
});
$('.quarter:nth-child(3)').mouseenter(function(){
$('.pointer').css('transform','rotate(-135deg)');
});
$('.quarter:nth-child(4)').mouseenter(function(){
$('.pointer').css('transform','rotate(135deg)');
});
});
There are two issues with what I've made:
If there would be an element before or somewhere in-between the rectangle divs - the arrow would point in the wrong direction (this is because "nth-child()" selects the children regardless of class)
When hovering between 3rd and the 4th rectangles the arrow doesn't go straight to the next block but goes through the first and second first (quite obvious why this happens).
But how to make it right? I'm quite a noob with javascript so this is the best I could do and I ask for your guidance.
P.S. Sorry if I didn't explain it very good, english is not my native.
P.P.S. Sorry, I forgot to mention I can't edit HTML.
Regarding adding elements before or somewhere in-between the rectangle divs, here are some possible solutions:
Best option: Just don't do it. Add other elements outside the container and use CSS positioning to position.
Use :nth-of-type instead of :nth-child
Instead of :nth-child use classes q1, q2...
Regarding arrow direction: See how using -225deg in q4 changes the behaviour:
$('.quarter:nth-child(4)').mouseenter(function(){
console.log($('.pointer').css('transform')); // get prev value
$('.pointer').css('transform','rotate(-225deg)'); // instead of 135deg
});
You can check the previous value to change the degrees dynamically, selecting the best option of the 2 candidates (where the absolute value of previous degrees - new degrees is minimal, adding or subtracting 360 degrees).
I am building a site with a right aligned nav.
The last menu item drop down runs off the page as it is positioned absolute to the left of its parent.
I am trying to create a solution for my menu below.
jsfiddle -http://jsfiddle.net/ashconnolly/6gjVr/
I cannot hardcode the pos left -xx style, because the width of the last menu item will vary (due to the text inside it), hence my use of js.
I've nearly cracked it, but i just need to apply a variable as a position absolute left style only on hover.
There maybe a better css only solution, but i couldn't find one.
Any help is appreciated! :D
Edit: updated explanation.
You have already calculated the left of your last menu, why didn't you use?
$(document).ready(function () {
var menuitemwidth = document.getElementById("last-menu-item").offsetWidth;
var menuitemdropdownwidth = document.getElementById("last-menu-item-drop-down").offsetWidth;
//alert(menuitemwidth);
var leftval = menuitemdropdownwidth - menuitemwidth;
//alert(leftval);
$("#last-menu-item").mouseenter(function(){
$("#last-menu-item-drop-down").css({'position':'absolute','left':'-'+leftval+'px','display':'block'});
});
$("#last-menu-item").mouseleave(function(){
$("#last-menu-item-drop-down").css({'display':'none'});
});
});
Check Here
As you probably already know, it is bad practice to "print" javascript values using a framework. It will pretty soon become unmaintainable.
But you can separate (element) logic from (element) presentation, i.e. print/format html elements in your templates by setting a data-attribute like this in your html:
<ul id="last-menu-item-drop-down" data-pos="left" data-val="-133px">
Then change your javascript to:
// cache last element, no need to jquery search on every hover
var last_elem = $("#last-menu-item-drop-down");
// set position and alignment
last_elem.css('position','absolute').css(last_elem.data("pos"), last_elem.data("val"));
// set dropdown meny visibility to hidden (do it by css)
last_elem.hide()
// show/hide
// ...
You can also do the offset calculations in javascript and only specify position in your templates
Fiddle at: http://jsfiddle.net/cYsp6/7/
I cant Make with css
$("#last-menu-item").mouseenter(function(){
var a=-(parseInt($("#last-menu-item-drop-down").css('width'))-parseInt($("#last-menu-item").css('width')));
$("#last-menu-item-drop-down").css('position','absolute').css('left',a);
$("#last-menu-item-drop-down").show();
});
$("#last-menu-item").mouseleave(function(){
$("#last-menu-item-drop-down").hide();
});
Updated Fiddle:
Fiddle
I've got a container div with a bunch of scrollable content (for the record I'm using iScroll - if that changes the solution). When I scroll to the top I want to load content above the current scroll position. If I simply prepend the div using jQuery "prepend();" the contents in my scrollable area shift down. Ideally we'd want to keep the current content in the frame and have the scrollable area grow upwards above the content.
Any thoughts?
Thanks!
According to the iScroll website, it has a method called scrollToElement:
scrollToElement(el, runtime): scrolls to any element inside the scrolling area. el must be a CSS3 selector. Eg: scrollToElement("#elementID", '400ms')
If you always prepend a fixed amount of divs (e.g. always a single div), I imagine you could use it to scroll to (e.g.) the second element right after you've prepended the new content:
// ... (prepend new content)
myScroll.scrollToElement('#scroller :nth-child(2)', '0ms');
I haven't tried this, so please let us know if this works for you.
After a quick look through iScroll's source, here's what I've found:
The current x and y are always available through myScroll.x and myScroll.y.
iScroll has an internal function _offset(el), which returns the left and top offset of any given element.
This basically opens up two solutions:
Use _offset(el). While possible, this is inadvisable. The underscore is a convention for marking a function "private", meaning, amongst other things, that it's not part of the official API.
or
Use the newly added element's height:
var x = myScroll.x;
var y = myScroll.y;
// ... (prepend new content)
y += $('#scroller :first-child').outerHeight();
myScroll.scrollTo(x, y, '0ms');
You may need to pass true to .outerHeight(), which makes it include margins.
Once again, I haven't tested this, so please let us know if it works.
I'm placing a div, by using another div id as a reference on the page (to make sure that it appears where I want it to). The code is as follows:-
$('#' + contentDiv).offset({top:($('#' + placementID).offset().top), left: ($('#' + placementID).offset().left)});
The problem is, that though the placementID offset figures are the same each time. Whenever I call this again, it seems to double and put a new left offset that is the the same amount on-top of the previous offset.
E.g. I call a function on a click and say, place this div next to this placement div please. It does it. User then exits and then does another click and the same function is used to place another div next to the same placement div. It does it, but instead of placing it in the same position as last time, seems to reference the position of last time as the 0 point and adds the left amount to that. Meaning the div is placed double distance away now.
Please note; I have consoled out the placement box top and left dimensions and it hasn't changed after each time.
Not sure what's going on.
If someone runs into this, I've managed to solve the problem very simply... by using css instead of offset. I.e.
$('#contentDiv').css({top:placeTop,left:placeLeft});
Im guessing that when you change the offset of $('#' + contentDiv) it affects the offset of your $('#' + placementID) that you subsequently call.
Say you have 3 placement Id's #1,#2 and #3.
With offsets #1: 0,0 #2: 0,100 and #3: 0,200.
Then you set #contentDiv's offest to #1's offset.
Now, #contentDiv's offset is 0,100. This makes your placement offsets #1: 0,100 #2: 0,200 and #3: 0,300 respectively now. Which is probably what is throwing you off.
According to
http://bugs.jqueryui.com/ticket/6868
The element must be visible before calling .position().
after changing my code to show the element before calling offet() it worked like a charm.
Reset your properties before setting the desired offset-value with (e. g.)
$(this).css('top', '').offset({top: desiredTopOffset});