javascript框架设计之浏览器的嗅探和特征侦测


Posted in Javascript onJune 23, 2015

浏览器的嗅探现在已经不推荐了,但在某些场合还是需要的。比如一些统计脚本。在标准浏览器里,提供了document.implementation.hasfeature,可惜有bug,不准确,目前,w3c又推出了CSS.supports方法,显示出大家对这块的关注。

1.判定浏览器。

主流的浏览器有ie firefox opera chorme safari 早期这些框架都是通过navigator.userAgent进行判定,目前国外的浏览器几乎都是可以判定的。

关于浏览器的判断脚本,jQuery已经移出本体,形成一个插件。更多的方式不多介绍,

移动设备的相关判定,这个建议看jQuery mobile与zepto的源代码。

    isIPone = /isIPone/i.test(navigator.userAgent);

    isIPone4 = window.devicePixelRatio >= 2 //在网页中,pixel与point比值称为device-pixel-ratio,普通设备都是1,iPhone4是2,有些 安卓机型是1.5

    isIpad = /ipad/i.test(navigator.userAgent)

    isAndroid = /android/i.test(navigator.userAgent)

    isIOS = isIPone || isIpad

国内的浏览器判定可以看Tangrame或qwrap,它们基本是IE,webkit,blink内核。

2.事件的支持侦测

prototype的核心成员kangax写了一篇文章,来判断浏览器对某种事件的支持。里面给出的实现如下:

var isEventSupported = (function() {
    var TAGNAMES = {
      'select':'input','change':'input',
      'submit':'form','reset':'form',
      'error':'img','load':'img','abort':'img'
    }
    function isEventSupported(eventName){
      var el = document.createElement(TAGNAMES[eventName] || 'div');
      eventName = 'on' + eventName;
      var isSupported = (eventName in el);
      if (!isSupported) {
        el.setAttribute(eventName, 'return;');
        isSupported = typeof el[eventName] == 'function';
      }
      el = null;
      return isSupported;
    }
    return isEventSupported;
  })();

现在jQuery等框架都是使用脚本的简化版

不过哪一个也好,这种检测只对DOM0奏效,像DOMMouseScroll DOMContentLoaded DOMFocusIn DOMFocusOut DOMSubtreeModified DOMNodeInserted DOMNodeRemoved DOMNodeRemovedFromDocument DOMNodeInsertedIntoDocument DOMAttrModified DOMCharactorDataModified这些以DOM开头的就无能为力了。

这些事件中,有的非常有用,如DOMMouseScroll,firefox一直不支持mousesheel,只能用它做替代品。
DOMContentLoaded是实现domReady的重要事件;DOMNodeRemoved是判定元素是否从其父节点移除,父节点可能是其它元素节点或文档碎片;DOMNodeRemovedFromDocument 是移离DOM树,DOMAttrModified 以前经常用于模拟IE的onpropertyChange

css3添加两种动画,一种是transition动画,另外一种是keyframe补间动画。它们在事件结束时都用事件回调。但在标准化过程中,浏览器给它们起的名字相当于没规则。这个也需要预先侦测出来。

下面是bootstrap的实现。听说来源于modernizr,比较粗糙。比如你使用的Oprera已经支持不带事件标准事件名。它还是返回oTransitionEnd.

$.supports.transition = (function(){
    var transitionEnd = (function(){
      var el = document.createElement('bootstarp'),
          transEndEventNames = {
            'WebkitTransition':'webkitTransitionEnd',
            'MozTransition':'transitionend',
            'OTransition':'OTransitionEnd otransitionend',
            'transition':'transitionend'
          };
        for (var name in transEndEventNames){
          if (el.style[name] !== undefined){
            return transEndEventNames[name]
          }
        }
    }());
    return transitionEnd && {
      end: transitionEnd
    }
  })();

keyframe补间动画来自mass的fx_neo模块

var eventName = {
    AnimationEvent:'animationend',
    WebKirAnimationEvent: 'WebKirAnimationEnd'
  },animationend;
  for(var name in eventName) {
    if (/object|function/.test(typeof window[name])){
      animationend = eventName[name]
      break
    }
  }

3.样式的支持侦探

css3带来许多好用的样式,但是麻烦的是每个浏览器都有自己的私有前缀,massFramework提供了一个cssName方法来处理它们,有就返回可用的驼峰样式名,没有就null

var prefixes = ['','-webkit-','-o-','-moz-','-ms-'];
  var cssMap = {
    "float" : $.support.cssFloat ? 'cssFloat' : 'styleFloat',background:'backgroundColor'
  };
  function cssName(name, host, camelCase){
    if(cssMap[name]) {
      return cssMap[name];
    }
    host = host || document.documentElement
    for (var i = 0 || n = prefixes.length; i < n; i++) {
      camelCase = $.String.camelize(prefixes[i] + name);
      if (camelCase in host) {
        return (cssMap[name] = camelCase)
      }
    }
    return null
  }

一个样式对于N种样式值,比如display有n种取值,如果要侦测浏览器是否支持某一种,会很麻烦。为此,浏览器做了一个善举,给出一个css.supports的API,如果不支持,则尝试下一个开源项目。显然,不是很完美。

https://github.com/termi/CSS.supports

4.jQuery的一些常用的特征的含义

jQuery在support模块例举了一些常用的DOM特征支持情况,不过名字起的很怪,不同版本差别也很大,本章以jQuery1.8为准。

leadingWhitespace:判定浏览器在进行innerHTML赋值时,是否存在trimLeft操作,这个功能原本是IE发明的,结果其他浏览器认为要忠于以后的原始值,最前面的空白不能神略掉,要变成一个文本节点,最终IE678返回false,其他浏览器返回true

tobody:指在用innerHTML动态创建元素时,浏览器是否会在table内自动补上tobody,jQuery希望浏览器别处理,让jQuery来补全。判断浏览器是否只能插入tobody。在表格布局的年代,这个特性十分受用。如果没有tbody,table会在浏览器解析到闭合标签时才显示出来。如果起始标签和闭合标签相隔很远,换言之,这个表格很长,用户会什么都看不到,但有了tbody分段显示和识别,避免了长时间空白后一下子显示出来的情况。

    var div = document.createElement("div");

    div.innerHTML = '<table></table>'

    alert(div.innerHTML) //=>ie678返回<table><tbody></tbody></table>,其它返回<table></table>

html.Serialize:判断浏览器是否完好支持用innerHTML转换一个符合html标签规则的字符串为一个元素节点,此过程jQuery称为序列化,但IE支持不够完好。包括scirpt link style mata在内的no-scope元素都转换失败。

style:这个命名很难看懂,不看代码不知道什么意思,真像是判定getAttribute是否返回style的用户预设值。IE678没有返回区分特性的特征,返回一个CSSStyleDeclaration对象。

hrefNormalized:判定getAttribute能否返回href的用户预设值。IE会补充给你完整的路径给你

opacity:判定浏览器是否支持opacity属性,ie678要使用滤镜

cssFloat: 判定float的样式在DOM的名字是那个,W3c为cssFloat,IE678为styleFloat

CheckOn: 在大多数浏览器中checkBox的value为on,chorme返回空字符串

optSelected: 判定是否正确取得动态添加option元素的seleted,ie6-10与老版的safari对动态添加option没有设置为true。解决办法,在访问selected属性前,先访问父节点的selectedIndex属性,再强制计算option的seleted.

<select id='optSelected'></select>
<script type="text/javascript">
  var select = document.getElementById('optSelected');
  var option = document.createElement('option');
  select.appendChild(option);
  alert(option.selected);
  select.selectedIndex;
  alert(option.selected)
</script>

optDisabled : 判定select元素的disable属性是否影响到子元素的disabled取值.在safari中,一旦select元素被disabled,它的子元素也disabled,导致一个值也取不到

checkClone:是指一个checkbox元素,如果设置了checked=true,且在多次克隆后,它的复制品能否保持为true。这个方法只有在safari4中返回false,其它的都true

inlineBlockNeedsLayout:判定是否使用hasLayout方法让dispaly:inline-block生效。这个方法只有ie678为true

getSetAttribute:判定是否区分特性属性,只有ie678为false

noCloneEvent:判定在克隆元素时是否克隆attachEvent绑定事件。只有旧版本的ie及其兼容模式返回false

enctype:判定浏览器是否支持encoding属性,ie67使用encoding属性来代替

boxModel:判定浏览器是否在content-box盒子渲染模式下

submitBubbles, changeBubbles, focusinBubble:判定浏览器是否支持这些事件,一直冒泡到document

shrinkWrapBlocks:判定元素是否会被子元素撑开。在IE678中,非替换元素在设置了大小与hasLayout的情况下,将将其父级元素撑大。

html5Clone:判定能否使用cloneNode克隆HTML5新标签 ,旧版本的IE不支持。需要用到outerHTML

deleteExpando:判定能否删除元素节点上的自定义元素,这用于jQuery缓存系统。旧版本的IE不支持,直接undefined

pixelPosition:判定getComputedStyle能否转换元素的top left bottom right元素的百分比值。这个在webkit系统会出现问题,需要用到 Dean Edwards神的hack

reliableMarginRight:判定getComputedStyle能否正确的取得元素的marginRiht.

clearCloneStyle :ie9 10 会出现奇怪的bug,当复制了一个元素的background-*样式的元素,对复制的元素进行清空时,会清空原来的样式。

随着浏览器疯狂更新版本,标准浏览器引发的各种bug已经超越IE,特征侦测不退反进,越来越重要了。

以上所述就是本文的全部内容了,希望大家能够喜欢。

Javascript 相关文章推荐
JavaScript实际应用:innerHTMl和确认提示的使用
Jun 22 Javascript
js select常用操作控制代码
Mar 16 Javascript
Jquery选择子控件&quot;大于号&quot;和&quot; &quot;区别介绍及使用示例
Jun 25 Javascript
在jquery中combobox多选的不兼容问题总结
Dec 24 Javascript
一看就懂:jsonp详解
Jun 01 Javascript
js实现超简单的展开、折叠目录代码
Aug 28 Javascript
JQuery操作textarea,input,select,checkbox方法
Sep 02 Javascript
每天一篇javascript学习小结(Boolean对象)
Nov 12 Javascript
Angular在一个页面中使用两个ng-app的方法
Feb 20 Javascript
详解npm 配置项registry修改为淘宝镜像
Sep 07 Javascript
使用layui日期控件laydate对开始和结束时间进行联动控制的方法
Sep 06 Javascript
原生JS实现记忆翻牌游戏
Jul 31 Javascript
简述AngularJS相关的一些编程思想
Jun 23 #Javascript
javascript框架设计之种子模块
Jun 23 #Javascript
在JavaScript的AngularJS库中进行单元测试的方法
Jun 23 #Javascript
javascript框架设计之框架分类及主要功能
Jun 23 #Javascript
js的flv视频播放器插件使用方法
Jun 23 #Javascript
使用Raygun来自动追踪AngularJS中的异常
Jun 23 #Javascript
使用JavaScript的AngularJS库编写hello world的方法
Jun 23 #Javascript
You might like
PHP 类商品秒杀计时实现代码
2010/05/05 PHP
php 学习资料零碎东西
2010/12/04 PHP
php实现单链表的实例代码
2013/03/22 PHP
什么是OneThink oneThink后台添加插件步骤
2016/04/13 PHP
phpMyAdmin无法登陆的解决方法
2017/04/27 PHP
PHP机器学习库php-ml的简单测试和使用方法
2017/07/14 PHP
yii框架redis结合php实现秒杀效果(实例代码)
2017/10/26 PHP
ExtJS 2.2.1的grid控件在ie6中的显示问题
2009/05/04 Javascript
jQuery学习笔记 操作jQuery对象 CSS处理
2012/09/19 Javascript
Jquery+CSS3实现一款简洁大气带滑动效果的弹出层
2013/05/15 Javascript
捕获浏览器关闭、刷新事件不同情况下的处理方法
2013/06/02 Javascript
在Javascript中处理字符串之big()方法的使用
2015/06/08 Javascript
谈谈impress.js初步理解
2015/09/09 Javascript
浅析AngularJs HTTP响应拦截器
2015/12/28 Javascript
js HTML5 Canvas绘制转盘抽奖
2020/09/13 Javascript
jQuery继承extend用法详解
2016/10/10 Javascript
基于daterangepicker日历插件使用参数注意的问题
2017/08/10 Javascript
解决seaborn在pycharm中绘图不出图的问题
2018/05/24 Python
Linux系统(CentOS)下python2.7.10安装
2018/09/26 Python
Python使用while循环花式打印乘法表
2019/01/28 Python
Flask框架模板渲染操作简单示例
2019/07/31 Python
Python @property原理解析和用法实例
2020/02/11 Python
Python如何实现小程序 无限求和平均
2020/02/18 Python
Python小白不正确的使用类变量实例
2020/05/29 Python
用CSS3的box-reflect设置文字倒影效果的方法讲解
2016/03/07 HTML / CSS
加州风格的游泳和沙滩装品牌:Cupshe
2019/06/10 全球购物
德国受欢迎的旅游和休闲网站:lastminute.de
2019/09/23 全球购物
EJB的几种类型
2012/08/15 面试题
大学校园活动策划书
2014/02/04 职场文书
财务学生的职业生涯发展
2014/02/11 职场文书
小学社会实践活动总结
2014/07/03 职场文书
企业员工集体活动方案
2014/08/17 职场文书
2016年学习贯彻十八届五中全会精神心得体会
2016/01/05 职场文书
opencv用VS2013调试时用Image Watch插件查看图片
2021/07/26 Python
Redis 中使用 list,streams,pub/sub 几种方式实现消息队列的问题
2022/03/16 Redis
python manim实现排序算法动画示例
2022/08/14 Python