Compatible.js 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479
  1. //#region 浏览器兼容使用
  2. /*
  3. 设置兼容性的写法 ie里面有innerText,outerHTML,而HTML5没有这些属性,为了使得TML5兼容ie特性,写了如下兼容js,HTML5也在逐步形成上诉函数。
  4. */
  5. Namespace.register("U.UF.CP"); //C是compatible兼容的简写
  6. //通过修改浏览器内置属性 设置兼容,添加兼容,此兼容模块兼容ie6以上,firefox,safiry,chrome
  7. /**
  8. * 滚轮事件兼容
  9. *
  10. * @param {function} fun 滚动时触发的函数
  11. */
  12. U.UF.CP.wheel = function (fun) {//onwheel支持所有html5浏览器 onmousewheel 支持所有非firefox的浏览器 DOMMouseScroll支持firefox浏览器
  13. this.onwheel = fun; //onwheel 事件在鼠标滚轮在元素上下滚动时触发
  14. }
  15. /**
  16. * 滚轮事件兼容
  17. */
  18. U.UF.CP.wheelGet = function () {
  19. return this.onwheel; //onwheel 事件在鼠标滚轮在元素上下滚动时触发
  20. }
  21. /**
  22. * 打印标签之间的纯文本信息
  23. *
  24. * @param {string} str 需要打印的元素的内容
  25. */
  26. U.UF.CP.setInnerText = function (str) {//参数str txt是内容
  27. this.textContent = str; //获得元素的文本内容 = str
  28. }
  29. /**
  30. * innerText与textContent的兼容处理
  31. */
  32. U.UF.CP.setInnerTextGet = function () {
  33. return this.textContent; //获得元素的文本内容
  34. }
  35. /**
  36. * 打印开始和结束标签之间的HTML
  37. *
  38. * @param {string} str 字符串
  39. */
  40. U.UF.CP.outerHtml = function (str) {
  41. var i,
  42. _this = U.selectEl(this), //i为变量
  43. _div = $$("div", { "innerHTML": str }).childNodes, //创建一个div 内容为str
  44. _create = $$("frag"); // createDocumentFragment:创建一个 documentFragment
  45. //循环插入
  46. for (i = 0; i < _div.length; i++) {//
  47. _create.appendChild(_div[i]); //在_create添加_div
  48. }
  49. _create.insertBefore(_create, this); //向列表中插入一个项目
  50. _this.remove(); //拷贝并删除本身
  51. }
  52. /**
  53. * 打印开始和结束标签之间的HTML
  54. *
  55. * 给元素原型添加一个outerHtml方法
  56. */
  57. U.UF.CP.outerHtmlGet = function () {
  58. var _copy = this.cloneNode(true); //克隆源元素
  59. var _div = $$("div", {}); //创建一个临时div,用于把克隆元素放入
  60. _div.appendChild(_copy); //div里面插入克隆元素
  61. return _div.innerHTML; /*如果不支持就使用innerhtml插入*/
  62. }
  63. /**
  64. * 返回了元素上的样式表
  65. *
  66. * 给元素原型添加一个currentStyle方法
  67. */
  68. U.UF.CP.getStyleGet = function () {
  69. return getComputedStyle(this, false); //返回的元素样式的属性
  70. }
  71. /**
  72. * 可以将鼠标事件锁定在指定的元素上
  73. *
  74. * 给元素原型添加一个setCaptureGet方法
  75. */
  76. U.UF.CP.setCapture = function () {
  77. return function () { //可以将鼠标事件锁定在指定的元素上
  78. window.captureEvents(Event.MOUSEMOVE | Event.MOUSEUP);
  79. }
  80. }
  81. /**
  82. * 释放鼠标捕获
  83. * 给元素原型添加一个releaseCaptureGet方法
  84. */
  85. U.UF.CP.releaseCapture = function () {//兼容火狐
  86. return function () {
  87. window.releaseEvents(Event.MOUSEMOVE | Event.MOUSEUP)
  88. } //释放鼠标捕获
  89. }
  90. /**
  91. * 浏览器窗口被调整尺寸时发生
  92. * @param {function} fun 被调整的对象
  93. */
  94. U.UF.CP.onresize = function (fun) {
  95. if (this.tagName) {//存在元素的标签名
  96. //设置Set事件
  97. var _position,
  98. _sizeelement = this.__SizeElement__; //自定义 __SizeElement__ 元素大小
  99. if (!_sizeelement || U.selectEl(_sizeelement).Parent() != this && fun) {//如果不存在SizeElement或者SizeElement的父级等于他本身并且存在el 往下执行
  100. _position = U.UF.EL.getStyle(this, "position");
  101. if (_position == "" || _position == "static") { this.style.position = "relative"; }
  102. _sizeelement = this.__SizeElement__ = $$("object", {//创建一个元素
  103. "onload": function () {
  104. if (fun) {
  105. _sizeelement.contentDocument.defaultView.onresize = function () {
  106. fun();
  107. }
  108. // U.UF.C.apply(retElement, [[执行函数的事件]])
  109. //retElement 将要绑定事件与属性的对象,如没有,可以传递null或者this,此处还需要优化,很多地方都会调用此函数,会导致速度降低。
  110. //arr 时间和属性组成的参数数组
  111. }
  112. else {
  113. try {//try...catch语句将能引发错误的代码放在try块中,并且对应一个响应,然后有异常被抛出。
  114. delete this.__SizeElement__;
  115. } catch (e) { }
  116. }
  117. }, //当触发onload时执行此函数
  118. "type": "text/html",
  119. "data": "about:blank",
  120. "style": {
  121. "cssText": "display:block;position:absolute;top:0;left:0;height:100%;width:100%;overflow:hidden;pointer-events:none;z-index:-1;visibility:hidden;margin:0;padding:0;"
  122. }
  123. }, this);
  124. }
  125. else {//如果上述条件不成立则直接往下执行
  126. if (fun) {
  127. _sizeelement.contentDocument.defaultView.onresize = function () { fun(); }
  128. }
  129. else {
  130. try {//try...catch语句将能引发错误的代码放在try块中,并且对应一个响应,然后有异常被抛出。
  131. delete this.__SizeElement__;
  132. } catch (e) { }
  133. }
  134. }
  135. }
  136. }
  137. /**
  138. * 浏览器窗口被调整尺寸时发生
  139. *
  140. * 给元素原型添加一个onresize方法
  141. */
  142. U.UF.CP.onresizeGet = function () {
  143. try { //try...catch语句将能引发错误的代码放在try块中,并且对应一个响应,然后有异常被抛出。
  144. return this.__SizeElement__.contentDocument.defaultView.onresize;
  145. }
  146. catch (e) {
  147. return null;
  148. }
  149. }
  150. /**
  151. * 代表事件的状态
  152. * 比如事件在其中发生的元素、键盘按键的状态、鼠标的位置、鼠标按钮的状态。
  153. */
  154. U.UF.CP.eventGet = function () {//arguments.callee ->指向参数arguments对象的函数
  155. var _currentfun = arguments.callee;
  156. while (_currentfun.caller) { //一直往上寻找直到 寻找到顶层作用域 返回null 再往下执行
  157. _currentfun = _UDE.caller;
  158. }
  159. if (_currentfun.arguments[0]) { //对于火狐的兼容
  160. return _currentfun.arguments[0];
  161. }
  162. else {
  163. return null; //返回null
  164. }
  165. }
  166. /**
  167. * 捕获当前事件作用的对象的兼容处理
  168. */
  169. U.UF.CP.targetGet = function () {//支持firefox
  170. return event.target; //返回事件的目标节点(触发该事件的节点)
  171. }
  172. /**
  173. * 获得键盘的按键码的兼容处理
  174. */
  175. U.UF.CP.keyCodeGet = function () {
  176. return event.which; //获取按下的键盘按键Unicode值
  177. }
  178. /**
  179. * onreadystatechange加载设置事件的兼容
  180. */
  181. U.UF.CP.onreadystatechangeGet = function () {
  182. return this.onload; //当不兼容onreadystatechange的浏览器设置onreadystatechange的时候那么就相当于设置了onload
  183. }
  184. /**
  185. * onreadystatechange加载获取事件的兼容
  186. */
  187. U.UF.CP.onreadystatechange = function (cb) {
  188. this.onload = cb; //当不兼容onreadystatechange的浏览器获取onreadystatechange的时候那么就相当于获取onload
  189. }
  190. /**
  191. * 特定事件返回对象在指定坐标下的位置。 outside 说明制定的位置在元素之外
  192. */
  193. U.UF.CP.componentFromPoint = function () {
  194. return function () {
  195. var _position = U.UF.EL.getMousePosition();
  196. var _elinfo = U.UF.EL.getElementInfo(this);
  197. if ((_position["X"] > _elinfo["CW"] + _elinfo["TX"]) || (_position["Y"] > _elinfo["CH"] + _elinfo["TY"])) {
  198. return "outside";
  199. }
  200. return "";
  201. }
  202. }
  203. /**
  204. * 在浏览器初始化的时候执行这个函数,给浏览器的兼容属性添加方法
  205. */
  206. U.UF.CP.init = function () {
  207. //如果是html5浏览器,则执行判断内的内容,ie则不用进入下面内容。
  208. if (window.HTMLElement) {
  209. //注: HTMLElement.prototype.__defineGetter__(event, fucntion)的作用是给指定的event设置得到的回调函数,如event=onmousewheel的时候,当我们给页面上任意的元素设置事件的时候会触发指定fucntion
  210. //当浏览器不支持onmousewheel滚轮事件的时候,给浏览器的全局HTMLElement设置滚轮事件,让页面上所有的元素都有onmousewheel这个事件
  211. //由于firefox不支持onmousewheel,这里利用__defineGetter__和__defineSetter__给HTMLElement绑定onmousewheel这个事件
  212. /*检测浏览器是否支持onmousewheel这个方法,Safiri,火狐没有这个方法*/
  213. if (!("onmousewheel" in HTMLElement.prototype)) {
  214. //IE里面或者safiri的处理方法?
  215. if ("onwheel" in HTMLElement.prototype) {
  216. //滚轮事件兼容处理,分为get获取和set设置处理
  217. HTMLElement.prototype.__defineGetter__("onmousewheel", U.UF.CP.wheelGet); //元素onmousewheel的get处理
  218. HTMLElement.prototype.__defineSetter__("onmousewheel", U.UF.CP.wheel); //元素onmousewheel的set处理
  219. }
  220. //火狐的滚动处理
  221. else {
  222. window.addEventListener("DOMMouseScroll", function (e) {
  223. //监控Scroll事件
  224. var _fun = null,
  225. _currentevent = e.srcElement; //e.srcElement当前事件的源
  226. do {
  227. _fun = U.selectEl(_currentevent).attr("onmousewheel") || _currentevent.onmousewheel;
  228. _currentevent = U.selectEl(_currentevent).Parent();
  229. }
  230. while (!(_fun || !_currentevent)); //冒泡的顶部获取
  231. if (_fun) {//如果存在_fun
  232. if (U.UF.C.isString(_fun)) {//判断_fun 是否为字符串
  233. _currentevent.onmousewheel = new Function(_fun);
  234. }
  235. U.UF.EV.stopDefault(); //阻止页面固定事件
  236. //异步执行 解决卡死的bug
  237. setTimeout(function () {
  238. obj.call(this, e);
  239. }, 0);
  240. }
  241. }, false);
  242. }
  243. }
  244. //当浏览器不支持onreadystatechange的时候,给浏览器的全局HTMLElement设置onload,让页面上所有的元素都有onreadystatechange这个事件
  245. //由于chrome和friefox不支持onreadystatechange,这里利用__defineGetter__和__defineSetter__给HTMLElement绑定onreadystatechange这个事件
  246. // if (!("onreadystatechange" in HTMLElement.prototype)) {
  247. // HTMLElement.prototype.__defineGetter__("onreadystatechange", U.UF.CP.onreadystatechangeGet); //onreadystatechange加载设置事件的兼容
  248. // HTMLElement.prototype.__defineSetter__("onreadystatechange", U.UF.CP.onreadystatechange); //onreadystatechange加载设置事件的兼容
  249. // }
  250. //当浏览器不支持innerText的时候,给浏览器的全局HTMLElement设置textContent,让页面上所有的元素都有innerText这个事件
  251. //由于低版本的firefox不支持innerText,这里利用__defineGetter__和__defineSetter__给HTMLElement绑定innerText这个事件
  252. if (!("innerText" in HTMLElement.prototype)) {/*检测浏览器是否支持innerText这个方法*/
  253. HTMLElement.prototype.__defineGetter__("innerText", U.UF.CP.setInnerTextGet); //给元素原型添加一个innerText事件并且绑定U.UF.CP.setInnerText
  254. HTMLElement.prototype.__defineSetter__("innerText", U.UF.CP.setInnerText);
  255. }
  256. //当浏览器不支持outerHTML的时候,给浏览器的全局HTMLElement设置innerHTML,让页面上所有的元素都有outerHTML这个事件
  257. //由于低版本的firefox(FF7-)不支持outerHTML,这里利用__defineGetter__和__defineSetter__给HTMLElement绑定outerHTML这个事件
  258. if (!("outerHTML" in HTMLElement.prototype)) {/*检测浏览器是否支持outerHTML这个方法*/
  259. HTMLElement.prototype.__defineGetter__("outerHTML", U.UF.CP.outerHtmlGet); //给元素原型添加一个outerHtml事件并且绑定U.UF.CP.outerHtml
  260. HTMLElement.prototype.__defineSetter__("outerHTML", U.UF.CP.outerHtml);
  261. }
  262. //当浏览器不支持currentStyle的时候,给浏览器的全局HTMLElement设置getComputedStyle事件,让页面上所有的元素都有currentStyle这个事件
  263. //由于低版本的firefox不支持currentStyle,这里利用__defineGetter__给HTMLElement绑定currentStyle这个事件
  264. if (!("currentStyle" in HTMLElement.prototype)) {/*检测浏览器是否支持currentStyle这个方法*/
  265. HTMLElement.prototype.__defineGetter__("currentStyle", U.UF.CP.getStyleGet); //给元素原型添加一个currentStyle事件并且绑定U.UF.CP.getStyle
  266. }
  267. //当浏览器不支持setCapture的时候,给浏览器的全局HTMLElement设置captureEvents事件,让页面上所有的元素都有setCapture这个事件
  268. //由于firefox不支持setCapture,这里利用__defineGetter__给HTMLElement绑定setCapture这个事件
  269. if (!("setCapture" in HTMLElement.prototype)) {
  270. HTMLElement.prototype.__defineGetter__("setCapture", U.UF.CP.setCapture); //给元素原型添加一个setCapture事件并且绑定U.UF.CP.setCapture
  271. }
  272. //当浏览器不支持releaseCapture的时候,给浏览器的全局HTMLElement设置releaseEvents事件,让页面上所有的元素都有releaseCapture这个事件
  273. //由于firefox不支持releaseCapture,这里利用__defineGetter__给HTMLElement绑定releaseCapture这个事件
  274. if (!("releaseCapture" in HTMLElement.prototype)) {
  275. HTMLElement.prototype.__defineGetter__("releaseCapture", U.UF.CP.releaseCapture); //给元素原型添加一个releaseCapture事件并且绑定U.UF.CP.releaseCapture
  276. }
  277. //当浏览器不支持onresize的时候,给浏览器的全局HTMLElement设置focus,让页面上所有的元素都有onresize这个事件
  278. //由于低版本的firefox不支持onresize,这里利用__defineGetter__和__defineSetter__给HTMLElement绑定onresize这个事件
  279. if (!("onresize" in HTMLElement.prototype) || !(U.UF.CI.getBrowser().browser == "msie")) { /*检测浏览器是否支持onfocus事件*/
  280. HTMLElement.prototype.__defineGetter__("onresize", U.UF.CP.onresizeGet); //给元素原型添加一个onresize事件并且绑定U.UF.CP.onresize
  281. HTMLElement.prototype.__defineSetter__("onresize", U.UF.CP.onresize);
  282. }
  283. /*检测浏览器是否支持componentFromPoint事件*/
  284. if (!("componentFromPoint" in HTMLElement.prototype)) {
  285. HTMLElement.prototype.__defineGetter__("componentFromPoint", U.UF.CP.componentFromPoint); //当获取元素的componentFromPoint时候出发该函数
  286. }
  287. //当浏览器不支持event的时候,给浏览器的全局HTMLElement设置releaseEvents,让页面上所有的元素都有event这个事件
  288. //由于firefox不支持event,这里利用__defineGetter__给HTMLElement绑定event这个事件
  289. if (!("event" in window.constructor.prototype)) { /*检测浏览器是否支持event事件*/
  290. window.constructor.prototype.__defineGetter__("event", U.UF.CP.eventGet); //给元素原型添加一个event事件并且绑定U.UF.CP.event
  291. }
  292. //给window.event添加兼容属性方法
  293. if (window.Event.prototype) {
  294. //当浏览器不支持srcElement的时候,给浏览器的全局HTMLElement设置target事件,让页面上所有的元素都有srcElement这个事件
  295. //由于firefox不支持srcElement,这里利用__defineGetter__给HTMLElement绑定srcElement这个事件
  296. if (!("srcElement" in window.Event.prototype)) {/*检测浏览器是否支持srcElement事件*/
  297. window.Event.__defineGetter__("target", U.UF.CP.targetGet); //给元素原型添加一个target事件并且绑定U.UF.CP.target
  298. }
  299. //当浏览器不支持keyCode的时候,给浏览器的全局HTMLElement设置which事件,让页面上所有的元素都有keyCode这个事件
  300. //由于firefox不支持keyCode,这里利用__defineGetter__给HTMLElement绑定keyCode这个事件
  301. if (!("keyCode" in window.Event.prototype) && window.Event.__defineGetter__) {
  302. window.Event.__defineGetter__("keyCode", U.UF.CP.keyCodeGet); //给元素原型添加一个keyCode事件并且绑定U.UF.CP.keyCheck
  303. }
  304. }
  305. }
  306. }
  307. //#region querySelector 兼容处理
  308. U.UF.C.style; //防止选择器创建多个样式style
  309. /**
  310. * querySelectorAll 兼容
  311. *
  312. * @param {string} 搜索的内容
  313. * @param {element} 搜索的元素区域
  314. */
  315. document.querySelectorAll = document.querySelectorAll || function (str, el) {
  316. var _addstyle = U.UF.C.style, //判断是否已经添加了上style识别样式
  317. _returnarr = [], //创建一个空的数组
  318. _firstchild = document.documentElement.firstChild, //document.documentElement的第一个子元素
  319. _arr = (el || document).all, //搜索区域
  320. i = _arr.length; //_arr的长度
  321. //添加的style link
  322. try {
  323. _addstyle.styleSheet.cssText = str + "{q:1}";
  324. }
  325. catch (e) {
  326. U.UF.C.style = $$("style", {//U.UF.C.style:防止选择器创建多个样式style
  327. "type": "text/css",
  328. "styleSheet": {
  329. "cssText": str + "{q:1}"
  330. }
  331. }, _firstchild);
  332. }
  333. //全局筛选
  334. while (i--) {
  335. if (_arr[i].currentStyle.q) {
  336. _returnarr.unshift(_arr[i]);
  337. }
  338. }
  339. return _returnarr;
  340. };
  341. /**
  342. * querySelector 兼容
  343. *
  344. * @param {number} 搜索的内容
  345. */
  346. document.querySelector = document.querySelector || function (num) {//返回文档中匹配指定 CSS 选择器的一个元素
  347. var _num = document.querySelectorAll(num);
  348. if (_num.length) {//如果_num存在
  349. return _num[0]; //返回_num[0]
  350. }
  351. else {//不存在
  352. return null; //返回null
  353. }
  354. };
  355. /**
  356. * 选择元素区域 自定义搜索元素选择函数
  357. *
  358. * @param {string} 搜索的内容
  359. * @param {object} 搜索的元素
  360. */
  361. U.UF.CP.selectorElement = function (str, el) {
  362. var _ishasid = (el.id === "" && el != document), //判断是否支持选择器
  363. _query = $$("div").querySelectorAll;
  364. if (_ishasid) {//如果支持
  365. el.id = el.uniqueID; //uniqueID : 绝对唯一地标识一个 HTML 元素
  366. }
  367. try { //尝试执行代码块
  368. if (_query) {//如果浏览器支持querySelectorAll ,那么直接使用浏览器的
  369. return (el || document).querySelectorAll((el.id ? ("#" + el.id + " ") : " ") + str, el);
  370. }
  371. //否则调用上面自定义的方法
  372. else {
  373. return document.querySelectorAll((el.id ? ("#" + el.id + " ") : " ") + str, el);
  374. }
  375. }
  376. catch (e) {//捕获错误的代码块
  377. return null;
  378. }
  379. finally {//无论 try / catch 结果如何都会执行的代码块
  380. if (_ishasid) {
  381. el.id = "";
  382. }
  383. }
  384. }
  385. //#endregion
  386. //#region 手机兼容处理,只要引用了uform框架,会自动使手机在滑动的过程中不会触发点击事件
  387. /**
  388. * 手机点击处理
  389. */
  390. U.UF.CP.touch = function () {
  391. //这里有个bug如果多次引用uform的时候这里的事件会注册监视多次
  392. if (U.UF.C.touchstart) {
  393. U.UF.EV.delElementEvent("touchstart", document, U.UF.C.touchstart, true);
  394. }
  395. //监视touchstart,注册函数事件 U.UF.EV.addElementEvent(事件名称,添加事件的元素,事件触发后调用的函数,指定事件是否在捕获或冒泡阶段执行)
  396. U.UF.EV.addElementEvent("touchstart", document, U.UF.C.touchstart, true);
  397. }
  398. /**
  399. * touchstart处理
  400. */
  401. U.UF.C.touchstart = function () {
  402. var i,
  403. _eventsrc = event.srcElement; //时间触发的元素
  404. //默认触发的时候是没有移动的状态
  405. U.UF.C.ismove = null;
  406. //停止事件分发
  407. U.UF.EV.stopBubble();
  408. //移除start事件事件取消,防止下面直接出发touch事件的时候给重复监听
  409. U.UF.EV.delElementEvent("touchstart", document, U.UF.C.touchstart, true);
  410. //直接执行touchstart事件
  411. U.UF.EV.simulatePhoneTouch(_eventsrc, "touchstart");
  412. //取消后重新添加事件进去
  413. U.UF.EV.addElementEvent("touchstart", document, U.UF.C.touchstart, true);
  414. //监视在鼠标移动的处理
  415. U.UF.EV.addElementEvent("touchmove", document, U.UF.C.touchmove);
  416. //end事件等待
  417. U.UF.EV.addElementEvent("touchend", document, U.UF.C.touchend, true);
  418. }
  419. /**
  420. * touchmove处理
  421. */
  422. U.UF.C.touchmove = function () { //移动监视
  423. U.UF.C.ismove = true; //设置鼠标在移动
  424. U.UF.EV.delElementEvent("touchmove", document, U.UF.C.touchmove); //移除鼠标移动事件
  425. U.UF.EV.simulatePhoneTouch(event.srcElement, "touchmove"); //执行事件touch移动的处理
  426. U.UF.EV.stopBubble(); //停止冒泡处理
  427. }
  428. /**
  429. * touchend处理
  430. */
  431. U.UF.C.touchend = function () {
  432. U.UF.EV.delElementEvent("touchend", document, U.UF.C.touchend, true); //touchend抓取成功后的处理
  433. U.UF.EV.stopBubble(); //移除事件
  434. //如果用户的touchstart后没有处理touchmove事件,那么允许用户出发touchend事件
  435. if (!U.UF.C.ismove) {
  436. U.UF.EV.simulatePhoneTouch(event.srcElement, "touchend"); //触发touchend事件
  437. }
  438. }
  439. //#endregion