每天记录一点新遇到的浏览器方法和属性

问题1:document的elementFromPoint方法

这个方法可以根据坐标的点来获取元素,不过是获取最上层的元素,而且浏览器兼容也是需要考虑的,因为不同的浏览器传入的参数有可能是clientx,也有可能是pagex。下面的代码就可以实现这个功能。

function init() {
  document.onclick = getElement;
  writeroot = document.getElementById('offsetTree');
  // for iPhone
  var all = document.getElementsByTagName('*')
  for (var i=0;i<all.length;i++) {
    all[i].onclick = getElement;
    all[i].onclick = null;
  }
}

function getElement(e) {
  var evt = e || window.event;
  try {
    var el = document.elementFromPoint(evt.clientX,evt.clientY);
  } catch (e) {
    alert('elementFromPoint not supported by this browser');
    return;
  }
  writeroot.value = el.nodeName;
}
init();
至于浏览器兼容的解决方法可以参见 document.elementFromPoint
问题2:document的document.scrollingElement获取浏览器滚动的距离

chrome浏览器中不管是怪异模式还是标准模式下都是通过document.body.scrollTop,而其他浏览器下标准模式下通过document.documentElement来完成的。因此在webkit浏览中我们可以通过如下属性获取:

var rootElement = document.scrollingElement || docuemnt.body;

具体可以参考Chrome 中的 document.scrollingElement

问题3:document.getClientRects属性

document.getElementById("span").onclick = function() {
    var objRectList = this.getClientRects(), i = 0, length = objRectList.length;
    var string = "有" + length + "个矩形\r\n";
    for (var i=0; i<length; i+=1) {
        string = string + "第"+ (i+1) +"个矩形: top:" + objRectList[i].top + ", right:" + objRectList[i].right + ", bottom:" + objRectList[i].bottom + ", left:" + objRectList[i].left + "\r\n";
    }
    alert(string);
};

返回元素的数个矩形区域,返回的结果是个对象列表,具有数组特性。这里的矩形选区只针对inline box,因此,只针对a, span, em这类标签元素。IE6, IE7还有一个问题,就是按照定义,如果是block水平标签内的文字,不过文字有多少行,返回的都是这个block水平的标签区域。但是,IE6, IE7却不走寻常路,反而“正常模样”地返回行数等。例如上面的demo页面,如果把span标签换成p标签,则其他所有浏览器返回的列表个数是1,就IE6,IE7返回的是文字行数相等的矩形区域。CSSOM视图模式(CSSOM View Module)相关整理。参考这个文章也可以学习colorDepth和pixelDepth相关知识。

问题4:一些元素常见的属性

检测webkit内核:

window.webkitURL
检测表单是否满足要求

document.forms["myform"].addEventListener('invalid', function() {
  //Optional response here.
}, false);

document.forms["myform"].addEventListener('submit', function() {
  document.forms["myform"].reportValidity();//返回true如果输入满足要求,否则返回false。返回false的时候触发valid事件,但是在chrome40+才行
}, false);

问题4:图像的naturalWidth和naturalHeight属性

  在HTML 5中,新增加了两个用来判断图片的宽度和高度的属性,分别为.naturalWidth 和naturalHeight属性,例子如下:

var rw = myimage.naturalWidth;	// 真实图片宽度
var rh = myimage.naturalHeight;	//真是图片高度
但有个前提是,必须在图片完全下载到客户端浏览器才能判断,,目前在ie 9,Firefox, Chrome, Safari 和Opera都是可以使用的,如果是不支持的版本浏览器,那可以用传统方法判断,如下:
var myimage = document.getElementById("myimage");
if (typeof myimage.naturalWidth == "undefined") {
// IE 6/7/8
var i = new Image();
i.src = myimage.src;
var rw = i.width;
var rh = i.height;
}
else {
// HTML5 browsers
var rw = myimage.naturalWidth;
var rh = myimage.naturalHeight;
}
在retina.js中,如果是修改img的src,为了防止由于图片大小的变化而导致占据的空间发生变化,在设置src之前我们首先保证了了img图片占据的空间没有变化:

function forceOriginalDimensions(image) {
  if (!image.hasAttribute('data-no-resize')) {
    //让图片不改变原来所占据的空间!
    if (image.offsetWidth === 0 && image.offsetHeight === 0) {
      image.setAttribute('width', image.naturalWidth);
      image.setAttribute('height', image.naturalHeight);
    } else {
      image.setAttribute('width', image.offsetWidth);
      image.setAttribute('height', image.offsetHeight);
    }
  }
  return image;
}

问题5:影子元素方法createShadowRoot

   var host = document.querySelector('.widget');
    var root = host.createShadowRoot();
    root.textContent = '我在你的 div 里!';

通过这种方式可以实现创建影子DOM,具体关于shadow DOM概念请自行google

问题6:parentElement属性获取父级Element元素

/**
	 * Check whether the given target element is a child of a scrollable layer and if so, set a flag on it.
	 * @param {EventTarget|Element} targetElement
	 * (1)为targetElement添加一个fastClickScrollParent属性,表示当前元素所在的滚动父元素
	 * (2)为targetElement添加一个fastClickScrollParent属性的同时,为我们的fastClickScrollParent属性又添加一个fastClickLastScrollTop属性
	 * 该属性表示滚动父元素当前已经滚动的scrollTop距离
	 */
	FastClick.prototype.updateScrollParent = function(targetElement) {
		var scrollParent, parentElement;
		//获取fastClickScrollParent属性
		scrollParent = targetElement.fastClickScrollParent;
		// Attempt to discover whether the target element is contained within a scrollable layer. Re-check if the
		// target element was moved to another parent.
		//用于判断一个指定的元素是否在一个scrollable layer中,如果目标元素移动到另外一个父元素时候又需要重新检查
		if (!scrollParent || !scrollParent.contains(targetElement)) {
			parentElement = targetElement;
			do {
				//如果scrollHeight>offsetHeight表示元素在垂直方向上存在滚动
				if (parentElement.scrollHeight > parentElement.offsetHeight) {
					scrollParent = parentElement;
					targetElement.fastClickScrollParent = parentElement;
					break;
				}
                 //更新parentElement元素
				parentElement = parentElement.parentElement;
			} while (parentElement);
		}
		// Always update the scroll top tracker if possible.
		//获取到了滚动的父元素后,我们要更新scrollParent的fastClickLastScrollTop属性
		if (scrollParent) {
			scrollParent.fastClickLastScrollTop = scrollParent.scrollTop;
		}
	};
问题7:firstElementChild来为head元素添加meta属性

 if (!metaEl) {
        metaEl = doc.createElement('meta');
        metaEl.setAttribute('name', 'viewport');
        metaEl.setAttribute('content', 'initial-scale=' + scale + ', maximum-scale=' + scale + ', minimum-scale=' + scale + ', user-scalable=no');
        if (docEl.firstElementChild) {//获取head
            docEl.firstElementChild.appendChild(metaEl);
        } else {
            var wrap = doc.createElement('div');
            wrap.appendChild(metaEl);
            doc.write(wrap.innerHTML);
        }
    }

问题8:Node.prototype.addEventListener属性

	if (!Event.prototype.stopImmediatePropagation) {
			layer.removeEventListener = function(type, callback, capture) {
				var rmv = Node.prototype.removeEventListener;
				//获取Node元素上的prototype的removeEventListener方法
				if (type === 'click') {
					//callback的hijacked属性,默认是callback
					rmv.call(layer, type, callback.hijacked || callback, capture);
				} else {
					rmv.call(layer, type, callback, capture);
				}
			};
            //如果是click事件,那么我们获取hijacked属性,因为这个方法是用于取消冒泡的!添加事件监听的时候我们直接进行设置了
            //如果不是click事件,那么我们直接回调方法就可以了,如果是click事件那么我们监听到以后停止冒泡
			layer.addEventListener = function(type, callback, capture) {
				var adv = Node.prototype.addEventListener;
				if (type === 'click') {
					//留意这里 callback.hijacked 中会判断 event.propagationStopped 是否为真来确保(安卓的onMouse事件)只执行一次
                    //在onMouse事件里会给 event.propagationStopped 赋值 true
					adv.call(layer, type, callback.hijacked || (callback.hijacked = function(event) {
						if (!event.propagationStopped) {
							callback(event);
						}
					}), capture);
				} else {
					adv.call(layer, type, callback, capture);
				}
			};
		}
		// If a handler is already declared in the element's onclick attribute, it will be fired before
		// FastClick's onClick handler. Fix this by pulling out the user-defined handler function and
		// adding it as listener.
		//用户自己定义的方法onclick也要添加进去,否则在点击的时候会在FastClick之前触发
		if (typeof layer.onclick === 'function') {
			// Android browser on at least 3.2 requires a new reference to the function in layer.onclick
			// - the old one won't work if passed to addEventListener directly.
			oldOnClick = layer.onclick;
			layer.addEventListener('click', function(event) {
				oldOnClick(event);
			}, false);
			layer.onclick = null;
		}
	}

可以通过Node.prototype直接获取原型上的方法

问题9:window.matchMedia方法

window.matchMedia("(min-width:400px)")//返回值有一个matches属性表示是否满足

参考文献:

Retina graphics for your website

你可能感兴趣的:(每天记录一点新遇到的浏览器方法和属性)