I'm using a qTip2 tooltip to display a little notification at the bottom-left of the browser window when an update has occurred to certain elements on the page (so that the user is aware that a page save might be required to persist the change).
That was working reasonably well under my old test environment (Windows Vista, Firefox 52). However, with Windows 10 and Firefox Quantum (57.0.4), I'm seeing a console message which says:
This site appears to use a scroll-linked positioning effect. This may
not work well with asynchronous panning.
The warning links to a MDN page which talks about asynchronous scrolling, and indeed I'm now seeing a delayed qTip2 element-reposition when scrolling the page.
JSFiddle which demonstrates the issue - click the button and scroll the rendered context to see the effect.
I'd appreciate it if someone could recommend a solution that would eliminate the scroll/position-update delay. Thank you.
JSFiddle script:
<button id='mybutton'>Press me</button>
<div style='height: 1000px'></div>
function delay(ms)
{
var d = $.Deferred();
setTimeout(function()
{
d.resolve();
}, ms);
return d.promise();
}
function qTipHint(titleTxt, contentTxt, anchorElement, timeOut, topCenter)
{
if (anchorElement.length > 0)
{
var locationMy = '';
var locationAt = '';
if (topCenter)
{
locationMy = 'top center';
locationAt = 'bottom center';
}
else
{
locationMy = 'bottom left';
locationAt = 'bottom left';
}
var test = anchorElement.qtip(
{
content:
{
text: contentTxt,
title: titleTxt
},
show:
{
effect: function()
{
$(this).slideDown();
}
},
hide:
{
event: '',
effect: function()
{
$(this).slideUp();
}
},
style:
{
classes: 'qtip-jtools',
tip: false
},
position:
{
my: locationMy,
at: locationAt,
target: anchorElement
}
});
var api = test.qtip('api');
api.show();
delay(timeOut).then(function()
{
api.destroy();
});
}
}
$('#mybutton').click(function()
{
qTipHint('Title', 'Some hint text', $(window), 10000, false);
})
I've come to the conclusions I was trying to force the qTip2 library into a role for which it was not intended.
I've switched to Bootstrap Notify as an alternative, and it does a very satisfactory job.
Related
I am currently using the following code to initialize a lazy initialization version of Bootstrap tooltip. After the first hover everything works fine in regards to the delay, but on the initial hover it shows right away. I know this is because of the $(this).tooltip('show'); method, but I dont know how to use the delay and show at the same time. I have to use the $(this).tooltip('show'); because once hovered the element doesnt show the tooltip unless I move out and back in.
$(element).on('hover', '.item', function () {
matchup = ko.dataFor(this).Matchup;
if (matchup) {
if ($(this).attr('data-original-title') != '') {
$(this).tooltip({ title: matchup.Title, html: true, delay: 1000 });
$(this).tooltip('show');
}
}
});
Updated Answer
$(element).on('mouseenter', '.item', function (e) {
matchup = ko.dataFor(this).Matchup;
if (matchup) {
if ($(this).attr('data-original-title') != '') {
$(this)
.addClass('tooltip-init')
.tooltip({ title: matchup.Title, html: true, delay: { show: 1000, hide: 0 } })
.trigger(e.type);
}
});
try use trigger
try the following code
$(this).tooltip({
title: matchup.Title,
html: true,
trigger: 'hover',
delay: delay: { show: 2000, hide: 3000 }
}).trigger('hover');
I found Holmes answer using delay to work, but not reliably. When moving through a series of items, the hover seemed to stop showing. With the help of another stackoverflow answer leading to this jsfiddle by Sherbrow, I simplified the code and got it working in this jsfiddle. Simplified code below:
var enterTimeout = false;
$('[rel="tooltip"]').tooltip({trigger:'manual'}).on('mouseenter', function() {
var show = function(n) {
enterTimeout = setTimeout(function(n) {
var isHovered = n.is(":hover");
if (isHovered) n.tooltip('show');
enterTimeout = false;
}, 750);
};
if(enterTimeout) clearTimeout(enterTimeout);
show( $(this) );
});
$('[rel="tooltip"]').on('mouseout click',function() {
$(this).tooltip('hide');
});
I am using JQuery 1.4.2 along with PhoneGap to create an app. Is there a function or plugin available to detect an idle screen or active screen? I want to hide/show some navigation buttons with a function. Any direction would be really appreciated.
An example I have found, which did not work:
$('body').bind('touchstart',function() {
clearInterval(myTimer);
});
$('body').bind('touchend', function() {
myTimer = setInterval(function() {
/* return user to homepage */
},30000);
});
and tried this as well, with no results:
$("#eventPage").on("scrollstart",function() {
$("#preEventBtn").hide();
$("#nextEventBtn").hide();
});
Solution:
$(document).on("scrollstart",function() {
$("#preEventBtn").show();
$("#nextEventBtn").show();
});
$(document).on("scrollstop",function() {
$("#preEventBtn").fadeOut().delay(5000);
$("#nextEventBtn").fadeOut().delay(5000);
});
$(document).on("tap",function() {
$("#preEventBtn").show();
$("#nextEventBtn").show();
});
This will help with your scrolling issue...
var _scrollTimeout = 0;
var $fixedDiv = $("#fixed-div");
$(window).on("scroll", function() {
clearTimeout(_scrollTimeout);
$fixedDiv.stop().fadeIn(500);
_scrollTimeout = setTimeout(function() {
$fixedDiv.stop().fadeOut(1000);
}, 500);
});
It's obviously an example and you'll need to modify it to suit your specific needs, but here's a working example...
http://jsfiddle.net/ArchersFiddle/tK2mY/2/
I'm using the following code to scroll the window when a user clicks on a few different links:
$(document).ready(function(){
$("#footerlink").click(function(){
$("#slide1").slideto({});
});
$("#logo").click(function(){
$("#slide1").slideto({});
});
$("#home").click(function(){
$("#slide1").slideto({});
})
$("#others").click(function(){
$("#slide2").slideto({});
})
$("#me").click(function(){
$("#slide3").slideto({});
});
$("#laughs").click(function(){
$("#slide4").slideto({});
});
})
The slide functionality is coming from this script:
(function(b) {
b.fn.slideto = function(a) {
a = b.extend({
slide_duration: 1000,
highlight_duration: 3E3,
highlight: false,
highlight_color: "#FFFF99"
}, a);
return this.each(function() {
obj = b(this);
b("body").animate({
scrollTop: obj.offset().top
}, a.slide_duration, function() {
a.highlight && b.ui.version && obj.effect("highlight", {
color: a.highlight_color
}, a.highlight_duration)
})
})
}
})(jQuery);
My problem is the scrolling only works in Chrome and not Firefox or IE. FF and IE degrade nicely so the links still work, but I really like the scrolling animation.
FYI: I am calling Jquery with these two lines:
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.1/jquery.min.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.23/jquery-ui.min.js"></script>
Here is a Fiddle of my code: http://jsfiddle.net/LwXR3/
Can you help me track down my issue?
Okay this is too long to be in a comment. You should really avoid the copy paste mess in that code above. The code is almost exactly the same minus the ids. Use the href to get the location instead of hard coding it.
HTML
<a class="slideLinks" href="#foo">go to foo</a>
JavaScript
$(".slideLinks").on("click", function(e){
e.preventDefault(); //p[revent the click
$(this.hash).slideto({}); //call your slide to function with the hash value for the id
});
I'm using the Overlay plugin from jQuery Tools: http://flowplayer.org/tools/overlay/index.html to display a full size image when a link is clicked, but the overlay is displayed immediately and shows the image loading.
I'd like to change this behavior and wait until the image is loaded before launching the overlay. The Overlay plugin has an onBeforeLoad property to which a callback function can be attached. But, of course, the overlay display resumes as soon as this callback is executed, and will not wait for the image load event to be fired.
The plugin has a few API methods, but they don't seem very helpful for my purpose.
In my example below, the two lines I've commented out should give you an idea of what I thought might work, but doesn't.
Here's a simplified test case: http://jsfiddle.net/GlauberRocha/9jkU5/
Any idea?
var $trigger = $("#trigger"),
api;
$trigger.overlay({
fixed: true,
mask: {
color: "#000",
opacity: .8
},
onBeforeLoad: function() {
console.log("onBeforeLoad");
api = $trigger.data("overlay"); // see http://flowplayer.org/tools/overlay/index.html "Scripting API"
//api.close(); // Temporarily "close" the overlay?
setTimeout(function() { // This will be replaced by the image load event
console.log("Waiting is over!");
//api.load(); // Load the overlay now?
}, 2000);
},
onLoad: function() {
console.log("onLoad");
}
});
Ok, I think I understand what you are wanting. To prevent the overlay from loading, you need to return false, but only if the image is not yet loaded. See if this JSFIDDLE helps:
var $trigger = $("#trigger"),
api;
var imageLoaded = false;
$trigger.overlay({
fixed: true,
mask: {
color: "#000",
opacity: .8
},
onBeforeLoad: function() {
console.log("onBeforeLoad");
api = $trigger.data("overlay"); // see http://flowplayer.org/tools/overlay/index.html "Scripting API"
//api.close(); // Temporarily "close" the overlay?
if(!imageLoaded){
setTimeout(function() { // This will be replaced by the image load event
console.log("Waiting is over!");
api.load(); // Load the overlay now?
}, 2000);
imageLoaded = true;
return false;
}
},
onLoad: function() {
console.log("onLoad");
}
});
I've modified my code. This version seems to work (see http://jsfiddle.net/GlauberRocha/rwtvK/). The main difference comes from the way the API method is called ($trigger.overlay().load() vs $trigger.data("overlay").load()). This inconsistency is present in the jQuery Tools docs and examples.
$(function () {
var $trigger = $("#trigger");
$trigger.overlay({
fixed: true,
mask: {
color: "#000",
opacity: .4
},
onBeforeLoad: function () {
if (typeof this.init === "undefined") {
this.init = true;
setTimeout(function () { // This will be replaced by the image load event handler
console.log("OK, let's show it!");
$trigger.overlay().load(); // Load the overlay
}, 5000);
console.log("Not now!");
return false;
}
}
});
});
I'm building a simple photolog using jQuery, jflickrfeed and jQuery.Masonry - but I'm having some trouble getting the event chain right in Safari.
Here's some example code:
$(document).ready(function() {
$('#container').jflickrfeed({
limit: 20,
qstrings: {
id: '58201136#N00'
},
itemTemplate: '<div class="box"><img src="{{image_m}}" /><h3>{{title}}</h3>{{description}}</div>'
}, function(data) {
console.log("1st");
});
});
$(window).load(function() {
console.log("2nd");
$('#container').masonry({
singleMode: true
});
});
So, jflickrfeed pulls a photo from my flickr feed, wraps it in the template code and appends it inside #container, and repeats this until the limit is reached. After all photos are inserted, Masonry kicks in and arranges the divs.
This works beautifully in Chrome and Firefox, but not in Safari - where the .load event fires before all photos are finished loaded, thus breaking the layout.
I've updated the example to better show illustrate what I mean.
In Chrome/Firefox the console output is "1st, 2nd" while in Safari it is "2nd, 1st"
Any tips?
You can pass the load callback as the second parameter to "jflickrfeed" call and this will ensure that the "masonry" will be invoked only when the images from Flickr have been loaded.
here is a possible sample:
$('#container').jflickrfeed({
limit: 20,
qstrings: {
id: '58201136#N00'
},
itemTemplate: '<div class="box"><img src="{{image_m}}" /><h3>{{title}}</h3>{{description}}</div>'
},
function () {
$('#container').masonry({
singleMode: true
});
});
Hope it helps.
I'm not sure how useful this will be, or if if will make any difference at all. But for a guess, if the issue is that #container is not available when $(window).load fires, you could try setting up a timer to repeatedly check for its existence, and when it is detected, set up masonry, then kill the timer:
$(window).load(function () {
var i = setInterval(function() {
if($("#container").length) {
$('#container').masonry({
singleMode: true
});
clearInterval(i);
}},
20);
});
Solved it myself by adding a counter:
var counter = 0;
$(document).ready(function () {
$('#container').jflickrfeed({
limit: 20,
qstrings: {
id: '58201136#N00'
},
itemTemplate: '<div class="box"><img src="{{image_m}}" /><h3>{{title}}</h3>{{description}}</div>',
itemCallback: function () {
counter++;
}
});
});
$(window).load(function () {
var i = setInterval(function () {
if (counter = 20) {
$('#container').masonry({
singleMode: true
});
clearInterval(i);
}
}, 20);
});
Ugly, but it works..