jQuery UI tooltip is stuck open when the source DOM element moves - javascript

I have a div that contains a few thumbnails which can be dragged and dropped. When one thumbnail is dropped over top of another thumbnail, they switch places. I do this using AngularJS and manipulating the underlying data on the $scope.
Anyway, here's the problem:
The thumbnails have tooltips that open when I hover over them. When I click and start dragging a thumbnail (let's call this one the source thumbnail), its tooltip disappears (as it should). So far so good. When I drop the thumbnail over top of the other, however, there's a brief moment where the target thumbnail's tooltip appears, since the mouse is currently hovering over the target tooltip.
A split second later, the underlying model swaps the two pieces of data, and the DOM updates to reflect the change - effectively swapping the two thumbnails. Now, the target's tooltip is STILL open, but my mouse is no longer over the target, because it was just swapped! The tooltip will remain open until I re-trigger the tooltip events at the new location.
This behaviour is observed roughly 50% of the time, but I can artificially reproduce it 100% of the time by adding a short (~1 second) delay before changing the underlying data, causing the thumbnails to switch places.
NOTE: This problem does NOT occur in Chrome, but it does in Firefox and IE. I haven't tried Safari.
Has anyone experienced this problem, or something similar? Please let me know if I can provide any further details. Thanks!
Edit: Here's a jsfiddle example that illustrates the problem: jsfiddle
<script src="http://code.jquery.com/jquery-1.11.2.min.js"></script>
<script src="http://code.jquery.com/ui/1.11.2/jquery-ui.js"></script>
<script>
$.widget.bridge('uitooltip', $.ui.tooltip);
</script>
<div ng-app="myApp">
<div ng-controller="ContentController">
<div class="indent">
<div ng-repeat="square in squares" style="width: 400px">
<item data="square" helper="helperFunction"></item>
</div>
Drag the top box onto the bottom box and keep the mouse cursor stationary for ~1 second. The tooltip will be stuck open when the boxes switch places. Dragging the bottom box to the top box, however, does not have this problem.
<br><br>
Also, this problem seems to only be present in Firefox and IE. Chrome works as expected.
</div>
</div>
</div>

You could replace the default browser tooltips with the jquery version:
$('*').tooltip({track: true});
Then you could set the tooltips to be disabled while you drag your elements:
$('.thumbnail').tooltip('disable');
On drop, enable them again:
$('.thumbnail').tooltip('enable');
http://jsfiddle.net/uHuDp/1/
Edit: for your example:
$(element).find("span.item-outer").uitooltip('disable');
$(element).find("span.item-outer").uitooltip('enable');
http://jsfiddle.net/uHuDp/260/

Related

weird scroll issue in IE8

I have an weird issue in IE8. I have a bunch of div's in an area. Each div has the same structure. Here is the basic structure.
<div class="brandImage">
<div style="display:none;">
<a><img/></a>
<div><span>See More</span></div>
</div>
</div>
Each brandImage div has an on hover listener which will give the inner div a display:block reveling the image and allowing the user to click through.
All these "tiles" are contained in a div with a set height and is scroll-able using the jquery.mCustomScrollbar plugin.
It works with all the tiles above the fold, however, when a you start to scroll down below the fold, if you click on one of the tiles, on mousedown will cause the container to scroll up. If the container does not have to scroll very far or you release the mouse button fast enough to complete the click it will work.
My question is what could be causing the scroll up on the mousedown event?
The plugin defaulted to scroll on focus. The function that was called on focusin. This was scrolling the container. Here is the code from the plugin.
/*scrolling on element focus (e.g. via TAB key)*/
if($this.data("autoScrollOnFocus")){
if(!$this.data("bindEvent_focusin")){
mCustomScrollBox.bind("focusin",function(){
mCustomScrollBox.scrollTop(0).scrollLeft(0);
var focusedElem=$(document.activeElement);
if(focusedElem.is("input,textarea,select,button,a[tabindex],area,object")){
var mCSB_containerPos=mCSB_container.position().top,
focusedElemPos=focusedElem.position().top,
visibleLimit=mCustomScrollBox.height()-focusedElem.outerHeight();
if($this.data("horizontalScroll")){
mCSB_containerPos=mCSB_container.position().left;
focusedElemPos=focusedElem.position().left;
visibleLimit=mCustomScrollBox.width()-focusedElem.outerWidth();
}
if(mCSB_containerPos+focusedElemPos<0 || mCSB_containerPos+focusedElemPos>visibleLimit){
$this.mCustomScrollbar("scrollTo",focusedElemPos,{trigger:"internal"});
}
}
});
$this.data({"bindEvent_focusin":true});
}
}
When I initialize the plugin, I set autoScrollOnFocus to false and there was no issue.

iscroll issue with two dimensional ( horizontal + vertical ) scrolling, scrollable are related issue?

Problem in brief
I have got a piece of working two dimensional scrolling code. Scrolling as such is working fine. Scrolling can be done in any direction (not like restricted to only horizontal or only vertical at a ti,e) but there are two problems -
Scrolling beyond the visible area towards top and left, does not bounce back the scrollable area.
Scrolling to right and bottom bounces back.
Problem demo - http://jsfiddle.net/sandeepan_nits/pAhjU/6/
Note - Test in webkit browsers only (Google chrome and Safari).
Solution I am looking for
Either, point out what is wrong in my code.
Or share any properly implemented working demo of both ways scroll (horizontal + vertical) using the same version of iscroll, so that I can follow the same. I am using - version 3.7.1, preferable, or using iscroll version 4, fine as well.
Or any pointers, of course, would be appreciated.
Problem Description
Please check working code here - http://jsfiddle.net/sandeepan_nits/pAhjU/6/
Note -
Test in webkit browsers only (Google chrome and Safari).
I have knowingly put everything inside the HTML section in the jsfiddle, because if I separate things completely, the scrolling does not work, and I am not sure where exactly it stops working. Thanks if you can point out.
Code
Here is the HTML -
<div class="header">
<div class='left_link'></div>Demo</div>
<div id="main_content" class="main_content">
<b><div id=scroller1><br/>
<div class='center_data'>Scrollable area</div>
<div class='center_data'>hello world!</div>
<br/>
</div></b>
</div>
Note - I know there is invalid html there - <div id=scroller1> is inside <b></b> and I am not sure why if I remove the <b></b> tags, horizontal scrolling does not work anymore - check here.
Here is the js -
var myScroll;
var a = 0;
function loaded() {
//setHeight(); // Set the wrapper height. Not strictly needed, see setHeight() function below.
// Please note that the following is the only line needed by iScroll to work. Everything else here is to make this demo fancier.
myScroll = new iScroll('scroller1', {desktopCompatibility:true});
//myScroll2 = new iScroll('scroller2', {desktopCompatibility:true});
}
// Prevent the whole screen to scroll when dragging elements outside of the scroller (ie:header/footer).
// If you want to use iScroll in a portion of the screen and still be able to use the native scrolling, do *not* preventDefault on touchmove.
document.addEventListener('touchmove', function (e) { e.preventDefault(); }, false);
// Load iScroll when DOM content is ready.
document.addEventListener('DOMContentLoaded', loaded, false);
I guess the reason is that the scrollable div is by default rendered at the bottom-right corner of the scrollable area. But I am not sure about the proper way to configure those things - how to set where to render the scrollable div inside the scollable area. So far I did not find any working demo of both ways scrolling - horizontal + vertical scrolling.
I checked out the documentation of iscroll and many working demos, but did not find any demo where scrolling can be done both ways - horizontally as well as vertically. I checked the "Accepted options are:" section under "Syntax" section in http://cubiq.org/iscroll but none of those params seem to be what I am exactly looking for.
Other things
Also, one more thing, I am not able to view the area covered by dom elements in chrome browser, while I inspect the given scroll demo. By viewing the area I mean moving the mouse over the dom inspector panel highlights the dom in the browser view. When does it not appear? I checked with validated HTML as in http://jsfiddle.net/sandeepan_nits/pAhjU/12/.
Somebody please create a tag iscroll or iscroll3 so that I can retag my question.
Update
I just want to have normal two dimensional scrolling with the scroll area being properly inside the visible screen and there should be bounce back on taking outside the screen. Right now there is no bounce back (in my jsfiddle) on scrolling towards top and left, outside screen. Bounce back happens on scrolling to right and bottom. I just want the scrolling area to be well placed inside the screen. I guess bounce back will automatically get fixed then.
I think the last version (4.1.8) on the github repo will fix your problem ;) I'm using it on some projects and it is now optimized for desktop browser ;)
Edit
From the documentation :
hScroll, used to disable the horizontal scrolling no matter what. By default you can pan both horizontally and vertically, by setting this parameter to false you may prevent horizontal scroll even if contents exceed the wrapper.
vScroll, same as above for vertical scroll.
By default, when creating a new iScroll('idOfElement') the scroll is vertical and horizontal. It can be disabled with these parameters. Dual Scroll is totally possible as this video shows it.
So, to force dual Scroll :
var myScroller = new iScroll('idOfElement', {vScroll:true, hScroll:true});
This is not a complete solution, but this might help you.
First of all, The HTML code was not properly nested, and so you were needed to put the <div> inside the <b>. I fixed up the HTML a bit and its working without the <b>
http://jsfiddle.net/Aexhz/
And with properly nested HTML and correct settings, This worked even after dividing the HTML/JS/CSS
For me, it does show some Horizontal as well as Vertical Scrolling, but i don't know if that's how you want it to be. i Edited the Class initialization line as well
myScroll = new iScroll('scroller1', {desktopCompatibility:true});
TO
myScroll = new iScroll('scroller1', {
snap: true,
momentum: false,
hScrollbar: false,
vScrollbar: false,
desktopCompatibility: true
});
This doesn't affects much but i still put that.
I will continue looking into this and update my answer if i find anything new.
I know you want to fix this using iscorll but wanted to share this with you, i had great results using it: http://jscrollpane.kelvinluck.com/#usage
It is highly customizable with css, a demo here with vertical and horizontal scroll: http://jscrollpane.kelvinluck.com/basic.html

Getting javascript events to an object that's covered up

I'm trying to build a jquery app where I have a fixed image and a second draggable image. I need the fixed image to display z-index on top of the moveable image -- the fixed image is a picture with an alpha cut-out hole for a face like you might find at an amusement park. The problem is that as soon as the moveable (face) image is overlapping with the fixed image, click and drag events get captured by the fixed image which is on top and don't get to the moveable image. So it's no longer moveable. Here's my code...
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.8/jquery-ui.min.js"></script>
<div id="fixed" style="position:relative; z-index: 2">
<img src="background.png">
</div>
<div id="face" style="position:relative; z-index: 1">
<img src="face.png">
</div>
<script>
$(function() {
$("#face").draggable();
});
</script>
How can I get the face object to be draggable when it's behind the fixed background? Can I manually fire the mouse events on the object underneath? If so, how do I invoke them so the jquery-ui draggable() works properly? Can I somehow get the fixed image just not to capture events? Or do I need to write my own draggable mechanism by hand?
I think i found a pretty simple solution for you. Basically you can relay the event only when certain conditions are met (eg #face is under the #fixed). Check out this fiddle for example.
A quick look at the even data revealed that draggable only binds mousedown, so that seems to be the only event you will need to relay.
$('#face').draggable();
$('#fixed').bind('mousedown', function(e){
// TODO: IF #face is under #fixed AND mouse is over #face THEN
$('#face').trigger(e); // trigger the event on face
});
I think you might be better off creating some sort of "drag handle" to the element underneath, which would always be visible (at least while dragging is enabled). That, or a separate UI control separated from the images which would act as a "joystick" for the draggable image, so that you could move the image without having to manually drag/drop the image itself.
Think about it: lets say they drag the item underneath the top item, then drop it; how are they to pick it up again? If this is setup like you explained (a cut-out hole for a face like you might find at an amusement park), then the user would not be able to visibly see the element underneath, and as such, it would be impossible for them to interact with that element using the mouse.

JQuery UI slide effect creates a new line

I want to enable an effect on my web app where a user clicks an "Edit" icon and a text box elegantly slides out horizontally immediately to the right of the icon. Currently it is sliding out, but not very elegantly, because when I click on the icon for some reason a new row is created in the browser below where I clicked (and all content below is bumped down). The text box slides out, and then bizarrely jumps back up to where I originally wanted it to go, and the new row created disappears.
Please note, however, that if I put the textbox on its own line so that it is fully left-justified against the margin, that it works just fine. But I want it to scroll it to the right of the icon.
This behavior is the same for IE8 and Firefox.
Here is the HTML:
<img src="../images/edit.gif" onclick="toggleNotebox()" style="cursor:pointer"/>
<span id="AddText" style="display:none">
<input name="AddNoteText" id="TextBox" onkeypress="return addNote(event);" />
</span>
And here is the relevant Javascript:
function toggleNotebox() {
var options = {};
$('#AddText').toggle('slide', options, 500);
}
Here is the jsbin.com URL to see this behavior in action: http://jsbin.com/alopu/edit
Try putting a float: left on both elements.
http://jsbin.com/uzoqo
edit: for some reason the above works but if you try to edit it it doesn't show my changes to the code. not sure what happened.
Inline elements, which spans and inputs are by default, don't honour explicit widths. So jQuery's either changing the display of the animated element to block, or wrapping it in a block element so that that element can be animated.
That's why Samuel's change works - floated elements honour widths.

Ignore mouse interaction on overlay image

I have a menu bar with hover effects, and now I want to place a transparent image with a circle and a "handdrawn" text over one of the menu items. If I use absolute positioning to place the overlay image above the menu item, the user will not be able to click the button and the hover effect will not work.
Is there any way to somehow disable mouse interaction with this overlay image so that the menu will keep on working just as before even though it's beneath an image?
Edit:
Because the menu was generated with Joomla I could not tweak just one of the menu items. And even if I could, I did not feel a Javascript solution was appropriate. So in the end I "marked" the menu item with an arrow outside the menu-item element. Not as nice as I had wanted it to be, but it worked out okey anyway.
The best solution I've found is with CSS Styling:
#reflection_overlay {
background-image:url(../img/reflection.png);
background-repeat:no-repeat;
width: 195px;
pointer-events:none;
}
pointer-events attribute works pretty good and is simple.
So I did this and it works in Firefox 3.5 on Windows XP. It shows a box with some text, an image overlay, and a transparent div above that intercepts all clicks.
<div id="menuOption" style="border:1px solid black;position:relative;width:100px;height:40px;">
sometext goes here.
<!-- Place image inside of you menu bar link -->
<img id="imgOverlay" src="w3.png" style="z-index:4;position:absolute;top:0px;left:0px;width:100px;height:40px;" \>
<!-- Your link here -->
<a href="javascript:alert('Hello!')" >
<div id="mylinkAction" style="z-index:5;position:absolute;top:0px;left:0px;width:100px;height:40px;">
</div>
</a>
</div>
What I've done:
I've crafted a div and sized it to be what a menu option could be sized to, 100x40px (an arbitrary value, but it helps with illustrating the sample).
The div has an image overlay, and a link overlay. The link contains a div sized to be the same as the 'menuOption' div. This way a user click is captured across the whole box.
You will need to provide your own image when testing. :)
Caveat:
If you expect your menu button to respond to the user interaction (for example, changing color to simulate a button), then you will need extra code attached to the javascript you will invoke on the tag, this extra code could address the 'menuOption' element through the DOM and change it's color.
Also, there is no other way I know of that you can take a click event, and have it register on an element underneath a visible page element. I've tried this as well this summer, and found no other solution but this.
Hope this helps.
PS:
The writeup on events at quirksmode went a long way to help me understand how events behave in browsers.
Give the button a higher z-index property than the hand-drawn image:
<img src="hand_drawn_image.gif" style="z-index: 4">
however, make sure you test it in all major browsers. IE interprets z-index differently from FF.
For somebody to come up with more details, you would have to post more info, a link would be best.
Building on what Pekka Gaiser said, I think the following will work. Taking his example and reworking it:
<a href="#" style="z-index: 5">
<!-- Place image inside of you menu bar link -->
<img src="hand_drawn_image.gif" style="z-index: 4">
<!-- Your link here -->
</a>
Here you should be able to place an event on the underlying a-tag and, unless your image has an event, initiates a capture (!IE browsers) and then kills propagation of the event.
If you need a bit more help, let us know a bit more about the situation.
If the image will be statically positioned, you can capture the click event from the image as it bubbles up, by placing the img tag inside the menu item element.
<div onclick="menuclick()">
<img src="overlay.png" style="position:absolute;" />
</div>

Categories

Resources