Jquery Fancybox draggable issue with Scrollbars - javascript

I am using a fancybox with plugin jquery.easydrag.js. The reason for this is to be able to drag the fancybox around.
It seems to be working fine, but the problem comes when the fancybox has scrollbars. I.e. for example when clicking on submit and not entering any fields the valdidation on screen causes scrollbars. Which is fine normally but the scrollbars causes all sorts of issues with the draggable feature so that when I am trying to click the scrollbar up and down, it actually moves the entire windows. So it seems to be confused as to what content can be moved and what to do with a scrollbar.
claimLink.fancybox({
'width': 500,
'height': 590,
'autoDimensions': false,
'onCleanup': function (e) {
var modelClaimFormId = $j(e).attr("href").replace("body", "");
var modalClaimForm = $j(modelClaimFormId);
if (!($j(modalClaimForm).valid())) {
$j(claimForm).remove();
$j(e).parents("tr").remove();
}
}
});
$j("#fancybox-wrap").easydrag(true);
EDIT :
I managed to add something for input and textareas to ignore the scrolling see below...just wondering what I can do for scrollbars.
$j("#fancybox-wrap").easydrag(true);
$j("#fancybox-wrap input,textarea").click(function(){
$j("#fancybox-wrap").dragOff();
});
$j("#fancybox-wrap input,textarea").mouseover(function () {
$j("#fancybox-wrap").dragOff();
});
$j("#fancybox-wrap input,textarea").blur(function () {
$j("#fancybox-wrap").dragOn();
});
$j("#fancybox-wrap input,textarea").mouseout(function () {
$j("#fancybox-wrap").dragOn();
});
This is the link to JS for easydrag plugin

I posted the first example about how to make fancybox draggable back in 2009 for v1.2.1. Then I posted some notes to make it work with v1.3.1 as seen here but when fancybox v1.3.4 was introduced, the easyDrag plugin was not working as smooth as with the previous versions and started behaving buggy. I didn't have the time to find a workaround ... so I just drop it.
The solution was simple though: the easyDrag plugin provides a way to set a "handler" as explained here so instead of holding and dragging the whole #fancybox-wrap container, which blocks access to the scroll bars if any, you just drag the lightbox from a specific defined element. Such handler can be appended to #fancybox-wrap selector and set it within the EasyDrag plugin using the onComplete callback API option like:
'onComplete': function(){
// append the handler on the top-left corner of fancybox
$("#fancybox-wrap").append("<button id='handler'>Drag me</button>");
// set the handler using the handler's element ID
$("#fancybox-wrap").setHandler('handler');
}
Notice that you can use any element as handler, in my example I used a html button but you may use an image if preferred. The important thing is to assign the minimum important css properties to the handler so it can be appended to the #fancybox-wrap container without issue like:
width: 80px; /* or whatever needed */
height: 24px;
position: absolute; /* important to position the handler into the fancybox wrap */
top: 0; /* top-left corner of the box but can be anywhere */
left: 0;
display: block;
z-index: 1120; /* important to be over the box */
other properties can be cosmetic.
See it working here!!!
Once you complete and submit the form, the response will be a new fancybox with scroll bars that you can use independently from the easyDrag handler.
Please feel free to analyze the code and customize it to your own needs (and don't forget to grant me the bounty ;)
UPDATE: Notice that since we are appending the handler to the #fancybox-wrap container every time we fire fancybox, then we need to remove it once we close fancybox using the onClosed callback, otherwise we will duplicate the handler if we open fancybox again with unexpected results:
'onClosed' : function() {
$("#fancybox-wrap #handler").remove();
}
I updated my DEMO too.
LAST NOTE: This solution is for fancybox v1.3.4.
I haven't tested it with v2.x but I don't see why it wouldn't work. Just make sure that you bind EasyDrag and append the handler to the .fancybox-wrap selector instead
$(".fancybox-wrap").easydrag();
You may use the afterShow callback to append the handler to it and afterClose to remove it.

Using the above solution to add a handler for the #fancybox-wrap selector along with the EasyDrag plugin using the onComplete callback API, I found this works nicely with the fancybox 1.3.4 title element to create a dragable fancybox with scroll functionality. Using the title, there is no need to remove it after close.
<script type="text/javascript" src="#Url.Content("~/fancybox/jquery.mousewheel-3.0.4.pack.js")"></script>
<script type="text/javascript" src="#Url.Content("~/fancybox/jquery.fancybox-1.3.4.pack.js")"></script>
<script src="#Url.Content("~/Scripts/jquery.easydrag.handler.beta2.js")" type="text/javascript"></script>
<script>
//Fancybox
$(document).ready(function () {
$("#iframeVideoPop").fancybox({
'width': 890,
'height': 595,
'type': 'iframe',
'autoScale': 'false',
'hideOnContentClick': false,
'onComplete': function() {
//Style the title where and how you want it
$("#fancybox-title").css({'top':'-20px', 'bottom':'auto'});
//Set the fancybox-title as the handler
$("#fancybox-wrap").setHandler('fancybox-title');
}
});
$("#fancybox-wrap").easydrag();
}); //ready
<script>

In order to eliminate the scrollbar problem caused by combining Easydrag with Fancybox, you'll need to eliminate the scrollbars. By default, the Fancybox CSS stylesheet applies the overflow:auto rule to the element -- generated by Fancybox -- that wraps around the content displayed inside the Fancybox.
To override it, include your own CSS rule that supersedes the one that Fancybox applies to the wrapper. Place this style block in the <head> section of your web page:
<style>
/* id of the element generated and used by Fancybox as a wrapper around
the generated content. */
#fancy_ajax {
/* Use the important identifier to ensure the overflow:auto is suppressed */
overflow:none !important;
}
</style>
This will eliminate the scrollbars and allow the easy drag plugin to work smoothly.

After testing these solutions I ran into the problem with dragging an iframe. To resolve, I switched to the jQuery 1.9.1 UI plugin for dragging and created a transparent image while dragging. Remove the image after dragging to access the content. Works great with fancybox iframe and enables fast dragging over the iframe. See sample code below.
$("#iframePop").fancybox({
'width': 890,
'height': 430,
'type': 'iframe',
'autoScale': 'false',
'hideOnContentClick': false,
'onComplete': function() {
$("#fancybox-title").css({'top':'-2px', 'left':'15px', 'bottom':'auto', 'cursor':'move'});
$("#fancybox-wrap" ).draggable({ handle: "fancybox-title", iframeFix: true,
start: function(ev,ui){$("#fancybox-wrap").append("<img src='#Url.Content("~/Content/Images/transparent.png")' id='hidenImg' style='border: 1px solid black; width: 640px; height: 400px; top: 20px; position: absolute; z-index: 10000;' />")},
drag: function(ev,ui){},
stop: function(ev, ui){$("#fancybox-wrap #hidenDiv").remove()}
});
}
});

Related

Using flickity to resize as tabs

So I have a project now that is basically defusing bugs and this one in particular is a very annoying case. Flickity is supposed to be "resizing" a specific elements within <div> and working as tabs in the bottom to scroll to the specific informational element. However, all the text is just mashing together.
.
I have figured out, though, when you resize the browser, it works correctly and puts everything in its place by showing one <div> at a time and using buttons at the bottom to switch between <div>.
Here is the flickity part of the jQuery:
modalPopup(e, function() {
if ($(".key .active").not("#resetFilters").length) {
$(".button-group").find($(".key .active").data("filter"));
}
else {
$('.button-group li:first-child').addClass('is-selected');
}
$('.button-group').on( 'click', 'li', function() {
var index = $(this).index();
$(this).addClass('is-selected').siblings('.is-selected').removeClass('is-selected');
gallery.flickity( 'select', index );
});
var gallery = $('.chapters').flickity({
// options
//imagesLoaded: true,
//percentPosition: false,
cellAlign: 'center',
contain: true,
prevNextButtons: false,
pageDots: false,
resize: true
});
});
Where modalPopup() is a function that loads in the information.
Any help or suggestions, are highly appreciated!
I have figured out the issue. The issue is that the width of the element I was using flickity on was at 0px width initially using CCS transitions. Flickity thought the width of the parent element was at 0px and therefore didn't expand out its width elements.
So if you use CSS transitions with flickity resize, make sure you have a width defined.

How to make infinite-scroll plugin works in a DIV?

There is a fixed-height div, which has scrollbar. When its only-child element ol being scrolled to the bottom, the ol needs to load more new li.
I'm using jQuery infinite-scroll plugin.
I can't get the plugin to work in the aforementioned situation on desktop browsers.
In iOS, it sorta works, and is buggy. When I scroll the ol to the bottom, it doesn't load. And then when I try to scroll the ol more (it actually can't be scrolled more), it successfully loads.
Here is a simple demonstration of my code.
Here is the demonstration code.
Taken from the infinite-scroll documentation:
To scroll inside an element having overflow, use the local behavior.
So rather than having a #container element that has the overflow, just use the infinite scroll on the list:
$('#container').infinitescroll({
behavior: 'local',
binder: $('#container'),
bufferPx: 0,
navSelector : '#nav', // selector for the paged navigation
nextSelector : '#nav a', // selector for the NEXT link (to page 2)
itemSelector : 'li' // selector for all items you'll retrieve
});
Having the ol as the #container:
<ol id="container">
Here's a working example and there's the relevant documentation.
EDIT
It seems that to use the local behaviour, you need to override a method responsible for determining if the scroll is near the bottom (although this doesn't seem to appear anywhere in the documentation). There is a file in the repository /behaviors/local.js that would need to be included to make this work, but I tried it and is doesn't seem to work properly. So instead you can use this code to take care of the those computations:
jQuery.extend(jQuery.infinitescroll.prototype, {
_nearbottom_local: function infscr_nearbottom_local()
{
var opts = this.options;
var binder = $(opts.binder);
return (binder.scrollTop() + binder.innerHeight() >= binder[0].scrollHeight - opts.bufferPx);
}
});

Can't get hidden image to display with .show()

I'm using the vimeo api to slide a video off the screen after it finishes playing. Underneath the video player, hidden, I have an image that says 'replay'. The image though is slightly bigger than the player so I want to hide the image via .hide() or display: none in the css and then show it after the animation of the video player completes.
Here's my js:
$(document).ready(function() {
$(".vimeo-container img").hide();
$('iframe.vimeo').each(function(){
Froogaloop(this).addEvent('ready', ready);
});
function ready(playerID){
Froogaloop(playerID).addEvent('finish', onFinish);
}
function onFinish(playerID) {
var player = "#" + playerID;
$(player).animate({width: "0%"}, 750, function() {
$(player).next("img").show();
});
}
});
So the first line is hiding the image. And then when the onFinish function completes I'm trying to show() the image, but it won't work. I should note that when I reverse it and do:
$(player).next("img").hide();
it works.
Here's my HTML:
%section#container1
.row.video-left
.large-8.columns
.vimeo-container
.flex-video.widescreen.vimeo
%iframe.vimeo#player1{allowfullscreen: "", frameborder: "0", height: "225", mozallowfullscreen: "", src: "http://player.vimeo.com/video/60122989?api=1&player_id=player1", webkitallowfullscreen: "", width: "400"}
= image_tag "behind1.png", class: "behind1"
And CSS:
.vimeo-container {
position: relative;
.behind1 {
margin-top: -27em;
}
I've also tried setting display: none in the css, but that wont work either. Not sure what I'm missing.
Thanks.
EDIT
function onFinish(playerID) {
var player = "#" + playerID;
$(player).animate({width: "0%"}, 750, function() {
console.log($(player));
$(player).next().show();
});
}
When I log out ($(player) it returns:
And when I log out console.log($(player).next()); it logs out the image that I am trying to show.
According to the jQuery documentation on the animate method here:
Note: Unlike shorthand animation methods such as .slideDown() and .fadeIn(), the .animate() method does not make hidden elements visible as part of the effect. For example, given $( "someElement" ).hide().animate({height: "20px"}, 500), the animation will run, but the element will remain hidden.
I had a similar need in a project and what worked for me there was to set the z-index of the element I wanted to hide to be less than that of the background. Then, when I wanted to show (or, in your case, animate) I could apply the jQuery methods to the element as if they were hidden (by increasing the z-index so that the element becomes visible), yet not incur the undefined behaviour of attempting to manipulate a hidden element.
Another option would be to move the element off the screen by way of a negative (x, y) coordinate and work from there. I'm not sure which visually would be more appealing in your use case but mention it for completeness.

Toggle Galleria Full Screen Mode

I am wondering if anyone knows how to toggle between full screen and normal mode in Galleria
The only way I can think of is to switch between themes : default, and Fullscreen theme (which i bought from there)
If you know an even better way, I would appreciate your help.
I’m just going to add to #Ohgodwhy’s answer:
The best way to get the Galleria instance and use the API is to use the Galleria.ready function:
Galleria.ready(function() {
var gallery = this; // galleria is ready and the gallery is assigned
$('#fullscreen').click(function() {
gallery.toggleFullscreen(); // toggles the fullscreen
});
});
Or, you can access the instance via the $.data object if you know that the gallery is initialized:
$('#fullscreen').click(function() {
$('#galleria').data('galleria').toggleFullscreen(); // toggles the fullscreen
});
I am assuming you have a link/button with the ID 'fullscreen' and the gallery is at ID 'galleria'.
I'm using:
lightbox: true,
before Galleria.run(). This allows you to display fullscreen Overlay after clicking on image in the gallery.
This should work:
JS
Galleria.loadTheme('http://aino.github.com/galleria/demos/categories/themes/classic/galleria.classic.min.js');
$('#galleria').galleria();
Galleria.ready(function() {
var gallery = this;
this.addElement('fscr');
this.appendChild('stage','fscr');
var fscr = this.$('fscr')
.click(function() {
gallery.toggleFullscreen();
});
this.addIdleState(this.get('fscr'), { opacity:0 });
});
CSS
.galleria-fscr{
width:20px;
height:20px;
position:absolute;
bottom:0px;
right:10px;
background:url('fullscreen.png');
z-index:4;
cursor: pointer;
opacity: .3;
}
.galleria-fscr:hover{
opacity:1;
}
Where fullscreen.png is an appropriate image of your choice.
The approach from Richard is working very well.
You could also do it by extending Galleria with-out the ready function:
JS
Galleria.run('.galleria', {
// configure
autoplay: true,
lightbox: true,
idleMode: true,
// extend theme
extend: function() {
var gallery = this; // "this" is the gallery instance
//fullscreen button
this.addElement('fscr');
this.appendChild('stage','fscr');
var fscr = this.$('fscr').click(function() {
gallery.toggleFullscreen();
});
// this.addIdleState(this.get('fscr'), { opacity:0 });
}
});`
And if you'd like to use a fontAwesome icon for the maximize icon you can implement it as following (other CSS styles see Richard's post):
CSS
.galleria-fscr:before {
content: "\f065"; /* char code for fa-expand */
position: absolute;
font-family: FontAwesome;
color: #fff;
}
(keep in mind to include the style sheet of fontAwesome with <link rel="stylesheet" href="css/font-awesome.min.css">)
I'm still having one problem with the maximize button. If I'm hovering over it, it doesn't get white and stays gray. Maybe something with the IDLE state is wrong, but I haven't found a solution yet. (If I remove the code line with this.addIdleState(...) the hovering works. I need to do more tests here.)
I'd also like to change the icon from maximize to the minimize icon once the screen is on fullscreen, but I don't know how to do that yet. That's also on my todo list.
Update 07.02.2014
I figured out how to solve these two issues:
For the "IDLE state" issue - I've removed the IDLE state. Because I don't care if these controls are permanently there and now hovering works as expected. Maybe I check another solution later.
To change an icon on click you can do it with CSS and jQuery:
Add an overriding CSS rule below the first before filter of the maximize icon in your CSS e.g.:
.galleria-fscr.minimize:before{
content: "\f066";
}
Add these JS line after gallery.toggleFullscreen() - that toggles the icon with every click between the normal before style and the minimize before style:
$(".galleria-fscr").toggleClass("minimize");
This works also for a play / resume button (rest of the code is the simillar to the fullscreen code):
JS
...
gallery.playToggle();
$('.galleria-pauseResumeBtn').toggleClass("resume");
From the Galleria documentation.
.enterFullscreen( [callback] )
This will set the gallery in fullscreen mode. It will temporary manipulate some document styles and blow up the gallery to cover the browser screen. Note that it will only fill the browser window, not the client screen (javascript can’t do that).
.toggleFullscreen( [callback] )
Toggles fullscreen mode.
If you need any further explanation of the use of these, please don't hesitate to ask.

Load Galleria when navigating to specific Jquerytools tab

I'm having trouble to integrate the Galleria image gallery plugin onto one of my Jquerytools tabs. When navigating directly to the page with Galleria (example: www.domain.com/index.php#tabnameofgalleriapane), there's no problem.
Whenever the pane with galleria is not loaded immediately (default pane is another pane), Gallery throws an error: Fatal error: Could not extract a stage height from the CSS. Traced height: 0px., which is logical, because when the Galleria pane is not active, it's css is probably display:none;...
Defining the height & width literally does not seem to work. This was the previous setup:
jQuery("#jp_nav").tabs(".jp_pane", { history: true } );
jQuery('#gallery').galleria({
imageCrop: false,
transition: 'slide',
autoplay: 7000,
width: 960,
height: 640
});
So I was thinking to bind the load of the Galleria plugin onload of the pane that contains the Galleria plugin, because in that moment, the Galleria pane does have a height... I've found something to help me on my way, but now I'm getting other JavaScript conflict errors (see below for explanation).
jQuery("#jp_nav").tabs(".jp_pane", {
initialIndex: 0,
onBeforeClick: function(event, i) {
// get the pane to be opened
var pane = this.getPanes().eq(i);
var src = this.getTabs().eq(i).attr("href");
pane.load(src, "#jp_images", function(){
jQuery('#gallery').galleria({
imageCrop: false,
transition: 'slide',
autoplay: 7000,
width: 960,
height: 640
});
});
},
history: true
});
For reasons beyond my control, the website I'm writing this for uses both jQuery and Prototype/Scriptaculous. So please take into account that the script has to be written in noConflict mode. (Which I'm doing in my setup $.noConflict();)
Can someone please tell me if the script below puts me on the right track?
Can someone help me modify the script to work when the #jp_images tab is loaded?
Right now, the above script gives me conflict errors with Prototype.
Anxiously awaiting your expert views!
Regards,
Maarten
I've managed to find a quick and dirty solution (thanks to vfxdude)
Anytime the tab with the Galleria is clicked, I force a page reload, like so:
tabName = 'jp_images';
jQuery('#jp_nav a[href="#'+tabName+'"]').click(function() { if (location.hash == '') location.replace(location.href+'/#'+tabName); });
After this, I can just use the regular old Galleria plugin initialisation.
Granted, it is a little dirty, but it's an easy and quick fix for when on a deadline.

Categories