dragable and responsive sidebar - javascript

I'm looking for a template for a responsive, dragable (horizontal resizeable) sidebar.
Optional based on bootstrap (I use bootstrap 4.6, but other version are fine), may make use of jQuery.
This for example fits my needs:
https://bootsnipp.com/snippets/BDWlD
But's it not dragable!
I've try to use some code for dragable divs, but they do not work because of the use of negative margins and some more to toogle sidebar in template above (and the most other respontive sidebar templates) (most all use negative margins to support css-animations).
One example, which didn't work: https://jsfiddle.net/RainStudios/mw786v1w/, but I'd try a lot more
var element = document.getElementById('element');
var resizer = document.createElement('div');
resizer.className = 'resizer';
resizer.style.width = '10px';
resizer.style.height = '10px';
resizer.style.background = 'red';
resizer.style.position = 'absolute';
resizer.style.right = 0;
resizer.style.bottom = 0;
resizer.style.cursor = 'se-resize';
element.appendChild(resizer);
resizer.addEventListener('mousedown', initResize, false);
function initResize(e) {
window.addEventListener('mousemove', Resize, false);
window.addEventListener('mouseup', stopResize, false);
}
function Resize(e) {
element.style.width = (e.clientX - element.offsetLeft) + 'px';
element.style.height = (e.clientY - element.offsetTop) + 'px';
}
function stopResize(e) {
window.removeEventListener('mousemove', Resize, false);
window.removeEventListener('mouseup', stopResize, false);
}
So I look for a joined code from both or a other template for a dragable responsive sidebar.
(If possible without big libaraies, because I still have to further develop the code.)
I've google a lot but did not find a well solutions.
A more detailed description of the problem:
The width of the sidebar (e.g. 250px) and a negative margin (-250px) with the same value is set in one class (in the example of the link from above #sidebar-wrapper). In a second class, the padding is set to 250px. If the second class is active, the sidebar is shown, otherwise it is hidden.
To modify that dynamicly is tricky.
To adjust this dynamically, I would have to adjust all three classes dynamically, which is possible but very cumbersome and ugly.
Alternatively I would have to write the sidebar handling completely new in JS without classes (directly assigned values) incl. the responsive variants (from media queries). Also not nice. May there is a way to dynamicly compute the values in css??
Any idea?
Some links are suffient, I do the rest.
Or an idea to handle that CSS-stuff (must not be complete code)
(At the end should end up in a help page with a table of contents in the sidebar, a search with instant search via ajax and a load of the help content also via ajax in the main div. But I'm not worried about this part, I've built something like that before - but if I find something ready-made, I won't say no ;-) )

Finaly I managed by myself:
Changes to above:
var wrapperElement = document.getElementById('wrapper');
...
function Resize(e) {
element.style.width = (e.clientX - element.offsetLeft) + 'px';
wrapperElement.style.paddingLeft = (e.clientX - element.offsetLeft) + 'px'; /new
}
Changes to script from Sidebar-Example:
$("#menu-toggle").click(function(e) {
e.preventDefault();
$("#wrapper").toggleClass("toggled");
element.style.width = ""; //new
wrapperElement.style.paddingLeft = ""; // new
});
Full code: https://codepen.io/MichaelBootstrap/pen/BapJzYz
This works fine.
Disadvantages:
After fading in and out, the sidebar has the old width again.
There are still problems when the sidebar becomes too small
Draging is not so smooth
If some one have a besser solution, then I would be very pleased.

Related

Jquery scroll problems

I have some uncommon wishes about scrolling in the page I'm making. I already tried a lot of things, but those aren't working like they should. All I want is that when people use their scroll wheel (wherever their cursor stands) the search-results are scrolling.
I've uploaded my result so far at http://www.veylau.be/testzone/scrollfix/searchtwee.html
Just click the search button to see the dummy results.
Problems:
1) With the script I'm using now I'm having a sort of a parallax effect. I just want the results to scroll, not the rest of the page.
2) When the rest of the page is done scrolling, it isn't possible to scroll through anymore.
3) is it possible to catch the scroll-event when the cursor is over the #googleMap or the #mapContainer div? I tried like this, but only the second one is executing.
$("#mapContainer").scroll(function(event){...});
$(window).scroll(function(event){...});
Thank you very much for your help guys!
You can catch the $(window).scroll(function(event){...}); and inside this function check if the mouse is hover the mapContainer with the check if($("#mapContainer:hover").length>0)
You can do something like tracking the mouse movement , and when scroll occurs setting the position to the last known position
I have tried a sample, Here is my code , Not perfectly refined. still i think this may help
var MouseposX;
var MouseposY;
$(window).bind("mousemove", function (event) {
MouseposX = event.pageX;
MouseposY = event.pageY;
});
$(window).scroll(function (event) {
placeDiv(MouseposX, MouseposY);
});
function placeDiv(x_pos, y_pos) {
var d = document.getElementById('searchResults');
d.style.position = "absolute";
d.style.left = x_pos+'px';
d.style.top = y_pos+'px';
}
Check the fiddle
http://jsfiddle.net/46WLt/3/

Improving the performance of a pure Javascript smooth scroll with multiple list elements

I'm playing with replicating the recent, 30-year Apple Mac retrospective in pure CSS and Javascript for a small timeline of projects. I have the basic layout of the first full screen hero and the scalloped, expand-on-hover working appropriately. But the smooth scrolling of the timeline in the second half of the screen isn't working, even very slow scrolling is obviously jittery in Google Chrome 32.0.1700.102 on Mac OS X. You can download a folder with a single index.html and the necessary CSS and JS here.
Specifically, my two questions are:
What is a pure CSS/JavaScript solution to fixing this smooth scrolling? I'd appreciate something which debugged this example rather than pointed me to another, working one.
And related, what could/should I do to approach debugging this to isolate the problem? I naïvely tried collecting a JavaScript CPU Profile, but nothing jumped out as needing attention.
Basic Structure
The timeline is structured as a nav containing an ordered list, each li containing project, i.e.
<nav id='timeline'>
<ol>
<li class='project' id='zero'>
<div class='description'>
<h2> Project 0 </h2>
<span> The project that changed everything </span>
<div class='icon'></div>
</div> <!-- div.description -->
</li> <!-- li.project#zero -->
</ol>
</nav> <!-- nav#timeline -->
I have a simple event loop to detect global mouse position and handle scroll detection,
// 20ms event loop to update a global mouseX, mouseY position and handle scroll detection
var mouseX = null;
var mouseY = null;
var scrollTimeline = null;
var updateInterval = 10;
var scrolling = false;
window.onmousemove = function(event) {
mouseX = event.clientX;
mouseY = event.clientY;
if (!scrollTimeline) {
scrollTimeline = window.setInterval(scroll, updateInterval);
}
};
Which in turn calls a simple scroll handler every 10ms,
function scroll(event) {
var buffer = window.innerWidth/4;
var distanceToCenter = Math.abs(window.innerWidth/2-mouseX);
var speed = distanceToCenter/(window.innerWidth/2);
if (mouseX < buffer) {
scrolling = true;
scrollLeft(speed);
}
else if ((window.innerWidth - mouseX) < buffer) {
scrolling = true;
scrollRight(speed);
}
else {
scrolling = false;
window.clearInterval(scrollTimeline);
scrollTimeline = null;
}
}
All the actual scrolling is accomplished by adjusting the left attribute of the containing nav via two functions, scrollRight and scrollLeft, called with a speed argument depending on the mouse position.
function scrollRight(speed) {
var leftPixels = parseInt(getStyleProp(timeline, 'left'), 10);
var toShift = Math.pow(speed,3)*updateInterval;
var newLeft = leftPixels - toShift;
if (newLeft >= -1400 && newLeft <= 0) {
timeline.style.left = newLeft + 'px';
}
}
(getStyleProp is a simple utility function for getting the computed left attribute if it hasn't been explicitly set which I copied from this answer):
// Utility function to grab style properties when unset
function getStyleProp(elem, prop){
if(window.getComputedStyle)
return window.getComputedStyle(elem, null).getPropertyValue(prop);
else if(elem.currentStyle) return elem.currentStyle[prop]; //IE
}
What I've tried
So, with all of those basics out of the way, I've tried:
Removing some of the CSS transitions that create the scalloped effect
Using one image instead of six
Adjusting left in a loop, one pixel at a time, instead of in small jumps
Removing any of the contained text and their transitions.
And removing any contained li's in the nav--this solved the problem, but I'm not sure why/how that would be causing the observed jitter
Thanks!
Turns out the original jitter was because of the overhead of using the saturate transform in CSS. I found a far better solution using requestAnimationFrame.

Universal javascript resize function

Basically this function is meant to store the height value of the element that calls it and then if that height matches the element it will expand its height by 200px and if it does not match the stored value it restores that value (in essence shrinking the element container). How do I get it to read from the external style sheet to get the var heightVal = parseInt(boxStyle.height);?
function expand(e){
var box = document.getElementById(e);
var boxStyle = box.style;
var heightVal = parseInt(boxStyle.height);
if(boxStyle.height == heightVal){
boxStyle.height = heightVal + 200 +'px';
}
else{
boxStyle.height = heightVal;
}
}
This is my revised answer... This code allows for the function to be used universally to re-size any elements height regardless of whether you want it to start minimized or maximized and/or whether you want it to expand or collapse. I developed this function as an improvement on the answer I had previously written. This is actually a result of another function I have been working on to change the CSS class to allow for animation without using either javascript nor jquery. I now have both functions working and universal!
The parameters are pretty straight forward... box represents the element you want to resize, hNew represents the height you want to resize it to (can be larger or smaller than the current height of the element and the function still works).
function resize_height(box, hNew){
if(box.style.height != hNew || box.style.height == box.old_height){
box.old_height = box.style.height
box.style.height = hNew;
}
else{
box.style.height = box.old_height;
}
}

Adjusting window scroll position in JavaScript to counteract element's resizing above

I'm trying to counteract an adjustment to the height of an element which is above the scroll offset by calculating the difference in height and then updating the current scroll position to account for it.
The problem is that there's no way that I can prevent a very quick flickering artefact. Whether I adjust the element's height and then the scroll position, or vice versa, I can't seem to prevent a quick visual jump.
Does anyone know how this could be overcome? I want these to operations to happen at the same time with no rendering in-between but I'm not sure if it's possible.
// Setup
...
var myElement = ...
var oldHeight = ...
var scrollOffset = window.scrollY;
var newHeight = 100;
var diff = newHeight - oldHeight;
// Determine if we need to counteract new size
var adjustScroll = (absoluteOffset(myElement) < scrollOffset);
// Adjust size
myElement.style.height = newHeight+'px';
// Adjust scroll to counteract the new height
if (adjustScroll) window.scrollTo(0, scrollOffset+diff);
I'm working with WebKit, specifically on iOS.
for webkit you can use CSS transitions/animations to smooth this but it's still sound like you are going the wrong way to begin with. I am sure that whatever is it you are trying to do can be solved purely with CSS (maybe with some very minimal Javaqscript). Post an example of you HTML + CSS + JS.
You could use scrollIntoView with timers to simulate multiple threads.
Or you could do it inside a document fragment beforehand.
Sorry to be reviving an old post here, but i came across this looking for a solution to a similar problem to do with browser resizing.
Stackoverflow user James Kyle created this little jsfiddle using jQuery that attempts to maintain scroll position as best as possible when a page is resized
var html = $('html'),
H = html.outerHeight(true),
S = $(window).scrollTop(),
P = S/H;
$(window).scroll(function() {
S = $(window).scrollTop();
P = S/H;
});
$(window).resize(function() {
H = html.outerHeight(true);
$(window).scrollTop(P*H);
});
http://jsfiddle.net/JamesKyle/RmNap/
you could try using this same code and trigger a 'resize' event on the html when the image has loaded by using a jQuery library like imagesLoaded

Scroll to an element using jQuery

I need the page to scroll just so that an element is visible.
Options I've tried:
jQuery's scrollTo: the problem is that the page scrolls so that the element is on top (or at least it tries to do that, much like how this works: <a name="xyz"> / <a href="#xyz">). I want the minimum amount of scrolling, so that the entire element is visible (and, if the element is too tall, work like the anchor there).
scrollIntoView: awful. I want it to scroll smoothly (like $.scrollTo($('#id1'), 'fast');). Also, it doesn't seem to do what I want either.
What you need to do is identify the position within the page of the element, top and bottom (and left/right if you are considering horizontal scrolling). Then identify the current position of the viewport on the window, the scrollTop of the window should then be animated to whatever value will bring the other just in to view.
I just knocked up the following in this editor, so it's untested, but will give you the general idea for a plugin.
Updated - to show version that worked for the OP, as well as a smoother version
jQuery.fn.scrollMinimal = function(smooth) {
var cTop = this.offset().top;
var cHeight = this.outerHeight(true);
var windowTop = $(window).scrollTop();
var visibleHeight = $(window).height();
if (cTop < windowTop) {
if (smooth) {
$('body').animate({'scrollTop': cTop}, 'slow', 'swing');
} else {
$(window).scrollTop(cTop);
}
} else if (cTop + cHeight > windowTop + visibleHeight) {
if (smooth) {
$('body').animate({'scrollTop': cTop - visibleHeight + cHeight}, 'slow', 'swing');
} else {
$(window).scrollTop(cTop - visibleHeight + cHeight);
}
}
};
$('#item').scrollMinimal();
There's a plugin for just what you need
I don't want to copy the code from blog post, because it can get outdated (due to upgrades). But anyway. You can find all details and code about the .scrollintoview() jQuery plugin on blog post.
Usage
Contrary to scrollTo() plugin where you have to provide scrollable element this plugin only requires you to provide the element you'd like to scroll into view. Plugin finds nearest scrollable ancestor (with scrollbars) and scrolls to the element with animation, so user doesn't loose track of their position in the page.
The good thing is also that it won't scroll anything if element is already within visible boundaries of scrollable ancestor.
$("ElementSelector").scrollintoview();
That's it most of the time. But if you need to set some additional settings, there are some you can change and provide custom behaviour:
scrollintoview: function (options) {
/// <summary>Scrolls the first element in the set into view by scrolling its closest scrollable parent.</summary>
/// <param name="options" type="Object">Additional options that can configure scrolling:
/// duration (default: "fast") - jQuery animation speed (can be a duration string or number of milliseconds)
/// direction (default: "both") - select possible scrollings ("vertical" or "y", "horizontal" or "x", "both")
/// complete (default: none) - a function to call when scrolling completes (called in context of the DOM element being scrolled)
/// </param>
/// <return type="jQuery">Returns the same jQuery set that this function was run on.</return>
FYI, jQuery scrolling element into viewport plugins alternative:
intoViewPort plugin
scrollIntoView plugin

Categories

Resources