jQuery Mobile And a js counter executed twice - jquery-mobile

I have a e-commerce site with a 20 min max basket time. I wrote a simple counter in JS to display the timeleft like this :
function basketCounter() {
var minutes = Math.floor(count / 60);
var sec = count - minutes * 60;
if (sec < 10) {
sec = '0' + sec;
}
console.log("hello");
$(".temps_restant").html("reste: " + minutes + " : " + sec );
$("#tunnel_panier_temps").html("" + minutes);
if (count == 0) {
window.location = '{{serverRequestUri}}flush_panier/1/';
}
count--;
}
And in the body :
var count = {{panierTmp.lifetime - now}};
$(document).bind('pageinit', function() {
$("img.lazy").unveil();
if (count > 0) {
setInterval('basketCounter()', 1000);
}
});
It works fine when I'm navigate on the site without ajax.
But when i'm trying to navigate trought ajax in JQM, the counter is re-executing each time and speeding, 2sec by 2sec, and if I go back twice it will be 3sec by 3 sec..
I can't find any solution..

Your pageinit is wrong, it should be executed only once:
var count = {{panierTmp.lifetime - now}};
var interval=null;
$(document).bind('pageinit', function() {
$("img.lazy").unveil();
if (count > 0 && !interval) {
interval=setInterval('basketCounter()', 1000);
}
});
Without this check, every pageinit event will add another interval calling basketCounter.
You could also check data existence instead of setting a variable.
if(!$(document).hasData('basketCounter')){
$(document).data('basketCounter',{{panierTmp.lifetime - now}});
}

You could try the following:
1) try removing any hidden pages
<head>
document.on('pagehide', function(e) {
$(e.target).remove();
});
</head>
2) Unbind and bind the page event.
$(document).off('pageinit').on('pageinit', ....

Related

Reset/Allow addEventListener after removeEventListener

Still pretty new to Javascript so apologies if this Q has been asked a hundred times, not completely sure what I should be searching for (terminology).
I have a couple nested events and these so far work, and removing these events works as well. The issue is that once the event is removed with removeEventListener, the addEventListener events no longer fire again without a page reload.
Current code:
// Listen for mousedown.
handle.addEventListener("mousedown", function icHandleDrag (e) {
e.preventDefault();
dragging = true;
// Listen for mousemove.
document.body.addEventListener("mousemove", function icResizeResize (ex) {
var adjustOffsetLeft = ex.pageX - icContainerLeft,
offsetLocation = ((adjustOffsetLeft / icContainerWidth) * 100) + "%";
if (adjustOffsetLeft > (icContainerWidth * 0.01) && adjustOffsetLeft < (icContainerWidth * 0.99)) {
resize.style.width = offsetLocation;
handle.style.left = offsetLocation;
}
// Listen for mouseup.
handle.addEventListener("mouseup", function icStopDragging () {
if (dragging) {
// Remove event listeners.
handle.removeEventListener("mousedown", icHandleDrag);
document.body.removeEventListener("mousemove", icResizeResize);
handle.removeEventListener("mouseup", icStopDragging);
dragging = false;
}
});
});
});
In most docs/posts I've read, the suggestions say to create a function, then pass that function to a separate event listener (not quite sure how to do that with the current nested structure).
Is there a way I can keep my addEventListener's functioning after a removeEventListener? Or will I have to look at a different approach for structurinng this code?
Thanks!
It's because you are removing the mousedown EventListener and it never gets added again.
I've changed the code you provided. Now the mousedown is not being removed, and have isolated the functions for readability.
See if this helps.
// Listen for mousedown.
handle.addEventListener("mousedown", icHandleDrag);
function icHandleDrag (e) {
e.preventDefault();
dragging = true;
// Listen for mousemove.
document.body.addEventListener("mousemove", icResizeResize);
}
function icResizeResize (ex) {
var adjustOffsetLeft = ex.pageX - icContainerLeft,
offsetLocation = ((adjustOffsetLeft / icContainerWidth) * 100) + "%";
if (adjustOffsetLeft > (icContainerWidth * 0.01) && adjustOffsetLeft < (icContainerWidth * 0.99)) {
resize.style.width = offsetLocation;
handle.style.left = offsetLocation;
}
// Listen for mouseup.
handle.addEventListener("mouseup", icStopDragging);
}
function icStopDragging () {
if (dragging) {
// Remove event listeners.
document.body.removeEventListener("mousemove", icResizeResize);
handle.removeEventListener("mouseup", icStopDragging);
dragging = false;
}
}

Detect Session Timeout and display popup when session is about to clear in mvc

I have to display a popup window when my session is about to clear in .net MVC.
example
I want same thing implement in MVC. What should I do???
Here I have try some code:
This is the controller page(error comes that ClientScript doesnot exist):
Configuration config = WebConfigurationManager.OpenWebConfiguration("~/Web.Config");
SessionStateSection section = (SessionStateSection)config.GetSection("system.web/sessionState");
int timeout = (int)section.Timeout.TotalMinutes * 1000 * 60;
ClientScript.RegisterClientScriptBlock(this.GetType(),"SessionAlert", "SessionExpireAlert(" + timeout + ");", true);
Here is my script in view(that I call from controller):
<script type="text/javascript">
function SessionExpireAlert(timeout) {
var seconds = timeout / 1000;
document.getElementsByName("secondsIdle").innerHTML = seconds;
document.getElementsByName("seconds").innerHTML = seconds;
setInterval(function () {
seconds--;
document.getElementById("seconds").innerHTML = seconds;
document.getElementById("secondsIdle").innerHTML = seconds;
}, 1000);
setTimeout(function () {
//Show Popup before 20 seconds of timeout.
$find("mpeTimeout").show();
}, timeout - 20 * 1000);
setTimeout(function () {
window.location = "Expired.aspx";
}, timeout);
};
function ResetSession() {
//Redirect to refresh Session.
window.location = window.location.href;
}
</script>
Get the timeout for the users session first:
int sessionTimeout = HttpContext.Current.Session.Timeout;
DateTime timeoutDate = DateTime.Now.AddMinutes(sessionTimeout);
You can pass that to your view through your Model or ViewBag and use a javascript timer to pop up an alert. (Since session is refreshed on every request, this will be an accurate timeout).
View:
#{
int milliseconds = (int)ViewBag.sessionTimeout * 60 * 1000;
}
setTimeout(function(){alert("SessionPop!");}, #milliseconds.ToString());
But since sessions are refreshed on hitting controller actions you might want to provide real time support (especially if your app is going to be used in multiple tabs or heavily utilizes AJAX calls). You could look into using SignalR to update in real time when the new session timeout will expire to the user.
AFAIK, MVC controller doesn't require ClientScript.RegisterClientScriptBlock when passing a script content into view. You can just register the script block using ViewBag/ViewData and Html.Raw like this one, just ensure that the controller returns view with ViewBag/ViewData included:
public ActionResult WarnTimeout()
{
Configuration config = WebConfigurationManager.OpenWebConfiguration("~/Web.Config");
SessionStateSection section = (SessionStateSection)config.GetSection("system.web/sessionState");
int timeout = (int)section.Timeout.TotalMinutes * 1000 * 60;
ViewBag.Script = "\r\n<script type='text/javascript'>\r\nSessionExpireAlert(" + timeout + ");\r\n</script>\r\n");
return View();
}
// View (use Html.Raw to include script tag into view)
#Html.Raw(ViewBag.Script)
<script type="text/javascript">
function SessionExpireAlert(timeout) {
var seconds = timeout / 1000;
document.getElementsByName("secondsIdle").innerHTML = seconds;
document.getElementsByName("seconds").innerHTML = seconds;
setInterval(function () {
seconds--;
document.getElementById("seconds").innerHTML = seconds;
document.getElementById("secondsIdle").innerHTML = seconds;
}, 1000);
setTimeout(function () {
//Show Popup before 20 seconds of timeout.
$find("mpeTimeout").show();
}, timeout - 20 * 1000);
setTimeout(function () {
// when using MVC, you may use Url.Action instead of providing ASPX relative path
window.location = "#Url.Action("Expired", "Controller")";
}, timeout);
};
function ResetSession() {
//Redirect to refresh Session.
window.location = window.location.href;
}
</script>
Alternatively, jQuery ajax call ($.ajax({ ... })) with certain data provided then setting desired alert box operation inside success part may be used.
Any suggestions welcome.
Reference to similar problem:
How do I warn the user that their web session is about to time out?

photoswipe returning to initial hash of current page instead of last scroll position

On IOS, when I close photoswipe to return to the page, it wont return to the scroll position I was at when I clicked the thumbnail.
Instead the page scrolls back to the # which was specified when I initially called the page.
For example if photoswipe is on www.somepage.html, and I navigate to the page using:
www.somepage.html#footer
and then scroll up and click a thumnail in #middle of page, on closing photoswipe, the page scrolls back down to the footer.
I've tried disabling history in the photswipe options, and i've also tried clearing the hash data from the url using:
//clear hash
//$(document).ready(function (e) {
// window.location.hash = '';
// window.history.pushState("", document.title, window.location.pathname);
//
//});
But none of it seems to work. If I navigate to the page without the # in the page, everthing is fine.
I'm guessing I may have to pass a variable in the url instead of the # and scroll to the div in question via javascript?
I already have the javascript in place to scroll, but I'm not sure how to read the variable from the url and then use it's value in Javascript.
If this is likely to be the best fix for the issue, could anyone give an example of the javascript code needed?
Here's my current scroll code:
$(function () {
$('a[href*=#]:not([href=#],[data-toggle],[data-target],[data-slide])').click(function () {
if (location.pathname.replace(/^\//, '') == this.pathname.replace(/^\//, '') || location.hostname == this.hostname) {
var target = $(this.hash);
target = target.length ? target : $('[name=' + this.hash.slice(1) + ']');
if (target.length) {
$('html,body').animate({
scrollTop: target.offset().top
}, 1000);
return false;
}
}
});
});
If anyone else has the same issue, I've managed to fix this by passing the div id to the page in the query string rather than using a #.
Here's the code:
$(window).ready(function () {
if (document.location.search.length) {
target = getUrlVars()["id"];
scrollToID('#' + target, 750);
} else {
return;
}
//target = $url().param('id');
//if (target == '') return;
});
function getUrlVars() {
var vars = [], hash;
var hashes = window.location.href.slice(window.location.href.indexOf('?') + 1).split('&');
for (var i = 0; i < hashes.length; i++) {
hash = hashes[i].split('=');
vars.push(hash[0]);
vars[hash[0]] = hash[1];
}
return vars;
}
// scroll function
function scrollToID(id, speed){
var offSet = 100;
var targetOffset = $(id).offset().top - offSet;
var mainNav = $('#main-nav');
$('html,body').animate({scrollTop:targetOffset}, speed);
if (mainNav.hasClass("open")) {
mainNav.css("height", "1px").removeClass("in").addClass("collapse");
mainNav.removeClass("open");
}
}
if (typeof console === "undefined") {
console = {
log: function() { }
};
}

Showing Events on a Datepicker with Server-side data

I have been busy creating a solution to a client that has proven to be a bit more difficult than I thought it would be. I am using the jQuery Datepicker widget to display calendar events (monthly view) from server-side code. Every thing in the following code works EXCEPT the CSS. It is not changing anything and it seems I've tried everything in the world.
A Calendar is shown in month-view on page-load (MVC) and if a user has events the day should have a different background-color. Also, when the user changes month-to-month, the same logic happens (ajax call to server). Again, this all is working well. My directive to change the background color will not.
<script type="text/javascript">
$(document).ready(function () {
$.expr[":"].exactly = function (el, i, m) {
var s = m[3];
if (!s) return false;
return eval("/^" + s + "$/i").test($(el).text());
};
var currentYear = (new Date).getFullYear();
var currentMonth = (new Date).getMonth();
function getTheData(year, month) {
var theYear = year;
var theMonth = month;
//alert(theYear + ", " + theMonth);
$.post("GetMeSomeData", { year: theYear, month: theMonth }, function(data) {
//cycle through the dates and address the CSS appropriately
var i = 0;
for (i = 0; i < data.length; i++) {
$('.ui-datepicker-calendar td a:exactly(' + data[i]['d'] + ')')
.css({ backgroundColor: 'blue' });
}
});
}
$('#date').datepicker({
inline: true,
beforeShowDay: getTheData(currentYear, currentMonth),
onSelect: function (dateText, inst) {
Date.prototype.toString = function () { return isNaN(this) ? 'NaN' : [this.getDate(), this.getMonth(), this.getFullYear()].join('/'); };
d = new Date(dateText);
//alert(d.getDate() + ", " + d.getFullYear());
getTheData(d.getFullYear(), d.getDate());
},
onChangeMonthYear: function (year, month, inst) {
//alert(year + ", " + month);
getTheData(year, month);
}
});
});
</script>

Displaying Twitter stream on webpage?

I want to display a twitter feed of a user on my website. What is the simplest way to do this? I guess Javascript. What I want specifically is for the last 5 tweets to load & then, when another tweet is made, for that to automatically appear at the top of the Tweets. It needs to cover pretty much the whole website, apart from the header & footer. Any suggestions/code to do that?
Cheers, help greatly appreciated!
Loading new data without refreshing will need to be AJAX. To get the data, ses the Twitter API http://apiwiki.twitter.com/. The API will allow you to get the data in the format of choice (xml, json, ect...) which you can then parse and return either the data or HTML to the page that submitted the AJAX call. That should give you a push in the right direction.
Simplest way would be adding the Twitter widget : http://twitter.com/goodies/widget_profile and it updates new tweets automatically (using AJAX I think). You ca set the dimensions too.
use any twitter wrapper calss for example this http://emmense.com/php-twitter/ to get the status and display it. than use javascript time function inside function make ajax call to php script and append latest tweet on top of your container.
you can use jquery for dom update
$('#dividhere').prepend('Bla bla bla');
use jQuery, sry for my programming language, but i like our czech lang
<script type="text/javascript">
jQuery(document).ready(function($){
$.getJSON('http://api.twitter.com/1/statuses/user_timeline/##USERNAME##.json?count=2&callback=?', function(zpravicky){
$("#twitter").html(formatujExtSocialniProfil(zpravicky));
});
});
</script>
in external javascript file code like this
function formatujExtSocialniProfil(twitters) {
var statusHTML = [];
for (var i=0; i<twitters.length; i++){
var username = twitters[i].user.screen_name;
var status = twitters[i].text.replace(/((https?|s?ftp|ssh)\:\/\/[^"\s\<\>]*[^.,;'">\:\s\<\>\)\]\!])/g, function(url) {
return ''+url+'';
}).replace(/\B#([_a-z0-9]+)/ig, function(reply) {
return reply.charAt(0)+''+reply.substring(1)+'';
});
statusHTML.push('<li><span>'+status+'</span> <br/><b>'+relative_time(twitters[i].created_at)+'</b></li>');
}
return statusHTML.join('');
}
function relative_time(time_value) {
var values = time_value.split(" ");
time_value = values[1] + " " + values[2] + ", " + values[5] + " " + values[3];
var parsed_date = Date.parse(time_value);
var relative_to = (arguments.length > 1) ? arguments[1] : new Date();
var delta = parseInt((relative_to.getTime() - parsed_date) / 1000);
delta = delta + (relative_to.getTimezoneOffset() * 60);
if (delta < 60) {
return 'seconds ago';
} else if(delta < 120) {
return 'minute ago';
} else if(delta < (60*60)) {
return (parseInt(delta / 60)).toString() + ' minutes';
} else if(delta < (120*60)) {
return 'hours ago';
} else if(delta < (24*60*60)) {
return 'ago ' + (parseInt(delta / 3600)).toString() + ' hours';
} else if(delta < (48*60*60)) {
return 'yesterday';
} else {
return 'since ago' + (parseInt(delta / 86400)).toString() + ' days';
}
}

Resources