dojo/dom模块作为一个基础模块,最常用的就是byId方法。除此之外还有isDescendant和setSelectable方法。

  dom.byId(myId)方法:

    各种前端类库都免不了与DOM节点打交道,操作DOM的方法千变万化最终还是要回到原生的那几个方法中,因为类库再快也快不过原生。所以在dom.byId方法中,还是要依靠document.getElementById('myId')方法。假如没有ie,假如不要考虑兼容性,getElementById方法可以完全满足我们的需求。但是,ie毁了一切,借用美国同事的一句话:Fuck the stupid IE! 兼容性问题有两条:

  • ie8及较低版本中,myId不区分大小写,所以myid跟myId会返回同样的结果
  • ie7及较低版本中,如果name名称与给定ID相同的表单元素且表单元素在给定ID元素的前面,那么IE就会返回那个表单元素

  这就要求我们在必须判断一下得到的元素的id是否真与传入参数相同。判断方法是利用id属性或id特性节点:

var te = id && document.getElementById(id)
te && (te.attributes.id.value == id || te.id == id)

如果上帝为你关上了一扇门,他一定会为你打开另一扇门(好矫情,就行天无绝人之路嘛)。ie4开始提供了document.all,它是一个代表所有元素的集合。document.all[myId]返回id为myId的一个元素或者包含name为myId的一个类数组。我们可以循环判断其中的元素是否满足要求:

var eles = document.all[id];if(!eles || eles.nodeName){eles = [eles];}// if more than 1, choose first with the correct idvar i = 0;while((te = eles[i++])){if((te.attributes && te.attributes.id && te.attributes.id.value == id) || te.id == id){return te;}}

所以,dojo/dom中的实现根据浏览器的不同,有不同的实现:

if(has("ie")){dom.byId = function(id, doc){if(typeof id != "string"){return id;}var _d = doc || win.doc, te = id && _d.getElementById(id);// attributes.id.value is better than just id in case the// user has a name=id inside a formif(te && (te.attributes.id.value == id || te.id == id)){return te;}else{var eles = _d.all[id];if(!eles || eles.nodeName){eles = [eles];}// if more than 1, choose first with the correct idvar i = 0;while((te = eles[i++])){if((te.attributes && te.attributes.id && te.attributes.id.value == id) || te.id == id){return te;}}}};}else{dom.byId = function(id, doc){// inline'd type check.// be sure to return null per documentation, to match IE branch.return ((typeof id == "string") ? (doc || win.doc).getElementById(id) : id) || null; // DOMNode};}

  dom.isDescendant(node, ancestor)方法:

  这个方法用来判断node是否是ancestor的一个子节点,其实就是孩子找父亲。孩子找父亲比较简单,而父亲找孩子是比较难的,因为子节点一定有父节点,所以只要一级一级的找上去即可。

dom.isDescendant = function(/*DOMNode|String*/ node, /*DOMNode|String*/ ancestor){try{node = dom.byId(node);ancestor = dom.byId(ancestor);while(node){if(node == ancestor){return true; // Boolean}node = node.parentNode;}}catch(e){ /* squelch, return false */ }return false; // Boolean};

其实还有一个原生的函数也可以满足要求:element.contains方法,不过这个方法并没有被纳入规范中。但是几乎所有的浏览器都支持,包括IE(最初就是ie增加的该方法,总算做了件好事。。)。所以该方法也可以这样实现:

dom.isDescendant = function(/*DOMNode|String*/ node, /*DOMNode|String*/ ancestor){try{node = dom.byId(node);ancestor = dom.byId(ancestor);return ancestor.contains(node);}catch(e){ /* squelch, return false */ }return false; // Boolean};

 dom.setSelectable(node, selectable)方法:

  看名字也知道是用来设置一个节点及其自己点是否可选中的。css属性中可以通过设置“user-select”来控制一个元素是否可选择,但这个属性并未被纳入标准中去,所以各个浏览器中都需要加浏览器前缀,如:-webkit、-moz、-ms、-o等;所以我们可以通过设置元素的style属性中的相应属性来控制元素的可选择性。但是,ie总是太操蛋,大多数情况下,ms前缀都可以解决问题,但是如果一个将一个frame作为编辑器使用时,设置msUserSelect为none时无法达到效果,所以在ie中我们利用unselectable特性来解决这个问题。ie下存在的这个特性:unselectable, 设为on则不可选中,移除这个属性则表示可选中。

  dojo的实现中,首先判断userSelect属性是否能使用:

has.add("css-user-select", function(global, doc, element){// Avoid exception when dom.js is loaded in non-browser environmentsif(!element){ return false; }var style = element.style;var prefixes = ["Khtml", "O", "Moz", "Webkit"],i = prefixes.length,name = "userSelect",prefix;// Iterate prefixes from most to least likelydo{if(typeof style[name] !== "undefined"){// Supported; return property namereturn name;}}while(i-- && (name = prefixes[i] + "UserSelect"));// Not supported if we didn't return before nowreturn false;});

  这里省略了ms前缀。

  然后根据对"css-user-select"的支持,使用不同的实现:

var cssUserSelect = has("css-user-select");dom.setSelectable = cssUserSelect ? function(node, selectable){// css-user-select returns a (possibly vendor-prefixed) CSS property namedom.byId(node).style[cssUserSelect] = selectable ? "" : "none";} : function(node, selectable){node = dom.byId(node);// (IE < 10 / Opera) Fall back to setting/removing the// unselectable attribute on the element and all its childrenvar nodes = node.getElementsByTagName("*"),i = nodes.length;if(selectable){node.removeAttribute("unselectable");while(i--){nodes[i].removeAttribute("unselectable");}}else{node.setAttribute("unselectable", "on");while(i--){nodes[i].setAttribute("unselectable", "on");}}};

ie中,循环改变所有子节点的unselectable特性来控制选择性。

  分享一条小经验:设置一个元素不可选中时,最好在能满足需求的最远祖先上设置,如果仅仅在一个元素上设置未必能够达到效果;比如:设置一个图片不可选中,但是祖先可以选中,用户可能会祖先选中时会变蓝,看起来好像图片依然能够被选中。

  如果您觉得这篇文章对您有帮助,请不吝点击下方的推荐按钮,您的鼓励是我分享的动力!

dojo/dom源码学习相关推荐

  1. vue实例没有挂载到html上,vue 源码学习 - 实例挂载

    前言 在学习vue源码之前需要先了解源码目录设计(了解各个模块的功能)丶Flow语法. src ├── compiler # 把模板解析成 ast 语法树,ast 语法树优化,代码生成等功能. ├── ...

  2. VUE源码学习第一篇--前言

    一.目的 前端技术的发展,现在以vue,react,angular为代表的MVVM模式以成为主流,这三个框架大有三分天下之势.react和angular有facebook与谷歌背书,而vue是以一己之 ...

  3. Vue源码学习 - 组件化一 createComponent

    Vue源码学习 - 组件化一 createComponent 组件化 createComponent 构造子类构造函数 安装组件钩子函数 实例化 VNode 总结 学习内容和文章内容来自 黄轶老师 黄 ...

  4. php连接tidb,TiDB源码学习笔记:启动TiDB

    作者:院长,神州数码云基地开发工程师,目前专注于TiDB源码研究. TiDB源码研究系列第一篇,简述TiDB的核心架构,从tidb-server/mian.go开始,探索启动TiDB的方法. 最近因为 ...

  5. 【iScroll源码学习01】准备阶段 - 叶小钗

    [iScroll源码学习01]准备阶段 - 叶小钗 时间 2013-12-29 18:41:00 博客园-原创精华区 原文  http://www.cnblogs.com/yexiaochai/p/3 ...

  6. Vue源码学习 - 准备工作

    Vue源码学习 - 准备工作 准备工作 认识Flow 为什么用 Flow Flow 的工作方式 类型推断 类型注释 数组 类和对象 null Flow 在 Vue.js 源码中的应用 flow实践 总 ...

  7. Shiro源码学习之二

    接上一篇 Shiro源码学习之一 3.subject.login 进入login public void login(AuthenticationToken token) throws Authent ...

  8. Shiro源码学习之一

    一.最基本的使用 1.Maven依赖 <dependency><groupId>org.apache.shiro</groupId><artifactId&g ...

  9. mutations vuex 调用_Vuex源码学习(六)action和mutation如何被调用的(前置准备篇)...

    前言 Vuex源码系列不知不觉已经到了第六篇.前置的五篇分别如下: 长篇连载:Vuex源码学习(一)功能梳理 长篇连载:Vuex源码学习(二)脉络梳理 作为一个Web前端,你知道Vuex的instal ...

最新文章

  1. python答辩结束语_Beta答辩总结
  2. 如何使用 CODING 实践 DevOps 全流程
  3. mysql日常错误信息解决方法:InnoDB: and force InnoDB to continue crash recovery here.
  4. WPF实现背景透明磨砂,并通过HandyControl组件实现弹出等待框
  5. Windows Phone开发(46):与Socket有个约会 转:http://blog.csdn.net/tcjiaan/article/details/7669315...
  6. 通过UIBezierPath贝塞尔曲线画圆形、椭圆、矩形
  7. a*算法流程图_光伏逆变器MPPT基本算法介绍李星硕
  8. Java 类锁、对象锁、私有锁
  9. fuck-KUNLUN昆仑ECRS会员管理系统
  10. 国庆期间新闻回顾:微软智斗盗版 华为出手3Com
  11. vs关于_CRT_SECURE_NO_WARNINGS警告说明
  12. whitepages 配合调查_“你好,我是警察!请配合我们的调查......”_政务_澎湃新闻...
  13. MySQL图书管理系统设计
  14. java连接HDFS+Kerberos配置参数示例
  15. DRM破解再升级 支持新版WM11
  16. proxy代理配置及解析
  17. winform 窗体设置成无边框、可拖拽、四周圆角
  18. 【MobileNet V2】《MobileNetV2:Inverted Residuals and Linear Bottlenecks》
  19. 联诚发龙显P1.25系列LED大屏亮相宝安区区政府会议室
  20. 体脂秤Flash MCU:HT45F75 入坑手册

热门文章

  1. sqlite3里类似top的用法
  2. TiXml使用详解(转)
  3. 重构风险程序员一定要遵守的规则
  4. GDI+中发生一般性错误
  5. 9102年webpack4搭建vue项目
  6. ASP.NET Core 2.0 : 九.从Windows发布到CentOS的跨平台部署
  7. 运维监控利器Nagios:概念、结构和功能
  8. 国庆七天乐——第一天
  9. IOS开发之UI手势
  10. var_dump()