I have 2 vertical div: left and central panel.
I use the left div like a sidebar menu and I would like to implement a drag&drop to move the left sidebar to a new right sidebar (to move the menu from left to right side).
When the user start to drag, I would like to show where is possible to drop the panel (so I need to show a right empty sidebar) and when the user drop the panel from left to the right destination I need to hide the left panel. Same situation when the user start to drag from right to left panel.
I have see some possible ways to implement this using jQuery UI or directly DnD integrated of HTML5 (example).
Do you know which one is the best solution (also as speed of implementation of it)?
I think that to get exactly what I want (also with the show/hide of the three panels), I need to write some code.. Do you know any tutorial / example very close to what I would like to do?
Here is an example with animation: https://jsfiddle.net/Twisty/jf6urpep/
As you did not provide an example of the HTML, script, or concept, I created a basic example.
HTML
<!-- Sidebar Left -->
<div class="sidebar-l" style="height:100%; position: relative;">
<div class="w3-sidebar w3-light-grey w3-bar-block" style="width:25%; position: absolute;">
<h3 class="w3-bar-item">Menu</h3>
Link 1
Link 2
Link 3
</div>
</div>
<!-- Sidebar Right -->
<div class="sidebar-r" style="margin-left: 75%; width:0; height:100%; position: relative;">
</div>
<!-- Page Content -->
<div class="content" style="margin-left:25%">
<div class="w3-container w3-teal">
<h1>My Page</h1>
</div>
<img src="https://www.w3schools.com/w3css/img_car.jpg" alt="Car" style="width:100%">
<div class="w3-container">
<h2>Sidebar Navigation Example</h2>
<p>The sidebar with is set with "style="width:25%".</p>
<p>The left margin of the page content is set to the same value.</p>
</div>
</div>
JavaScript
$(function() {
$(".w3-sidebar").draggable({
handle: "h3.w3-bar-item",
drag: function(e, ui) {
if (ui.position.left > $(window).width() / 2) {
$(".sidebar-l").css({
"width": 0
});
$(".sidebar-r").css({
"width": "25%"
});
$(".content").css({
"margin-left": 0,
"margin-right": "25%"
});
} else {
$(".sidebar-l").css({
"width": "25%"
});
$(".sidebar-r").css({
"width": 0
});
$(".content").css({
"margin-left": "25%",
"margin-right": 0
});
}
},
stop: function(e, ui) {
var side, pos, center;
pos = ui.position;
center = $(window).width() / 2;
console.log(pos, center);
if (pos.left > center) {
side = "r";
} else {
side = "l";
}
console.log("target", side);
var sidebar = $(".w3-sidebar").detach();
console.log("detach", sidebar);
sidebar.appendTo($(".sidebar-" + side)).position({
my: "left top",
at: "left top",
of: $(".sidebar-" + side),
using: function(css, calc) {
$(this).animate(css, "fast");
}
})
console.log("append to", $(".sidebar-" + side));
}
});
$("h3.w3-bar-item").disableSelection();
});
Depending on where the item is dragged, we swap which side has the margin space. This helps indicate to the user where the sidebar will land. The user can basically drop the sidebar on either side and it will snap to position.
Hope that helps.
Psuedo code based on your example link:
Put both sidebar elements in your HTML as sidebar sidebar--left and sidebar sidebar--right
Fill one with the actual sidebar content.
Add the class sidebar--hidden to the other. Style that to hide the element.
On dragstart, remove the class sidebar--hidden and add a class to both sidebars like sidebar--droppable. Style them appropriately
On drop, remove sidebar--droppable from both and add sidebar--hidden to the other
Don't forget to accommodate for drops that do not fall on a sidebar drop target. You can use dragend for that case and just put it back to where it started (or maybe test the position and if >50%, make it a right sidebar...)
Though, if this is really just a choice between left and right sidebars, probably easier to have a button/checkbox type control on the sidebar and simply move it in the DOM when toggled (and on page load via some persistence mechanism). Or have both sidebars in the DOM and move the innerHTML. If you don't use padding or borders on the sidebars elements themselves they should collapse to hidden when they have no content.
Related
Currently, I have three tabs in my nav bar, BOARD, SKILLS, and ABOUT, all in one container with a boarder-bottom for the container. When I click on one of the divs, the appropriate div name is selected, to indicate which tab I am on. That is what is currently working and can be seen in my codePen.io:
What I have so far - click here
.
What I am trying to do is when I go from BOARD to SKILLS or BOARD to ABOUT, is to have a bar slide from one one tab to the next, rather than being static-like (which is what I have currently) e.g. a smooth scroller on click from one tab to the next. How can I go about doing this? I have no idea where to begin.
You can use this function to slide an element:
function scaleSlider(to) {
var $slider = $('.slider', '.tabs'),
$elSpan = to.find('span'),
width = $elSpan.width(),
left = $elSpan.position().left;
$slider.animate({
width: width,
left: left
});
}
In your HTML you need to add the .slider element:
<div class="col-md-8 tabs">
<div class="slider"></div>
<!-- your html here -->
</div>
CSS:
.tabs .slider {
position: absolute;
height:100%;
border-bottom: 4px solid grey;
}
So when you click a menu element you call scaleSlider:
$('.skills').on("click", function() {
//Your code here
scaleSlider($(this));
});
Please check out this demo: http://codepen.io/anon/pen/EyoBmg
I have a web page with a top horizontal navigation bar – it is Twitter's Bootstrap Fixed Top Navbar to be more precise – with a bottom-fixed position (actually it's not really fixed by CSS; see JavaScript below) so the navigation bar will first be visible at the bottom of the page and later displayed at the top of the page when scrolling (position: fixed; top: 0).
I have the navigation links set up with anchor tags to take the viewer to various places in the body of the page. Unfortunately, sometimes it takes the user a bit too far down (especially if the user is at the top of the page and the navigation bar has not yet became fixed).
Take a look at my HTML structure:
<div id="landing"></div>
<nav class="navbar navbar-default">
<div class="container-fluid">
<div class="collapse navbar-collapse">
<ul class="nav navbar-nav">
<li>Home</li>
<li>Section 1</li>
<li>Section 2</li>
<li>Section 3</li>
</ul>
</div>
</div>
</nav>
<div id="section1"></div>
<div id="section2"></div>
<div id="section3"></div>
I'm using the following JavaScript to ensure that the navbar sticks to the top of the page after scrolling down:
function init() {
nh = 50; // navbar height
sh = $(window).height();
ih = sh-nh;
$("#landing").css('height', ih+'px');
}
function navbarState() {
if ($(window).scrollTop() > ih) {
$('.navbar').addClass('navbar-fixed-top');
} else {
$('.navbar').removeClass('navbar-fixed-top');
}
}
init();
navbarState();
$(window).on('load scroll resize orientationchange', function () {
init();
navbarState();
});
One can observe that repeatedly pressing the first anchor link causes a bouncing effect. How can I prevent that?
My goal is to have the navigation scroll to the proper anchors, no matter whether the user is at the landing page or not.
Why not using navbar-fixed-bottom as well?
See here: https://jsfiddle.net/y7soL4ej/
I added the mentioned class as default to nav. And modified minor things:
CSS
html, body, div#landing {
height: 100%
}
section, [id*=section] {
padding-top: 52px;
}
JS
function init() {
nh = 50 + 2; // navbar height + 2x border width (top + bottom)
sh = $(window).height();
ih = sh-nh;
//$("#landing").css('height', ih+'px');
}
function navbarState() {
if ($(window).scrollTop() > ih) {
$('.navbar').removeClass('navbar-fixed-bottom').addClass('navbar-fixed-top');
} else {
$('.navbar').removeClass('navbar-fixed-top').addClass('navbar-fixed-bottom');
}
}
init();
navbarState();
$(window).on('load scroll resize orientationchange', function () {
init();
navbarState();
});
The jumpy behaviour: When the navbar is at the bottom in your example it is part of the dom flow - it seperates the landing div and the section1 div by its height. As soon as it is clicked the browser jumps to the location, the navbar is then set as fixed at the top - and is no longer part of the flow (the both divs are no longer seperated by it). The section divs are therefore moved accordingly up to the landing div closing the gap. So clicking the same section anchor again will result in an additional jump, because the section was repositioned due to the landing div went from position:static to position:fixed.
That's an additional reason why I recommend to use navbar-fixed-bottom.
Update
new fiddle: https://jsfiddle.net/y7soL4ej/2/
I removed .navbar-fixed-bottom from HTML and JS as the navbar should not jump from bottom to top.
To make it smooth and avoid the earlier mentioned jumpy behaviour, I had to set it to absolute position.
some CSS needed to be added:
div#landing {
padding-bottom: 72px;
margin-bottom: -72px;
}
nav.navbar {
position: absolute;
left: 0; right: 0;
}
nav.navbar.navbar-fixed-top {
position: fixed;
}
I have setup a few elements with superscrollorama and at the one point when scrolling down one element comes in from the left and another comes from the right and they meet at the middle.
The problem is that before scrolling down the user can actually scroll the page way over to the right, to where the element is actually hiding.
Is there a way to prevent this from happening with superscrollorama?
The code I have for the HTML and Javascript is something like this...
<div class="row">
<div class="col-md-6" id="fly-from-left">This content comes from the left</div>
<div class="col-md-6" id="fly-from-right">This content comes from the right</div>
</div>
<script>
$(document).ready(function() {
var sscr = $.superscrollorama();
sscr.addTween('#fly-from-left', TweenMax.from($('#fly-from-left'), 0.5, { css:{right:'10000px'}, ease:Quad.easeInOut }), 0, -350);
sscr.addTween('#fly-from-right', TweenMax.from($('#fly-from-right'), 0.5, { css:{left:'10000px' }, ease:Quad.easeInOut }), 0, -350);
});
</script>
Assuming you don't have nothing to scroll horizontally in your website, you can use:
body{
overflow-x:hidden;
}
I have a set of seven div's with the following properties:
height: 100px;
width: 100px;
display: inline-block;
I have a wrapper div containing these seven blocks with only enough room to fit four and change.
The overflow is hidden.
How can I make this function so that when you clicked and dragged horizontally, or swiped with your finger on mobile, the entire row of div blocks would slide to show the previously hidden ones?
Please refer to this jsFiddle for the example.
We can use css or jQuery here.
*Bonus, show fractions of otherwise entirely hidden div's at the edges of the container.
Based on jfriend00's answer I modified this so it will work on touch/click and move with the mouse.
var last_x = null;
var holding = false;
//Mark the wrapper as clicked/touched
$('.wrapper').mousedown(function(){
holding=true;
});
//We do this on document so that even if movement goes outside of the container the event will fire
$(document).mouseup(function(){
holding=false;
});
$('.wrapper').mousemove(function(e){
if(last_x === null || !holding) //If this is the first movement
{
last_x = e.pageX;
return;
}
var ammount = e.pageX - last_x;
$('.slider',this).css('margin-left', '+=' + ammount);
last_x = e.pageX;
});
The gist of how this works is that when the mousedown event is detected on the container the script starts tracking all mouse movement and moves the content with the mouse. When the mouse is released it stop tracking movement.
Fiddle: http://jsfiddle.net/NvJam/2/
Since no one has mentioned jQuery.Kinetic I'll add this:
<div class="carousel">
<div class="wrapper">
<div class="first">First</div>
<div class="second">Second</div>
<div class="third">Third</div>
<div class="fourth">Fourth</div>
<div class="fifth">Fifth</div>
<div class="sixth">Sixth</div>
<div class="seventh">Seventh</div>
</div>
</div>
$('.carousel').kinetic();
Demo: http://jsfiddle.net/louisbros/2pRBg/6/
see here
.wrapper {
width: 900px;
height: 100px;
overflow: hidden;
}
You can put an additional container div and use absolute positioning on that div to move the items left/right. Here's a demo:
http://jsfiddle.net/jfriend00/7edc9/
HTML looks like this:
<div class="wrapper">
<div class="slider">
<div class="first">First</div>
<div class="second">Second</div>
<div class="third">Third</div>
<div class="fourth">Fourth</div>
<div class="fifth">Fifth</div>
<div class="sixth">Sixth</div>
<div class="seventh">Seventh</div>
</div>
</div>
You weren't entirely clear how you wanted to move them on non-touch screens, but here's some event handlers that work on buttons:
$("#left").click(function() {
$(".slider").stop(true, true).animate({left: "-=125px"}, 500);
});
$("#right").click(function() {
$(".slider").stop(true, true).animate({left: "+=125px"}, 500);
});
Something similar could be hooked up for touch events.
Even better solution: use the JQuery UI draggable:
$('.slider').draggable({
axis: 'x',
});
http://jsfiddle.net/DCuGV/2/
I need to flip a div panel left once a some item div get clicked and hide,once item div get clicked again. (exactly like new twitter reading panel).
i have tried several methods but i couldn't animate it smooth.
recently i identified it not happen smoothly because of the bad what have i done.i increased width of outter div and decrese width.
are there any good suggestion or code snippet to work my need??
Here is the code that i have used for animate and gt show the more read div panel
$("#more-item").animate({"width": "toggle"}, { duration: 500,specialEasing: {width: 'linear', height: 'easeOutBounce'} });
Here is the scenario that i need to see.
1. clicked on item div
2. more read div panel animate and flip to left and show the
3. click again item div
4. more read div panel animate and flip right and hide
when we at third point if we again click another item div just load content of recent clicked div instead animate and hide the more read div
here is the screen shot what my need functioning on new twitter reading panel.
You can easily do this by adding a fixed positioned <div> to the right, wrap your items in a container and animate the panel and the container's margin accordingly.
The trick is to use the top, bottom and right css properties to position the reading panel.
Here's a demo: http://jsfiddle.net/wUGaY/1/
HTML:
<div class="panel"></div>
<div class="container">
<div class="item">One</div>
<div class="item">Two</div>
<div class="item">Three</div>
<div class="item">Four: This contains a bit longer text to test if wrapping is working correctly.</div>
<div class="item">Five</div>
<div class="item">Six</div>
<div class="item">Seven</div>
<div class="item">Eight</div>
<div class="item">Nine</div>
<div class="item">Ten</div>
</div>
CSS:
.panel {
position:fixed;
top:0px;
bottom:0px;
right:0px;
width:200px;
padding:20px;
border:1px solid #eee;
background-color:white;
}
.item {
border:1px solid #eee;
padding:20px;
}
.active {
background-color: #eee;
}
Javascript:
$(function(){
function showPanel() {
// Show the panel and animate it into view
$('.panel').stop().show().animate({
right: '0px'
});
// Animate the container's margin to make room
// for the reading panel
$('.container').stop().animate({
marginRight: '232px'
});
}
function hidePanel() {
// Move the panel off the screen and hide it when done
$('.panel').stop().animate({
right: '-232px'
}, function(){
$(this).hide();
});
// Animate the container's margin back to normal
$('.container').stop().animate({
marginRight: '0px'
});
}
// Hide the panel initially and set its position
$('.panel').hide().css('right','-232px');
// What happens when they click on inactive items?
$('.container').delegate('.item:not(.active)', 'click', function() {
var $this = $(this);
// Make the current item the only active item
$('.active').removeClass('active');
$this.addClass('active');
// Add some content to the reading panel
$('.panel').html($this.html());
// Show the reading panel
showPanel();
});
// What happens when they click on an active item?
$('.container').delegate('.active', 'click', function() {
// Make it inactive
$(this).removeClass('active');
// Hide the reading panel
hidePanel();
});
});