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对象及属性
Feb 13 Javascript
Jquery和JS用外部变量获取Ajax返回的参数值的方法实例(超简单)
Jun 17 Javascript
浅析JavaScript中的delete运算符
Nov 30 Javascript
Javascript 拖拽的一些简单的应用(逐行分析代码,让你轻松了拖拽的原理)
Jan 23 Javascript
BootStrap.css 在手机端滑动时右侧出现空白的原因及解决办法
Jun 07 Javascript
JavaScript判断是否是微信浏览器
Jun 13 Javascript
js变量提升深入理解
Sep 16 Javascript
JavaScript中浅讲ajax图文详解
Nov 11 Javascript
JavaScript实现短暂提示框功能
Apr 04 Javascript
JavaScript数组去重实现方法小结
Jan 17 Javascript
基于Element的组件改造的树形选择器(树形下拉框)
Feb 27 Javascript
浅析 Vue 3.0 的组装式 API(一)
Aug 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字符串截取中文截取2,单字节截取模式
2007/12/10 PHP
PHP实现将HTML5中Canvas图像保存到服务器的方法
2014/11/28 PHP
smarty内置函数{loteral}、{ldelim}和{rdelim}用法实例
2015/01/22 PHP
Yii2 如何在modules中添加验证码的方法
2017/06/19 PHP
解决laravel上传图片之后,目录有图片,但是访问不到(404)的问题
2019/10/14 PHP
JavaScript与C# Windows应用程序交互方法
2007/06/29 Javascript
Tab切换组件(选项卡功能)实例代码
2013/11/21 Javascript
jQuery中的$.ajax()方法应用
2014/05/06 Javascript
点击button获取text内容并改变样式的js实现
2014/09/09 Javascript
学习jQuey中的return false
2015/12/18 Javascript
全面解析标签页的切换方式
2016/08/21 Javascript
详解JavaScript时间处理之几个月前或几个月后的指定日期
2016/12/21 Javascript
详解Angular的双向数据绑定(MV-VM)
2016/12/26 Javascript
JS中from 表单序列化提交的代码
2017/01/20 Javascript
JavaScript实现瀑布流图片效果
2017/06/30 Javascript
React中使用collections时key的重要性详解
2017/08/07 Javascript
js实现把时间戳转换为yyyy-MM-dd hh:mm 格式(es6语法)
2017/12/28 Javascript
创建echart多个联动的示例代码
2018/11/23 Javascript
vue和iview实现Scroll 数据无限滚动功能
2019/10/31 Javascript
微信小程序实现菜单左右联动
2020/05/19 Javascript
Python标准库笔记struct模块的使用
2018/02/22 Python
python单线程文件传输的实例(C/S)
2019/02/13 Python
pyqt5 实现工具栏文字图片同时显示
2019/06/13 Python
利用Python产生加密表和解密表的实现方法
2019/10/15 Python
python 利用已有Ner模型进行数据清洗合并代码
2019/12/24 Python
django-crontab实现服务端的定时任务的示例代码
2020/02/17 Python
python GUI库图形界面开发之PyQt5图片显示控件QPixmap详细使用方法与实例
2020/02/27 Python
判断单链表中是否存在环
2012/07/16 面试题
财务主管岗位职责
2014/02/28 职场文书
三月法制宣传月活动总结
2014/07/03 职场文书
网络文明传播志愿者活动方案
2014/08/20 职场文书
2014年国庆节庆祝建国65周年比赛演讲稿
2014/09/21 职场文书
教师求职自荐信范文
2015/03/04 职场文书
500字作文之难忘的同学
2019/12/20 职场文书
详细介绍python操作RabbitMq
2022/04/12 Python
纯CSS打字动画的实现示例
2022/08/05 HTML / CSS