Something is wrong with this 3-panes splitter - javascript

I'm trying to resize 3 panes inside a container , when resized, they shouldn't exceed the width of container (do not get out of it)..
But in this snippet http://jsfiddle.net/KXsrd/ , when I resize the second one, it successfully decreases the next element or increases depending on the direction. but sometimes it causes the next sibling to drop below the container and although the next sibling decreases its size when I expand one , it keeps 'shaking' ..
Here is the main function:
$(function () {
$('.col').each(function (e, u) {
$(u).data({ow: $(u).width()});
})
$(".col").resizable(
{
handles: 'e',
start: function (e) {
},
resize: function (e, ui) {
var el = ui.element;
var parent = el.parent();
var next = el.next();
var siblings = el.siblings();
var siblingsWidth = (function () {
var totalWidth = 0;
_.each(siblings, function (el) {
totalWidth += $(el).width();
});
return totalWidth;
})();
var currentSize = ui.size;
if (currentSize.width > $(el).data('ow')) {
next.css({width: '-=' + (currentSize.width - $(el).data('ow'))});
} else {
next.css({width: '+=' + ( $(el).data('ow') - currentSize.width )});
}
if (currentSize.width + siblingsWidth >= $(parent).width()) {
$(el).width($(parent).width() - siblingsWidth)
}
$(el).data({ow: currentSize.width});
},
stop: function (e, ui) {
}
});
});
Any help would be much appreciated ..
(PS. I tried many plugins for resizable panes. but they all work on 2 panes only)

Related

jQuery sortable keep table's width

Couldn't find a simple solution for jquery's sortable to keep width of table during dragging element, forcePlaceholderSize is not actually working this time, if table have some large element - if i start dragging it then the table resized to still-in-table element's max width, so here is what I've done:
jQuery("#sortable1").sortable({
items: "tbody:not([not-sortable])",
cursor: "move",
zIndex: 9999,
start: function (event, ui) {
var colW = jQuery(".faq_glyph_owner").width();
self.textWidth = ui.item.innerWidth() - colW * 3;
jQuery(".faq_text").width(self.textWidth);
jQuery("#sortable1").css("table-layout", "fixed");
ui.item.find("div").parent().width(self.textWidth + colW);
},
stop: function (event, ui) {
jQuery("#sortable1").css("table-layout", "auto");
}
});
So i'm generally just counting size as it supposed to be and apply fixed layout to table, here is sample of this with table. So my question is : Is there any built-in ways to keep table width during sorting, as if dragged element is still inside table? Please note that i do not want to keep table's layout fixed.
P.S. please ignore 'jQuery', we just still have legacy prototype code that interferes with it
var fixHelper = function(e, ui) {
ui.children().each(function() {
console.log(e);
$(this).width($(this).width());
});
return ui;
};
$("#sortable1 tbody").sortable({
helper: fixHelper
}).disableSelection();
JSfiddle
Source article
How about this:
$("#sortable1").sortable({
items: "tbody:not([not-sortable])",
helper: 'clone',
cursor: "move",
zIndex: 9999,
start: function (event, ui) {
$(ui.item[0]).show().css('opacity','0');
},
stop: function (event, ui) {
$(ui.item[0]).css('opacity','1');
}
});
You are basically cloning the element and instead of hiding it whilst moving, you just apply opacity of 0 and then applying opacity of 1 once dropped. I didn't really have time to test it.
This is the code I use for this. I create a helper function that gets the height and width of everything in the row and then explicitly sets it to those heights and widths, plus adds a row back in as a placeholder.
var fixHelper = function (e, ui) {
ui.children().each(function () {
if ($(this).children().length > 0) {
fixHelper(e, $(this));
}
if(parseInt($(this).css("margin-left")) != 0)
$(this).css("margin-left", $(this).css("margin-left"));
if (parseInt($(this).css("margin-right")) != 0)
$(this).css("margin-right", $(this).css("margin-right"));
$(this).width($(this).realWidth(true));
$(this).height($(this).realHeight(true));
});
ui.height(ui.realHeight());
return ui;
};
var unfixHelper = function (ui) {
ui.children().each(function () {
if ($(this).children().length > 0) {
unfixHelper($(this));
}
$(this).css("margin-left", "");
$(this).css("margin-right", "");
$(this).css("width", "");
$(this).css("height", "");
});
ui.css("height", "");
};
var sortableOptions = new Object({
items: "tbody:not([not-sortable])",
cursor: "move",
zIndex: 9999,
helper: fixHelper,
start: function (e, ui) {
ui.placeholder.height(ui.item.height());
ui.placeholder.html("<td colspan=\"10\"> </td>");
},
stop: function (e, ui) {
unfixHelper(ui.item);
ui.placeholder.html("");
}
});
jQuery("#sortable1").sortable(sortableOptions);
Another file (real-dimensions.js):
$.fn.realWidth = function (inner) {
var $t = $(this);
var rect = this[0].getBoundingClientRect();
var width;
if (rect.width) {
// `width` is available for IE9+
width = rect.width;
} else {
// Calculate width for IE8 and below
width = rect.right - rect.left;
}
if (inner)
width -= parseInt($t.css("padding-left")) + parseInt($t.css("padding-right"));
return width;
}
$.fn.realHeight = function (inner) {
var $t = $(this);
var rect = this[0].getBoundingClientRect();
var height;
if (rect.height) {
// `height` is available for IE9+
height = rect.height;
} else {
// Calculate height for IE8 and below
height = rect.top - rect.bottom;
}
if (inner)
height -= parseInt($t.css("padding-top")) + parseInt($t.css("padding-bottom"));
return height;
}
There is an option called helper in the sortable widget. Its purpose is to add some behaviour to the dragging display action.
The relevant part of the modification is:
jQuery('#sortable1').sortable({
helper: fixedWidth
});
function fixedWidth(e, ui) {
var max_w = 0;
// get the max width from all the children
ui.children().each(function() {
var w = $(this).width();
if (w > max_w) max_w = w;
});
// set the width of the table to be the max
$('#sortable1').width(max_w);
return ui;
}
A full implementation can be found in this JSFiddle. I got inspiration from this blog.
Also, if you mind my opinion, I would build this structure in a simpler way, using <ul> instead of <table>. Like this. You only have to style the <ul> in order to have a fixed width.
add colgroup to table tag
<colgroup>
<col style="width: 0%"/>
<col style="width: 0%"/>
<col style="width: 100%"/>
<col style="width: 0%"/>
</colgroup>
set width in 'table'
table {
border-collapse : collapse;
width: 550px;
}

JQuery resize performance issue

I built a slider that moves left or right if some items are hidden. Obviously this needs to work responsively, so I am using a resize (smartresize) function to check when the browser is resized. It works, but after resizing when you click more (right arrow) it takes 2-5 seconds to actually calculate what is hidden and then execute.
Can anyone explain to me why this is happening, and how to possibly fix it?
Thanks!
$(window).smartresize(function () {
var cont = $('#nav-sub-menu-2 .container');
var ul = $('#nav-sub-menu-2 ul');
var li = $('#nav-sub-menu-2 ul li');
var amount = li.length;
var width = li.width();
var contWidth = cont.width();
var ulWidth = width * amount;
var remainder = ulWidth - contWidth;
ul.width(ulWidth);
if(remainder <= 0) {
$('.more, .less').fadeOut();
} else {
$('.more').fadeIn();
}
$('.more').click(function() {
ul.animate({ 'right' : remainder });
$(this).fadeOut();
$(".less").fadeIn();
});
$('.less').click(function() {
ul.animate({ 'right' : 0 });
$(this).fadeOut();
$(".more").fadeIn();
});
}).smartresize();
It could be because it is recalculating the screen size at every interval as you are resizing...
Try using a debouncer to delay the function calls until everything's settled.
/* Debounce Resize */
function debouncer( func , timeout ) {
var timeoutID , timeout = timeout || 200;
return function () {
var scope = this , args = arguments;
clearTimeout( timeoutID );
timeoutID = setTimeout( function () {
func.apply( scope , Array.prototype.slice.call( args ) );
} , timeout );
}
}
$( window ).resize( debouncer( function ( e ) {
/* Function */
}));

Showing animations through page scrolling

So I've been trying to follow this tutorial http://www.netmagazine.com/tutorials/getting-animations-trigger-right-time and realised those effects only work for elements that contain images. I wanted to get this effect on elements that don't contain images (i.e: a block of text) but couldn't make it work. Does anyone have any idea on how to achieve this? Thank you guys!
Here's the script:
<script>
if (Modernizr.csstransitions) {
function preloadImages(imgs, callback) {
var cache = [],
imgsTotal = imgs.length,
imgsLoaded = 0;
$(imgs).each(function (i, img) {
var cacheImage = document.createElement('img');
cacheImage.onload = function () {
if (++imgsLoaded == imgsTotal) callback();
};
cacheImage.src = $(img).attr('src');
cache.push(cacheImage);
});
};
$.fn.trans = function () {
var t = arguments[0],
d = arguments[1] || '';
if (t) {
$.each(this, function (i, e) {
$(['-webkit-', '-moz-', '-o-', '-ms-', '']).each(function (i, p) {
$(e).css(p + 'transition' + d, t);
});
});
}
};
document.write('<link rel="stylesheet" href="animations.css" />');
$(function(){
//preload images contained within elements that need to animate
preloadImages($('.services img, .featured img'), function () {
$('.services, .featured').appear({
once: true,
forEachVisible: function (i, e) {
$(e).data('delay', i);
},
appear: function () {
var delay = 150,
stagger = 800,
sequential_delay = stagger * parseInt($(this).data('delay')) || 0;
$(this).children().each(function (i, e) {
$(e).trans(i * delay + sequential_delay + 'ms', '-delay');
});
$(this).removeClass('animationBegin');
}
});
});
});
}
</script>
You can find Lightweight jQuery scrolling script that handles viewport css3 animations SEE HERE
I have created one demo which show how it works, scroll the fiddle and you will see the animation when element is in viewport.
SEE THE DEMO HERE

Jquery resizeable auto resize parent

I've got a couple of nested resizable div's that need to resize to accommodation the child size.
Everything works fine until i try to resize one of the outer div's (vertically) then it gets stuck.
Here's a fiddle.
$(function () {
$('.block').resizable();
$('.block').resize(resize_handler);
});
function checkChildren(object) {
$(object).children(".block").each(function (index, item) {
var itemH = $(item).position().top + $(item).height();
var itemW = $(item).position().left + $(item).width();
if ($(object).width() < itemW) {
$(item).width($(object).width());
checkChildren($(item));
}
if ($(object).height() < itemH) {
$(item).height($(object).height());
checkChildren($(item));
}
});
}
function checkParent(e) {
var object = $(e);
var par = object.parent();
var totalW = object.width() + object.position().left;
var totalH = object.height() + object.position().top;
if (totalH > par.height()) {
par.height(totalH);
checkParent(par);
}
if (totalW > par.width()) {
par.width(totalW);
checkParent(par);
}
}
function resize_handler(e, ui) {
e.stopPropagation();
var object = $(this);
var par = object.parent();
if (par.hasClass("block")) {
checkParent(object);
}
if (object.children('.block').length > 0) {
checkChildren(object);
}
}
Sure you've already thought of this but could you try limiting the resizeability of the parent div if its height is too close to the height of its child. Meaning when it is about to come in contact with the edge of a child then don't allow it to come any closer. Maybe maintain a buffer around the children of a few pixels which would force the user to adjust the child first before they could adjust the parent any smaller.
Just a thought.

JQuery Resizable - Update element absolute position while resizing

I have many divs distributed in rows and columns, (generated using jQuery). Each one of these divs is re-sizable, using JQuery UI Resizable. In order to define the requirements, all divs must use absolute positioning. So, when I re-size any of these divs, the script should update the top attribute of all divs below this, (located in the same column and one row after the current resizing div).
This is the code I have now:
updatePositions: function() {
var update = 0;
$(".element").resizable({
handles: 's',
start: function(event, ui) {
event.stopPropagation();
var el = $(this);
var el_row = parseInt(el.attr("row"));
var el_rel = parseInt(el.attr("rel"));
var el_col = parseInt(el.attr("col"));
update = $(".element").filter(function() {
return(
$(this).attr("row") > el_row &&
$(this).attr("col") == el_col &&
$(this).attr("rel") != el_rel
);
});
},
resize: function(event, ui) {
update.each(function(event){
var top = $(this).position().top + $(this).height() + 20;
$(this).css("top", top )
});
}
})
}
And here is an example: JSFiddle
As you can see, all the divs are found just right and I can update the top position. But for some reason it's getting crazy when resizing! It seems like I'm doing the update as many times as found tiles on each selected div.
finally I solved this problem. JSFiddle
this is the js code:
function CacheType(){
corrtop = 0;
rel = 0;
}
$.extend({
updatePositions: function() {
var update = 0;
var arr = new Array();
$(".element").resizable({
handles: 's',
start: function(event, ui) {
event.stopPropagation();
var el = $(this);
var el_row = parseInt(el.attr("row"));
var el_rel = parseInt(el.attr("rel"));
var el_col = parseInt(el.attr("col"));
var ex = el.position().top;
var ey = el.height();
update = $(".element").filter(function() {
if(
$(this).attr("row") > el_row &&
$(this).attr("col") == el_col &&
$(this).attr("rel") != el_rel
){
var tmp = new CacheType();
tmp.corrtop = $(this).position().top - ex - ey;
tmp.rel = $(this).attr('rel');
arr.push(tmp);
return true;
}else{
return false;
}
});
},
resize: function(event, ui) {
var x = $(this).height() + $(this).position().top;
update.each(function(event){
for(var i=0;i<arr.length; i++){
var tmp = arr[i];
var rel = $(this).attr('rel');
if(rel == tmp.rel)
$(this).css("top", x + tmp.corrtop);
}
});
}
})
}
});
$(document).ready(function(){
$.updatePositions();
});

Categories

Resources