How do I keep my error message from flashing twice? - javascript

I have a little error mechanism that displays an error by fading it in, waiting a few secs, and fading out. It works if I let it run through the whole process, but if I quickly click on a lot of things that show errors, here is where it goes wrong.
The error message shows, then fades in and out. So I tried solving this by adding a var called is_fading to check the current status of the error, but it didnt work. Here is my code:
errors: {
is_fading: false,
render: function (msg) {
GroupManagement.error.html(msg);
if (GroupManagement.errors.is_fading == true)
{
GroupManagement.error.delay(1500).fadeOut();
GroupManagement.errors.is_fading = false;
return;
}
else
{
GroupManagement.error.fadeIn('normal', function()
{
GroupManagement.errors.is_fading = true;
$(this).delay(1500).fadeOut();
GroupManagement.errors.is_fading = false;
});
}
}
},
As mentioned before, this is just what I thought would solve the problem, but doesn't. Does anyone know why?

Credit goes to #Mehdi, the answer is:
errors: {
is_fading: false,
render: function (msg) {
GroupManagement.error.html(msg);
if (GroupManagement.errors.is_fading == true)
{
GroupManagement.error.delay(1500).fadeOut('', function () {
GroupManagement.errors.is_fading = false;
});
return;
}
else
{
GroupManagement.error.fadeIn('normal', function()
{
GroupManagement.errors.is_fading = true;
$(this).delay(1500).fadeOut('', function () {
GroupManagement.errors.is_fading = false;
});
});
}
}
},

Related

CasperJS: WaitFor timeout function to do rescroll?

I met some problem when I use CasperJS to scrape a website. The website is dynamically loaded like Twitter, so I want to do infinite scroll,
and thanks to #Artjom B. I found you code to do this.
var tryAndScroll = function (casper) {
try {
casper.echo('SCROLL!!');
casper.scrollToBottom();
if (casper.exists('div.loading')) {
var curItems = casper.evaluate(getCurrentInfosNum);
casper.echo(curItems);
casper.waitFor(function check() {
return curItems != casper.evaluate(getCurrentInfosNum);
}, function then() {
casper.wait(800);
tryAndScroll(casper);
}, function onTimeout() {
casper.emit('scroll.timeout',curItems);
}, 15000);
} else {
casper.echo("No more items");
return true;
}
} catch (err) {
casper.echo(err);
}
} //casper.tryAndScroll
And now, I want to continue to scroll many times when the timeout function invoked so I create my own event listener,‘scroll.timeout’.
var SRCOLL_NUM = 0;
var PreOfLoaded = 0;
casper.on('scroll.timeout', function (NumOfLoaded) {
if (SRCOLL_NUM <= 4) {
if (PreOfLoaded == NumOfLoaded)
SRCOLL_NUM++;
this.echo("Scroll Timeout,reScroll");
PreOfLoaded = NumOfLoaded;
tryAndScroll(casper);
} else {
this.echo("Scroll Timeout,reScroll times maximum");
SRCOLL_NUM = 0;
PreOfLoaded = 0;
}
});
However, when scroll timeout occurred, it printed Scroll Timeout,reScroll on the console. Then it skips tryAndScroll() and go to the next step in the main function. I want to continue to next step after retry scroll many times. What should I do?
I found CasperJS author illustrate :Automatic retry when open fails
var casper = require('casper').create();
casper.tryOpen = function(url, then) {
return this.then(function() {
this.open(url);
this.waitFor(function testStatus() {
return this.getCurrentHTTPStatus === 200;
}, then, function onFail() {
console.log('failed, retrying');
this.tryOpen(url);
}, 2000);
});
};
casper.start().tryOpen('http://failing.url.com/foo.bar', function() {
this.echo('wow, it worked, wtf');
}).run();
unfortunately, it doesn't work for me.
Try this
return this.currentHTTPStatus === 200;
I tested with the newest version of casperjs 1.1.1, it's working fine

jQuery - If browser tab is focused, then do AJAX - Not working

I have a code that determines if current browser window or tab is active. If it's active, the title of the tab says "active" and if not it says "blurred"
It is working fine. Here's the code:
$(window).on("blur focus", function (e) {
var prevType = $(this).data("prevType");
if (prevType != e.type) { // reduce double fire issues
if (e.type == "blur") {
document.title = 'blurred';
} else if (e.type = "focus") {
document.title = 'focus';
}
}
$(this).data("prevType", e.type);
})
The code above is working fine.
Now if I add AJAX to it, it doesn't work.
$(window).on("blur focus", function (e) {
var prevType = $(this).data("prevType");
if (prevType != e.type) { // reduce double fire issues
if (e.type == "blur") {
document.title = 'blurred';
} else if (e.type = "focus") {
var interval = function () {
$.ajax({
url: "<?php echo base_url('home/get') ?>",
cache: false,
success: function (html) {
$("#text").val(html);
document.title ='focus';
},
});
};
setInterval(interval, <?php echo $int ?>);
}
}
$(this).data("prevType", e.type);
})
It says focused if it's in focus. If I go out of focus, it says "blurred" for less than a second, then says focus again. I don't know why. I want it to say blurred if it's not in focus. Adding the AJAX code doesn't make it work.
Please help. Thanks.
You need to use clearTimeout() in your blur event. My code continuously polls my server for data, but when I go out of the page, it stops polling. Please look at the implementation below. I have done the similar one in my application here:
$(window).blur(function() {
clearTimeout(getJsonTmr);
clearTimeout(updatePreviewTmr);
}).focus(StartTimers);
function StartTimers () {
// Every half a second,
getJsonTmr = setInterval(function () {
$.get("/doodles/update?getJson&DoodleID=" + DoodleOptions.DoodleID, function (data) {
data = JSON.parse(data);
if (!DoodleOptions.isActive)
clearDoodleCanvas();
$.each(data, function (index) {
drawFromStream(data[index]);
});
});
}, 500);
updatePreviewTmr = setInterval(function () {
$.post("/doodles/update?updatePreview", {
"DoodleID": DoodleOptions.DoodleID,
"DoodlePreview": canvas.toDataURL()
});
}, 5000);
}
StartTimers();
You can use the above code as reference and change yours.
A simple reference implementation for you...
function timers() {
tmrAjax = setInterval(function () {
$.get(/* ... */);
}, 1000);
}
timers();
$(window).blur(function () {
clearInterval(tmrAjax);
}).focus(timers);

Need help stopping slideshow using jQuery

I've run into an issue with jQuery code that I'd like some help on. While the next and previous buttons work correctly, there appears to be an issue correctly stopping a slideshow. This is probably something we're completely overlooking, but I can't see what.
There is no JavaScript errors showing in the console. The interrupt method was being reached - at one point I had console.log calls in there to verify (cleaned up for presentation reasons).
http://jsfiddle.net/eLn83ep0/
Your help is much appreciated.
The below code is the functionality for prev/stop/start/next:
if ($(settings.next).size()) {
$(settings.next).bind('click.scrollface', function (e) {
methods.interrupt.call($this);
methods.next.call($this);
});
}
if ($(settings.pause).size()) {
$(settings.pause).bind('click.scrollface', function (e) {
methods.interrupt.call($this);
});
}
if ($(settings.play).size()) {
$(settings.play).bind('click.scrollface', function (e) {
methods.interrupt.call($this);
methods.start.call($this);
});
}
/*
* Setup up prev bindings
*/
if ($(settings.prev).size()) {
$(settings.prev).bind('click.scrollface', function (e) {
methods.interrupt.call($this);
methods.prev.call($this);
});
}
Here is the method for interrupt:
interrupt: function (time) {
return $(this).each(function () {
var data = $(this).data('scrollface');
console.log(data);
console.log('...');
if (!data) {
return false;
}
var $this = $(this),
period = 0;
/*
* Stop the timer, and wait a period of time before restarting it.
* Period defaults to the timer interval
*/
if (data.timer) {
if (typeof time !== "number") {
period = data.interval;
} else {
period = time;
}
methods.stop.call(this);
setTimeout(function resume_timer () {
clearInterval(data.timer);
data.timer = null;
methods.start.call($this);
}, period);
}
});
},
if ($(settings.pause).size()) {
$(settings.pause).bind('click.scrollface', function (e)
methods.stop.call($this);
});
}
if ($(settings.play).size()) {
$(settings.play).bind('click.scrollface', function (e) {
methods.start.call($this);
});
}
and delete the interrupt call in prev and next
//methods.interrupt.call(this);
because the interrupt method stopping the interval method and after timeout starting again, so most time you pause in this timeout but after this timeout the interrupt method starting the intervall again and dont care if you stoped it manually
see your updated fiddle working here http://jsfiddle.net/7ko4rdda/
Edit:
if you call interrupt with 0 for the buttons prev next click handler then you have the expected behavier that the period for the intervall starts new after next/prev click
if ($(settings.prev).size()) {
$(settings.prev).bind('click.scrollface', function (e) {
methods.interrupt.call($this,0);
methods.prev.call($this);
});
}
if ($(settings.next).size()) {
$(settings.next).bind('click.scrollface', function (e) {
methods.interrupt.call($this,0);
methods.next.call($this);
});
}
http://jsfiddle.net/7ko4rdda/1/

Returning true on Link Click Event isn't working

I am trying to execute some code that has a callback when clicking on specific links. The callback is to click the link again, but on the second pass, the method returns true to follow normal behavior. But for some reason, it's not working? I use clickedLink for proper scope. In the event callback, this was referring to window.
UPDATE
For a little more clarity, I agree normally this wouldn't be an optimal solution, but I am using Google's Tag Manager to monitor eCommerce traffic. I am trying to make sure product clicks get pushed to their dataLayer, and using their event callback to resume normal behavior. More info here: https://developers.google.com/tag-manager/enhanced-ecommerce#product-clicks
This is my updated method based on the answers below, but it still doesn't work.
var shopCartBtnClicked = false;
var clickedLink;
jQuery('#pdp_add_cart, .add_to_cart_button').click(function(e) {
if (shopCartBtnClicked === true) {
shopCartBtnClicked = false; //I make it here just fine
} else {
e.preventDefault();
clickedLink = this;
var pdp = false;
if (mmProduct) {
//On detail page
mmProduct.qty = jQuery('input[name="quantity"]').val();
pdp = true;
} else {
//on a shopping page
mmProduct = findProductClicked(this);
mmProduct.qty = 1;
}
dataLayer.push({
'event': 'addToCart',
'ecommerce': {
'currencyCode': 'USD',
'add': {
'products': [{
'name': mmProduct.name,
'id': mmProduct.id,
'price': mmProduct.price,
'quantity': mmProduct.qty
}]
}
},
'eventCallback': function () {
//Are we on a product detail page with a form, or just a shopping page with a link?
if (pdp) {
jQuery('form.cart').submit(); //This part works just fine
} else {
mmProduct = null;
shopCartBtnClicked = true;
$(clickedLink).trigger('click'); //This doesn't
}
}
});
}
});
Its not very well done, but this should work:
var shopCartBtnClicked = false;
var clickedLink;
jQuery('.add_to_cart_button').click(function(e) {
if (shopCartBtnClicked === true) {
shopCartBtnClicked = false;
// dont return, just let javascript handle this one
} else {
// only execute when you have not set it to true
e.preventDefault();
clickedLink = this;
shopCartBtnClicked = true;
$(clickedLink).trigger('click');
}
});
I do have to wonder why you don't just execute your other logic first and then not prevent default anyway.
Taking #somethinghere's answer, your code can further be simplified to improve readability:
var shopCartBtnClicked = false;
jQuery('.add_to_cart_button').click(function(e) {
if( shopCartBtnClicked ) {
shopCartBtnClicked = false;
// dont return, just let javascript handle this one
} else {
// only execute when you have set it to true
e.preventDefault();
shopCartBtnClicked = true;
this.click();
}
});
Or, as suggested by #Regent:
var shopCartBtnClicked = false;
jQuery('.add_to_cart_button').click(function(e) {
shopCartBtnClicked = !shopCartBtnClicked;
if( shopCartBtnClicked ) {
e.preventDefault();
this.click();
}
});
OK guys, thank you for helping me get there. Normally, all of the other answers would work great, but for this specific tag manager instance, it appears (for some unknown reason), document.location works in the event callback fine here. This works.
It's weird because I used $(this).('form.cart').submit(); in a callback earlier in the code.
'eventCallback': function () {
//Are we on a product detail page with a form, or just a shopping page with a link?
if (pdp) {
jQuery('form.cart').submit();
} else {
mmProduct = null;
document.location = $(clickedLink).attr('href');
//$(clickedLink).trigger('click');
}
}

Where in this code do I need to put 'return false'?

When I click on the 'slide-toggle' link, my url turns from mysite.com to mysite.com/#
I was told that I needed to put a 'return false' somewhere in here but I'm not sure where. Can someone kindly help me out?
$(document).ready(function() {
$('a#slide-up').click(function () {
$('.slide-container').slideUp(function(){
$('#slide-toggle').removeClass('active');
});
return false;
});
$('a#slide-toggle').click(function() {
var slideToggle = this;
if ($('.slide-container').is(':visible')) {
$('.slide-container').slideUp(function() {
$(slideToggle).removeClass('active');
});
}
else {
$('.slide-container').slideDown();
$(slideToggle).addClass('active');
}
});
});
It would be nicer not to use return false but to use event.preventDefault instead. You can put this at the very top of your event handler:
$('a#slide-toggle').click(function(e) { // note e added as the function's parameter
e.preventDefault();
var slideToggle = this;
if ($('.slide-container').is(':visible')) {
$('.slide-container').slideUp(function() {
$(slideToggle).removeClass('active');
});
}
else {
$('.slide-container').slideDown();
$(slideToggle).addClass('active');
}
});
This has the same effect as return false, but with the following advantages:
It is semantically more logical -- it does what it says
You can put it at the head of the function, so it is immediately obvious
You can have multiple exit points without having to ensure they are all return false
If any part of your code causes an error, the default action will still be prevented
like this:
$('a#slide-toggle').click(function() {
var slideToggle = this;
if ($('.slide-container').is(':visible')) {
$('.slide-container').slideUp(function() {
$(slideToggle).removeClass('active');
});
}
else {
$('.slide-container').slideDown();
$(slideToggle).addClass('active');
}
return false;
});
Probably you need to add the return false also in the $('a#slide-toggle').click() function
$(document).ready(function() {
$('a#slide-up').click(function () {
$('.slide-container').slideUp(function(){
$('#slide-toggle').removeClass('active');
});
return false;
});
$('a#slide-toggle').click(function() {
var slideToggle = this;
if ($('.slide-container').is(':visible')) {
$('.slide-container').slideUp(function() {
$(slideToggle).removeClass('active');
});
}
else {
$('.slide-container').slideDown();
$(slideToggle).addClass('active');
}
**return false;**
});
});
I think, it should be like this:
$('a#slide-toggle').click(function() {
var slideToggle = this;
if ($('.slide-container').is(':visible')) {
$('.slide-container').slideUp(function() {
$(slideToggle).removeClass('active');
});
}
else {
$('.slide-container').slideDown();
$(slideToggle).addClass('active');
}
return false;
});
You have one at the end of slide-up; add one to the end of slide-toggle.

Categories

Resources