1、
/**
* 在浏览器环境下测试任何对象的某个特性是否存在
* 使用函数isHostMethod()
*/
function isHostMethos(object, property) {
let t = typeof object[property];
return t === 'function' || (!!(t==='object' && object[property])) || t === 'unknown';
}
result = isHostMethos(xhr, "open"); // true
2、
/**
* 识别呈现引擎和浏览器、Windows操作平台、移动设备和游戏系统
*/
let client = function () {
let engine = {
//呈现引擎
ie: 0,
gecko: 0,
webkit: 0,
khtml: 0,
opera: 0,
// 具体的版本
ver: null
};
let browser = {
// 浏览器
ie: 0,
firefox: 0,
kong: 0,
opera: 0,
chrome: 0,
// 具体的版本
ver: null
};
// 平台、设备、操作系统
let system = {
win: false,
mac: false,
xll: false,
// 移动设备
iphone: false,
ipod: false,
ipad: false,
ios: false,
andriod: false,
nokiaN: false,
winMobile: false,
// 游戏系统
wii: false,
ps: false
};
// 检测呈现引擎和浏览器
let ua = navigator.userAgent;
if (window.opera) {
engine.ver = browser.ver = window.opera.version();
engine.opera = browser.opera = parseFloat(engine.ver);
} else if (/AppleWebkit\/(\S+)/.tset(ua)) {
engine.ver = RegExp["$1"];
engine.webkit = parseFloat(engine.ver);
// 确定是Chrome 还是 Safari
if (/Chrome\/(\S+)/.test(ua)) {
browser.ver = RegExp["$1"];
browser.chrome = parseFloat(browser.ver);
} else if (/Version\/(S+)/.test(ua)) {
browser.ver = RegExp["$1"];
browser.safari = parseFloat(browser.ver);
} else {
// 近似确定版本号
let safariVersion = 1;
if (engine.webkit < 100) {
safariVersion = 1;
} else if (engine.webkit < 312) {
safariVersion = 1.2;
} else if (engine.webkit < 412) {
safariVersion = 1.3;
} else {
safariVersion = 2;
}
browser.safari = browser.ver = safariVersion;
}
} else if (/KHTML\/(\S+)/.test(ua) || /Konqueror\/([^;]+)/.test(ua)) {
engine.ver = browser.ver = RegExp["$1"];
engine.Khtml = browser.kong = parseFloat(engine.ver);
} else if (/rv:([^\)]+)\) Gecko\/\d{8}/.test(ua)) {
engine.ver = RegExp["$1"];
engine.gecko = parseFloat(engine.ver);
// 确定是不是Firefox
if (/Firefox\/(\S+)/.test(ua)) {
browser.ver = RegExp["$1"];
browser.firefox = parseFloat(engine.ver);
}
} else if (/MSIE ([^;]+)/.test(ua)) {
engine.ver = RegExp["$1"];
engine.ie = browser.ie = parseFloat(engine.ver);
}
// 检测浏览器
browser.ie = engine.ie;
browser.opera = engine.opera;
// 检测平台
let p = navigator.platform;
system.win = p.indexOf("Win") === 0;
system.mac = p.indexOf("Mac") === 0;
system.xll = (p === "Xll") || (p.indexOf("Linux") === 0);
// 检测windows 操作系统
if (system.win) {
if (/Win(?:dows )? ([^do]{2})\s?(\d+\.\d+)?/.test(ua)) {
if (RegExp["$1"] === "NT") {
switch(RegExp["$2"]) {
case "5.0":
system.win = "2000";
break;
case "5.1":
system.win = "XP";
break;
case "6.0":
system.win = "Vista";
break;
case "6.1":
system.win = "7";
break;
default:
system.win = "NT";
break;
}
} else if (RegExp["$1"] === "9x") {
system.win = "ME";
} else {
system.win = RegExp["$1"];
}
}
}
// 移动设备
system.iphone = ua.indexOf("iPhone") > -1;
system.ipod = ua.indexOf("iPode") > -1;
system.ipad = ua.indexOf("iPad") > -1;
system.nokiaN = ua.indexOf("NokiaN") > -1;
// windows mobile
if (system.win === "CE") {
system.winMobile = system.win;
} else if (system.win === "Ph") {
if (/Windows Phone OS (\d+.\d+)/.test(ua)) {;
system.win = "Phone";
system.winMobile = parseFloat(RegExp["$1"]);
}
}
// 检测ios版本
if (system.mac && ua.indexOf("Mobile") > -1) {
if (/CPU (?:iphone ) ?OS (\d+_\d+)/.test(ua)) {
system.ios = parseFloat(RegExp.$1.replace("_", "."));
} else {
system.ios = 2; // 不能真正检测出来,只能猜测(我。。。。)
}
}
// 检测Android版本
if (/Android (\d+\. \d+)/.test(ua)) {
system.android = parseFloat(RegExp.$1);
}
// 检测游戏系统
system.wii = ua.indexOf("Wii") > -1;
system.ps = /playstation/i.test(ua);
// 返回相应对象
return {
engine: engine,
browser: browser,
system: system
};
}();
3、
/**
* 检查某个节点是否是另一个节点的后代
* 通用的contains()方法
* !!双非操作符会将该数值转换为布尔值,对掩码16执行按位操作会返回一个非零数值
*/
function contains(refNode, otherNode) {
if (typeof refNode.contains === "function" && (!client.engine.webkit || client.engine.webkit >= 522)) {
return refNode.contains(otherNode);
} else if (typeof refNode.compareDocumentPosition === "function") {
return !!(refNode.compareDocumentPosition(otherNode) & 16);
} else {
let node = otherNode.parentNode;
do {
if (node === refNode) {
return true;
} else {
node = node.parentNode;
}
} while (node !== null);
return false;
}
}
4、
/**
* 支持innerText 属性的浏览器包括 IE4+ 、 Opera 8+ Chrome
* Firefox 支持作用类似的 textContent属性
* 支持 textContent 属性的还有IE9+ Safari 3+ Opera 10+ 和 Chrome
* 跨浏览器 检测可以使用哪个属性的函数
*/
function getInnerText(element) {
return (typeof element.textContent === "string") ? element.textContent : element.innerText;
}
function setInnerText(element, text) {
if (typeof element.textContent === "string") {
element.textContent = text;
} else {
element.innerText = text;
}
}
5、
/**
* 跨浏览器的事件处理程序
* 创建一个EventUtil 对象来解决各个浏览器的差异
* DOM2级方法:addEventListener,removeEventListener 接受三个参数: 传入事件类 * 型、事件处理程序函数,第三个布尔值--
* true: 在捕获阶段调用事件处理程序; false:则在冒泡阶段调用事件处理程序
*/
let EventUtil = {
// 添加事件
addHandler: function (element, type, handler) {
if (element.addEventListener) {
element.addEventListener(type, handler, false);
} else if (element.attachEvent) {
element.attachEvent("on" + type, handler);
} else {
element["on" + type] = handler;
}
},
// 返回对event 对象的引用
getEvent: function(event) {
return event ? event : window.event;
},
// 返回事件的目标
getTarget: function (event) {
return event.target || event.srcElement;
},
// 取消事件的默认行为
preventDefault: function (event) {
if (event.preventDefault) {
event.preventDefault()
} else {
event.returnValue = false;
}
},
// 移除事件
removeHandler: function (element, type, handler) {
if (element.removeEventListener) {
element.removeEventListener(type, handler, false);
} else if (element.detachEvent) {
element.detachEvent("on" + type, handler);
} else {
element["on" + type] = null;
}
},
// 禁止事件冒泡
stopPropagation: function (event) {
if (event.stopPropagation) {
event.stopPropagation();
} else {
event.cancelBubble = true;
}
},
// 跨浏览器取得相关元素
getRelatedTarget: function (event) {
if (event.relatedTarget) {
return event.relatedTarget;
} else if (event.toElement) {
return event.toElement;
} else if (event.fromElement) {
return event.fromElement;
} else {
return null;
}
},
// 获取鼠标按键的属性 DOM的button 属性有三个值 0(左键) 1(滚轮) 2(鼠标次键) IE8及之前版本的button属性有八个值 0-7
getButton: function (event) {
if (document.implementation.hasFeature("MouseEvents", "2.0")) {
return event.button;
} else {
switch(event.button) {
case 0:
case 1:
case 3:
case 5:
case 7:
return 0;
case 2:
case 6:
return 2;
case 4:
return 1;
}
}
},
// 取得鼠标滚轮增量值(delta)的方法
getWheelDelta: function (event) {
if (event.wheelDelta) {
return (client.engine.opera && client.engine.opera < 9.5 ? -event.wheelDelta : event.wheelDelta);
} else {
return -event.detail * 40;
}
},
// 取得键盘按键的字符编码
getCharCode: function (event) {
if (typeof event.charCode === "number") {
return event.charCode;
} else {
return event.keyCode;
}
},
// 操作剪贴板文本
getCliboardText: function (event) {
let clipboardData = (event.clipboardData || window.clipboardData);
return clipboardData.getData("text");
},
setClipboardText: function (event, value) {
if (event.clipboardData) {
return event.clipboardData.setData("text/plain", value);
} else if (window.clipboardData) {
return window.clipboardData.setData("text", value);
}
}
}
6、自动切换焦点:
(function () {
function tabForward(event) {
event = EventUtil.getEvent(event);
let target = EventUtil.getTarget(event);
if (target.value.length === target.maxLength) {
let form = target.form;
for (let i = 0, len=form.element.length; i < len; i++) {
if (form.element[i] === target) {
if (form.element[i+1]) {
form.elements[i+1].focus();
}
return;
}
}
}
}
})();
高程第22章的高级技巧还有好多的技巧,每一个技巧都应该值得深深去研究体味