使用 ALT+TAB 切换程序/窗口或单击任务栏时不会触发 VisibilityChange 事件

2024-04-26

问题在于事件“visibilitychange”的行为。

已触发:- 当我切换到浏览器窗口内的不同选项卡时。

  • 当我单击浏览器窗口的最小化/恢复按钮时。

(还行吧)

它没有被触发:- 当我使用 ALT+TAB 切换到不同的窗口/程序时。

  • 当我切换到不同的窗口/程序时,单击任务栏。

(这应该触发,因为就像最小化时一样,窗口的可见性可能会改变)


W3 页面可见性 API 文档: http://www.w3.org/TR/page-visibility/ http://www.w3.org/TR/page-visibility/

There is no definition of "page visibility" regarding ALT+TAB/program switching in the spec sheet. I'm guessing it has something to do in between the OS and the Browser.


测试过

  • Browsers: Chrome 40.0.2214.115 m / 火狐 36.0.1 / Internet Explorer 11.0.9600.17107
  • OS:Windows 8.1

有解决方法可以解决此行为吗?实现相当简单,我使用 jQuery 监听“visibilitychange”事件,然后在其回调中检查“document.visibilityState”的值,但问题是该事件没有按预期触发。

$(document).on('visibilitychange', function() {

    if(document.visibilityState == 'hidden') {
        // page is hidden
    } else {
        // page is visible
    }
});

This can be done without jQuery too, but the ALT+TAB and taskbar switch hide/show expected behaviour is still missing:

if(document.addEventListener){
    document.addEventListener("visibilitychange", function() {
        // check for page visibility
    });
}

我还尝试过 ifvisible.js 模块(https://github.com/serkanyersen/ifvisible.js https://github.com/serkanyersen/ifvisible.js)但行为是相同的。

ifvisible.on('blur', function() {
    // page is hidden
});

ifvisible.on('focus', function() {
    // page is visible
});

我还没有在其他浏览器中进行测试,因为如果我不能让它在 Windows 上的 Chrome 中工作,我真的不关心其他浏览器。

有什么帮助或建议吗?


UPDATE

I tried using different vendor prefixes for the event name (visibilitychange, webkitvisibilitychange, mozvisibilitychange, msvisibilitychange) but but still the event is not triggered when I switch to a different program in the taskbar or ALT+TAB, or even if I open the start menu thing in windows with the windows key, which covers the whole screen.

我可以在 Chrome、Firefox 和 Internet Explorer 中重现完全相同的问题。

更新#2

Here's https://stereologics.wordpress.com/2015/04/02/about-page-visibility-api-hidden-visibilitychange-visibilitystate/我为此问题撰写了一篇综述文章,并使用纯 JavaScript 编写了解决遇到的问题的解决方法。

更新#3

编辑以包含来源博客文章的副本。 (参见已接受的答案)


Here's https://stereologics.wordpress.com/2015/04/02/about-page-visibility-api-hidden-visibilitychange-visibilitystate/我为此问题撰写了一篇综述文章,并使用纯 JavaScript 编写了解决遇到的问题的解决方法。

编辑以包含来源博客文章的副本:


在我们开发的任何类型的 javascript 应用程序中都可能存在 功能或应用程序中的任何更改根据 当前用户可见性状态,这可能是暂停正在播放的视频 当用户 ALT+TAB 切换到不同窗口时,跟踪有关如何进行的统计信息 用户与我们的应用程序交互,他多久切换到 不同的标签,他需要多长时间才能返回以及很多 可以从这种 API 中受益的性能改进。

页面可见性 API 为我们提供了两个顶级属性: document.hidden (布尔值) 和 document.visibilityState (可以是 这些字符串中的任何一个:“隐藏”、“可见”、“预渲染”、“已卸载”)。 如果没有我们可以听到的活动,这还不够好 不过,这就是为什么 API 还提供了有用的visibilitychange 事件。

因此,这是一个关于我们如何对可见性采取行动的基本示例 改变:

function handleVisibilityChange() {
  if(document.hidden) {
    // the page is hidden
  } else {
    // the page is visible
  }
}

document.addEventListener("visibilitychange", handleVisibilityChange, false);

我们还可以检查 document.visibilityState 值。

处理供应商问题 George Berkeley 作者:John Smibert

某些浏览器上的某些实现仍然需要 属性甚至事件名称都是供应商前缀的,这意味着我们 可能需要监听 msvisibilitychange 事件或检查 document.webkitHidden 或 document.mozHidden 属性。为了 为此,我们应该检查是否设置了任何供应商前缀属性,并且 一旦我们知道当前浏览器中使用的是哪一个(仅当 需要前缀),我们可以命名事件和属性 适当地。

以下是如何处理这些前缀的示例方法:

var browserPrefixes = ['moz', 'ms', 'o', 'webkit'];

// get the correct attribute name
function getHiddenPropertyName(prefix) {
  return (prefix ? prefix + 'Hidden' : 'hidden');
}

// get the correct event name
function getVisibilityEvent(prefix) {
  return (prefix ? prefix : '') + 'visibilitychange';
}

// get current browser vendor prefix
function getBrowserPrefix() {
  for (var i = 0; i < browserPrefixes.length; i++) {
    if(getHiddenPropertyName(browserPrefixes[i]) in document) {
      // return vendor prefix
      return browserPrefixes[i];
    }
  }

  // no vendor prefix needed
  return null;
}

// bind and handle events
var browserPrefix = getBrowserPrefix();

function handleVisibilityChange() {
  if(document[getHiddenPropertyName(browserPrefix )]) {
    // the page is hidden
    console.log('hidden');
  } else {
    // the page is visible
    console.log('visible');
  }
}

document.addEventListener(getVisibilityEvent(browserPrefix), handleVisibilityChange, false);

其他问题“页面可见性”存在一个具有挑战性的问题 定义:如何确定应用程序是否可见 另一个窗口的窗口焦点丢失,但实际的窗口焦点没有丢失 屏幕上的可见性?不同类型的可见性怎么样 丢失,如 ALT+TAB、WIN/MAC 键(开始菜单/破折号)、任务栏/dock 操作、WIN+L(锁定屏幕)、窗口最小化、窗口关闭、选项卡 交换。移动设备上的行为怎么样?

我们可能会通过很多方式失去或获得知名度,而且很多 浏览器和操作系统之间可能的交互,因此我 不认为有一个正确且完整的“可见页面”定义 W3C 规范。这是我们得到的 document.hidden 的定义 属性:

隐藏属性 获取时,隐藏属性必须返回 true,如果 顶级浏览上下文(根窗口 在浏览器的视口中)[HTML5]根本不可见。这 如果顶层包含 Document,则属性必须返回 false 浏览上下文在至少一个屏幕上至少部分可见。

如果 Document 的 defaultView 为 null,则在获取时隐藏 属性必须返回 true。

为了适应通常是全屏但 仍然显示页面视图,如果适用,此属性可以 当用户代理未最小化但已完全最小化时返回 false 被其他应用程序遮挡。

我发现活动实际时间存在一些不一致之处 例如(Chrome 41.0.2272.101 m,在 Windows 8.1 上)触发该事件 当我 ALT+TAB 切换到不同的窗口/程序时,也不会触发 再次按 ALT+TAB 返回,但如果我按 CTRL+TAB 然后它会被触发 CTRL+SHIFT+TAB 在浏览器选项卡之间切换。当我的时候它也被解雇了 单击最小化按钮,但如果窗口未打开,则不会触发该按钮 最大化,然后单击浏览器后面的编辑器窗口 窗户。所以这个API的行为和它不同 实施仍然模糊。

解决这个问题的方法是利用更好的优势进行补偿 实现了焦点和模糊事件,并制定了自定义方法 使用内部标志来防止整个“页面可见性”问题 多次执行,这就是我想出的:

var browserPrefixes = ['moz', 'ms', 'o', 'webkit'],
    isVisible = true; // internal flag, defaults to true

// get the correct attribute name
function getHiddenPropertyName(prefix) {
  return (prefix ? prefix + 'Hidden' : 'hidden');
}

// get the correct event name
function getVisibilityEvent(prefix) {
  return (prefix ? prefix : '') + 'visibilitychange';
}

// get current browser vendor prefix
function getBrowserPrefix() {
  for (var i = 0; i < browserPrefixes.length; i++) {
    if(getHiddenPropertyName(browserPrefixes[i]) in document) {
      // return vendor prefix
      return browserPrefixes[i];
    }
  }

  // no vendor prefix needed
  return null;
}

// bind and handle events
var browserPrefix = getBrowserPrefix(),
    hiddenPropertyName = getHiddenPropertyName(browserPrefix),
    visibilityEventName = getVisibilityEvent(browserPrefix);

function onVisible() {
  // prevent double execution
  if(isVisible) {
    return;
  }
 
  // change flag value
  isVisible = true;
  console.log('visible');
}

function onHidden() {
  // prevent double execution
  if(!isVisible) {
    return;
  }

  // change flag value
  isVisible = false;
  console.log('hidden');
}

function handleVisibilityChange(forcedFlag) {
  // forcedFlag is a boolean when this event handler is triggered by a
  // focus or blur eventotherwise it's an Event object
  if(typeof forcedFlag === "boolean") {
    if(forcedFlag) {
      return onVisible();
    }

    return onHidden();
  }

  if(document[hiddenPropertyName]) {
    return onHidden();
  }

  return onVisible();
}

document.addEventListener(visibilityEventName, handleVisibilityChange, false);

// extra event listeners for better behaviour
document.addEventListener('focus', function() {
  handleVisibilityChange(true);
}, false);

document.addEventListener('blur', function() {
  handleVisibilityChange(false);
}, false);

window.addEventListener('focus', function() {
    handleVisibilityChange(true);
}, false);

window.addEventListener('blur', function() {
  handleVisibilityChange(false);
}, false);

我欢迎有关此解决方法的任何反馈。其他一些很棒的来源 有关此主题的想法:

使用页面可见性 API 更有效地使用 PC 硬件 HTML5:新的 Web 性能 API,第 2 部分页面简介 Visibility API 结论 Web 技术不断发展 不断发展,我们仍在从黑暗的过去中恢复过来,那里的桌子 标记之王,语义并不重要,而且它们也不是任何 关于浏览器如何呈现页面的标准。

我们推动这些新标准很重要,但有时我们的 发展的要求使我们还需要适应这些 转换,通过处理供应商前缀,在不同的环境中进行测试 浏览器和不同的操作系统或依赖第三方工具来正确 识别这种差异。

我们只能希望 W3C 规范的未来 浏览器开发团队严格修改、严格执行, 也许有一天我们会有一个共同的工作标准 和。

至于页面可见性 API,我们稍微引用一​​下乔治·伯克利 (George Berkeley) 并说:

“可见”是被感知。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用 ALT+TAB 切换程序/窗口或单击任务栏时不会触发 VisibilityChange 事件 的相关文章

  • 如何在不阻止触摸启动的情况下防止“过度滚动历史导航”?

    我正在实现基于滑动的导航 但我在使用 Chrome 时遇到了麻烦 当页面向右拖动时 会触发新实现的功能 过度滚动历史导航 从而导致跳回 到 历史 1 为了防止这种情况 我必须打电话 preventDefault on touchstart
  • 我怎样才能让这个脚本在 WordPress 上运行?

    我有这个脚本 document ready function text1 click function this hide 代码html div class div1 p class text1 text to appear when th
  • 设置双指缩放时精确的滚动位置

    我正在创建一个地图应用程序 它将标记图像放置在画布上并滚动到它 我正在使用浏览器的捏缩放和滚动来放大 缩小地图 然而 我注意到有一些奇怪的行为 我想知道如何解决它 这有点难以解释 但我们开始吧 假设您处于网页的标准缩放级别 无法进一步缩小
  • jQuery输入文件点击方法和IE上拒绝访问

    我尝试仅使用一个按钮作为输入文件 它在 Firefox Chrome Safari 中工作正常 但在 IE 中不行 提交表单时我总是收到 访问被拒绝 的消息 代码 input file click 有真正的解决方法吗 我在谷歌上浪费了大约2
  • 将html数据解析成python列表进行操作

    我正在尝试读取 html 网站并提取其数据 例如 我想查看公司过去 5 年的 EPS 每股收益 基本上 我可以读入它 并且可以使用 BeautifulSoup 或 html2text 创建一个巨大的文本块 然后我想搜索该文件 我一直在使用
  • 如何在 select 和 option 标签中添加 JSON 数据?

    我有这个html代码 div class searchfilter div class searchwrapper div div
  • 如何在 React Native 上显示 SVG 文件?

    我想显示 svg 文件 我有一堆 svg 图像 但我找不到显示的方式 我尝试使用Image and Use的组成部分反应本机 svg https github com magicismight react native svg但他们不这样做
  • 将 Firebase FCM 添加到 ReactJS 应用程序

    我正在尝试向我的 ReactJS 应用程序中的用户发送推送通知 我已添加 firebase 请求用户通知权限 这正在发挥作用 但现在我想注册设备令牌 但这给了我错误 消息传递 我们无法注册默认的 Service Worker 无法注册 Se
  • 如何将 arraylist 从 servlet 传递到 javascript?

    我通过在属性中设置数组列表并将其转发到 jsp 来从 servlet 传递数组列表 Servlet ArrayList
  • 如何使跨度标签不可删除?

    我正在尝试使 contenteditable div 内的跨度标记不可删除 div Editable span Read Only span div 只读范围确实是只读的 但我可以通过单击删除键来删除整个范围 有没有一种属性方法可以告诉sp
  • 如何使用新的analytics.js跟踪多个帐户?

    我需要使用 Google 的新的analytics js 跟踪一个页面上两个帐户的综合浏览量 有大量教程和示例如何使用较旧的 ga js 进行操作 但我发现的只是这个分析文档页面 https developers google com an
  • Web组件中嵌套槽的内容不可见

    我有一个 Web 组件 它应该接受任意元素来包装其内容 虽然我可以在 Chrome 开发工具中看到插槽已正确分配 但 DOM 中什么也没有出现 以前有人见过这个问题吗 定义 class ExampleParent extends HTMLE
  • 如何使整个跨度落入新行?

    这个片段显示了我想要的 http jsfiddle net 945Df 3 http jsfiddle net 945Df 3 div class sup strong a href Rosario Santa Fe Argentina a
  • 呃!尝试将包发布到 npm 时出现 403

    我正在尝试将包发布到 npm 您可以在此处查看存储库 https github com biowaffeln mdx state https github com biowaffeln mdx state 我登录到 npmnpm login
  • Javascript 浮点乘以 100 仍然有错误

    我有一个货币字段的文本输入 我在字段中输入 33 91 并在尝试使用 乘以 100 技术时得到以下结果 var curWth parseInt trans withdraw index val 100 3390 var curWth par
  • Service Worker 与 Shared Worker

    Service Worker 和 Shared Worker 有什么区别 我什么时候应该使用 Service Worker 而不是 Shared Worker 反之亦然 Service Worker 具有共享 Worker 之外的附加功能
  • 摩纳哥:如何添加内联自动完成/代码建议?

    我找不到任何有关如何添加内联自动完成功能的示例 如下图所示 有人可以指导我如何在摩纳哥做到这一点吗 这可以在 v1 66 中启用 现在在 Insiders 中 The editor quickSuggestions设置现在接受内联为 配置值
  • PDF 在 Safari 中隐藏 Jquery Modal

    这是与我有关的事情this https stackoverflow com questions 24052681 pdf hide jquery modal in ie问题 在 IE 中 我在对话框中使用 iframe 解决了问题 所以它工
  • 为什么 Node.js 应用程序只能从 127.0.0.1/localhost 访问?

    我本来打算教我的朋友介绍 Node 但是后来 我想知道为什么这个代码来自nodejs org var http require http http createServer function req res res writeHead 20
  • 以角度访问窗口 TemplateUrl 内的范围

    我的模式有一个 windowTemplateUrl 如下 div class modal fade div class modal dialog div class modal content square btn div div div

随机推荐

  • 如何在VueJS中将所有事件传递给父级

    传递道具 In VueJS如果你设置inheritAttrs to false并使用v bind attrs 您将组件中未声明的所有 props 传递给其子组件 是否有类似的方法将来自子级的所有事件传递给其父级VueJS 代码示例 Wrap
  • 无法加载 Spring ApplicationContext

    我正在为一个有点复杂的 spring 应用程序编写单元测试 我想加载 spring 上下文以便使用定义的 bean 我的 context xml 位于 src main resources context xml Maven 构建后 con
  • Keras模型拟合多项式

    我从四次多项式生成了一些数据 并希望在 Keras 中创建一个回归模型来拟合该多项式 问题是拟合后的预测似乎基本上是线性的 由于这是我第一次使用神经网络 我认为我犯了一个非常微不足道且愚蠢的错误 这是我的代码 model Sequentia
  • 基于程序描述的多线程推荐

    我想描述我的程序的一些细节 并获得有关最适用的最佳多线程模型的反馈 我现在花了很多时间阅读有关 ThreadPool Threads Producer Consumer 等的内容 但尚未得出可靠的结论 我有一个文件列表 格式相同 但内容不同
  • 将 best_in_place 与富文本编辑器(如 TinyMCE)一起使用

    我正在使用best in placegem 在 Rails 应用程序中进行就地编辑 但是 我需要对某些文本区域进行 X HTML 编辑 因此我需要一个富文本编辑器 TinyMCE 正在该网站的其他地方使用 然而 添加一个编辑器并不简单bes
  • 有没有办法扩展 PHP 中的特征?

    我想使用现有的功能trait并创建我自己的trait在此之上只是为了稍后将其应用到课堂上 我想延长Laravel SoftDeletes特质SaveWithHistory函数 因此它将创建一个记录的副本作为已删除的记录 我也想扩展它reco
  • 我无法通过引用捕获传递 lambda

    以下代码失败并出现此错误 E0413 不存在从 lambda float int i gt float 到 float int i 的合适转换函数 int test float f int i int i gt float return t
  • 使用 Asp.net/C# 使用 USB 令牌对文本文件进行数字签名?

    我有一个 USB 令牌 Epass Capricorn 我的要求是使用它来签署文本 平面文件 PS 我相信我必须从代 码中获取 START SIGNATURE START CERTIFICATE 和 SIGNER VERSION 数据并附加
  • 模拟器卡在从 10.0.2.2:8081 加载时,有什么问题吗?

    I am working on a react native project and I run it on emulator android AVD manager 我跑了adb 反向 tcp 8081 tcp 8081在 cmd 但我的
  • Visual Studio Code 中的“Markdown 片段链接导航”是什么?

    Visual Studio Code 2017 年 2 月 版本 1 10 发行说明描述了他们所谓的 Markdown 片段链接导航 这是描述 包含片段的 Markdown 文件的链接现在将尝试打开相应标题处的文件 Section head
  • Bootstrap 4 导航栏折叠菜单右对齐

    我正在使用 Bootstrap 4 我试图通过单击折叠按钮在右侧而不是左侧打开来弹出菜单 我尝试在 ul 元素上使用 ml auto 当导航栏未折叠时 导航栏项目正确位于右侧 当它折叠时 按钮正确地位于右侧 但菜单在左侧弹出 我也尝试过将
  • 一般:如何更改 Android 核心 API 类?

    这只是一个一般性问题 供我参考 我知道如何创建标准的 Android 应用程序 但我想知道 这怎么可能 人们如何增强 Android 核心功能并深入挖掘系统 例如 假设我想调整下载管理器 http developer android com
  • Laravel 通知监听器在实现队列时没有用

    Laravel 版本 5 5 PHP 版本 7 1 根据文档https laravel com docs 5 5 notifications https laravel com docs 5 5 notifications notifica
  • android 获取设备整体音频输出(PCM)

    有什么方法可以拦截或读取 Android 设备中的音频输出吗 我需要从 myActivity 内部读取 PCM 中的整个音频输出 包括后台的媒体播放器应用程序 通话中的语音 myActivity 内的 MediaPlayer 实例等 以及扬
  • Android SDK 工具 Rev.17 - onClick - 未找到相应的方法处理程序

    我将 Android SDK 工具更新到修订版 17 打开 Eclipse 后 我在 问题 视图中发现了更新之前不存在的新错误列表 这些错误出现在 XML 布局文件中 我在其中定义了按钮的 onClick 属性 鼠标悬停时错误消息示例 未找
  • 将 localStorage 数据设置为只读

    我正在开发 AngularJs 应用程序 我将数据存储在 localStorage 中 localStorageService set selectedUserCategory Circle 现在当我看到浏览器的 localStorage
  • Neo4j.rb 创建独特的关系

    这是我的 Neo4j 活动节点 class User include Neo4j ActiveNode has many out following type following model class User end john User
  • 将图像从 CV_64F 转换为 CV_8U

    我想转换类型的图像CV 64FC1 to CV 8UC1在 Python 中使用 OpenCV 在 C 中 使用convertTo函数 我们可以使用以下代码片段轻松转换图像类型 image convertTo image CV 8UC1 我
  • 如何获取 CakePHP 3.0 中最后一个插入 ID?

    使用 CakePHP 3 0 beta 似乎是一个简单的问题 但我搜索了文档但找不到任何东西 使用 this gt Model gt save 插入新记录后 我想获取新创建记录的 auto increment 主键 ID 使用 Cake 2
  • 使用 ALT+TAB 切换程序/窗口或单击任务栏时不会触发 VisibilityChange 事件

    问题在于事件 visibilitychange 的行为 已触发 当我切换到浏览器窗口内的不同选项卡时 当我单击浏览器窗口的最小化 恢复按钮时 还行吧 它没有被触发 当我使用 ALT TAB 切换到不同的窗口 程序时 当我切换到不同的窗口 程