I have a function that shows a menu when clicking on it, and I want it to disappear after 5 seconds. This is my javascript - it works properly on desktop browser but it doesn't disappear on the mobile ones.
$(function() {
$('#prod_btn').click(function() {
$(this).addClass('selected').next('ul').css('display', 'block');
setTimeout(hideMenu, 5000);
});
});
function hideMenu() {
$('#prod_btn').removeClass('selected').next('ul').css('display', 'none');
}
Where is the problem?
Thanks
I've just had the same problem. My code is running great in any browser on my Mac, but on iOs devices it doesn't work.
I use ".bind(this)" on my timeout function and that is what is causing the problem for me.
When I extend the function object with ".bind" in my script it works like a charm.
My code is something like this:
searchTimeout = setTimeout(function() {
...
}.bind(this),250);
For this to work on iOs devices I (like mentioned above) just added this:
Function.prototype.bind = function(parent) {
var f = this;
var args = [];
for (var a = 1; a < arguments.length; a++) {
args[args.length] = arguments[a];
}
var temp = function() {
return f.apply(parent, args);
}
return(temp);
}
I don't see any .bind on your setTimeout, but for others with the same problem this may be the issue. That's why I'm posting :-)
I moved your example to a jsbin, and it's working on my iphone 4.
Please test it out going here from your devices: http://jsbin.com/asihac/5
You can see the code here http://jsbin.com/asihac/5/edit
The example is using jQuery - latest and I only added the required css class.
this doesn't apply to your code, but a common problem with long-running scripts failing on iOS devices is that MobileSafari kills a javascript thread after 10 seconds have elapsed. you should be able to use setTimeout and/or setInterval to work around this, or you can avoid it by making a shortcut to it and thereby running it as an app. see https://discussions.apple.com/thread/2298038, particularly the comments by Dane Harrigan.
Keep in mind also that any setTimeout function is actually likely fire while DOM elements are rendering if the delay is set to a value too short. While that might seem obvious, it can be easily confused with no method firing whatsoever. A good way to test is to have an alert prompt run.
window.onLoad(alert("hey!"));
Then check to see if your function fires after.
Related
At our job we're using a communication portal that logs out after a while. Some of my co-workers asked me for a javascript, that disables the autologout. All i could achieve was to reset the displayes timer, but the timer itself keeps running anyway. Here is how the timer is started:
<body class='asam_body' onLoad='window.setTimeout("DsplTime()",1);' >
As you can see, setTimeout is called at onLoad, but there is no reference to the setTimeout-call, so i can't use the clearTimeout() function. I've also tried to call DsplTime() out of my script, but that still doesn't stop the timer. Everything i found doesn't apply to my case, so i gave up my search after two hours.
Is there any way to influence this serverside body-definition, e.g. by
overriding the onLoad (tried with #document-start)
replacing the string for the definition of the body itself (i guess because the server delivers that, its to late for my script to inject, when the line is there)
getting a reference to the setTiming-Object retroactively
Here's my rather useless approach, that only resets the displayed time:
setInterval(CalcTime, 130000);
setInterval(resetStart, 130000);
setInterval(DsplTime, 130000);
//resetStart and CalcTime are prefined functions,
// without any impact on the timer itself, unfortunately
Thanks in advance!
P.S.: thats the first time i asked something on stackoverflow, so i hope, i asked appropiately:)
Edit:
I tried the brute force approach from Cancel all Javascript's setTimeouts and setIntervals, with
for (var i = 1; i < 99999; i++) {
window.clearInterval(i);
window.clearTimeout(i);
window.mozCancelAnimationFrame(i); // Firefox
}
But still i'm logged out after the same amount of time.
This codesnipped leads to the logout after 1440 minutes:
if (absSec >= 1440)
{
document.location.href = "../project/auth/logout.php";
}
This is part of the function DsplTime() metioned above. Is there any way of manipulating this function, instead of preventing it's call? absSec is out of scope, so i can't change it's value (and i think this wouldn't help anyway?
Edit 2:
So i could manage to stop the timer by
// #run-at document-start
//...
var highestTimeoutId = setTimeout(";");
for (var i = 0 ; i < highestTimeoutId ; i++) {
window.clearTimeout(i);
// window.alert(i);
}
Unfortunately, the script only works every now and then (in like 80% of the pageloading). Plus, isn't this generating a lot of load for the server? I don't want to be blocked...
Why not just override the javascript function DsplTime() so that it doesn't log you out?
go to the debug console and type something like DsplTime = new function(){}
when the interval is up and DsplTime(), the function will do nothing.
I need to set the background color of one of the buttons in the form's ribbon. This isn't supported through Ribbon Workbench, so I have written following javascripts to achieve the same:
function setOpportunityRibbonsAppearance() {
var submitToForeCastButton = parent.document.getElementById("opportunity|NoRelationship|Form|sfw.opportunity.Button1.Button");
if (submitToForeCastButton != null) {
submitToForeCastButton.style.backgroundColor = "lightyellow";
}
}
I have registered this scripts in Form Load event. However the issue is that, I always get parent.document.getElementById as null only.
Surprisingly, I am able to see the control while running the parent.document.getElementById statement in the browser's console, and can also change the styling attributes.
Can anyone please suggest what could be wrong here?
P.S. - I understand document.getElementById is not recommended to use in CRM, however, I am left with no other choice while trying to change the appearance of some of the buttons.
Any help on this, will be much appreciated.
You could upload an icon with a yellow background, to keep everything supported. You won't see text on yellow but it might work for you. Easy and standard.
To keep it unsupported and ugly, you could just keep on trying until you make it, setInterval allows for a function to be repeated:
function setOpportunityRibbonsAppearance() {
var submitToForeCastButton = null;
var interval = setInterval(function(){
submitToForeCastButton = parent.document.getElementById("opportunity|NoRelationship|Form|sfw.opportunity.Button1.Button");
if(submitToForeCastButton != null) {
submitToForeCastButton.style.backgroundColor = "lightyellow";
clearInterval(interval);
}
}, 500); // Every 500ms. Adjust as needed, not too fast or browser will choke.
}
Its probably because your script is running before the page is fully loaded.
Try adding a delay to the to the function Put a Delay in Javascript
For several years I've used the waitForKeyElements() function to track changes in webpages from a userscript. However, sometimes I've found it doesn't trigger as expected and have worked around out. I've run into another example of this problem, and so am now trying to figure out what the problem is. The following is the barest example I can create.
Given a simple HTML page that looks like this:
<span class="e1">blah</span>
And some Javascript:
// function defined here https://gist.github.com/BrockA/2625891
waitForKeyElements('.e1', handle_e1, false);
function handle_e1(node) {
console.log(node.text());
alert(node.text());
}
setInterval(function() {
$('.e1').text("updated: "+Math.random());
}, 5000);
I would expect this code to trigger an alert() and a console.log() every 5 seconds. However, it only triggers once. Any ideas?
Here's a codepen that demonstrates this.
By design and default, waitForKeyElements processes a node just once. To tell it to keep checking, return true from the callback function.
You'll also want to compare the string (or whatever) to see if it has changed.
So, in this case, handle_e1() would be something like:
function handle_e1 (jNode) {
var newTxt = jNode.text ();
if (typeof this.lastTxt === "undefined" || this.lastTxt !== newTxt) {
console.log (newTxt);
this.lastTxt = newTxt;
}
return true; // Allow repeat firings for this node.
}
With the constant string comparisons though, performance might be an issue if you have a lot of this on one page. In that scenario, switching to a MutationObserver approach might be best.
Have anybody out there found a simple way of detecting whether the browser supports the transitionend event or not in vanillaJs, especially in a way that actually works in all major browsers? :(
I have found this unanswered thread in here: Test for transitionend event support in Firefox, and quite a lot of almost working hacks.
Right now I am bulk adding eventlisteners to all the vendor prefixes, and it kind of works out (even though I think it is a hideous approach that hurts my eyes every time I look at it). But IE8 and IE9 does not support it at all, so I need to detect those two, and treat them separately.
I would prefer to do this without browser sniffing, and definitely without huge libraries/frameworks like jQuery
I have made a jsfiddler snippet that illustrates my problem. There is a button that spawns a dialog. When the dialog is removed by clicking close, it is transitioned in top and opacity, and after ended transition it is supposed to display=none. But if the transitionend is never fired (like in IE8 and IE9), the dialog is never removed, making it cover the show dialog button, destroying the UX. If I could detect when transitionend is not working, I could just set the display=none when closing for those browsers.
http://jsfiddle.net/QJwzF/22/
window.listenersSet = false;
window.dialogShouldBeVisible = false;
window.showMyDialog = function () {
var myDialog = document.getElementById('dialog'),
myClose = document.getElementById('close');
if (!listenersSet) {
if (!window.addEventListener) { // IE8 has no addEventListener
myclose.attachEvent('onclick', function () {
hideMyDialog();
});
} else {
myClose.addEventListener('click', function () {
hideMyDialog()
});
['webkitTransitionEnd','oTransitionEnd', 'otransitionend', 'transitionend'].forEach(function (eventName) {
myDialog.addEventListener(eventName, function (e) {
if (e.target === myDialog && e.propertyName === 'top') { // only do trigger if it is the top transition of the modalDialog that has ended
if (!dialogShouldBeVisible) {
myDialog.style.display = 'none';
e.stopPropagation();
}
}
});
});
}
listenersSet = true;
}
myDialog.style.display = 'block';
myDialog.style.top = '15px';
myDialog.style.opacity = '1';
dialogShouldBeVisible = true;
}
window.hideMyDialog = function () {
var myDialog = document.getElementById('dialog'),
myClose = document.getElementById('close');
myDialog.style.top = '-5%';
myDialog.style.opacity = '0.1';
dialogShouldBeVisible = false;
}
It is working in Opera, Firefox, Chrome and IE10, but not in IE8 and IE9 (afaik)
If I did a bad job explaining my problem, please let me know, and I will try do a better job! :)
Copied from bootstrap transition, it not only returns true if browser supports transition but also returns proper name of event
function transitionEnd() {
var el = document.createElement('div')//what the hack is bootstrap
var transEndEventNames = {
WebkitTransition : 'webkitTransitionEnd',
MozTransition : 'transitionend',
OTransition : 'oTransitionEnd otransitionend',
transition : 'transitionend'
}
for (var name in transEndEventNames) {
if (el.style[name] !== undefined) {
return transEndEventNames[name];
}
}
return false // explicit for ie8 ( ._.)
}
Hope this helps.
EIDT:
I modified a little bit default bootstrap function so it doesn't return object but string.
I would definitely use this small script available on Github.
It's listed among Modernizr "Cross-browser polyfills" page so it can be trusted but Modernizr itself is not required.
The examples in the Github page of the script are written using jQuery (and I can't understand why) but jQuery is also not required as it's written in vanilla js.
Like so you'll have a useful whichTransitionEnd method available. I can't test it right now being on my laptop without IE8/IE9 available but I guess that this method will return false (or anything falsy) in those browsers.
var transition = transitionEnd(box).whichTransitionEnd();
// return for example "webkitTransitionEnd"
It will then be quite easy to target those browsers where transitions (and thus transitionend events) are not supported. Hope this will be a nudge in the right direction.
EDIT
After tweaking with the above code the OP came up with a much shorter version of the original script. It saves a good deal of bytes and only detects support for this event, and, in case it's supported returns the name of the event itself.
You can find it here as a gist and read more about it in the comments to this answer.
I'd been using Swiffy to output .fla files pretty easily, but then I was tipped off that the display would alternate "flashing" white over half the project if viewed in Landscape Mode on a iPad. Very strange behavior, which I couldn't replicate on any other device.
So, I've moved on to trying to use CreateJS to fix the issue. I only know enough JS at this time to get by editing code developed by others, so I've been very ineffective so far.
I've gotten this far:
/* js
this.stop();
var t=setTimeout(function(){(this.play())}, 1000);
*/
or
/* js
this.stop();
setTimeout(this.play(), 1000);
*/
I've not been able to get the animation to mind the timeout, and I've tried MANY different variants to try and make some magic happen. All it does is immediately loads the next frame, it doesn't pause at all. Where am I going wrong here?
Here is the original Actionscript:
stop();
var shortTimer:Timer=new Timer(1000);
shortTimer.addEventListener(TimerEvent.TIMER, timerN1);
shortTimer.start();
function timerN1(e:TimerEvent):void{
play();
shortTimer.reset();
}
Any help would be very appreciated, as I've gotten no where on my own trying to fix this is in my off time for several weeks, and my client is becoming increasingly angry. More of a designer, still very uneducated as far as programming is concerned. Again, even a suggestion would be super helpful at this point. Can't seem to crack it.
This syntax is more correct:
/* js
this.stop();
var t=setTimeout(function(){(this.play())}, 1000);
*/
However, you may find that "this" is Window, not the MovieClip that calls it. You can get around this by using a local reference (in this case, its "_this").
/* js
this.stop();
var _this = this;
var t=setTimeout(function(){
console.log(this, _this);
_this.play();
}, 1000);
*/
You can test this by looking at your console, and seeing what the difference between "this" and "_this" is.
Cheers.
Could you possibly post more of the code you are working with? Have you tried using the onAnimationEnd function:
var _this = this;
_this.onAnimationEnd = function() {
_this.stop();
setTimeout(function(){
_this.play();
}, 1000)
}
Try this to keep your scope alive inside your setTimeout function :
sprite.on('animationend', function(event) {
event.target.stop();
setTimeout(animationend.bind(event.target), 1000);
});
function animationend() {
this.gotoAndPlay('run');
}
With the use of .bind() you can pass an object as the scope in the called function. More information here.