This question already has answers here:
JqueryUI Draggable - Auto resize parent container
(2 answers)
Closed 7 years ago.
I am sorry my English is not that great. I would like my container element to resize to always contain its child elements.
Visit jsfiddle.net/datakolay/LakYy/
$(document).ready(function() {
var
$document = $(document),
$parent = $("#parent"),
$container = $(".container", $parent),
offset = $container.offset(),
scrollbarSafety = 15;
$container.height($document.height() - offset.top - scrollbarSafety);
$("#eleman,#eleman2")
.draggable(
{
containment: $container,
drag:
function(event, ui)
{
var
$draggee = $(this),
draggeePosition = $draggee.position(),
shouldHeight = draggeePosition.top + $draggee.height() + 15;
if($parent.height() < shouldHeight)
{
$parent.height(shouldHeight);
}
if($parent.height() > shouldHeight)
{
$parent.height(shouldHeight);
}
}
}
);
});
You can use the following to figure out the shouldHeight - essentially:
use a selector to get all the draggables
Get its height and compare it to what you currently have
Set the height.
Here's the meat of the how to:
var shouldHeight = 0;
$(".ui-draggable").each(function () {
var draggeePosition = $(this).position();
if (shouldHeight < draggeePosition.top + $(this).height() + 15) {
shouldHeight = draggeePosition.top + $(this).height() + 15;
}
});
fiddle: http://jsfiddle.net/LakYy/3/
http://jsfiddle.net/LakYy/5/
$(document).ready(function() {
var
$document = $(document),
$parent = $("#parent"),
$container = $(".container", $parent),
offset = $container.offset(),
scrollbarSafety = 15;
$container.height($document.height() - offset.top - scrollbarSafety);
$("#eleman,#eleman2")
.draggable(
{
containment: $container,
drag:
function(event, ui)
{
var shouldHeight = getdraggablemaxheight();
if($parent.height() < shouldHeight)
{
$parent.height(shouldHeight);
}
if($parent.height() > shouldHeight)
{
$parent.height(shouldHeight);
}
}
}
);
});
function getdraggablemaxheight() {
var $parent = $("#parent"),
$container = $(".container", $parent),
maxheight = 0,
currentheight = 0,
currentposition;
$container.children().each(function(index, element) {
currentposition = $(element).position();
currentheight = currentposition.top + + $(element).height() + 15;
if(currentheight > maxheight)
maxheight = currentheight;
});
return maxheight;
Based on the solution by #caspian you may find this variation scales better with many draggables. Same thing really, but only finds the dom positions once per item:
$(".ui-draggable").each(function () {
var draggeeHeight = $(this).position().top + $(this).height() + 15;
if (shouldHeight < draggeeHeight) {
shouldHeight = draggeeHeight;
};
});
if ($parent.height() != shouldHeight) {
$parent.height(shouldHeight);
}
I needed this as well for a project, here is the fiddle
http://jsfiddle.net/genkilabs/WCw8E/2/
To #coding_idiot, what you are asking about will w the default behavior if you use overflow-x: scroll;
Related
I have 4 sub-banners with display: block; width: 100%; that each have a div with text inside. These divs hangs down outside the parent element using transform: translateY(238px).
Each div that holds the text is of varying height so I was trying to write a function to check each text div's height and apply the margin to the bottom of that specific parent element accordingly.
What I got so far is this, but I can't figure out how to get the variable respectiveMargin passed into my second each function so that it matches up with the right parent element. Right now it just applies the same margin on all sub-banners. Thanks for any and all help!
const resize = () => {
if ($(window).width() < 768) {
$('.sub-banner-text-wrapper').each(function () {
var textHeight = $(this).height();
var responiveMargin = (textHeight - 62) + 25;
});
$('.sub-banner').each(function () {
$(this).css("margin-bottom", responiveMargin);
});
}
};
$(window).on('resize', resize);
Seems the main problem is that you're trying to use two .eaches when you only need one:
const resize = () => {
if ($(window).width() < 768) {
$('.sub-banner-text-wrapper').each(function () {
var textHeight = $(this).height();
var responiveMargin = (textHeight - 62) + 25;
$(this).closest('.sub-banner').css("margin-bottom", responiveMargin);
});
}
};
$(window).on('resize', resize);
So reference the index when you loop over the one set.
var banners = $('.sub-banner');
$('.sub-banner-text-wrapper').each(function (ind) {
var textHeight = $(this).height();
var responiveMargin = (textHeight - 62) + 25;
banners.eq(ind).css("margin-bottom", responiveMargin);
});
If it happens to be a child/parent element, than you can just select it.
var banners = $('.sub-banner');
$('.sub-banner-text-wrapper').each(function (ind) {
var textHeight = $(this).height();
var responiveMargin = (textHeight - 62) + 25;
//If a child
$(this).find(".sub-banner").css("margin-bottom", responiveMargin);
//or a parent
$(this).parent().css("margin-bottom", responiveMargin);
});
Maybe Something like this?
if ($(window).width() < 768) {
$('.sub-banner-text-wrapper').each(function () {
var subBanner = $(this).closest('.sub-banner').attr('class');
var textHeight = $(this).height();
var responiveMargin = (textHeight - 62) + 25;
$(subBanner).css("margin-bottom", responiveMargin);
});
}
I wrote following functon and I am trying to use that in different elements but it doesn't work.
$.fn.sticky = function() {
var
scrollTop = $(window).scrollTop();
replace_class = $(this),
sticky = "ceras_sticky_header",
elementOffset = replace_class.offset().top,
distance = (elementOffset - scrollTop),
leftPositionofImage = replace_class.offset().left,
windowWidth = $(window).width(),
elementWidth = replace_class.width(),
rightPosition = (windowWidth - leftPositionofImage - elementWidth - 12);
$(window).scroll(function() {
if( $(this).scrollTop() > distance) {
replace_class.addClass(sticky);
replace_class.css('right',rightPosition);
replace_class.draggable();
} else {
replace_class.removeClass(sticky);
}
});
};
I want to it to work like:
$( ".ancor_controls" ).sticky();
$( ".ancor_controls1" ).sticky();
Currently I have a script which starts a progress bar the moment a user starts scrolling.
Is it possible to change this to when the user gets to 340px from the top of the page?
Here is a demo of my site: http://pixsols.com/test/wordpress/reading-progress/
Here is my current code:
(function ( $ ) {
$.fn.progressScroll = function(options) {
var settings = $.extend({
fontSize : 20,
color : '#009ACF',
height : '5px',
textArea : 'dark',
}, options);
// element state info
var docOffset = $(this).offset().top,
elmHeight = $(this).height(),
winHeight = $(window).height();
// listen for scroll changes
$(window).on('scroll', function() {
var docScroll = $(window).scrollTop(),
windowOffset = docOffset - docScroll,
viewedPortion = winHeight + docScroll - docOffset;
if($(window).scrollTop() > 0) {
if($('.scrollWrapper').hasClass('hidden')) {
$('.scrollWrapper').removeClass('hidden').hide();
$('.scrollWrapper').slideDown('slow');
}
} else {
$('.scrollWrapper').slideUp('slow');
$('.scrollWrapper').addClass('hidden');
}
if(viewedPortion < 0) { viewedPortion = 0; }
if(viewedPortion > elmHeight) { viewedPortion = elmHeight; }
// calculate viewed percentage
var viewedPercentage = viewedPortion / elmHeight;
// set percent in progress element
$('.scroll-bar').css('width', (viewedPercentage*100)+'%' );
});
var self = this;
$(window).on('resize', function() {
docOffset = $(self).offset().top;
elmHeight = $(self).height();
winHeight = $(window).height();
$(window).trigger('scroll');
});
$(window).trigger('scroll');
var $el = $('.scroll-bar').css(settings);
return $el;
};
}( jQuery ));
My guess would be to manipulate this:
windowOffset = docOffset - docScroll,
Probably you should add or subtract 320px from windowOffset. So for example"
windowOffset = docOffset - docScroll + 320,
Can someone tell me how to adjust this .js? I want it to be able to apply on H1 and H2 with an ID in my html. Now it is only working on css background-image. Below is the .js I'm using. I'm a beginner with javascript;)
Hope you guys can help me out!
(function( $ ){
var $window = $(window);
var windowHeight = $window.height();
$window.resize(function () {
windowHeight = $window.height();
});
$.fn.parallax = function(xpos, speedFactor, outerHeight) {
var $this = $(this);
var getHeight;
var firstTop;
var paddingTop = 0;
//get the starting position of each element to have parallax applied to it
$this.each(function(){
firstTop = $this.offset().top;
});
if (outerHeight) {
getHeight = function(jqo) {
return jqo.outerHeight(true);
};
} else {
getHeight = function(jqo) {
return jqo.height();
};
}
// setup defaults if arguments aren't specified
if (arguments.length < 1 || xpos === null) xpos = "50%";
if (arguments.length < 2 || speedFactor === null) speedFactor = 0.1;
if (arguments.length < 3 || outerHeight === null) outerHeight = true;
// function to be called whenever the window is scrolled or resized
function update(){
var pos = $window.scrollTop();
$this.each(function(){
var $element = $(this);
var top = $element.offset().top;
var height = getHeight($element);
// Check if totally above or totally below viewport
if (top + height < pos || top > pos + windowHeight) {
return;
}
$this.css('backgroundPosition', xpos + " " + Math.round((firstTop - pos) * speedFactor) + "px");
});
}
$window.bind('scroll', update).resize(update);
update();
};
})(jQuery);
It should be background-position. Can you try changing?
$this.css('background-position', xpos + " " + Math.round((firstTop - pos) * speedFactor) + "px");
Im creating myself a drag functions just for my personal use so I can drag elements around. I'm having a problem. At the moment trying to make the drag so one you pick up the element you can drag it but once you drop it, it goes back to the original position. This is not working as you can see here. When I let go of #drag2 or #drag3 then it goes to the position of #drag1.
My Function:
function drag(el) {
var position = $(el).position();
var ptop = position.top;
var pleft = position.left;
var down = false;
$(el).mousedown(function(event) {
down = true;
$(this).css({
cursor: 'crosshair',
});
$(this).mousemove(function(event) {
if (down == true) {
$(this).css({
cursor: 'crosshair',
});
var w = $(this).width();
var h = $(this).height();
var left3 = (w / 2) + 7;
var top3 = (h / 2) + 7;
$(this).css({
cursor: 'crosshair',
left: (event.clientX) + (3 * 3) - left3,
top: (event.clientY) + (3 * 3) - top3
});
}
}).mouseup(function() {
down = false;
$(this).css({
cursor: 'default',
});
$(this).animate({
top: ptop,
left: pleft
}, 300);
});
});
}
I have to get the old position:
var position = $(el).position();
var ptop = position.top;
var pleft = position.left;
So should it not get the position of all of them and bring them self back to where they were? Any help will be appreciated.
EDIT: I DO NOT WANT TO USE ANY PLUGIN OR JQUERY UI, THANKS ANYWAYS
The solution is very simple
See this fiddle: http://jsfiddle.net/BggPn/4/
you define 1 var for left and 1 for top. All 3 the elements use the same variables. If you loop through the elements then you make a new scope where each element has it's own vars.
Working code:
$(document).ready(function() {
drag('#drag, #drag2, #drag3')
});
function drag(el) {
$(el).each(function(){
var position = $(this).position();
var ptop = position.top;
var pleft = position.left;
var down = false;
$(this).mousedown(function(event) {
down = true;
$(this).css({
cursor: 'crosshair',
});
$(this).mousemove(function(event) {
if (down == true) {
$(this).css({
cursor: 'crosshair',
});
var w = $(this).width();
var h = $(this).height();
var left3 = (w / 2) + 7;
var top3 = (h / 2) + 7;
$(this).css({
cursor: 'crosshair',
left: (event.clientX) + (3 * 3) - left3,
top: (event.clientY) + (3 * 3) - top3
});
}
}).mouseup(function() {
down = false;
$(this).css({
cursor: 'default',
});
$(this).animate({
top: ptop,
left: pleft
}, 300);
});
});
});
}
Make it a plugin:
$.fn.drag = function drag(){
return this.each(function(){
var position = $(this).position();
var ptop = position.top;
var pleft = position.left;
var down = false;
$(this).mousedown(function(event) {
down = true;
$(this).css({
cursor: 'crosshair',
});
$(this).mousemove(function(event) {
if (down == true) {
$(this).css({
cursor: 'crosshair',
});
var w = $(this).width();
var h = $(this).height();
var left3 = (w / 2) + 7;
var top3 = (h / 2) + 7;
$(this).css({
cursor: 'crosshair',
left: (event.clientX) + (3 * 3) - left3,
top: (event.clientY) + (3 * 3) - top3
});
}
}).mouseup(function() {
down = false;
$(this).css({
cursor: 'default',
});
$(this).animate({
top: ptop,
left: pleft
}, 300);
});
});
});
}
Now you can call it by:
$("#drag1, #drag2").drag();
2 thoughts:
1.) Why don't you use jQuery UI (draggable)?
2.) The idea of giving a selector in stead of an element is wrong, a selector can lead to multiple elements, and that's the first reason why it's failing. If you start with
function drag(selector) {
$(selector).each(function() {
var el = $(this);
//rest of code
}
}
it would be better. But I think you'll run into a few other problems eventually
The problem is whenever you're sending in the list of selectors '#drag, #drag2. #drag3' and your position variable only cares about the first one (try changing the order and you'll see they snap to the first in the list). If you want to go about it this way then you'll want to perform an each iteration over them to get the right values.
get the current position of div after drag and set via this
.mouseup(function() {
var position = $(this).position();
down = false;
$(this).css({
cursor: 'default',
});
$(this).animate({
top: position.top,
left: position.left
}, 300);
DEMO
why don't you use drag and drop plugin. see this article
http://viralpatel.net/blogs/2009/05/implement-drag-and-drop-example-jquery-javascript-html.html
or this one
http://plugins.jquery.com/project/dragndrop