JQuery Resizable - Update element absolute position while resizing - javascript

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();
});

Related

jQuery - Multiple expanding galleries in tabs

I'm trying to get this code "Reveal gallery by Roko C. Buljan" - http://jsbin.com/zariku/9/edit?html,css,js,output - to work in multiple tabs here:
http://codepen.io/anon/pen/QjyMwg
JS:
var $prvw = $('#preview'),
$gall = $('.gooGallery'),
$li = $gall.find("li"),
$img = $prvw.find("img"),
$alt1 = $prvw.find("h2"),
$alt2 = $prvw.find("p"),
$full = $("<li />", {"class":"full", html:$prvw});
$li.attr("data-src", function(i, v){
$(this).css({backgroundImage: "url("+v+")"});
}).on("click", function( evt ){
var $el = $(this),
d = $el.data(),
$clone = $full.clone();
$el.toggleClass("active").siblings().removeClass("active");
$prvw.hide();
$full.after($clone);
$clone.find(">div").slideUp(function(){
$clone.remove();
});
if(!$el.hasClass("active")) return;
$img.attr("src", d.src);
$alt1.text(d.alt);
$alt2.text(d.title);
$li.filter(function(i, el){
return el.getBoundingClientRect().top < evt.clientY;
}).last().after($full);
$prvw.slideDown();
});
$(window).on("resize", function(){
$full.remove();
$li.removeClass("active");
});
2nd tab is working fine, but, when I'll try to open the first one the div isn't shown on the right position.
Can anyone please help me with a hint?
You're trying to use the same preview div for both gallerys. Try having 2 previews. Quickest way I could think would be do to something like this (be warned, this is kinda ugly):
var i = 1;
$('.gooGallery').each(function() {
var $gall = $(this);
var $prvw = $('#preview' + i); i = i+1;
var $li = $gall.find("li")
var $img = $prvw.find("img")
var $alt1 = $prvw.find("h2")
var $alt2 = $prvw.find("p")
var $full = $("<li />", {
"class" : "full",
html : $prvw
});
$li.attr("data-src", function (i, v) {
$(this).css({
backgroundImage : "url(" + v + ")"
});
}).on("click", function (evt) {
var $el = $(this),
d = $el.data(),
$clone = $full.clone(true);
$el.toggleClass("active").siblings().removeClass("active");
$prvw.hide();
$full.after($clone);
$clone.find(">div").slideUp(function () {
$clone.remove();
});
if (!$el.hasClass("active"))
return;
$img.attr("src", d.src);
$alt1.text(d.alt);
$alt2.text(d.title);
$li.filter(function (i, el) {
return el.getBoundingClientRect().top < evt.clientY;
}).last().after($full);
$prvw.slideDown();
});
$(window).on("resize", function () {
$full.remove();
$li.removeClass("active");
});
});
And then modify the preview div
<div id="preview1" class='preview'>
<img src="//placehold.it/300x180/369">
<div><h2></h2><p></p></div>
</div>
<div id="preview2" class='preview'>
<img src="//placehold.it/300x180/369">
<div><h2></h2><p></p></div>
</div>
Thought it looked weird so threw in the necessary css changes:
.preview{
display:none;
}
.preview > *{
float:left;
margin:3%;
}
.preview img{
max-width:100%;
}

Auto Resize Multiline Editable Text Field in Jquery

I'm looking auto-resize the font for each new line of equal width for a multi-line editable text field. Please check the url below:
http://api.pstr.co/html/template/003_script
Right now the font-size is like that
and I want to be like that:
The jquery code for this plugin is this:
function getBaseFontSize(){
var baseFontSize = Math.round(0.15*Math.min($(window).width(), $(window).height()));
return baseFontSize;
}
function editModeSetup(){
var contentBlock = $(".content");
var container = $(".block");
var scalableText = $(".scalable");
$('[contenteditable]').each(function (index) {
var $this = $(this);
$this
.on("keydown", function(){
clearTimeout($this.timeout);
fitTextMultiline(scalableText,contentBlock,container);
//if (!$this.hasClass("edited")) $(this).addClass("edited");
}).on("focus", function () {
//if (!$this.hasClass("edited")){
$this.selectText();
//}
// Work around Chrome's little problem
$this.mouseup(function() {
// Prevent further mouseup intervention
$this.unbind("mouseup");
return false;
});
}).on("keyup", function () {
$this.timeout = setTimeout(function(){ fitTextMultiline(scalableText,contentBlock,container); }, 400);
});
//$(".content").css("font-size", getBaseFontSize());
$("html").css("font-size", getBaseFontSize());
});
fitTextMultiline(scalableText,contentBlock,container);
$(window).resize(function() {
fitTextMultiline(scalableText,contentBlock,container);
});
var myWidth = window.innerWidth;
var myHeight = window.innerHeight;
ga('send',
'event',
'Viewport',
'Size',
myWidth+'x'+myHeight,
{'nonInteraction': 1});
}
function fitTextMultiline(scalableText, contentBlock, container) {
// startvwith small type and push the size up? to make sure more fits on one line...
var maxHeight = container.height();
var maxWidth = container.width();
//console.log(".\n")
//console.log(scalableText.text())
var fontSize = 7*getBaseFontSize(); // 20;
var fontUnits = "px"; // "vmin";
do {
scalableText.css('font-size', fontSize+fontUnits);
contentHeight = contentBlock.height();
contentWidth = contentBlock.width();
//console.log("--- " + fontSize +" ---")
//console.log(contentHeight + " ? " + maxHeight)
//console.log(contentWidth + " ? " + maxWidth)
fontSize = Math.round(fontSize - fontSize*0.1);
} while ((contentHeight > maxHeight || contentWidth > maxWidth ) && fontSize > 10);
//+ fontSize/2
alignPrices();
doubleLineAssignClasses();
return this;
}
// code that returns text from edit mode
function getPosterText() {
/*
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-61477423-5', 'auto');
ga('send', 'pageview');
*/
ga('send', 'event', 'Button', 'Save', document.title);
var list = $('[contenteditable]').map(function () {
//console.log($(this).text());
//console.log($(this).val());
//console.log(_jsonEscape($(this).val()));
//return $(this).text();
return $(this).html();
}).toArray();
return _jsonEscape(JSON.stringify(list));
}
// code that sets text in edit mode
function setPosterText(text) {
/*
var list;
console.log(text)
try {
list = JSON.parse(text)
}
catch (e) {
console.log('Cannot parse given texts json.');
list = [];
}
*/
//if (list.length > 0)
/*
$('[contenteditable]').each(function (index) {
//$(this).text(list[index] || "");
$(this).addClass("userText")
});
*/
//var contentBlock = $(".content");
//var container = $(".block");
//var scalableText = $(".scalable");
//fitTextMultiline(scalableText,contentBlock,container);
}
function _jsonEscape(str) {
//str = str.replace(/&/g,"&").replace(/£/g,"£");
//str.replace(/£/g,"£");
return str.replace(/\\n/g, "\\\\n").replace(/\\r/g, "\\\\r").replace(/\\t/g, "\\\\t");
}
function editableListFix(){
$('ul').on('keyup keydown', function() {
var $this = $(this);
if (! $this.html()) {
var $li = $('<li></li>');
var sel = window.getSelection();
var range = sel.getRangeAt(0);
range.collapse(false);
range.insertNode($li.get(0));
range = range.cloneRange();
range.selectNodeContents($li.get(0));
range.collapse(false);
sel.removeAllRanges();
sel.addRange(range);
} else {
//are there any tags that AREN'T LIs?
//this should only occur on a paste
var $nonLI = $this.find(':not(li, br)');
if ($nonLI.length) {
$this.contents().replaceWith(function() {
//we create a fake div, add the text, then get the html in order to strip out html code. we then clean up a bit by replacing nbsp's with real spaces
return '<li>' + $('<div />').text($(this).text()).html().replace(/ /g, ' ') + '</li>';
});
//we could make this better by putting the caret at the end of the last LI, or something similar
}
}
});
}
function alignPricesFix(){
alignPrices()
$('[contenteditable]').each(function (index) {
var $this = $(this);
$this
.on("keyup keydown", function(){
alignPrices();
});
});
}
function alignPrices(){
var positions = [];
var heights = [];
$( ".items>li" ).each(function( index ) {
positions.push( $( this ).position().top );
heights.push( $( this ).height() );
});
$( ".prices>li" ).each(function( index ) {
//$( this ).css("top", positions[index]);
$( this ).css("height", heights[index]);
});
ulPrices = $( "ul.prices" );
if (ulPrices) ulPrices.css("height", $( "ul.items" ).height());
}
function doubleLineAssignClasses(){
$( ".double-line>li" ).each(function( index ) {
$( this ).removeClass('item-header');
$( this ).removeClass('item-description');
//if (!$( this ).hasClass('item-header') && !$( this ).hasClass('item-description') ){
if (index % 2 != 1) $( this ).addClass('item-header')
else $( this ).addClass('item-description') ;
//console.log(index);
});
}
check this website for the jQuery/javascript solution https://css-tricks.com/forums/topic/is-it-possible-to-adapt-font-size-to-div-width/
I quote it here also:
"Hey, this isn’t going to be achievable with CSS alone, but you could certainly do this using jquery/javascript. For example you could enclose each word in a span, measure the width of that span, divide the width of the parent div by the span width, then multiply the font-size of the span text by that number.
i.e: (div width/span width) * span font-size"

jquery calculate height and width and animate content behind it

animate content behind h1
if h1 is top of the image don't animate
Currently works fine but I need to calculate the width of the h1 tag as well in order to animate the image just outside the h1.
Basically if the image sits outside the width of the h1 should show.
I hope this is enough clear.
Demo.
js:
// Get the divs that should change
function displayThese() {
var $heading = $('h1');
var h1top = $heading.position().top;
var h1bottom = h1top + $heading.height();
var divs = $('li').filter(function () {
var $e = $(this);
var top = $e.position().top;
var bottom = top + $e.height();
return top > h1bottom || bottom < h1top;
});
return divs;
}
(function fadeInDiv() {
var divs = displayThese();
var elem = divs.eq(Math.floor(Math.random() * divs.length));
if (!elem.is(':visible')) {
elem.prev().remove();
elem.animate({
opacity: 1
}, Math.floor(Math.random() * 1000), fadeInDiv);
} else {
elem.animate({
opacity: (Math.random() * 1)
}, Math.floor(Math.random() * 1000), function () {
window.setTimeout(fadeInDiv);
});
}
})();
$(window).resize(function () {
// Get items that do not change
var divs = $('li').not(displayThese());
divs.css({
opacity: .3
});
});
You just have to use $.fn.width :
var $heading = $('h1');
var h1top = $heading.position().top;
var h1bottom = h1top + $heading.height();
var h1left = $heading.position().left;
var h1right = h1top + $heading.width();
var divs = $('li').filter(function () {
var $e = $(this);
var top = $e.position().top;
var bottom = top + $e.height();
var left = $e.position().left;
var right = left + $e.width();
return top > h1bottom || bottom < h1top || left > h1right || right < h1left;
});
return divs;
Here is a fiddle : http://jsfiddle.net/33Ec8/3/
Is this what you are looking for:
$(<element>).width()
$(<element>).height()
Demo here.

Something is wrong with this 3-panes splitter

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)

get interval ID from else statement when set in IF

I am attempting to create a responsive slider, that will change to a simple set of dot points when in mobile mode (< 940).
The issue I am facing is in my else statement I am unable to clearintervals that were made in the if statement, because t comes up as undefined. I have resorted to using
for (var i = 1; i < 99999; i++) window.clearInterval(i); to clear the interval which works, but I don't like it because it's ugly and cumbersome, is there another way of accomplishing this?
$(document).ready(function() {
function rePosition() {
//get responsive width
var container_width = $('.container').width();
//Slider for desktops only
if(container_width >= 940) {
//get variables
var slide_width = $('.slider_container').width();
var number_of_slides = $('.slider_container .slide').length;
var slider_width = slide_width*number_of_slides;
//set element dimensions
$('.slide').width(slide_width);
$('.slider').width(slider_width);
var n = 1;
var t = 0;
$('.slider_container').hover(function() {
clearInterval(t);
}, function() {
t = setInterval(sliderLoop,6000);
});
var marginSize = i = 1;
//Called in Doc Load
function sliderLoop(trans_speed) {
if (trans_speed) {
var trans_speed = trans_speed;
}
else
{
var trans_speed = 3000;
}
if (i < number_of_slides) {
marginSize = -(slide_width * i++);
}
else
{
marginSize = i = 1;
}
$('.slider').animate({ marginLeft: marginSize }, trans_speed);
}
t = setInterval(sliderLoop,6000);
$('.items li').hover(function() {
$('.slider').stop();
clearInterval(t);
var item_numb = $(this).index();
i = item_numb;
sliderLoop(500);
}, function() {
t = setInterval(sliderLoop,6000);
});
}
else
{
for (var i = 1; i < 99999; i++)
window.clearInterval(i);
$('.slider').stop(true, true);
$('.slider').css('margin-left', '0px');
//rearrange content
if($('.slider .slide .slide_title').length < 1) {
$('.items ul li').each(function() {
var item_numb = $(this).index();
var content = $(this).text();
$('.slider .slide:eq(' + item_numb + ')').prepend('<div class="title slide_title">' + content + '</div>')
});
}
}
}
rePosition();
$(window).resize(function() {
rePosition();
});
});
Teemu's comment is correct. I'll expand on it. Make an array available to all of the relevant code (just remember that globals are bad).
$(document).ready(function() {
var myIntervalArray = [];
Now, whenever you create an interval you will need to reference later, do this:
var t = setInterval();//etc
myIntervalArray.push(t); //or just put the interval directly in.
Then to clear them, just loop the array and clear each interval.
for (var i=0; i<myIntervalArray.length; i++)
clearInterval(myIntervalArray[i]);
}
Umm, wouldn't t only be defined when the if part ran... as far as I can tell, this is going to run and be done... the scope will be destroyed. If you need to maintain the scope across calls, you'll need to move your var statements outside of reposition(), like so:
$(document).ready(function() {
var t = 0;
...
function rePosition() { ... }
});

Categories

Resources