I need to dynamically change the width of a <div> if it is dragged out of its parent element so its right edge stays "glued" to the parent's right edge and the contents of a <div> wrap inside the new width. After days of googling and reading posts here I've managed to resize the <div> once when it touches the parent. I tried mouseup/mousedown to restart it but it doesn't work.
The end result should work both ways (return to its original size when dragged back into the parent), something like resizing the <div> from the left edge while it's floated to the right. But for now, I at least want it to resize dynamically as I'm dragging it "out of" the parent.
I'm sure I've seen this somewhere and I refuse to believe it's impossible.
let item = $( '#item' );
let draggableRight;
let parentWidth = $('#parent').outerWidth();
function resizeMe() {
draggableRight = item.position().left + item.width();
if (draggableRight > parentWidth) {
item.width(item.width() - 50);
}
}
item.draggable({
scroll: false,
containment: 'parent',
drag: function (event, ui) {
resizeMe();
}
});
#parent {
height: 100vh;
}
#item {
position: absolute;
cursor: move;
}
<div id="parent">
<div id="item">
<span>Some random text</span>
<p>I want this to continue wrapping/shrinking as I'm dragging to the right.</p>
</div>
</div>
<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.min.js"></script>
Related
I've made several overlapping objects draggable and resizable via the JQuery Draggable and Resizable plugins. When dragging an object, it's instantly brought up to the frontmost position thanks to the stack option. The Resizable plugin doesn't have this option so when an element in the background is being resized but not dragged, it stays in the back.
How do I make an object being resized jump to the front just like it happens when it's being dragged?
Thanks
You can implement this yourself by using the start event of the resizable widget.
In that event you just loop through your draggable/resizable elements to find the highest zIndex, then set your currently resizing element higher in the stack.
For example (heavily commented for clarity).
// Common class of our draggable/resizable elements
const targetClass = ".foo";
$(targetClass)
.resizable({
start: (event, ui) => {
// current resizing element
const element = $(ui.element[0]);
let topZIndex = 0;
// loop over all our elements
$(targetClass).each((i, obj) => {
// get the current zIndex as an int, using the unary operator
// and accounting for NaN values like 'auto'
const currentZIndex = +$(obj).css("zIndex") || 0;
// if current zIndex is higher, update the topZIndex
currentZIndex > topZIndex && (topZIndex = currentZIndex);
});
// set the resizing elements zIndex above the highest
element.css("zIndex", topZIndex + 1);
}
})
.draggable({
stack: targetClass
});
.foo {
width: 100px;
height: 100px;
padding: 0.5em;
position: absolute !important;
}
.foo h3 {
text-align: center;
margin: 0;
}
<script src="https://code.jquery.com/jquery-3.6.0.js"></script>
<script src="https://code.jquery.com/ui/1.13.2/jquery-ui.js"></script>
<link rel="stylesheet" href="//code.jquery.com/ui/1.13.2/themes/base/jquery-ui.css">
<div id="container">
<div class="foo ui-widget-content">
<h3 class="ui-widget-header">test 1</h3>
</div>
<div class="foo ui-widget-content">
<h3 class="ui-widget-header">test 2</h3>
</div>
<div class="foo ui-widget-content">
<h3 class="ui-widget-header">test 3</h3>
</div>
</div>
I have side bullets that are menu scrolling to section of onepage, i did a scroll animation but i would like to change class="active" between bullets when scrolling. I know it can be easly achieved by jQuery(body,window).scroll() with $('#scrollspymenu li').each() but its really bad way. I can break out of each() function but this way i still need to get from first li element to (for example) 5th li. I thought about getting all data-target elements to some array with save offsetTop and offsetTop+height and in scroll event i will check which element is on middle of the screen. ( i mean window scroll top position + 1/2 window height)
I have no idea how to make like some kind of timeline with sections with calculated range AND what function can select (based on input) element that is attached to 2 range values.
I'm also using scrollMagic, maybe it does it better? Still would like to use pure js or jquery for future use.
I'm sorry i couldnt form a good specific question but i tried my best.
my comment
(..) I want fastest possible way to get from scrolll event to proper element. Best possible performance of the page. It's stupid when u scroll, 1 scroll tick is 100x on scroll function, and every function goes every element. For 4 elements its checks elements 400 times...
JS
var page = $("html, body");
$('#scrollspymenu a, .go-to, .go-to2').click(function(event) {
event.preventDefault();
var target = $(this).attr('data-target');
if(target){
page.on("scroll mousedown wheel DOMMouseScroll mousewheel keyup touchmove", function(){
page.stop();
});
page.animate({ scrollTop: $(target).offset().top-50 }, 700, function(){
page.off("scroll mousedown wheel DOMMouseScroll mousewheel keyup touchmove");
});
}
})
Html Side menu
<nav id="scrollspymenu">
<ul>
<li class="active"><span>Knauf Group</span></li>
<li><span>History</span></li>
<li><span>Values</span></li>
()...)
<li><span>Automobile industry</span></li>
<li><span>Solutions</span></li>
</ul>
First off, I am not 100% sure this resolves your issue, as the intent is not totally clear to me.
What THIS does is if you click on a menu, it scrolls to that associated target.
Also if you tab, shift-tab it scrolls to that associated target.
If you mouse over a menu, then scroll, it scrolls the target. I think you get the idea and if not a 100% solution perhaps you can build from this.
The console.logstuff should be removed eventually but will illustrate what is firing at what point for you.
var page = $("html,body");
$('#scrollspymenu').on('click scroll mousedown wheel DOMMouseScroll mousewheel keyup touchmove', 'a', function(event) {
// event.preventDefault();
event.stopImmediatePropagation();
var elem = $(this);
var target = elem.data('target');
$('.active').removeClass('active');
if (!!target) {
$(target).addClass('active');
elem.addClass('active');
console.log('in here');
page.off("scroll mousedown wheel DOMMouseScroll mousewheel keyup touchmove", function() {
console.log('in stop');
page.stop(); // stop any animation
});
page.animate({
scrollTop: ($(target).offset().top - 50)
}, {duration:700, start:function() {
console.log('in callback', $(target).offset().top - 50);
page.on("scroll mousedown wheel DOMMouseScroll mousewheel keyup touchmove");
}});
}
})
#pagethings {
margin-left: 200px;
}
#contentbody {
float: right;
width: 100%;
background-color: #F0F0F0;
}
#scrollspymenu {
float: left;
width: 200px;
margin-left: -200px;
background-color: #CCCCCC;
/* fix to top */
position: fixed;
/* force scroll bars */
overflow: scroll;
}
.section {
margin: 1em;
padding-bottom: 4em;
}
#clearingdiv {
clear: both;
}
.active{ background-color: #EECCAA;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="pagethings">
<nav id="scrollspymenu">
<ul>
<li class="active"><span>Knauf Group</span></li>
<li><span>History</span></li>
<li><span>Values</span></li>
<li><span>Automobile industry</span></li>
<li><span>Solutions</span></li>
</ul>
</nav>
<div id="contentbody">
<div class="section sec-company-home sec-home-knaufgroup">My Home of my grand thing</div>
<div class="section sec-company-history">History of my grand thing</div>
<div class="section sec-company-values">Values of my grand thing</div>
<div class="section sec-company-automobile">My great car of my grand thing. I might put something bigger in here, pictures etc so I fake this with some text to make it bigger. The brown cow jumped over the crazy blue moon but why is that moon blue and how can that cow breathe when jumping over
a moon and why is it "over" the moon not "around" the moon for a literal quotation?</div>
<div class="section sec-company-solutions">Solution of my grand thing, drive my great car fast</div>
</div>
</div>
This is the html code I have:
<div id="header_context" class="scroll">
<div id="column_scroll" class="column" ng-repeat="column in columns track by column.name" ng-hide="column.name == 'date'" ng-click="column.visible = !column.visible">
<div class="checkmark" ng-class="{'checked': column.visible}"></div>
<div class="" ng-bind-html="column.title"></div>
</div>
</div>
This I have in my css:
#column_scroll{
overflow: scroll;
}
.scroll{
overflow: scroll !important;
}
This is a function that I have inside the .js:
$('#timeline_container #content .trips_header').on('contextmenu', function(e) {
e.preventDefault();
e.stopPropagation();
hideContextMenu();
$('#header_context').css({
display: 'block',
left: e.clientX,
top: e.clientY,
overflow:scroll
});
$('#header_context > div').click(function(evt) {
evt.stopPropagation();
});
});
This is what my inspector sees:
https://s3.amazonaws.com/uploads.hipchat.com/39260/829560/lPNa4qbS34P6dVE/upload.png
PS: I tried changing from the inspector overflow - scroll, but still, it is blocked. Do I need to add something else?
PPS: This is how it looks on a PC or if the inspector is closed:
https://s3.amazonaws.com/uploads.hipchat.com/39260/829560/b37eCtrQIfgV4dt/upload.png
This is how it looks with the inspector on, or laptop:
https://s3.amazonaws.com/uploads.hipchat.com/39260/829560/qSquGYY8ZWulHZm/upload.png
As you can see, The list doesn't fit, and it is not scrollable.
I guess you are missing some html code.
By the way, if you want it to be scrollable, div "header_context" or any div that is going to contain the ng-repeat items has to have a height or max-height attribute defined, and then make it "overflow-y:scroll;" so if children ng-repeat divs height surpases parent height, parent becomes scrollable.
I'm trying to perform the Jquery function below when the element becomes visible in the viewport rather than on the page load. What would I need to change to allow that to happen? I'm using an external JS file to perform the Jquery, so keep that in mind.
Here's a piece of the HTML that is associated with the Jquery function -
<div class="skillbar clearfix " data-percent="70%">
<div class="skillbar-title" style="background: #FF704D;">
<span>Illustrator</span></div>
<div class="skillbar-bar" style="background: #FF704D;"></div>
<div class="skill-bar-percent">70%</div>
</div>
jQuery(document).ready(function(){
jQuery('.skillbar').each(function(){
jQuery(this).find('.skillbar-bar').animate({
width:jQuery(this).attr('data-percent')
},4000);
});
});
I once came across such problem and what I used is waypoints small library.
all you need is to include this library and do:
var waypoint = new Waypoint({
element: document.getElementById('waypoint'),
handler: function(direction) {
console.log('Element is in viewport');
}
})
Using CSS3 transitions instead of jQuery animations might be more performant and simpler. a cheap and nasty way of pushing it out of screen to demonstarate the effect.
There's a couple of things you'll need to do - firstly if you only want the animation to trigger when it's in the viewport then you'll need to check if anything is in the viewport on scroll. Then only update the bars width when it comes into view. If you want the effect to repeat every time it comes into viewport you'll need to set .skillbar-bar's width back to 0 if it's out of the viewport (just add an else statement to the viewport checking if)
I've added a 1000px margin-top and 400px margin-bottom in my example to .skillbar as a cheap and nasty way of demonstrating the effect
(function($){
$(document).ready(function(){
var $els = $('.skillbar'); // Note this must be moved to within event handler if dynamically adding elements - I've placed it for performance reasons
var $window = $(window);
$window.on('scroll', function(){
$els.each(function(){ // Iterate over all skillbars
var $this = $(this);
if($window.scrollTop() > $this.offset().top - $window.height()){ // Check if it's in viewport
$this.find('.skillbar-bar').css({'width' : $this.attr('data-percent')}); // Update the view with percentage
}
});
});
});
}(jQuery));
.skillbar{
margin-top: 1000px;
margin-bottom: 400px;
position: relative
}
.skillbar-bar{
transition: width 4s;
position: absolute;
height: 20px;
}
.skill-bar-percent{
position: absolute;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
Scroll down 1000px :)
<div class="skillbar clearfix " data-percent="70%">
<div class="skillbar-title">
<span>Illustrator</span></div>
<div class="skillbar-bar" style="background: #FF704D; width: 20%"></div>
<div class="skill-bar-percent">70%</div>
</div>
This might work for you.
var el = $('.yourElement'),
offset = el.offset(),
scrollTop = $(window).scrollTop();
//Check for scroll position
if ((scrollTop > offset.top)) {
// Code..
}
copied following code from http://jqueryui.com/demos/resizable/#default
<meta charset="utf-8">
<style>#resizable { width: 150px; height: 150px; padding: 0.5em; }
#resizable h3 { text-align: center; margin: 0; }
</style>
<script>
$(function() {
$( "#resizable" ).resizable();
});
</script>
<div class="demo">
<div id="resizable" class="ui-widget-content">
<h3 class="ui-widget-header">Resizable</h3>
</div>
</div>
It outputs this.
I want to capture the double click event for each of cursor position so that if
Double click by horizontal re-size cursor, i can toggle width of current resizable between original and maximun available width.
Double click by vertical re-size cursor, i can toggle height of current resizable between original and maximun available height.
Double click by diagonal re-size cursor, i can toggle width and height of current resizable between original and maximun available width and height.
The handlers have specific classNames:
ui-resizable-se//bottom right
ui-resizable-s//bottom
ui-resizable-e//right
You can select them and bind the dblclick:
$('.ui-resizable-se').dblclick(function(){alert('clicked bottom right handle');})
A pointer to the resizable you'll get inside the function using $(this).parent()
Use firebug to find out the elements you ant to attach the event (like: .ui-resizable-e - self explanatory) and use for example:$(".ui-resizable-e").dblclick(myFunctionToResize);
Is that what you mean?