我在我的一个网站上使用Paul Irish 的 jquery idle timer和fancyapps 的 fancybox。我想让空闲计时器检测正在播放的fancybox幻灯片(按下空格键)作为活动,直到它停止,从而保持会话处于活动状态。基本上我需要确保当有人观看大量图片的幻灯片时,它不会在我为不活动设置的计时器结束时停止。
我知道客户端脚本对于管理会话并不安全(我已经通过其他几篇文章经历过),所以这不是我的问题的重点;我完全了解我计划以不同方式管理的安全性倒退(即,如果未在浏览器中激活 js,则注销)。
相关代码是(我相信):
花式盒子:
$.extend(F, {
...
defaults: {
...
keys : {
...
play : [32], // space - start/stop slideshow
...
}
...
}
...
// Manage slideshow:
// $.fancybox.play(); - toggle slideshow
// $.fancybox.play( true ); - start
// $.fancybox.play( false ); - stop
play: function ( action ) {
var clear = function () {
clearTimeout(F.player.timer);
},
set = function () {
clear();
if (F.current && F.player.isActive) {
F.player.timer = setTimeout(F.next, F.current.playSpeed);
}
},
stop = function () {
clear();
$('body').unbind('.player');
F.player.isActive = false;
F.trigger('onPlayEnd');
},
start = function () {
if (F.current && (F.current.loop || F.current.index < F.group.length - 1)) {
F.player.isActive = true;
$('body').bind({
'afterShow.player onUpdate.player' : set,
'onCancel.player beforeClose.player' : stop,
'beforeLoad.player' : clear
});
set();
F.trigger('onPlayStart');
}
};
if (action === true || (!F.player.isActive && action !== false)) {
start();
} else {
stop();
}
}
...
}
空闲计时器:
( function( $ ) {
$.idleTimer = function( firstParam, elem, opts ) {
// defaults that are to be stored as instance props on the elem
opts = $.extend( {
startImmediately: true, //starts a timeout as soon as the timer is set up
idle: false, //indicates if the user is idle
enabled: true, //indicates if the idle timer is enabled
timeout: 30000, //the amount of time (ms) before the user is considered idle
events: "mousemove keydown DOMMouseScroll mousewheel mousedown touchstart touchmove" // activity is one of these events
}, opts );
elem = elem || document;
var jqElem = $( elem ),
obj = jqElem.data("idleTimerObj") || {},
/* (intentionally not documented)
* Toggles the idle state and fires an appropriate event.
* @return {void}
*/
toggleIdleState = function( myelem ) {
// curse you, mozilla setTimeout lateness bug!
if ( typeof myelem === "number" ) {
myelem = undefined;
}
var obj = $.data( myelem || elem, "idleTimerObj" );
//toggle the state
obj.idle = !obj.idle;
// reset timeout
var elapsed = ( +new Date() ) - obj.olddate;
obj.olddate = +new Date();
// handle Chrome always triggering idle after js alert or comfirm popup
if ( obj.idle && ( elapsed < opts.timeout ) ) {
obj.idle = false;
clearTimeout( $.idleTimer.tId );
if ( opts.enabled ) {
$.idleTimer.tId = setTimeout( toggleIdleState, opts.timeout );
}
return;
}
// create a custom event, but first, store the new state on the element
// and then append that string to a namespace
var event = $.Event( $.data( elem, "idleTimer", obj.idle ? "idle" : "active" ) + ".idleTimer" );
$( elem ).trigger( event );
},
/**
* Stops the idle timer. This removes appropriate event handlers
* and cancels any pending timeouts.
* @return {void}
* @method stop
* @static
*/
stop = function( jqElem ) {
var obj = jqElem.data("idleTimerObj") || {};
//set to disabled
obj.enabled = false;
//clear any pending timeouts
clearTimeout( obj.tId );
//detach the event handlers
jqElem.off(".idleTimer");
};
obj.olddate = obj.olddate || +new Date();
if ( typeof firstParam === "number" ) {
opts.timeout = firstParam;
} else if ( firstParam === "destroy" ) {
stop( jqElem );
return this;
} else if ( firstParam === "getElapsedTime" ) {
return ( +new Date() ) - obj.olddate;
}
/* (intentionally not documented)
* Handles a user event indicating that the user isn't idle.
* @param {Event} event A DOM2-normalized event object.
* @return {void}
*/
jqElem.on( $.trim( ( opts.events + " " ).split(" ").join(".idleTimer ") ), function() {
var obj = $.data( this, "idleTimerObj" );
//clear any existing timeout
clearTimeout( obj.tId );
//if the idle timer is enabled
if ( obj.enabled ){
//if it's idle, that means the user is no longer idle
if ( obj.idle ){
toggleIdleState( this );
}
//set a new timeout
obj.tId = setTimeout( toggleIdleState, obj.timeout );
}
});
obj.idle = opts.idle;
obj.enabled = opts.enabled;
obj.timeout = opts.timeout;
//set a timeout to toggle state. May wish to omit this in some situations
if ( opts.startImmediately ) {
obj.tId = setTimeout( toggleIdleState, obj.timeout );
}
// assume the user is active for the first x seconds.
jqElem.data( "idleTimer", "active" );
// store our instance on the object
jqElem.data( "idleTimerObj", obj );
};
$.fn.idleTimer = function( firstParam, opts ) {
// Allow omission of opts for backward compatibility
if ( !opts ) {
opts = {};
}
if ( this[0] ){
$.idleTimer( firstParam, this[0], opts );
}
return this;
};
})( jQuery );
已编辑(使用 JFK 的建议解决 - 等待他的回复)
这是我用来解决我的问题的最终代码(只是不想把 JFK 的功劳归于它):
<script type="text/javascript">
//<![CDATA[
var Timer;
var TotalSeconds;
var timethis;
function CreateTimer(TimerID, Time) {
Timer = document.getElementById(TimerID);
TotalSeconds = Time;
UpdateTimer()
timethis = window.setTimeout("Tick()", 1000);
}
function Tick() {
if (TotalSeconds <= 1) {
window.location.href = '<?php echo wp_logout_url(); ?>';
}
TotalSeconds -= 1;
UpdateTimer()
timethis = window.setTimeout("Tick()", 1000);
}
function UpdateTimer() {
var Seconds = TotalSeconds;
var Minutes = Math.floor(Seconds / 60);
Seconds -= Minutes * (60);
var TimeStr = Minutes + ":" + LeadingZero(Seconds)
Timer.innerHTML = TimeStr;
}
function LeadingZero(Time) {
return (Time < 10) ? "0" + Time : + Time;
}
function TimeThis() {
var hheight = $(window).height();
$( "#timepop" ).dialog({
resizable: false,
closeOnEscape: true,
height:150,
modal: true,
buttons: {
"Continue": function() {
window.clearTimeout(timethis);
$( this ).dialog( "close" );
},
"Logout": function() {
window.location.href = '<?php echo wp_logout_url(); ?>';
}
}
})
};
(function($){
var timeinmin = 40, // Time in mins before dialog box opens
countdown = 5, // Time in mins until dialog box remains open
timeout = timeinmin*60*1000,
countdial = countdown*60;
$.idleTimer(timeout);
$(document).bind("idle.idleTimer", function(){
parent.jQuery.fancybox.close();
CreateTimer("countd", countdial);
TimeThis();
});
$(document).ready(function() {
$(".fancybox").fancybox();
});
$(function(){
$(".fancybox")
.attr('rel', 'gallery')
.fancybox({
autoPlay: false,
playSpeed: 3000,
beforeShow: function () {
$.fancybox.wrap.bind("contextmenu", function (e) {
return false;
});
},
helpers : {
overlay : {
css : {
'background' : 'rgba(0, 0, 0, 0.9)'
}
}
},
padding : 0,
onPlayStart: function () {
$.idleTimer("destroy");
},
onPlayEnd: function () {
$.idleTimer(timeout);
$(document).bind("idle.idleTimer", function(){
parent.jQuery.fancybox.close();
CreateTimer("countd", countdial);
TimeThis();
});
},
});
});
})(jQuery);
$("img.lazy").lazyload({
effect : "fadeIn",
threshold : 200
});//]]>
</script>