基礎焦點 | 事件 | 健盤 | 移動 | 拖拽 筆記

焦点事件

txt1.onfocus = function () {
  if (this.value == 'please input something') {
    this.value = ''
  }
}
txt1.onblur = function () {
  if (this.value == '') {
    this.value = 'please input something'
  }
}

// obj.focus()//给指定元素设置焦点
// obj.blue() //取消元素焦点
// obj.select() /选择指定元素的文本

btn1.onclick = function () {   txt1.select() } 

事件对象
1、event:事件对象,当一个事件发生时,和当前对象发生的这个事件有关的一些详细的信息都会保存到一个指定地方:event对象供我们在需要时调用
2、如果一个函数被事件调用,那么这个函数定义的第一个参数就是事件对象

for (var attr in ev) {   console.log(attr + '=' + ev[attr]); } 

FF无even内部定义全局对象
div鼠标移动

document.onmousemove = function (ev) {
  var ev = ev || event;
  var sct = document.documentElement.scrollTop || document.body.scrollTop;
  var scl = document.documentElement.scrollLeft || document.body.scrollLeft;
  box.style.left = ev.clientX + scl + 'px'
  box.style.top = ev.clientY + sct + 'px'
}

事件流:1、事件冒泡;2、事件捕获

function fn1() {
  alert(this.id)
}
box1.onclick = fn1; //给元素加函数;//告诉box1,如果他接收到一个点击事件,那么他就去执行fn1  //事件函数绑定
box2.onclick = fn1;
box3.onclick = fn1;
//从中间截断,即不会再有冒泡,box3也冒泡不到box1
box2.onclick = function (ev) {
  var ev = ev || event
  ev.cancelBubble = true;
}
var box = document.getElementById('box')
var inp = document.getElementById('btn')
inp.onclick = function (ev) {
  box.style.display = 'block'
  //阻止inp的冒泡 阻止当前对象的当前事件冒泡  即只阻止onclick,如onmouseover等都会有冒泡
  var ev = ev || event
  ev.cancelBubble = true;
}
document.onclick = function () {
  box.style.display = 'none'
}
//FB显示隐藏
var div1 = document.getElementById('div1')
div1.onmouseover = function () { //移到div2时,冒泡到div1了,所以能显示
  this.style.left = 0
}
div1.onmouseout = function () {
  this.style.left = - 100 + 'px'
}

1、事件绑定第一种形式:obj.onclick = fn; 多个绑定会覆盖前面绑定;
2、事件绑定第二种形式:

IE:obj.attachEvent(事件名,事件函数) document.attachEvent('onclick',fn1) IE7下顺序会相反
   <blockquote> 1)无捕获
    2)事件名称有on
    3)IE7下事件执行顺序相反
    4)this指向window
    5)使用call,函数下一个方法,改变一个函数运行中this指向,第二个开始就是原来函数的参数
ockquote>
标准下:obj.addEventListener(事件名,事件函数,是否捕获?) obj.addEventListener('click','fn1', true)
ckquote> 1)有捕获<br />
    2)事件名称无on<br />
    3)顺序正常<br />
    4)this指向触发该函数的对象</blockquote>
//事件绑定方法封装
function on(obj, evt, fn) {
  if (obj.addEventListener) {
    obj.addEventListener(evt, fn, false)
  } 
  else {
    obj.attachEvent('on' + evt, function () {
      fn.call(obj);
    })
  }
}
on(document, 'click', fn1)
function fn1() {
  alert(this)
}
<div id="box1">
    <div id="box2">
        <div id="box3"></div>
    </div>
</div>
//先出后进
box1.addEventListener('click', function () {
  alert(1)
}, false)
box1.addEventListener('click', function () {
  alert(3)
}, true)
box3.addEventListener('click', function () {
  alert(2)
}, false)

取消事件绑定
ie:obj.adttachEvent(事件名称,事件函数)
标准 : obj.removeEventListener(事件名称,事件函数,是否捕获)

document.onclick = null;
document.removeEventListener('click',fn1,false)

健盘事件
onkeydown:按按下时触发
onkeyup:按健抬起时触发
event.keyCode:数字类型,健值
ctrlKey,shiftKey altKey ,boolean值,当一个事件发生时,如果ctrl || shift || alt是按下的状态返回true,否则返回false

document.onkeydown = function (ev) {
  var ev = ev || event
  alert(ev.keyCode)
}
document.onclick = function (ev) {
  var ev = ev || event
  alert(ev.ctrlKey)
}
txt1.onkeyup = function (ev) {
  var ev = ev || event
  //alert(this.value)
  if (this.value != '') {
    if (ev.keyCode == 13) {
      var oli = document.createElement('li')
      oli.innerHTML = this.value;
      if (ul1.children[0]) { //如果存在子元素
        ul1.insertBefore(oli, ul1.children[0])
      } 
      else { //如果不存在子元素
        ul1.appendChild(oli)
      }
    }
  }
}

移動元素,按健連續觸發延遲問題

<div id="div1" style="width: 100px; height: 100px; background: #bf0000; position: absolute;"></div>
var div1 = document.getElementById('div1')
//有焦点的元素才能够接收健盘事件;
var timer = null;
var onoff = true; //設置開關
var clw = document.documentElement.clientWidth;
var clh = document.documentElement.clientHeight;
document.onkeydown = function (e) { //把健盘事件加到document上
  e = e || event;
  switch (e.keyCode) {
    case 37: //左
      if (onoff) {
        timer = setInterval(function () {
          var dl = div1.offsetLeft;
          if (dl < 10) {
            dl = 10
          }
          onoff = false
          div1.style.left = dl - 10 + 'px'
        }, 14)
      }
      break;
    case 38://上
      if (onoff) {
        timer = setInterval(function () {
          var dt = div1.offsetTop
          if (dt < 10) {
            dt = 10
          }
          onoff = false
          div1.style.top = dt - 10 + 'px'
        }, 14)
      }
      break;
    case 39://右
      if (onoff) {
        timer = setInterval(function () {
          var dl = div1.offsetLeft;
          if (dl > (clw - div1.offsetWidth - 10)) {
            dl = clw - div1.offsetWidth - 10
          }
          onoff = false
          div1.style.left = dl + 10 + 'px'
        }, 14)
      }
      break;
    case 40://下
      if (onoff) {
        timer = setInterval(function () {
          var dt = div1.offsetTop
          if (dt > (clh - div1.offsetHeight - 10)) {
            dt = clh - div1.offsetHeight - 10
          }
          onoff = false
          div1.style.top = dt + 10 + 'px'
        }, 14)
      }
      break;
  }
}
document.onkeyup = function () {
  onoff = true;
  clearInterval(timer);
}

事件默認行為: return false;
自定義右健菜單

document.oncontextmenu = function (e) {
  var e = e || event;
  var scl = document.documentElement.scrollLeft || document.body.scrollLeft;
  var sct = document.documentElement.scrollTop || document.body.scrollTop;
  box.style.display = 'block'
  box.style.left = e.clientX + scl + 'px'
  box.style.top = e.clientY + sct + 'px'
  return false;
}
document.onclick = function () {
  box.style.display = 'none'
}

元素拖拽,方法封裝
拖拽過程如果有文字被選中會產生問題:
原因:默認行為
標準下:阻止拖拽默認行為;return false;
ie:全局捕獲 obj.setCapture() ; 當給一個元素設置全局捕獲以後,此元素會監聽後續發生的所有事件,當有事件發生時就會被當前設置了全局捕獲的元素觸發;

inp1.onclick = function(){
    alert(1);
}
inp2.onclick = function(){
    alert(2);
}
if(inp1.setCapture){
inp1.setCapture()
}  //第一次點任意地方都將觸發alert(1);
function drag(obj) {
  var cw = document.documentElement.clientWidth;
  var ch = document.documentElement.clientHeight;
  obj.onmousedown = function (e) {
    var e = e || event;
    var disW = e.clientX - this.offsetLeft;
    var disH = e.clientY - this.offsetTop;
    //解決IE文字選中後移動問題:
    if (obj.setCapture) {
      obj.setCapture();
    }
    document.onmousemove = function (e) {
      var e = e || event;
      var cw_w = e.clientX - disW;
      var ch_h = e.clientY - disH
      if (cw_w < 0) {
        cw_w = 0
      } 
      else if (ch_h < 0) {
        ch_h = 0
      } 
      else if (cw_w > cw - obj.offsetWidth) {
        cw_w = cw - obj.offsetWidth
      } 
      else if (ch_h > ch - obj.offsetHeight) {
        ch_h = ch - obj.offsetHeight
      }
      obj.style.left = cw_w + 'px'
      obj.style.top = ch_h + 'px'
    }
    document.onmouseup = function () {
      document.onmousemove = null;
      //解決IE8抬起鼠標,釋放全局捕獲 releaseCapture();
      if (obj.releaseCapture) {
        obj.releaseCapture()
      }
    }
    return false; //down事件觸發時陰止默認行為;
  }
}

基礎DOM | children | offset | 表格 | 表單 | BOM 筆記

背景

<ul id="ul">
    <li>001</li>
    <li>002</li>
    <li>003</li>
    <li>004</li>
</ul>

1、childNodes包含文本、元素、属性、等节点;
2、children只包含元素节点

var ul = document.getElementById('ul')
console.log( ul.childNodes.length ) //9
console.log( ul.children.lenght )  //4

// alert(ul.childNodes[0].nodeType)
// alert(ul.attributes.length)
//alert(ul.attributes[0].name)
//alert(ul.attributes[0].value)

使用children,IE7不会包含非法嵌套内容;
兼容写法:first/last/next/prev

var _first = ul.firstElementChild || ul.firstChild;
var _last = ul.lastElementChild || ul.lastChild;
var _next = _first.nextElementSibling || _first.nextSibling;
var _prev = _last.previousElementSibling || _last.previousSibling;

parentNode 无兼容性问题,得到的父节点只有一个;

<ul id="ul">
    <li>001 <a href="javascript:;">DEL</a></li>
    <li>002 <a href="javascript:;">DEL</a></li>
    <li>003 <a href="javascript:;">DEL</a></li>
    <li>004 <a href="javascript:;">DEL</a></li>
</ul>
var a = ul.getElementsByTagName('a')
for(var i=0;i<a.length;i++){
    a[i].onclick = function(){
        this.parentNode.style.display = 'none'
    }
}

offsetParent offsetLeft offsetTop

<div id="div1">
    <div id="div2">
        <div id="div3"></div>
    </div>
</div>
    var div1 = document.getElementById('div1')
    var div2 = document.getElementById('div2')
    var div3 = document.getElementById('div3')
console.log( div3.offsetLeft ) //自身无定位,则指向有定位父级,如果没有定位默认body
//自身有定位,父级无定位,则IE7指向html,其它指向body
//父级设置zoom,IE7指向html,其它指向body
console.log( div2.currentStyle.hasLayout ) //当前元素是否触发layout 
<div id='box' style='width:99px;height:99px;border:1px solid red;'></div>
var box = document.getElementById('box')
console.log( box.style.width )
console.log( box.clientWidth ) //可視區寬度 樣式寬+padding
console.log( box.offsetWidth ) //可視區寬+border

取得元素在頁面上left top方法

function getPos(obj) {
  var pos = { left: 0,top: 0 };
  while (obj) {
    pos.left += obj.offsetLeft;
    pos.top += obj.offsetTop;
    obj = obj.offsetParent;
  }
  return pos;
}
getPos(box).left;
getPos(box).top;

屬性操作
1、obj.attr 無法操作自定義屬性
2、obj['attr'] 無法操作自定義屬性
3、obj.getAttribute(attr) 可操作自定義屬性,如_a = '123'
4、_img.src _img['src'] 返回全鏈接值 _img.getAttribute('src') 返回相對鏈接值,IE7下還是返回全鏈接值

插入刪除
父級.appendChild( 要插入的元素 );
父級.removeChild( 要刪除的元素 );
父級.insertBefore( 新元素,被插入的元素 ) ;即在指定元素前面插入一個新元素;
父級.replaceChild( 新節點,被替換節點 );
obj.cloneNode( true ); 複製節點

兼容getClassName方法

function getClassName(parent, tagName, className) {
  var aEls = parent.getElementsByTagName(tagName)
  var arr = []
  for (var i = 0; i < aEls.length; i++) {
    var aClassName = aEls[i].className.split(' '); //当前classname拆分成数组
    for (var j = 0; j < aClassName.length; j++) {
      if (aClassName[j] == className) { //如果第j个class == classname
        arr.push(aEls[i]) //则把当前第i个class push进来
        break; //如果class='box box'相同名字,找到一个跳出for
      }
    }
  }
  return arr;
}
getClassName(document, 'li', 'box');

兼容addClass方法

function addClass(obj, className) {
  if (obj.className == '') { //原本无
    obj.className = className;
  } 
  else { //原本有
    var arrClassName = obj.className.split(' ');
    var _index = arrIndexOf(arrClassName, className);
    if (_index == - 1) { //不存在
      obj.className += ' ' + className;
    }
  }
}
//判斷一個數組裏是否存在元素
function arrIndexOf(arr, v) {
  for (var i = 0; i < arr.length; i++) {
    if (arr[i] == v) {
      return i; //当前重複的值出现位置
    }
  }
  return - 1;
}

addClass(box, 'box111');

兼容removeClass方法

function removeClass(obj, className) {
  if (obj.className != '') {   //如果有class
    var arrClassName = obj.className.split(' ');
    console.log(arrClassName);
    var _index = arrIndexOf(arrClassName, className);
    if (_index != - 1) {     //如果有需要移除的class
      arrClassName.splice(_index, 1); //删除数组裏需要移除的
      obj.className = arrClassName.join(' ');//再把處理完的數組class給obj
    } 
  }
}
//判斷一個數組裏是否存在元素
function arrIndexOf(arr, v) {
  for (var i = 0; i < arr.length; i++) {
    if (arr[i] == v) {
      return i; //当前重複的值出现位置
    }
  }
  return - 1;
}

removeClass(box, 'box3')

表格基本操作
tHead 表格頭
tHodie 表格正文 複合
tFoot 表格尾
rows 行 複合
cells 列 複合
數據操作:

var tb = document.getElementsTagName('table')[0];
console.log(tb.tBodies[0].rows[0].cells[0].innerHTML)
var data = [  //數組形式存放
    {id: 1, username: 'elos1', sex: '男'},
    {id: 2, username: 'edlo2', sex: '女'},
    {id: 3, username: 'elfo3', sex: '女'},
    {id: 4, username: 'elos4', sex: '男'}
]
for(var i=0;i<data.length;i++){
    var tr = document.createElement('tr'); //創建一行
//隔行變色
    if(i%2 == 0){
        tr.style.background = '#fff';
    }
    else{
        tr.style.background = '#ccc';
    }
    var td = document.createElement('td')//創建一列
    td.innerHTML = data[i].id;//列加內容
    tr.appendChild(td);//append到tr

    var td = document.createElement('td')
    td.innerHTML = data[i].username;
    tr.appendChild(td);

    var td = document.createElement('td')
    td.innerHTML = data[i].sex;
    tr.appendChild(td);

    tb.tBodies[0].appendChild(tr);
}

表單基本操作
重要屬性:name; form.name
onchange:當值發生改變時觸發,IE7下當值發生改變並且焦點離開時觸發
name屬性一個相同為單數,多個相同name則為複數,即[i]下標取值;
checked 選中屬性,都選中則以最後選中為准
onsubmit 提交時觸發
onreset reset時觸發

<form id="form1" action="">
    <input type="text" id="txt1" name="text1" value="內容"/>
    <input type="radio"  name="sex" value="男" checked/> 男
    <input type="radio"  name="sex" value="女" /> 女
</form>
var form = document.getElementById('form1')
console.log(form.text1.value);
    ofrom.sex[0].onchange = function (){
    ...
}
    if( ofrom.sex[i].checked ){
    ...
    }
form.onsubmit = function(){
    if(form.text1.value==''){
    alert('please input something')
    return false; //阻止提交
    }
}
form.onreset = function(){
    return confirm('are you sure to reset') //詢問對話
}

BOM操作
window.open (页面地址url,打开方式)
页面地址url为空,默认打开空页面
打开方式为空,默认新窗口打开,自身:_self

var opener = null;
opener = window.open();
alert( opener = window );
opener.document.body.style.background = 'red'  //新窗口背景为red

window.close() //兼容性,ff无效,ie chrome有效

opener.close();//关闭新窗口,无兼容性;

window.navigator.userAgent 浏览器信息,字符串

if(window.navigator.userAgent.indexOf('.NET') != -1){
    alert('IE')
}else{ alert('NOT IE') }

window.location 用户,浏览器地址信息
window.location.href
window.location.search: url? 问号后面的内容

window.location.hash: url# 后面的内容

可视区大小
document.documentElement.clientWidth;
document.documentElement.clientHeight

滚动距离
document.body.scrollTop / scrollLeft
document.documentElement.scrollTop / scrollLeft

内容高度
document.body.scrollHeight

文档高度
document.documentElement.offsetHeight
document.body.offsetHeight

//可视区宽
alert(document.documentElement.clientWidth)
//可视区大小兼容,chrome认为滚动是body的
var sTop1 = document.body.scrollTop || document.documentElement.scrollTop;
var sTop2 = Math.max(document.body.scrollTop, document.documentElement.scrollTop)
var sTop3 = document.body.scrollTop + document.documentElement.scrollTop
<div id="boxs" style = 'width: 100px;height: 100px;border: 1px solid red ;padding: 10px;margin: 10px;'>
        <div style="width: 100px;height: 200px;background: #000;"></div>  
</div>
//内容高度:抛开边框,外面的padding+内容内容高度,包括父级被撑开的高度,加隐藏内容不加border
alert(document.getElementById('boxs').scrollHeight)
/*
boxs不加overflow:hidden: 210;
boxs + overflow:hidden: 
    chrome: 220
    ff:210
    IE8+ 210
    IE8- 220
    safari 220
    opera  220
*/
alert( document.getElementById('boxs').offsetHeight ) //122  height + padding + border
alert( document.body.offsetHeight ) //142 height + padding + border + margin //如果body取值则需要加上margin

//IE下,body style =" height: 2000px;" 兼容问题,IE取不到
所以获取body内容高时,推荐使用: document.body.offsetHeight;

onscroll 当滚动条滚动时触发
onresize 当窗口大小发生改变时触发

//回到頂部 兼容寫法
var a = document.querySelector('a')
var timer = null;
window.onscroll = function () {
  var Dsroll = document.body.scrollTop || document.documentElement.scrollTop
Dsroll >= 200?a.style.display = 'block':a.style.display = 'none'
  a.onclick = function () {
    var Dsroll = document.body.scrollTop || document.documentElement.scrollTop
    timer = setInterval(function () {
      Dsroll -= 30;
      if (Dsroll <= 0) {
        clearInterval(timer)
      }
      document.body.scrollTop = Dsroll
      document.documentElement.scrollTop = Dsroll
    }, 30)
  }
}

select操作:

<select name="" id="s">
    <option value="0" selected>0</option>
    <option value="100">text文本100</option>
    <option value="200">text文本200</option>
</select>
<p>value是 <span id="sval"></span> text是 <span id="stxt"></span></p>
    var s = document.getElementById('s')
    var sval = document.getElementById('sval');
    var stxt = document.getElementById('stxt');
    s.onchange = function () {
        var sV = s.value;
        var sT = s.options[s.selectedIndex].text;
        sval.innerHTML = sV;
        stxt.innerHTML = sT;
    }