How to make nested layouts with jquery-layout resizable? - jquery-ui

I'm trying to create a 4-pane layout using the jQuery-Layout plugin.
Really basic stuff:
The layout (note that I use iframes):
<iframe class="ui-layout-center">Outer Center</iframe>
<iframe class="ui-layout-east">Outer East</iframe>
<div class="ui-layout-west ">
<iframe class="ui-layout-south">Middle South</iframe>
<div class="ui-layout-center ">
<iframe class="ui-layout-center">Inner Center</iframe>
</div>
</div>
The initialization:
$(document).ready(function () {
$('body').layout({
west__childOptions: {
center__childOptions: {
}
}
});
});
Here's a fiddle.
Updated, simpler fiddle.
All is well until I try to resize the panes. It kinda works, but is very rough. When dragging the pane resizer handles it looks like they lose contact with the mouse pointer and stop resizing.
If the panes are simple divs, everything works, but not if the panes are iframes (which is what I need).
Any idea on how I could debug this?

I have found the answer here
Basically, you need to mask each panel (and its parents, in case of nested panels) that contains an iframe.
Like this:
$('body').layout({
center__maskContents: true,
west__maskContents: true
});
Here's the working demo of the fiddle from the question: click

Related

jquery ui draggable element appears behind other elements?

I am using jquery ui draggable, and eventually droppable to make it possible to reorder pictures into different boxes.
When I drag a picture out of the box it appears under all the other elements once it leaves its direct container.
While googling I was able to found to add:
helper: 'clone',
appendTo: "body"
This makes it so what is being dragged appears on top of all elements, but it leaves the original copy still in the box and I do not want that.
Is there a way I can make the element stay on top of everything when being dragged? I have tried a high z-index to no avail.
Here is a jsfiddle that shows the first draggle element behind behind the second. it is not an issue the other way around.
i am not able to change the position relative on the containing divs without breaking a lot of other things.
http://jsfiddle.net/cBWhX/6/
I found a few issues with your code, I think I've worked them out and got it working.
Working Example
First fix your HTML:
<div id="container1" style="background-color:red;padding:20px">
<div class="draggableContainer">
<div class="draggable" style="background-color:blue;width:200px;height:200px;"></div>
</div>
<div class="draggableContainer">
<div class="draggable" style="background-color:yellow;width:200px;height:200px;"></div>
</div>
<div class="draggableContainer"></div>
</div>
Next You'll probably want to use the stack option:
$('.draggable').draggable({
revert: "invalid",
snap: ".draggableContainer",
stack: ".draggable"
});
$('.draggableContainer').droppable()
From the API documentation:
Stack
Controls the z-index of the set of elements that match the selector, always brings the currently dragged item to the front.
Though there is an option - 'stack' existing while initiating draggables, but it is not working properly, So I have wrote a small library dragToFront playing with z-index. Following is the plunkr link
https://embed.plnkr.co/mJqkxSJhf1Umg7r2oLQN/
Stack wasn't working for me either. I was able to correct the z-index issue by using the appendTo property.
function setupDraggableFields($elements) {
$elements.draggable({
helper: "clone",
handle: ".field-sort-handle",
appendTo: ".section-container"
});
}

How can I change or turn off jQuery UI accordion's fixed-height inline style?

I have a <p> in a jQuery UI accordion that appears:
<p class="ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom ui-accordion-content-active" style="height: 184px " role="tabpanel">
Earlier, when I had several text links in there, it fit perfectly. However, now I have image links, and the images are sharply clipped.
I can duct tape the matter by adding additional <br /> tabs to get more space, but I'd like the accordion panel to include all images, one above the other, and correctly sized.
In If I understand your question correctly you need to tell the accordion to base its height off the content.
$(function() {
$( "#accordion" ).accordion({
heightStyle: "content"
});
});
This is stated and shown on the jQuery UI site here: http://jqueryui.com/accordion/#no-auto-height
Hopefully this is what you are looking for.
I had the same problem with the jQuery Accordion, and I just found the fix!
Simply add this CSS code at the top of your page. It will override the auto crop happening on the thumbnails:
.ui-accordion-content {
min-height:auto !important;
}

jQuery mobile add animation to collapsible-set

I would like to add an animation to collapsible set with jQuery Mobile.
Let me show a simple example of this:
<div id="tiles" data-role="collapsible-set" data-iconpos="right">
<div class="tile" data-role="collapsible" data-iconpos="right">blablabla</div>
<div class="tile" data-role="collapsible" data-iconpos="right">blablabla</div>
<div class="tile" data-role="collapsible" data-iconpos="right">blablabla</div>
</div>
jQuery Mobile handles this perfectly and shows me collapsible set of 3 items. What I want is ANIMATION, however I seem not to find anything in the docs.
I haven't tested yet how simple CSS animation(animating height property) would work, however is there a jQuery Mobile way of doing it like turning some internal flag ?
EDIT
I have tested out a simple jQuery animate method and it actually works. Just in case anyone else needs this. It runs smoothly even on my 528MHz Android phone on a default browser. A snippet I have added is really simple:
$( ".ui-collapsible-heading" ).live( "click", function(event, ui) {
$(this).next().css('height', '0').animate({
height: '100px'
});
});
Here ya go:
$('[data-role="collapsible"]').bind('expand collapse', function (event) {
$(this).find('p').slideToggle(500);
return false;
});​
I liked the idea you were going for so I played around with it a bit. This hooks into the way jQuery Mobile controls collapsible widgets so it's a bit less hacky then binding to the heading element.
The return false; stops the default behavior and the other line toggles the content in/out of view using the jQuery slideUp/slideDown animations. You could also use .fadeToggle() or roll your own animations. If you check event.type you can animate based on the event fired.
Here is a demo: http://jsfiddle.net/VtVFB/
Please note that in jQuery Mobile 1.4 and up you need to bind to the collapsibleexpand and collapsiblecollapse events instead of expand and collapse. So the complete code becomes
$('[data-role="collapsible"]').on('collapsibleexpand collapsiblecollapse', function(event) {
$(this).find('p').slideToggle(500);
return false;
});
​The code is not entirely right.
It overrides the default jquery mobile implementation of the expand collapse events,
but does not handle the change of the expand collapse icons.
A better code will be:
$('[data-role="collapsible"] h3:first').bind('click', function (event) {
$(this).next('p').slideToggle(500);
return false;
});​
The accepted answer doesnt account for that it doesnt change the collapsible cursor because of return false, so this is my answer working:
In my Project it was the contents relative to the [date-role="collapsible"] are $(this).find('>*:not(h3)')
/* animate collapsible-set */
$('[data-role="collapsible"]').on('expand', function (event) {
$(this).find('>*:not(h3)').each(function() {
if (!$(this).is(':visible')) {
$(this).stop().slideToggle();
}
});
}).on('collapse', function (event) {
$(this).find('>*:not(h3)').each(function() {
if ($(this).is(':visible')) {
$(this).stop().slideToggle();
}
});
});

jquery UI draggable resizable with containment does not work in ie9?

The code works on Chrome and I am trying to get the code to work on ie9. It works properly with the draggable() without containment but messes up the behavior badly when containment is set to parent:
img = $("<img alt='Preview' id='preimg' src='" + data.result.url +"' />")
$('#preimage').append(img);
$('#preimage').resizable({
'aspectRatio':true,
'handles':"all",
'autoHide':true,
containment: "parent"
}).draggable({
containment: "parent"
});
The parent position is set to relative. I am using jquery 1.7.2 and jquery-ui 1.8.20
Is there any workaround?
EDIT
After much testing - I have found that the container size calculation for the div is not working correctly, I was able to get it to work with the resizable enabled but without actually resizing the div. As soon as I resize the draggable containment area reduces in size, resizing multiple times leads to this area becoming smaller until the drag option stops working.
I found that there are several bug reports with the jquery ui library about these issues - http://bugs.jqueryui.com/report/10?P=resizable
I was able to find a work around that I tested extensively and which should work in most situations. The key here is that you need to use a container div that is not floated and has position relative. If you need to use a floated/absolute div just create a div inside it and set the position to relative. For the code in the question the html looks like:
<div class="outer">
<div class="container">
<div id="preimage"></div>
</div>
</div>
and the css would be:
.outer{
position:absolute;
right:0;
}
.container{
position: relative;
}
Since you can't drag an element when you resize and vice-versa, a safer way(to avoid some of the issues) of using the javascript would be:
$('#sqoutline2').resizable({
'handles':"all",
'autoHide':false,
containment: "parent",
start:function(){$('#sqoutline2').draggable('options','disabled','true');},
stop:function(){$('#sqoutline2').draggable('options','disabled','false');}
}).draggable({containment:"parent",
start:function(){$('#sqoutline2').resizable('options','disabled','true');},
stop:function(){$('#sqoutline2').resizable('options','disabled','false');}
});

jQuery Draggable Handler inside IFrame

What a mouthful.
Basically I have a parent <div> and inside that an <iframe>. I need an element inside the iframe to be the handle to drag the parent div. Is this even possible?
I have tried:
$(node).draggable("option","handle",$('iframe',node).contents().find('#handle'));
$(node).draggable("option","handle",$('iframe',node).contents().find('#handle')[0]);
It is targeting the right DOM element but it just won't drag. It might be possible to overlay a hidden div ontop of the iframe but I have found the iframe takes the event over the div when position is absolute. Strange.
try this
$('#Div').draggable({ iframeFix: true });
this should work
I decided to take a stab at this and boy, it's a lot of work with little progress using an internal iframe node as a handle. Anyway, here are two solutions, the first one doesn't work really well, but if you can get it to work, it may be more desirable.
main.html (plagiarized from the demo)
<div id="draggable" class="ui-widget-content" style="position:relative;">
<p class="ui-widget-header">I can be dragged only by this handle</p>
<iframe name="iframe1" src="inner-handle.html" height=50 width=80></iframe>
</div>
inner-handle.html
<html>
<head>
<script type="text/javascript" src="../../jquery-1.4.2.js"></script>
</head>
<body>
<div id="innerHandle">handle</div>
</body>
</html>
JavaScript
$(function () {
var moveEvent;
$(document).mousemove(function (e) {
moveEvent = e;
});
$("#draggable").draggable();
$('iframe', '#draggable').load(function () {
$('iframe', '#draggable')[0].contentWindow.$('#innerHandle').mousedown(function (e) {
$('#draggable').draggable().data('draggable')._mouseDown(moveEvent);
return false;
});
});
});
It took me a while to find something that "worked." The problem here was that since the mousedown event occurred on an element inside the iframe, the mouse event is relative to the iframe, not the main document. The workaround is to have a move event on the document and grab the mouse position from there. The problem, once again, is that if the mouse is inside of the iframe, it is "not" moving according to the parent document. This means that the drag event only happens when the mouse reaches the edge of the iframe into the parent document.
A workaround for this might be to manually generate events with the calculated position of the iframe relative to its mouse movement. So when your mouse moves within the iframe, calculate its movement using the coordinate of the iframe to the parent document. This means that you need to use the event from the mousedown and not the mousemove,
$('iframe', '#draggable')[0].contentWindow.$('#innerHandle').mousedown(function (e) {
// do something with e
$('#draggable').draggable().data('draggable')._mouseDown(e);
return false;
});
The second solution is the way you have mentioned, have an absolute positioned div over the iframe itself. I have no trouble in getting the div to be on top of the iframe, that is,
<div id="draggable" class="ui-widget-content" style="position:relative;">
<p class="ui-widget-header">I can be dragged only by this handle</p>
<iframe name="iframe1" src="inner-handle.html" height=50 width=80></iframe>
<div style="position: absolute; height: 30px; width: 30px; background-color: black; z-index: 1000;"></div>
</div>
The problem with your div being behind the iframe might be because the z-index is off. If you declare your div before the iframe and you didn't specify the z-index, then the iframe will be on top.
Whichever way you choose, good luck!
what happens when you do this (with firebug activated):
var frameContent = $('iframe',node).contents()
var handle = frameContent.find('#handle');
console.debug(frameContent, handle)
Does handle contain a list of elements? And if so, look carefully at the Document object which is frameContent - is the URL "about:blank"? It's just a hunch, but if you get these outputs, it's probably executing the jQuery selector before the frame content has loaded (i.e., before the #handle element exists).
In which case, you can add an event to the IFRAME'd document, and communicate with the parent frame via window.parent.

Resources