使用 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 事件 的相关文章

  • 除了text/css之外还有其他样式类型吗? [复制]

    这个问题在这里已经有答案了 可能的重复 style type text css 还有什么 https stackoverflow com questions 6077905 style type text css what else is
  • onClick 在 p 标签上无法正常工作

    我想为每个绑定一个点击事件 p 但它似乎不能正常工作 当我运行脚本时 我立即收到三个警报 我只想在单击三个中的任何一个时获得它们 p p s 谁能告诉我我做错了什么 编辑 抱歉 这就是它的样子 HTML 应该是这样的 p p class s
  • HTML 表格换行列

    我有一个表 用户将数据输入到列中 每次用户输入数据时都会创建一个新列 一段时间后 他们有大量的专栏 我需要它们换行 我知道如何将文本换行在列内 但我需要将整个列换行在第一列下方 依此类推 您不应该为此使用表格 您应该使用具有 float l
  • Javascript 设置输入字段的值

    因为虽然我无法设置 type text 的输入字段的值 以前 我总是使用这样的东西
  • 使用 Android 浏览器的 HTML5 离线存储

    我正在研究如何使用 Android 设备来创建需要离线使用的网站 我还没有找到很多关于Android浏览器如何处理HTML5的localStorage和WebSQL的信息 有人知道这些的尺寸限制吗 它们是否可以更改 我知道移动 Safari
  • AngularJS ng-重复重新渲染

    我正在使用 AngularJS 构建一个简单的应用程序 应用程序向服务器发出异步 AJAX 调用 服务器返回一个如下所示的数组 paragraphs content content one content cnt two content r
  • 如何在 div 中加载页面?

    我被告知使用 Div 代替 iframe 是前进的方向 所以我使用横幅和主体中的框架 如何将我的index html加载到我的div中 你尝试过 jquery 的 load 吗 通过服务器端技术 您可以轻松地做到这一点
  • 如何确定输入的模式是“Int,VarChar,Date,Time ...”等

    我有一个下拉菜单 其中包含DataType 和一个文本框 这是用于输入的Regex Pattern 如果我进入 test 在文本框中 或从下拉菜单中选择Int 如果在文本框中输入 则其模式是错误的 0 9 那么它的correct patte
  • 如何最高效地更新MongoDB中的大量文档?

    我想要最有效地更新大量 gt 100 000 文档 我的第一个天真的方法是在 JS 级别上进行 编写脚本 首先获取 ids 然后循环 ids 并通过 id 调用更新 完整 文档或 set 补丁 我遇到了内存问题 还将数据分成了最大块 500
  • 调用事件,h(args) 与 EventName?.Invoke()

    我总是这样调用事件 void onSomeEvent string someArg var h this EventName if h null h this new MyEventArgs someArg 今天 VS 2015 告诉我这可
  • 为什么 justify-content 不以我的 div 为中心?

    我试图将两个 div 水平居中放在爸爸 div 内 爸爸 div 设置为flex direction column因为我希望子 div 一个在另一个之下 但位于页面的中心 justify content center 应该做但不起作用 我终
  • 从字符串中提取所有链接

    我有一个 javascript 变量 其中包含页面的 HTML 源代码 不是当前页面的源代码 我需要从该变量中提取所有链接 关于什么是最好的方法的任何线索 是否可以为变量中的 HTML 创建一个 DOM 然后遍历它 我不知道这是否是推荐的方
  • 如何使用 Angular/Ionic/JS 显示 Motion JPEG 二进制数据流?

    我正在为设备编写应用程序 此类设备将收到 POST 请求 并发回multipart x mixed replace二进制数据流 我必须在我的应用程序主页的一部分上显示此类流 我查了一下 这种情况的资源非常有限 到目前为止 我发现如果 Mot
  • Ember JS 过渡到嵌套路由,其中​​所有路由都是视图中的动态段

    我们正在使用 EmberJS 编写一个应用程序 然而 我们对这个框架仍然陌生 我们很难解决一些看似简单的问题 模型非常简单 有 3 个模型 Queue Task 和 Image 我们对所有路由使用动态 URI 段 并且这些模型的路由嵌套在以
  • JavaScript 使用多少位来表示数字?

    JavaScript 使用多少位来表示数字 一般JS实现使用64位双精度浮点数 对 32 位整数执行按位运算
  • Redux Spread 运算符与 Map

    我有一个数组中的对象状态 在我的 ReduxReducer 中 const initialState items id 1 dish General Chicken price 12 1 quantity 0 id 2 dish Chick
  • 使用 PHP 的 HTML 中的选项字段

    我想根据从下拉列表中选择的区域名称搜索员工列表 我可以将数据库中的区域名称检索到 PHP HTML 的下拉列表中 但现在我很困惑如何将下拉列表中的选定选项传递给 PHP 中的 SQL 查询 我还想要索引号 选定的选项 我的代码如下
  • 在现有 HTML 输入字段中加载图像/徽标 - UIWebView

    因为我是编程新手 所以我做了这样的事情 void completeUserFieldsForWebView UIWebView webView withUsername NSString username TextField Which h
  • 如何检查打开的跨域窗口是否准备好接收postmessage?

    我从另一个域启动一个 URL 然后向它发送消息 const child window open http urlfromanotherdomain com child postMessage you cant handle the mess
  • 什么是 Service Worker 控制台? & 它在 Chrome 浏览器中的什么位置?

    我正在研究推送通知并遇到一个陌生的术语 service worker console 我已阅读并使用过该术语console log or web console在浏览器中 但我不熟悉这个术语service worker console 之后

随机推荐

  • 如何在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 切换到不同的窗口 程序时 当我切换到不同的窗口 程