jquery ui sortable - clicking scrollbar breaks it - jquery-ui

Scrolling a div that is within a .sortable() container will start dragging the div when you release the scrollbar
In the fiddle, there are 3 different sortables, 1 of them is a scrolling one
http://jsfiddle.net/wnHWH/1/
Bug: click on the scrollbar and drag it up or down to scroll through the content, when you release the mouse, the div starts to drag, which makes it follow your mouse around and there is no way to unstick it without refreshing the page.

You can use .mousemove event of jquery like this:
$('#sortable div').mousemove(function(e) {
width = $(this).width();
limit = width - 20;
if(e.offsetX < width && e.offsetX > limit)
$('#sortable').sortable("disable");
else
$('#sortable').sortable("enable");
});
I have create fiddle that works here http://jsfiddle.net/aanred/FNzEF/. Hope it meets your need.

sortable() can specify a selector for a handle much like draggable() does. Then only the matched elements get the click events. You specify the handle selector like this:
$('#sortable').sortable( {handle : '.handle'});
You already have most of what you need for the rest. The inner div on your overflowing element makes a suitable handle, like this:
<div style="height: 200px;overflow:auto">
<div class="handle" style="height: 300;">
blah
blah
blah
Then you need to restore the sortability of everything else. You'd think you could just give those divs the handle class, but it's looking for children, so you need to wrap all of them like so:
<div><div class="handle">asadf</div></div>
Modified fiddle

Supplement to SubRed's answer:
This worked perfectly for my needs. However, rather than rely on the width of the scrollbar being 20 pixels (as above), I used the code from:
How can I get the browser's scrollbar sizes?
This allows the code to handle different scrollbar widths on different setups. The code is pasted here for convenience:
function getScrollBarWidth ()
{
var inner = document.createElement('p');
inner.style.width = "100%";
inner.style.height = "200px";
var outer = document.createElement('div');
outer.style.position = "absolute";
outer.style.top = "0px";
outer.style.left = "0px";
outer.style.visibility = "hidden";
outer.style.width = "200px";
outer.style.height = "150px";
outer.style.overflow = "hidden";
outer.appendChild (inner);
document.body.appendChild (outer);
var w1 = inner.offsetWidth;
outer.style.overflow = 'scroll';
var w2 = inner.offsetWidth;
if (w1 == w2) w2 = outer.clientWidth;
document.body.removeChild (outer);
return (w1 - w2);
}
I've also used the width value for the height of the scrollbar and modified SubRed's code to suit. This now works with one or both scrollbars.
I also used code from:
Detecting presence of a scroll bar in a DIV using jQuery?
To determine the presence of either scroll bar and adapted the turning on/off of the sortable code accordingly.
Many thanks.

Related

Scroll To Top button that only appears when you reached the end of the page

I think this is rather easy achieved, but I couldn't find out how to- and couldn't find much documentary about it.
I hate those 'scroll to top' buttons that appear after you already scrolled just 300px. Like I'm that lazy to scroll to top on myself. Therefor I would like to have a scroll to top button that only appears when you reached the bottom of the page (minus 100vh (100% viewport height).
Let's take in account the button is called .scrollTopButton and it's CSS is opacity: 0 and it's position: fixed on default.
How would I make the button appear when you reached the bottom of the page, minus 100vh and scroll along?
I was thinking of comparing the body height minus 100vh with (window).scrollTop().
var vH = $(window).height(),
bodyMinus100vh = ($('body').height() - vH);
if (bodyMinus100VH < $(window).scrollTop) {
$('.scrollTopButton').toggle();
};
Fixed it myself. Quite easy, honestly.
$(window).scroll(function () {
var vH = $(window).height(),
bodyHeight = ($(document).height() - (vH * 2)),
// When you open a page, you already see the website as big
// as your own screen (viewport). Therefor you need to reduce
// the page by two times the viewport
scrolledPX = $(window).scrollTop();
if (scrolledPX > bodyHeight) {
$('.scrollTopButton').css('opacity', '1');
} else {
$('.scrollTopButton').css('opacity', '0')
};
});

Reveal.js with highcharts

I'm using reveal.js (http://lab.hakim.se/reveal-js/) together with Highcharts JS but i have problems with tooltips position. For example, if i use a line with the months on the x axis, when i put the mouse over the point in january the tooltip its ok, but when i put the mouse over december the tooltip shows me the october data. The tooltip for each month is displaced more and more.
You can see http://lideria.net/presentacion/index1.php to see the problem
This may be problem with Highcharts which us already reported here. Also there is suggested workaround: http://jsfiddle.net/highcharts/BD3R7/
reveal.js autoscales the viewport with a css zoom tag. If you inspect class="slides" div, you'll see something like this:
<div class="slides" style="width: 960px; height: 700px; zoom: 0.8331428571428572;">
Here the content (the chart) is scaled 80% of normal size and Highcharts loses it's ability to calculate positions properly if the chart is scaled outside of its control.
With that knowledge, a quick stack overflow search talks about the ability to force 'reveal.js` to not auto-scale content.
You must overwrite the normalize of the H.Pointer.prototype (referenced WRAPPING UP A PLUGIN). Add the following code to document.ready function (maybe somewhere else works, I guess). The reasons are:
reveal.js has separate ways when zoom>1 and zoom<1, e.g., zoom:1.25 and transform:scale(0.75).
So, when a section has several charts and zoom>1, must adjust e.chartX by e.pageX.
(function (H) {
H.wrap(H.Pointer.prototype, 'normalize', function (proceed, e) {
var e = proceed.call(this,e);
var zoom = Reveal.getScale();
if(zoom>1) {
var positionX = e.pageX - e.chartX;
var positionY = e.pageY - e.chartY;
e.chartX = Math.round((e.pageX - positionX*zoom)/zoom);
e.chartY = Math.round((e.pageY - positionY*zoom)/zoom);
} else {
e.chartX = Math.round(e.chartX/zoom);
e.chartY = Math.round(e.chartY/zoom);
}
return e;
});
}(Highcharts));

Bootstrap jQuery UI positioned to float to the top

I've installed Datepicker for Bootstrap and its working nicely. But I can't figure out how to use the place method to position the datepicker above the element instead of below. I'm guessing it works similiar to the bootstrap popovers, but I haven't been able to figure it out.
Any suggestions?
The place function just auto places the date picker under your input box. Its not a function that lets you select where you want to place it.
However you can easily override the default functionality of that function with your own custom placement.
Here is an example of that http://jsfiddle.net/G7sWL/19/
All i did copy the original function and add an additional vertical offset of 10 and horizontal offset of 50.
$(function() {
var picker = $('.datepicker').datepicker();
var widget = picker.data('datepicker');
widget.place = function(){ //the original place function
var offset = this.component ? this.component.offset() : this.element.offset();
this.picker.css({
top: offset.top + this.height + 10, // change #1 = added "+10"
left: offset.left +50 // change #2 = added "+50"
});
}
});
From the page:
.datepicker('place')
Updates the date picker's position relative to the element
It only says it updates the position of the picker (which is absolutely positioned on the page), not that you can change its placement.

Preventing flexcroll on event

What I have currently is a very simple div that has a flexcroll scroll bar. This simple div contains some draggable itmes inside of it. My goal is to be able to drag one of the items and and move it about without the flexcroll scroll bar moving.
As it stands right now if I were to drag one of the items below the viewable area the simple div will scroll down. I would like to prevent this.
I'm using jQuery UI for the draggable items. I've already tried using the option "scroll:false" but this does not work for flexcroll.
I'm sorry I don't have any example code, I'm currently away from my work computer.
flexcroll: http://www.hesido.com/web.php?page=customscrollbar
I don't know if you have already resolved this problem. This morning, I have the same problem and I found your post. After that, I have googled a lot to find a solution without any lucky. So finally, I decided to do someting myself, I hope my idea will help you.
After read the Programming Guid, I found that in this version (2.0) of flexcroll, we could register a function for onfleXcroll whose description could be found by searching the keyword "Pseudo-event: onfleXcroll". This is to say that the method will be executed after a scroll is done. So here, what I restore the "top" style with the value before you drag an element.
Here are the code
var $assetswrapper; // This variable indicates the contentwrapper of you div.
var $assetsscrollbar; // This variable indicates the vscroller of you div.
window.onfleXcrollRun = function () { // This method will be executed as soon as the div has been rendered with the help of flexcroll
// You could find these two divs by using firebug, because the top value of these two divs will be changed when we scroll the div which use the class .flexcroll.
$assetswrapper = $('#contentwrapper');
$assetsscrollbar = $('#vscrollerbar');
}
var wrapperTopPosition = 0; // This is used to stock the top value of the wrapperContent before dragging.
var scrollbarTopPosition = 0; // This is used to stock the top value of the scrollbar before dragging.
var dragged; // This is a boolean variable which is used for indicating whether the draggable element has been dragged.
var dropped = false; // This is a boolean variable which used to say whether the draggable element has been dropped.
$('.draggable').draggable({ // you could change .draggable with any element.
start: function (event, ui) {
// Your code here.
wrapperTopPosition = $assetswrapper.position().top;
scrollbarTopPosition = $assetsscrollbar.position().top
dragged = true;
},
stop: function (event, ui) {
// Your code here.
dragged = false;
dropped = true;
}
});
$('your drag div')[0].onfleXcroll = function () { // This method will be called each time when a scroll has been done.
if (dragged) {
$assetswrapper.css('top', wrapperTopPosition);
$assetsscrollbar.css('top', scrollbarTopPosition);
} else {
// Code here is used for keeping the top position as before even though you have dragged an element out of this div for a long time.
// You could test the scrollbar without this piece of code, if you drag an element out of the div for a long time, the scrollbar will keep its position,
// but after you dropped this element and try to scroll the div, then the scrollbar will reach the end of the div. To solve this problem,
// I have introduced the method setScrollPos with the old top position plus 72. 72 here is to set the scroll increment for this scroll, I know
// this value is not fit for any size of windows, but I don't know how to get the scroll-increment automatically.
if (dropped) {
dropped = false;
$('your drag div')[0].fleXcroll.setScrollPos(false, Math.abs(wrapperTopPosition) + 72);
$('your drag div')[0].fleXcroll.setScrollPos(false, Math.abs(wrapperTopPosition) + 72);
}
}
};
I hope this could give you a help if you haven't found any solution yet.

How do I adjust where the calendar appears for the datePicker in the Grails UI plugin without the position changing when the page is resized?

I wanted to change where the calendar appeared for the datePicker portion of the Grails UI plugin. After a bit of digging, I found it in the InputTagLib.groovy file:
out << """
YAHOO.util.Event.on("${showButtonId}", "click", function() {
var buttonRegion = YAHOO.util.Dom.getRegion('${showButtonId}');
var buttonHeight = buttonRegion.bottom - buttonRegion.top;
var buttonWidth = buttonRegion.right - buttonRegion.left;
var xy = YAHOO.util.Dom.getXY('${showButtonId}');
var newXY = [xy[0] + buttonWidth, xy[1] + buttonHeight];
YAHOO.util.Dom.setXY('${id}_calContainer_c', newXY);
GRAILSUI.${jsid}Panel.show();
if (YAHOO.env.ua.opera && document.documentElement) {
// Opera needs to force a repaint
document.documentElement.className += "";
}
});"""
The position is set on this line:
YAHOO.util.Dom.setXY('${id}_calContainer_c', newXY);
The YAHOO.util.Dom.setXY() method takes two arguments.
The first argument of the setXY method is either the ID of an HTMLElement, or an actual HTMLElement object. The second argument is an array containing two values: [x, y] where x is the distance from the left edge of the document, and y is the distance from the top edge of the document.
Source: http://developer.yahoo.com/yui/examples/dom/setxy.html
So I can easily adjust where the calendar appears by changing the values in the newXY variable that is passed to the setXY method and it works fine.
However, if I resize the page, the calendar positions its top left corner directly under the showButton's bottom left corner. What is it that makes the repositioning happen when the page is resized and how can I resolve it?
EDIT : A little more info:
This happens in the most recent versions of IE, Firefox, and Chrome
If I resize the page and then click the button to show the calendar, the calendar shows in the expected place but it will reposition if I resize the page again once the calendar is open

Resources