J.chong - JS
type: channel
link: https://www.elmok.com/category/JS
description: 零JS系列，所以東西都看懂，即表示入門
items: openwrt 单网口设置旁路由模式
items: 一些方法记录
items: 零js基礎 | 程序設計 | 16-html脚本编程
items: 零js基礎 | 程序設計 | 15 - Canvas
items: 零js基礎 | 程序設計 | 14 - 表单
items: 零js基礎 | 程序設計 | 13 - 事件
items: 零js基礎 | 程序設計 | 12 - DOM2和DOM3
items: 零js基礎 | 程序設計 | 11 - DOM扩展
items: 零js基礎 | 程序設計 | 10 - DOM
items: 零js基礎 | 程序設計 | 9 - 客户端检测

openwrt 单网口设置旁路由模式
type: item
date: 2021-11-05T12:33:00+08:00
description: 1、使用 starwind-v2v-converter 把 iso 转为 vmdk2、按所需要的工具转换，如VMware Workstation 或 ESXi Server image3、若是ESXi,下一步选 Pre-allocated image4、旁路由，1G内存够用，可分配多一点CPU5、网络设置，VMware Workstation 直接桥接复制本地物理网卡6、vi /etc/config/network 改静态IP7、接口 -> 修改仅剩的LAN口，并填好IP网关DNS，其它删8、禁用通告、(DHCP)、DNP功能9、防火墙，区域这块，入站 出站 转发 全改为 接受10、联网检测即可11、若接管整个网关，关闭主路由DHCP，开启OP DHCP12、记录不需要科学上网的MAC地址，打开 vi /etc/config/dhcp13、增加//iot是tag名称，可任意，6开头表示DNS，3开头表示网关 //一、先定义模板 config tag 'iot' list dhcp_option '6,119.29.29.29' list dhcp_option '3,192.168.1.1' option force '1' //二、再定义需要使用iot的主机 config host option dns '1' option name 'test' option mac 'aa:7d:54:a4:f8:da' option tag 'iot'14、重启DHCP/etc/init.d/dnsmasq restart

一些方法记录
type: item
date: 2020-11-08T17:15:00+08:00
description: //获取图片原始宽高 function getImgNaturalDimensions(oImg, callback) { var nWidth, nHeight; if (!oImg.naturalWidth) { nWidth = oImg.naturalWidth; nHeight = oImg.naturalHeight; callback({w: nWidth, h:nHeight}); } else { var nImg = new Image(); nImg.onload = function() { var nWidth = nImg.width, nHeight = nImg.height; callback({w: nWidth, h:nHeight}); } nImg.src = oImg.src; } } getImgNaturalDimensions(e.querySelector('img'),function (_img) { console.log(_img.w) console.log(_img.h) })//复制文字 document.querySelector('.j-copy-mail').onclick=function(){ var _copymail = this.innerText var flag = copyTextToClipboard(_copymail) flag ? layer.msg(_copymail+' 已複製!',{offset: '128px'}) : layer.msg('複製失敗請重試!',{offset: '128px'}) function copyTextToClipboard(text) { var textArea = document.createElement("textarea"); textArea.style.background = 'transparent'; textArea.value = text; document.body.appendChild(textArea); textArea.select(); try { var successful = document.execCommand('copy'); var msg = successful } catch (err) { var msg= false } document.body.removeChild(textArea); return msg } }//flex布局 1 2 3 //对应css .b1{ background: #cccccc; order:2; /*flex是flex属性是flex-grow，flex-shrink与flex-basis三个属性的简写*/ flex:1 1 auto; /*等分放大缩小*/ flex:0 0 auto; /*不放大不缩小*/ } .b2{ background: #eeeeee; order:1; /*默认auto,或者以width为自身的宽度，但如果设置了flex-basis，权重会width属性高，因此会覆盖widtn属性*/ flex-basis:auto; flex-basis: 500px; /*表示是否继承父元素的 align-items属性，若没有父属性，默认stretch*/ align-self: auto; } .b3{ background: #939393; /*有用，更改元素排列 0开始，数字越小越靠前*/ order:0; /*默认0，用于决定项目在有剩余空间的情况下是否放大，0不放大，即使设置了固定宽度也会放大*/ /*若有多个1，则剩余空间平分*/ flex-grow:1; /*默认1，用于决定项目在有剩余空间的情况下是否缩小，即空间不足时大家一起等比例缩小*/ flex-shrink:0;/*设置了这个为0后，即使缩小父box，时，其它两项会缩小，但这项不会缩小宽度*/ } .b1,.b2,.b3{ text-align: center; font-size: 60px; line-height: 300px; width: 30%; width: 600px; } .box{ display: flex; /*width: 1200px;*/ height: 900px; /*控制排序方向与顺序*/ flex-direction: row-reverse;/*321*/ flex-direction: column;/*纵 123*/ flex-direction: column-reverse;/*纵321*/ flex-direction: row;/*123*/ …

零js基礎 | 程序設計 | 16-html脚本编程
type: item
date: 2014-03-09T22:01:00+08:00
description: XDM核心方法是：postMessage('一个消息'，'此消息的来源域')目的：：向另一个地方传递数据接收到XDM消息时，会触发window 对象的message 事件data:作为postMessage()第一个参数传入的字符串数据origin:发送消息的文档所在的域，例如"http://www.wrox.com"。source:发送消息的文档的window 对象的代理。这个代理对象主要用于在发送上一条消息的窗口中调用postMessage()方法。如果发送消息的窗口来自同一个域，那这个对象就是window。在onmessage 处理程序中检测消息来源可以确保传入的消息来自已知的页面。基本的检测模式如 EventUtil.addHandler('window','message',function(event){ if(event.origin == 'http://badiu.com'){ processMessage(event.data) event.source.postMessage('Received!','http://p2p.baidu.com') } }) 注：，event.source 大多数情况下只是window 对象的代理，并非实际的window 对象。换句话说，不能通过这个代理对象访问window 对象的其他任何信息。记住，只通过这个代理调用postMessage()就好，这个方法永远存在，永远可以调用最好只传入字符串，如果要传入结构化数据，要先在传入数据中JSON.stringify()；通过postMessage()传入得到的字符串，然后再在onmessage 事件处理程序中调用JSON.parse()拖放元素时，依次触发下列事件：1、dragstart2、drag3、dragend当某个元素被拖动到一个有效的放置目标上时，下列事件会依次发生：1、dragenter2、dragover3、dragleave 或 drop上述三个事件的目标都是作为放置目标的元素

零js基礎 | 程序設計 | 15 - Canvas
type: item
date: 2014-02-13T18:38:00+08:00

零js基礎 | 程序設計 | 14 - 表单
type: item
date: 2014-02-03T17:48:00+08:00
description: var form = document.getElementById("form1"); var firstForm = document.forms[0]; var myForm = document.forms["form2"]; objform.elements('objid')获取方法 Red Green Blue var formId = document.getElementById('myForm') var formName = document.getElementsByName('myFormname')[0] var form0 = document.forms[0] var colorId = formId.elements['colorName'] alert(colorId.length)//3 var colorName = formName.elements['colorName'] alert(colorName.length)//3，有3 个单选按钮，它们的name 都是"color"，意味着这3 个字段是一起的。在访问elements["color"]时，就会返回一个NodeList，其中包含这3 个元素；不过，如果访问elements[0]，则只会返回第一个元素。来看下面的例子。var form = document.getElementById("myForm"); var colorFields = form.elements["color"]; alert(colorFields.length); //3 var firstColorField = colorFields[0]; var firstFormField = form.elements[0]; alert(firstColorField === firstFormField); //true除了fieldset元素之外，所有表单字段都拥有相同的一组属性。由于input类型可以表示多种表单字段，因此有些属性只适用于某些字段，但还有一些属性是所有字段所共有的。表单字段共有的属性如下。 disabled：布尔值，表示当前字段是否被禁用。 form：指向当前字段所属表单的指针；只读。 name：当前字段的名称。 readOnly：布尔值，表示当前字段是否只读。 tabIndex：表示当前字段的切换（tab）序号。 type：当前字段的类型，如"checkbox"、"radio"，等等。 value：当前字段将被提var filed = form.elements[0] filed.value = 'auther Value' alert(filed.form === form) //true //把焦点设置到当前字段 field.focus(); //禁用当前字段 field.disabled = true; //修改type 属性（不推荐，但对input来说是可行的） field.type = "checkbox";这就是个问题：因为会导致费用翻番。为此，最常见的解决方案，就是在第一次单击后就禁用提交按钮。只要侦听submit 事件，并在该事件发生时禁用提交按钮即可。以下就是这样一个例子。EventUtil.addHandler(form, "submit", function(event){ event = EventUtil.getEvent(event); var target = EventUtil.getTarget(event); //取得提交按钮 var btn = target.elements["submit-btn"]; //禁用它 btn.disabled = true; });注意，不能通过onclick 事件处理程序来实现这个功能，原因是不同浏览器之间存在“时差”：有的浏览器会在触发表单的submit 事件之前触发click 事件，而有的浏览器则相反。对于先触发click 事件的浏览器，意味着会在提交发生之前禁用按钮，结果永远都不会提交表单focus()和 blur()。EventUtil.addHandler(window, "load", function(event){ document.forms[0].elements[0].focus(); });要注意的是，如果第一个表单字段是一个input元素，且其type 特性的值为"hidden"，那么以上代码会导致错误。另外，如果使用CSS 的display 和visibility 属性隐藏了该字段，同样也会导致错误。HTML5 为表单字段新增了一个autofocus 属性。在支持这个属性的浏览器中，只要设置这个属性，不用Java…

零js基礎 | 程序設計 | 13 - 事件
type: item
date: 2014-01-31T13:22:00+08:00
description: 使用try catch捕获错误 try { var dd = document.getElemedntById('dd') } catch (ex) { alert(123) }addEventListener(),最后这个布尔值参数如果是true，表示在捕获阶段调用事件处理程序；如果是false，表示在冒泡阶段调用事件处理程try { btn.addEventListener('click', function() { alert(this.id) }, false) } catch (ex) { btn.attachEvent('onclick', function() { alert(123) }) }removeEventListener(),要使用命名函数才能移除 btnfn = function() { alert(this.id) } btn.addEventListener('click', btnfn, false) btn.removeEventListener('click',btnfn,false)attachEvent()与detachEvent()，1、this作用域为window; 2、执行顺序由后往前；btn.attachEvent('onclick',function(){ alert(this) //特别注意，这里是window }) btn.attachEvent("onclick", function(){ alert("Clicked"); //弹2 }); btn.attachEvent("onclick", function(){ alert("Hello world!"); //弹1 });兼容方法：var 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; } }, 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; } } }; var handler = function() { alert('abc') } EventUtil.addHandler(btn, 'click', handler) EventUtil.removeHandler(btn, "click", handler);事件对象对象this 始终等于currentTarget 的值，而target 则只包含事件的实际目标。如果直接将事件处理程序指定给了目标元素，则this、currentTarget 和target 包含相同的值。来看下面的例子。btn.onclick = function(event){ alert(event.currentTarget === this) alert(event.target === this) }document.body.onclick = function(event) { alert(event.currentTarget == document.body) //true alert(this === document.body) //true alert(event.target == document.getElementById('mybtn')) //true }使用event.type判断不同事件；var handler = function(event) { switch (event.type) { case 'click': alert('clicked') break; case 'mouseover': alert('mouseovered') break; case 'mouseout': alert('mouseouted'); brea…

零js基礎 | 程序設計 | 12 - DOM2和DOM3
type: item
date: 2014-01-18T22:53:00+08:00
description: var supportsDOM2Core = document.implementation.hasFeature("Core", "2.0"); var supportsDOM3Core = document.implementation.hasFeature("Core", "3.0"); var supportsDOM2HTML = document.implementation.hasFeature("HTML", "2.0"); var supportsDOM2Views = document.implementation.hasFeature("Views", "2.0"); var supportsDOM2XML = document.implementation.hasFeature("XML", "2.0");混合svg写法 Example XHTML page <rect x="0" y="0" width="100" height="100" style="fill:red" /> 在DOM2 级中，Node 类型包含下列特定于命名空间的属性。localName：不带命名空间前缀的节点名称。namespaceURI：命名空间URI 或者（在未指定的情况下是）null。prefix：命名空间前缀或者（在未指定的情况下是）null。nodeName 等于prefix+":"+ localName 元素來說localName:htmltagName:htmlnamespaceURI:http://www.w3.org/1999/xhtmlprefix:null<s:svg>元素localName:svgtagName:s:svgnamespaceURI:http://www.w3.org/2000/svgprefix:sDOM3 级在此基础上更进一步，又引入了下列与命名空间有关的方法。isDefaultNamespace(namespaceURI)：在指定的namespaceURI 是当前节点的默认命名空间的情况下返回true。lookupNamespaceURI(prefix)：返回给定prefix 的命名空间。lookupPrefix(namespaceURI)：返回给定namespaceURI 的前缀。Document变化只有在文档中存在两个或多个命名空间时，这些与命名空间有关的方法才是必需的。 //创建一个新的SVG 元素 var svg = document.createElementNS("http://www.w3.org/2000/svg", "svg"); //创建一个属于某个命名空间的新特性 var att = document.createAttributeNS("http://www.somewhere.com", "random"); //取得所有XHTML 元素 var elems = document.getElementsByTagNameNS("http://www.w3.org/1999/xhtml", "*");Element变化getAttributeNS(namespaceURI,localName)：取得属于命名空间namespaceURI 且名为localName 的特性。getAttributeNodeNS(namespaceURI,localName)getElementsByTagNameNS(namespaceURI, tagName)hasAttributeNS(namespaceURI,localName)removeAttriubteNS(namespaceURI,localName)setAttributeNS(namespaceURI,qualifiedName,value)setAttributeNodeNS(attNode)除了第一个参数之外，这些方法与DOM1 级中相关方法的作用相同；第一个参数始终都是一个命名空间URI。NamedNodeMap变化getNamedItemNS(namespaceURI,localName)取得属于命名空间namespaceURI 且名为localName 的项。removeNamedItemNS(namespaceURI,localName)其它变化:DocumentType 类型的变化 类型新增了3 个属性：publicId、systemId 和internalSubset。 中的：publicId == "-//W3C//DTD HTML 4.01//EN"，systemId =="http://www.w3.org/TR/html4/strict.dtd"alert(document.doctype.…

零js基礎 | 程序設計 | 11 - DOM扩展
type: item
date: 2014-01-17T17:37:00+08:00
description: DOM扩展 var div = document.querySelector('#div') //返回NodeList實例 var div = document.querySelectorAll('.divClass') console.log(div.item(0)) console.log(div[0]) console.log(div)matchesSelector(CSS選擇符)，如果匹配 true,否則 falseif (matchesSelector(div[0], '#div.divClass')) { alert(true) } //兼容性 function matchesSelector(element, selector) { if (element.matchesSelector) { return element.matchesSelector(selector); } else if (element.msMatchesSelector) { return element.msMatchesSelector(selector); } else if (element.mozMatchesSelector) { return element.mozMatchesSelector(selector); } else if (element.webkitMatchesSelector) { return element.webkitMatchesSelector(selector); } else { throw new Error("Not supported."); } }支持Element Traversal 规范的浏览器有IE 9+、Firefox 3.5+、Safari 4+、Chrome 和Opera 10+。 childElementCount：返回子元素（不包括文本节点和注释）的个数。 firstElementChild：指向第一个子元素；firstChild 的元素版。 lastElementChild：指向最后一个子元素；lastChild 的元素版。 previousElementSibling：指向前一个同辈元素；previousSibling 的元素版。 nextElementSibling：指向后一个同辈元素；nextSibling 的元素版。二、困扰你我的NodeList与HTMLCollection 相同点： 1. 类数组。有length属性，可以用下标索引来访问其中的元素，但没有Array的slice等方法； 2. 只读。无法增删其中的元素； 3. 实时同步DOM树的变化。若DOM树有新元素加入，该类型的对象也会将新元素包含进来； 4. 可通过下标数字类型索引获取集合中指定位置的元素； 5. 可通过item({String | Number} 索引)方法获取集合中指定位置的元素，若通过索引找不到元素，则以第一个元素作为返回值。 不同点（主要表现在HTMLCollection比NodeList能力更强大）： 1. HTMLCollection对象可通过namedItem({String} id或name)获取首个匹配的元素，若没有则返回null； 2. HTMLCollection对象可通过点方式获取第个id或name匹配的元素，若没有则返回undefined。 各浏览器选择器返回类型差别： console.log(div instanceof NodeList) //true //帶有.divClass.username的元素 var div = document.getElementsByClassName('divClass username') console.log(div) console.log(div instanceof HTMLCollection) //true;傳統刪class var classNames = div.className.split(/\s+/); var pos = -1; for(var i=0;i<classNames.length;i++){ if(classNames[i] == 'user'){ pos = i; break; } } classNames.splice(i,1); div.className = classNames.join(' ');classList,IE10+,chrome,firefox div[0].classList.remove('username') div[0].classList.add('current') div[0].classList.toggle('divClas…

零js基礎 | 程序設計 | 10 - DOM
type: item
date: 2014-01-15T20:54:00+08:00
description: Node.nodeType == 1 元素节点Node.nodeType == 2 属性节点Node.nodeType == 3 文本节点 var h = document.getElementsByTagName('head')[0] // h.nodeType == 1 && console.log('this is an elem') h.nodeType == 1 && console.log(h.nodeName) //HEAD //每个节点都有一个childNodes 属性，其中保存着一个NodeList 对象。即类数组对象 console.log(h.childNodes[0]) console.log(h.childNodes[1]) console.log(h.childNodes[2]) console.log(h.childNodes[3]) console.log(h.childNodes[4]) console.log(h.parentNode) //5 console.log(h.childNodes.length)把NodeTypelist转为数组function convertToArray(nodes) { var array = null; try { array = Array.prototype.slice.call(nodes, 0); //针对非IE 浏览器 } catch (ex) { array = new Array(); for (var i = 0, len = nodes.length; i < len; i++) { array.push(nodes[i]); } } return array; }每个Node都有一个parentNode属性，该属性指向文档树中的父节点；nodeName //HEADparentNode //Html文档结构childNodes //Nodelists节点集合previousSibling //前一个nextSibling //后一个如果没有子节点，那么firstChild 和lastChild 的值均为nullhasChildNodes(),这个方法在节点包含一或多个子节点的情况下返回true；应该说，这是比查询childNodes列表的length 属性更简单的方法。h.hasChildNodes()ownerDocument，所有节点的共同属性，指向整个文档节点console.log(h.ownerDocument)操作节点末尾：appendChild()相当于向childNodes列表尾部添加一个节点，，如果是已有节点，则相当于剪切；中间：insertBefore()，向childNodes列表放在特定的位置上insertBefore(要插入的节点，作为参照的节点) 【插入之后按顺序前后排：要插入的节点，作为参照的节点】插入节点后，被插入的节点会变成参照节点的前一个同胞节点（previousSibling），returnedNode = someNode.insertBefore(newNode, null); alert(newNode == someNode.lastChild); //true //插入后成为第一个子节点 var returnedNode = someNode.insertBefore(newNode, someNode.firstChild); alert(returnedNode == newNode); //true alert(newNode == someNode.firstChild); //true //插入到最后一个子节点前面 returnedNode = someNode.insertBefore(newNode, someNode.lastChild); alert(newNode == someNode.childNodes[someNode.childNodes.length-2]); //true替换：replaceChild(要插入的节点，要替换的节点)//替换第一个子节点 var returnedNode = someNode.replaceChild(newNode, someNode.firstChild); //替换最后一个子节点 returnedNode = someNode.replaceChild(newNode, someNode.lastChild);移除：removeChild(要移除的节点)前面介绍的四个方法操作的都是某个节点的子节点，也就是说，要使用这几个方法必须先取得父节点（使用parentNode 属性）。另外，并不是所有类型的节点都有子节点，如果在不…

零js基礎 | 程序設計 | 9 - 客户端检测
type: item
date: 2014-01-13T17:46:00+08:00
description: 直接把函数作为属性访问会导致JavaScript 错误。使用typeof 操作符会更靠谱一点，但IE对typeof xhr.open 会返回"unknown",在浏览器环境下测试任何对象的某个特性是否存在，要使用下面这个函数。function isHostMethod(object, property) { var t = typeof object[property]; return t == 'function' || (!!(t == 'object' && object[property])) || t == 'unknown'; } result = isHostMethod(xhr, "open"); //true result = isHostMethod(xhr, "foo"); //false能力检测，不是浏览器检测检测某个或某几个特性并不能够确定浏览器。下面给出的这段代码（或与之差不多的代码）可以在许多网站中看到，这种“浏览器检测”代码就是错误地依赖能力检测的典型示例。//错误！还不够具体 var isFirefox = !!(navigator.vendor && navigator.vendorSub); //错误！假设过头了 var isIE = !!(document.all && document.uniqueID);一次性检测//确定浏览器是否支持Netscape 风格的插件 var hasNSPlugins = !!(navigator.plugins && navigator.plugins.length); //确定浏览器是否具有DOM1 级规定的能力 var hasDOM1 = !!(document.getElementById && document.在实际开发中，应该将能力检测作为确定下一步解决方案的依据，而不是用它来 判断用户使用的是什么浏览器。完整用户代理字条串检测脚本代码 var client = function() { //呈现引擎 var engine = { ie: 0, gecko: 0, webkit: 0, khtml: 0, opera: 0, //完整的版本号 ver: null }; //浏览器 var browser = { //主要浏览器 ie: 0, firefox: 0, safari: 0, konq: 0, opera: 0, chrome: 0, //具体的版本号 ver: null }; //平台、设备和操作系统 var system = { win: false, mac: false, x11: false, //移动设备 iphone: false, ipod: false, ipad: false, ios: false, android: false, nokiaN: false, winMobile: false, //游戏系统 wii: false, ps: false }; //检测呈现引擎和浏览器 var ua = navigator.userAgent; if (window.opera) { engine.ver = browser.ver = window.opera.version(); engine.opera = browser.opera = parseFloat(engine.ver); } else if (/AppleWebKit\/(\S+)/.test(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 { //近似地确定版本号 var 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;…